/**
 * REGIME SELECTOR
 * @packageDocumentation
 */
import { createHash } from "node:crypto";
import { createLogger } from "../common/logger.js";
const logger = createLogger({ component: "regime-selector" });
const CRYPTO_STRICTNESS = {
    standard: 0,
    "fips-140-2": 1,
    "sm-national": 2,
    "post-quantum": 3,
    "cnsa-2.0": 4,
};
const PROOF_STRICTNESS = {
    database: 0,
    "merkle-tree": 1,
    "blockchain-l2": 2,
    "tsa-rfc3161": 3,
    "hardware-hsm": 4,
};
const CONSENT_STRICTNESS = {
    implicit: 0,
    "opt-out": 1,
    "opt-in": 2,
    "explicit-granular": 3,
    "dual-consent": 4,
};
const ESCALATION_STRICTNESS = {
    "log-only": 0,
    "flag-review": 1,
    "block-escalate": 2,
    "hard-block": 3,
};
export function hasJurisdiction(ctx, ...js) {
    return js.some((j) => ctx.primaryJurisdictions.includes(j));
}
export function hasPolicyConstraint(ps, type) {
    return ps.constraints.some((c) => c.type === type);
}
export function extractPolicyConstraintValue(ps, type) {
    return ps.constraints.find((c) => c.type === type)?.value;
}
function pickStrictest(defaults, pv, map) {
    const all = pv ? [...defaults, pv] : defaults;
    return all.reduce((s, c) => ((map[c] ?? 0) > (map[s] ?? 0) ? c : s));
}
export function resolveCryptoSuite(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "crypto");
    const d = ["standard"];
    if (hasJurisdiction(ctx, "US-DOD"))
        d.push("cnsa-2.0");
    else if (hasJurisdiction(ctx, "US-FED"))
        d.push("fips-140-2");
    else if (hasJurisdiction(ctx, "CN"))
        d.push("sm-national");
    return pickStrictest(d, pv, CRYPTO_STRICTNESS);
}
export function resolveProofAnchoring(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "proof-anchoring");
    const d = ["database"];
    if (hasJurisdiction(ctx, "US-DOD"))
        d.push("hardware-hsm");
    else if (hasJurisdiction(ctx, "US-FED"))
        d.push("tsa-rfc3161");
    else if (hasJurisdiction(ctx, "EU"))
        d.push("merkle-tree");
    return pickStrictest(d, pv, PROOF_STRICTNESS);
}
export function resolveConsentModel(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "consent");
    const d = ["implicit"];
    if (hasJurisdiction(ctx, "EU"))
        d.push("explicit-granular");
    else if (hasJurisdiction(ctx, "CA"))
        d.push("opt-in");
    else if (hasJurisdiction(ctx, "US"))
        d.push("opt-out");
    return pickStrictest(d, pv, CONSENT_STRICTNESS);
}
export function resolveEscalationMode(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "escalation");
    const d = ["flag-review"];
    if (hasJurisdiction(ctx, "US-DOD"))
        d.push("hard-block");
    else if (hasJurisdiction(ctx, "US-FED", "EU"))
        d.push("block-escalate");
    return pickStrictest(d, pv, ESCALATION_STRICTNESS);
}
export function resolveAuditRetentionDays(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "retention");
    const d = [365];
    if (hasJurisdiction(ctx, "EU"))
        d.push(1825);
    if (hasJurisdiction(ctx, "US-FED"))
        d.push(2555);
    if (hasJurisdiction(ctx, "US-DOD"))
        d.push(3650);
    return Math.max(...(pv ? [...d, pv] : d));
}
export function resolveExternalServicesAllowed(ctx, ps) {
    if (hasJurisdiction(ctx, "US-DOD", "CN"))
        return false;
    const pv = extractPolicyConstraintValue(ps, "external-services");
    return pv !== undefined ? pv : true;
}
export function resolveMinimumTrustLevel(ctx, ps) {
    const pv = extractPolicyConstraintValue(ps, "trust-level");
    const d = [2];
    if (hasJurisdiction(ctx, "US-DOD"))
        d.push(6);
    else if (hasJurisdiction(ctx, "US-FED"))
        d.push(4);
    else if (hasJurisdiction(ctx, "EU"))
        d.push(3);
    return Math.max(...(pv !== undefined ? [...d, pv] : d));
}
export function generateRegimeId(p) {
    const canonical = {
        auditRetentionDays: p.auditRetentionDays,
        consentModel: p.consentModel,
        cryptoSuite: p.cryptoSuite,
        dataResidency: p.dataResidency,
        escalationMode: p.escalationMode,
        externalServicesAllowed: p.externalServicesAllowed,
        jurisdictions: [...p.jurisdictions].sort(),
        minimumTrustLevel: p.minimumTrustLevel,
        proofAnchoring: p.proofAnchoring,
    };
    return ("regime-" +
        createHash("sha256")
            .update(JSON.stringify(canonical))
            .digest("hex")
            .substring(0, 16));
}
export class RegimeSelector {
    select(ctx, ps) {
        const cs = resolveCryptoSuite(ctx, ps);
        const pa = resolveProofAnchoring(ctx, ps);
        const cm = resolveConsentModel(ctx, ps);
        const em = resolveEscalationMode(ctx, ps);
        const ard = resolveAuditRetentionDays(ctx, ps);
        const esa = resolveExternalServicesAllowed(ctx, ps);
        const mtl = resolveMinimumTrustLevel(ctx, ps);
        const rid = generateRegimeId({
            jurisdictions: ctx.primaryJurisdictions,
            cryptoSuite: cs,
            proofAnchoring: pa,
            consentModel: cm,
            escalationMode: em,
            auditRetentionDays: ard,
            dataResidency: ctx.dataResidency,
            externalServicesAllowed: esa,
            minimumTrustLevel: mtl,
        });
        const nameParts = ctx.primaryJurisdictions.length === 1
            ? ctx.primaryJurisdictions[0]
            : "Multi(" + ctx.primaryJurisdictions.join("+") + ")";
        const name = ctx.industry !== "general" ? nameParts + "-" + ctx.industry : nameParts;
        const regime = {
            regimeId: rid,
            name: name || "default",
            jurisdictions: ctx.primaryJurisdictions,
            policyNamespaces: ps.sourceBundles,
            cryptoSuite: cs,
            proofAnchoring: pa,
            auditRetentionDays: ard,
            consentModel: cm,
            escalationMode: em,
            dataResidency: ctx.dataResidency,
            externalServicesAllowed: esa,
            minimumTrustLevel: mtl,
            conformityAssessmentRequired: hasJurisdiction(ctx, "EU"),
            transparencyRequired: hasJurisdiction(ctx, "EU", "CA", "UK"),
            metadata: {},
        };
        if (hasJurisdiction(ctx, "US-DOD"))
            regime.fedrampImpactLevel = "high";
        else if (hasJurisdiction(ctx, "US-FED"))
            regime.fedrampImpactLevel = "moderate";
        logger.info({ regimeId: rid, name, cryptoSuite: cs, minimumTrustLevel: mtl }, "Regime assembled");
        return regime;
    }
}
//# sourceMappingURL=regime-selector.js.map