"use strict";
/**
 * AutonomySpectrumEnforcer -- Controlled autonomy Level 0-4 gate.
 *
 * Implements the SAE-inspired controlled autonomy spectrum for AI agents.
 * Operators set the autonomy level; agents cannot self-elevate.
 *
 * Levels:
 *   Level 0 -- Manual:      Every action requires human pre-approval.
 *   Level 1 -- Assisted:    Read-only actions execute; mutating actions queue.
 *   Level 2 -- Conditional: Mutating actions in pre-approved class execute;
 *                            others queue.
 *   Level 3 -- Bounded:     Mutating actions within blast-radius limits execute;
 *                            over-limit or undeclared scope queues or denies.
 *   Level 4 -- Autonomous:  All actions execute except explicitly gated classes.
 *
 * Critical invariants:
 *   - No self-elevation: only OPERATOR_ADMIN (ADMIN role) can call setLevel.
 *   - Strict packs (HIPAA, GDPR, PCI DSS, HMDA, DORA) cap at Level 3 without
 *     explicit attestation. Level 4 + strict pack without attestation throws.
 *   - Pack binding is mandatory on all writes.
 *   - Every level change emits AUTONOMY_LEVEL_CHANGED at severity ERROR.
 *   - Self-elevation attempts emit AUTONOMY_SELF_ELEVATION_ATTEMPT at severity ERROR.
 *
 * Declaration-based limitation (honest documentation):
 *   The blast-radius (L3) and action-class (L2) gates trust the agent's
 *   declaration. An agent can lie about its blast radius or class. The
 *   compensating control is audit recording: the declared value is written
 *   to the audit chain so forensic analysis can detect post-hoc discrepancies.
 *   Additionally:
 *   - blastRadius.systemsTouched === 0 on a mutating action emits
 *     BLAST_RADIUS_DECLARED_ZERO (warning) because zero is suspicious.
 *   - Class-frequency tracking emits CLASS_BURST_THRESHOLD_EXCEEDED when an
 *     agent uses a high-trust class more than classBurstThreshold times in
 *     a single cycle (default: 10).
 *
 * BUILD_PLAN_V3_FULL_LIFECYCLE.md line 266: "Controlled autonomy spectrum
 * enforcement (Level 0 through 4, no self-elevation) -- partial; need
 * Level enforcement gate".
 *
 * Compliance bindings:
 *   HIPAA 164.308(a)(3): Workforce authorization and supervision
 *   SOC 2 CC6.1: Logical access restrictions
 *   GDPR Art. 22: Automated decision-making controls
 *   DORA Art. 16: ICT risk management -- automation limits
 *   PCI DSS Req 7: Restrict access by need-to-know
 *
 * @connexum/ai-governance P3-T1
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutonomySpectrumEnforcer = exports.UnauthorizedOperatorError = exports.MissingReasonError = exports.MissingApproverIdentityError = exports.InvalidAutonomyLevelError = exports.SelfElevationAttemptError = exports.Level4RequiresAttestationForStrictPackError = exports.EmptyPackBindingError = void 0;
exports.verifyOperatorIdentity = verifyOperatorIdentity;
const crypto = __importStar(require("crypto"));
const operator_roles_1 = require("../security/operator-roles");
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/** Pack IDs that require attestation for Level 4. */
const STRICT_PACK_IDS = new Set([
    'hipaa',
    'hipaa-security',
    'hipaa-privacy',
    'gdpr',
    'gdpr-eu',
    'eu-gdpr',
    'pcidss',
    'hmda',
    'dora',
    'dora-eu',
]);
/** Max autonomy level without attestation for strict packs. */
const STRICT_PACK_MAX_LEVEL = 3;
/**
 * Action classes that require approval even at Level 4 by default.
 * Operators can add more; they cannot remove these defaults from the default
 * set (they can override at the instance config level).
 */
const DEFAULT_L4_APPROVAL_CLASSES = new Set([
    'production-write',
    'external-pr-comms',
    'financial-transaction',
]);
// ---------------------------------------------------------------------------
// Errors
// ---------------------------------------------------------------------------
class EmptyPackBindingError extends Error {
    constructor(operation) {
        super(`EmptyPackBindingError: packBinding must be a non-empty array for '${operation}'. ` +
            'Every autonomy operation must declare which compliance packs govern it.');
        this.name = 'EmptyPackBindingError';
    }
}
exports.EmptyPackBindingError = EmptyPackBindingError;
class Level4RequiresAttestationForStrictPackError extends Error {
    orgId;
    agentId;
    packBinding;
    strictPacks;
    constructor(opts) {
        super(`Level4RequiresAttestationForStrictPackError: Setting Level 4 autonomy for ` +
            `agent '${opts.agentId}' in org '${opts.orgId}' requires a documented ` +
            `attestation reason that mentions the operator name and date. ` +
            `Strict packs active: ${opts.strictPacks.join(', ')}. ` +
            `Provide a reason string containing the operator name and a date (YYYY-MM-DD or similar).`);
        this.name = 'Level4RequiresAttestationForStrictPackError';
        this.orgId = opts.orgId;
        this.agentId = opts.agentId;
        this.packBinding = opts.packBinding;
        this.strictPacks = opts.strictPacks;
    }
}
exports.Level4RequiresAttestationForStrictPackError = Level4RequiresAttestationForStrictPackError;
class SelfElevationAttemptError extends Error {
    constructor(agentId, requestedLevel) {
        super(`SelfElevationAttemptError: Agent '${agentId}' attempted to self-elevate to ` +
            `Level ${requestedLevel}. Only operator-identity tokens (ADMIN role) may ` +
            `call setLevel. This attempt has been logged.`);
        this.name = 'SelfElevationAttemptError';
    }
}
exports.SelfElevationAttemptError = SelfElevationAttemptError;
class InvalidAutonomyLevelError extends Error {
    constructor(level) {
        super(`InvalidAutonomyLevelError: '${level}' is not a valid autonomy level. ` +
            'Valid levels: 0, 1, 2, 3, 4.');
        this.name = 'InvalidAutonomyLevelError';
    }
}
exports.InvalidAutonomyLevelError = InvalidAutonomyLevelError;
class MissingApproverIdentityError extends Error {
    constructor() {
        super('MissingApproverIdentityError: approverIdentity must be a non-empty string. ' +
            'An ADMIN-role operator identity is required to change the autonomy level.');
        this.name = 'MissingApproverIdentityError';
    }
}
exports.MissingApproverIdentityError = MissingApproverIdentityError;
class MissingReasonError extends Error {
    constructor() {
        super('MissingReasonError: reason must be a non-empty string. ' +
            'All autonomy level changes require a documented reason for audit compliance.');
        this.name = 'MissingReasonError';
    }
}
exports.MissingReasonError = MissingReasonError;
class UnauthorizedOperatorError extends Error {
    approverIdentity;
    constructor(approverIdentity, detail) {
        super(`UnauthorizedOperatorError: '${approverIdentity}' is not authorized to change ` +
            `the autonomy level. Requires ADMIN role. Detail: ${detail}`);
        this.name = 'UnauthorizedOperatorError';
        this.approverIdentity = approverIdentity;
    }
}
exports.UnauthorizedOperatorError = UnauthorizedOperatorError;
// ---------------------------------------------------------------------------
// AutonomySpectrumEnforcer
// ---------------------------------------------------------------------------
class AutonomySpectrumEnforcer {
    operatorRoles;
    auditSink;
    classBurstThreshold;
    testOperatorMap;
    /** State per (orgId, agentId) key. */
    state = new Map();
    /** Running SHA-256 chain for audit continuity. */
    chainHead = new Map();
    constructor(config) {
        this.operatorRoles = new operator_roles_1.OperatorRoles({ operatorsDir: config.operatorsDir });
        this.auditSink = config.auditSink ?? ((_e) => { });
        this.classBurstThreshold = config.classBurstThreshold ?? 10;
        this.testOperatorMap = config._testOperatorMap ?? null;
    }
    // -------------------------------------------------------------------------
    // Public API
    // -------------------------------------------------------------------------
    /**
     * Set the autonomy level for an (orgId, agentId) pair.
     *
     * Throws:
     *   - EmptyPackBindingError if packBinding is empty.
     *   - MissingReasonError if reason is empty.
     *   - MissingApproverIdentityError if approverIdentity is empty.
     *   - UnauthorizedOperatorError if approverIdentity does not have ADMIN role.
     *   - SelfElevationAttemptError if the approverIdentity is the agent itself
     *     (detected via 'agent:' prefix convention).
     *   - InvalidAutonomyLevelError if level is not 0-4.
     *   - Level4RequiresAttestationForStrictPackError if level is 4 and any
     *     strict pack is in packBinding without adequate attestation reason.
     */
    setLevel(orgId, agentId, level, reason, approverIdentity, packBinding) {
        // Guard: pack binding mandatory
        if (!packBinding || packBinding.length === 0) {
            throw new EmptyPackBindingError('setLevel');
        }
        // Guard: reason mandatory
        if (!reason || reason.trim().length === 0) {
            throw new MissingReasonError();
        }
        // Guard: approver identity mandatory
        if (!approverIdentity || approverIdentity.trim().length === 0) {
            throw new MissingApproverIdentityError();
        }
        // Guard: valid level
        if (![0, 1, 2, 3, 4].includes(level)) {
            throw new InvalidAutonomyLevelError(level);
        }
        // Guard: self-elevation detection.
        // Agent runtime tokens use 'agent:' prefix by convention.
        if (approverIdentity.startsWith('agent:')) {
            const stateKey = this.stateKey(orgId, agentId);
            const prev = this.getAgentState(orgId, agentId);
            const prevLevel = prev.levelRecord?.level ?? null;
            this.emitEvent({
                type: 'AUTONOMY_SELF_ELEVATION_ATTEMPT',
                severity: 'ERROR',
                orgId,
                agentId,
                timestamp: new Date().toISOString(),
                data: {
                    attemptedLevel: level,
                    approverIdentity,
                    packBinding,
                    prevLevel,
                    reason,
                },
            }, stateKey);
            throw new SelfElevationAttemptError(agentId, level);
        }
        // Guard: verify approver has ADMIN role.
        this.verifyOperatorIdentity(approverIdentity, orgId, agentId, level, packBinding, reason);
        // Guard: Level 4 + strict pack requires attestation in reason.
        if (level === 4) {
            const strictPacks = packBinding.filter(p => STRICT_PACK_IDS.has(p));
            if (strictPacks.length > 0) {
                // Attestation: reason must mention operator name (approverIdentity) + a date
                // We do a best-effort check: approverIdentity appears in reason AND
                // a date-like pattern (YYYY-MM-DD or similar) appears in reason.
                const identityInReason = reason.includes(approverIdentity);
                const datePattern = /\b\d{4}[-\/]\d{2}[-\/]\d{2}\b/;
                const dateInReason = datePattern.test(reason);
                if (!identityInReason || !dateInReason) {
                    throw new Level4RequiresAttestationForStrictPackError({
                        orgId,
                        agentId,
                        packBinding,
                        strictPacks,
                    });
                }
            }
        }
        // Compute state hashes for audit chain continuity.
        const stateKey = this.stateKey(orgId, agentId);
        const currentState = this.getAgentState(orgId, agentId);
        const prevLevel = currentState.levelRecord?.level ?? null;
        const prevStateHash = this.chainHead.get(stateKey) ?? this.genesisHash(orgId, agentId);
        const newRecord = {
            level,
            reason,
            approverIdentity,
            packBinding: [...packBinding].sort(),
            setAt: new Date().toISOString(),
            prevLevel,
            prevStateHash,
            currentStateHash: '',
        };
        // Chain the new state hash.
        const statePayload = JSON.stringify({
            level,
            packBinding: newRecord.packBinding,
            setAt: newRecord.setAt,
            approverIdentity,
            prevStateHash,
        });
        const currentStateHash = crypto
            .createHash('sha256')
            .update(statePayload)
            .digest('hex');
        newRecord.currentStateHash = currentStateHash;
        currentState.levelRecord = newRecord;
        this.chainHead.set(stateKey, currentStateHash);
        // Emit audit event at severity ERROR (posture change).
        this.emitEvent({
            type: 'AUTONOMY_LEVEL_CHANGED',
            severity: 'ERROR',
            orgId,
            agentId,
            timestamp: newRecord.setAt,
            prevStateHash,
            currentStateHash,
            data: {
                prevLevel,
                newLevel: level,
                reason,
                approverIdentity,
                packBinding: newRecord.packBinding,
            },
        }, stateKey);
    }
    /**
     * Get the current autonomy level for an (orgId, agentId) pair.
     * Returns Level 1 (Assisted) if never explicitly set -- safe default.
     */
    getLevel(orgId, agentId) {
        const state = this.getAgentState(orgId, agentId);
        return state.levelRecord?.level ?? 1;
    }
    /**
     * Pre-execution gate. Returns a decision on whether the action may execute.
     *
     * Decision logic:
     *   Level 0: always 'approval-required'.
     *   Level 1: read-only -> execute; mutating -> approval-required.
     *   Level 2: read-only -> execute; mutating in-class -> execute; else approval-required.
     *   Level 3: as L2, plus mutating out-of-class within blast limits -> execute;
     *             over-limit -> approval-required; missing blastRadius -> denied.
     *   Level 4: execute unless action.class in requireApprovalEvenAtLevel4 list.
     *
     * Always routes 'approval-required' to the internal overflow tracker
     * (ApprovalQueue integration point via the returned approvalRequestId).
     */
    guardAction(orgId, agentId, action, packBinding) {
        if (!packBinding || packBinding.length === 0) {
            throw new EmptyPackBindingError('guardAction');
        }
        const level = this.getLevel(orgId, agentId);
        const state = this.getAgentState(orgId, agentId);
        // Track class frequency for PT-AUTONOMY-3 compensating control.
        if (action.class) {
            const freq = (state.classFrequency.get(action.class) ?? 0) + 1;
            state.classFrequency.set(action.class, freq);
            if (freq > this.classBurstThreshold) {
                const stateKey = this.stateKey(orgId, agentId);
                this.emitEvent({
                    type: 'CLASS_BURST_THRESHOLD_EXCEEDED',
                    severity: 'WARN',
                    orgId,
                    agentId,
                    timestamp: new Date().toISOString(),
                    data: {
                        class: action.class,
                        frequency: freq,
                        threshold: this.classBurstThreshold,
                        kind: action.kind,
                        packBinding,
                    },
                }, stateKey);
            }
        }
        // BLAST_RADIUS_DECLARED_ZERO compensating control (PT-AUTONOMY-2).
        if (action.mutates && action.blastRadius && action.blastRadius.systemsTouched === 0) {
            const stateKey = this.stateKey(orgId, agentId);
            this.emitEvent({
                type: 'BLAST_RADIUS_DECLARED_ZERO',
                severity: 'WARN',
                orgId,
                agentId,
                timestamp: new Date().toISOString(),
                data: {
                    kind: action.kind,
                    class: action.class ?? null,
                    blastRadius: action.blastRadius,
                    packBinding,
                    note: 'Declaring systemsTouched=0 on a mutating action is suspicious. ' +
                        'Non-mutating actions should set mutates:false instead. ' +
                        'This declaration is recorded for forensic review.',
                },
            }, stateKey);
        }
        let result;
        switch (level) {
            case 0:
                result = this.makeApprovalRequired(orgId, agentId, action, packBinding, 'Level 0 (Manual): every action requires human pre-approval.');
                break;
            case 1:
                if (!action.mutates) {
                    result = { decision: 'execute', reason: 'Level 1 (Assisted): read-only action permitted.' };
                }
                else {
                    result = this.makeApprovalRequired(orgId, agentId, action, packBinding, 'Level 1 (Assisted): mutating action requires human approval.');
                }
                break;
            case 2:
                if (!action.mutates) {
                    result = { decision: 'execute', reason: 'Level 2 (Conditional): read-only action permitted.' };
                }
                else if (action.class && state.preApprovedClasses.has(action.class)) {
                    result = {
                        decision: 'execute',
                        reason: `Level 2 (Conditional): action class '${action.class}' is pre-approved.`,
                    };
                }
                else {
                    result = this.makeApprovalRequired(orgId, agentId, action, packBinding, `Level 2 (Conditional): mutating action class '${action.class ?? '(none)'}' is not pre-approved.`);
                }
                break;
            case 3: {
                if (!action.mutates) {
                    result = { decision: 'execute', reason: 'Level 3 (Bounded): read-only action permitted.' };
                }
                else if (action.class && state.preApprovedClasses.has(action.class)) {
                    result = {
                        decision: 'execute',
                        reason: `Level 3 (Bounded): action class '${action.class}' is pre-approved.`,
                    };
                }
                else if (!action.blastRadius) {
                    // Missing blast radius on mutating out-of-class action: DENIED (unbounded).
                    result = {
                        decision: 'denied',
                        reason: 'Level 3 (Bounded): mutating action outside pre-approved class must declare ' +
                            'blastRadius. An action with no declared scope is treated as unbounded and denied.',
                    };
                }
                else {
                    // Check blast radius against configured limits.
                    const limits = state.blastRadiusLimits;
                    const over = limits ? this.blastRadiusExceedsLimits(action.blastRadius, limits) : null;
                    if (over) {
                        result = this.makeApprovalRequired(orgId, agentId, action, packBinding, `Level 3 (Bounded): blast radius exceeds limit -- ${over}.`);
                    }
                    else {
                        result = {
                            decision: 'execute',
                            reason: 'Level 3 (Bounded): blast radius within configured limits.',
                        };
                    }
                }
                break;
            }
            case 4: {
                const gated = action.class
                    ? state.requireApprovalEvenAtLevel4.has(action.class)
                    : false;
                if (gated) {
                    result = this.makeApprovalRequired(orgId, agentId, action, packBinding, `Level 4 (Autonomous): action class '${action.class}' is in the required-approval list.`);
                }
                else {
                    result = {
                        decision: 'execute',
                        reason: 'Level 4 (Autonomous): action is within autonomous execution scope.',
                    };
                }
                break;
            }
            default:
                result = {
                    decision: 'denied',
                    reason: `Unknown autonomy level ${level}.`,
                };
        }
        // Emit AUTONOMY_ACTION_GUARDED for full audit trail.
        const stateKey = this.stateKey(orgId, agentId);
        this.emitEvent({
            type: 'AUTONOMY_ACTION_GUARDED',
            severity: result.decision === 'denied' ? 'ERROR' : 'INFO',
            orgId,
            agentId,
            timestamp: new Date().toISOString(),
            data: {
                decision: result.decision,
                reason: result.reason,
                level,
                action: {
                    kind: action.kind,
                    mutates: action.mutates,
                    class: action.class ?? null,
                    blastRadius: action.blastRadius ?? null,
                },
                packBinding,
            },
        }, stateKey);
        return result;
    }
    /**
     * Register pre-approved action classes for Level 2 execution.
     * Only ADMIN operators can configure this.
     */
    configurePreApprovedClasses(orgId, agentId, classes, approverIdentity, packBinding) {
        if (!packBinding || packBinding.length === 0) {
            throw new EmptyPackBindingError('configurePreApprovedClasses');
        }
        this.verifyOperatorIdentity(approverIdentity, orgId, agentId, null, packBinding, 'configure-classes');
        const state = this.getAgentState(orgId, agentId);
        state.preApprovedClasses = new Set(classes);
    }
    /**
     * Configure blast-radius limits for Level 3 execution.
     * Only ADMIN operators can configure this.
     */
    configureBlastRadius(orgId, agentId, limits, approverIdentity, packBinding) {
        if (!packBinding || packBinding.length === 0) {
            throw new EmptyPackBindingError('configureBlastRadius');
        }
        this.verifyOperatorIdentity(approverIdentity, orgId, agentId, null, packBinding, 'configure-blast-radius');
        const state = this.getAgentState(orgId, agentId);
        state.blastRadiusLimits = limits;
    }
    /**
     * Configure which action classes still require approval at Level 4.
     * The default set (production-write, external-pr-comms, financial-transaction)
     * is pre-loaded per instance; this method merges additional classes.
     */
    addRequiredApprovalClassesAtLevel4(orgId, agentId, classes, approverIdentity, packBinding) {
        if (!packBinding || packBinding.length === 0) {
            throw new EmptyPackBindingError('addRequiredApprovalClassesAtLevel4');
        }
        this.verifyOperatorIdentity(approverIdentity, orgId, agentId, null, packBinding, 'configure-l4-approval-classes');
        const state = this.getAgentState(orgId, agentId);
        for (const c of classes) {
            state.requireApprovalEvenAtLevel4.add(c);
        }
    }
    /**
     * Reset class frequency counters. Call at the start of each cycle.
     * This is a lightweight operation -- agents manage their own cycle boundaries.
     */
    resetCycleCounters(orgId, agentId) {
        const state = this.getAgentState(orgId, agentId);
        state.classFrequency.clear();
    }
    // -------------------------------------------------------------------------
    // Private helpers
    // -------------------------------------------------------------------------
    stateKey(orgId, agentId) {
        return `${orgId}::${agentId}`;
    }
    getAgentState(orgId, agentId) {
        const key = this.stateKey(orgId, agentId);
        if (!this.state.has(key)) {
            this.state.set(key, {
                levelRecord: null,
                preApprovedClasses: new Set(),
                blastRadiusLimits: null,
                // Default L4 approval classes (always gated even at Level 4).
                requireApprovalEvenAtLevel4: new Set(DEFAULT_L4_APPROVAL_CLASSES),
                classFrequency: new Map(),
            });
        }
        return this.state.get(key);
    }
    genesisHash(orgId, agentId) {
        return crypto
            .createHash('sha256')
            .update(`autonomy-spectrum-genesis-${orgId}:${agentId}`)
            .digest('hex');
    }
    emitEvent(event, stateKey) {
        const head = this.chainHead.get(stateKey) ?? '';
        const full = {
            ...event,
            prevStateHash: event.prevStateHash ?? head,
            currentStateHash: event.currentStateHash ?? head,
        };
        try {
            this.auditSink(full);
        }
        catch {
            // Audit sink errors must never propagate to the caller.
            process.stderr.write(`[AUTONOMY SPECTRUM] Audit sink threw: ${event?.type}\n`);
        }
    }
    makeApprovalRequired(orgId, agentId, action, packBinding, reason) {
        // Generate a lightweight approval request ID.
        // Real integration: callers wire this ID to ApprovalQueue.submit().
        const approvalRequestId = `auto_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;
        return {
            decision: 'approval-required',
            reason,
            approvalRequestId,
        };
    }
    blastRadiusExceedsLimits(radius, limits) {
        if (radius.systemsTouched > limits.maxSystemsTouched) {
            return `systemsTouched ${radius.systemsTouched} > limit ${limits.maxSystemsTouched}`;
        }
        if (limits.maxFinancialImpactCents !== undefined &&
            radius.financialImpactCents !== undefined &&
            radius.financialImpactCents > limits.maxFinancialImpactCents) {
            return `financialImpactCents ${radius.financialImpactCents} > limit ${limits.maxFinancialImpactCents}`;
        }
        if (limits.maxUsersAffected !== undefined &&
            radius.usersAffected !== undefined &&
            radius.usersAffected > limits.maxUsersAffected) {
            return `usersAffected ${radius.usersAffected} > limit ${limits.maxUsersAffected}`;
        }
        return null;
    }
    /**
     * Verify that approverIdentity has ADMIN role.
     *
     * Self-elevation via 'agent:' prefix is already caught before this method
     * is called in setLevel(). This method handles the RBAC check.
     *
     * Two modes:
     *   1. _testOperatorMap: used in unit tests -- a plain Map<identity, role>.
     *   2. OperatorRoles file store: used in production.
     *
     * The identity string is the operator's name (as registered in OperatorRoles).
     * In production: operators register via OperatorRoles.createOperator(),
     * and their name is the approverIdentity string.
     */
    verifyOperatorIdentity(approverIdentity, orgId, agentId, requestedLevel, packBinding, operation) {
        if (this.testOperatorMap) {
            const role = this.testOperatorMap.get(approverIdentity);
            if (role !== 'ADMIN') {
                throw new UnauthorizedOperatorError(approverIdentity, `Test operator map: identity '${approverIdentity}' has role '${role ?? 'unknown'}', requires ADMIN.`);
            }
            return;
        }
        // Production: look up by name in OperatorRoles.
        // OperatorRoles.listOperators() returns all; find by name.
        const operators = this.operatorRoles.listOperators();
        const match = operators.find((op) => op.name === approverIdentity || op.id === approverIdentity);
        if (!match) {
            throw new UnauthorizedOperatorError(approverIdentity, `Operator '${approverIdentity}' not found in the operator registry. ` +
                'Register the operator via OperatorRoles.createOperator() first.');
        }
        if (!match.active) {
            throw new UnauthorizedOperatorError(approverIdentity, `Operator '${approverIdentity}' (id: ${match.id}) is deactivated.`);
        }
        const check = this.operatorRoles.checkPermission(match.id, 'governance.configure');
        if (!check.allowed) {
            throw new UnauthorizedOperatorError(approverIdentity, `Operator '${approverIdentity}' role '${match.role}' lacks 'governance.configure' permission. ${check.reason}`);
        }
    }
}
exports.AutonomySpectrumEnforcer = AutonomySpectrumEnforcer;
// ---------------------------------------------------------------------------
// Standalone helper: verify operator identity without a full enforcer instance.
// Exposed for callers that need a one-off check.
// ---------------------------------------------------------------------------
/**
 * verifyOperatorIdentity -- standalone helper for callers that do not
 * instantiate a full AutonomySpectrumEnforcer.
 *
 * Used by test scaffolding and integration code that needs a quick RBAC check
 * before delegating to the enforcer.
 */
function verifyOperatorIdentity(approverIdentity, operatorsDir) {
    try {
        const roles = new operator_roles_1.OperatorRoles({ operatorsDir });
        const operators = roles.listOperators();
        const match = operators.find((op) => op.name === approverIdentity || op.id === approverIdentity);
        if (!match) {
            return { authorized: false, reason: `Operator '${approverIdentity}' not found.` };
        }
        if (!match.active) {
            return { authorized: false, reason: `Operator '${approverIdentity}' is deactivated.` };
        }
        const check = roles.checkPermission(match.id, 'governance.configure');
        return {
            authorized: check.allowed,
            reason: check.reason,
        };
    }
    catch (err) {
        return {
            authorized: false,
            reason: `OperatorRoles error: ${err.message}`,
        };
    }
}
//# sourceMappingURL=autonomy-spectrum.js.map