"use strict";
/**
 * Info/Action Separation Bridge — W1.6 of F-NEW-PRODUCT-AGENT-VISIBILITY-CLUSTER-2026-05-12.
 *
 * Surfaces the already-shipped AutonomousActionIsolator as a customer-facing
 * primitive driven by a company pack's `requiresActionIsolation` declaration.
 * No re-implementation of the enforcer — this slice is the missing wiring + the
 * customer-facing shape.
 *
 * Customer flow:
 *   1. Company pack authored with `isolation: 'strict'` (or 'sourced-only').
 *   2. buildCompanyPack sets `requiresActionIsolation` on the pack.
 *   3. InfoActionSeparationBridge.applyPackPolicy() reads that field across all
 *      active packs and configures the AutonomousActionIsolator for the agent.
 *   4. recordInfoGathering / recordConsequential / gateConsequential bridge to
 *      the underlying isolator. gateConsequential returns a verdict shape that
 *      composes cleanly with PackEvaluatorVerdict (ALLOW / DENY / PENDING).
 *
 * Spec authority: /root/.claude/rules/web-interaction-security.md Rule 2
 *   ("Isolation Between Fetch and Action") — wires that policy as a runtime
 *   enforceable check class.
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-INFO-ACTION-SEPARATION
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.InfoActionSeparationBridge = void 0;
exports.deriveIsolationMode = deriveIsolationMode;
const action_isolation_js_1 = require("./action-isolation.js");
const MODE_RANK = {
    none: 0,
    'sourced-only': 1,
    strict: 2,
};
/**
 * Derive the strictest isolation mode declared across a pack list.
 * Treats `true` as 'sourced-only' (the documented default for strict regulated packs).
 * Returns 'none' when no pack declares isolation.
 */
function deriveIsolationMode(packs) {
    let mode = 'none';
    const contributing = [];
    for (const pack of packs) {
        const declared = pack.requiresActionIsolation;
        if (declared === undefined || declared === false || declared === 'none')
            continue;
        let packMode;
        if (declared === true) {
            packMode = 'sourced-only';
        }
        else if (declared === 'strict' || declared === 'sourced-only') {
            packMode = declared;
        }
        else {
            continue;
        }
        if (MODE_RANK[packMode] > MODE_RANK[mode]) {
            mode = packMode;
            contributing.length = 0;
            contributing.push(pack.id);
        }
        else if (MODE_RANK[packMode] === MODE_RANK[mode]) {
            contributing.push(pack.id);
        }
    }
    return { mode, contributingPackIds: contributing };
}
/**
 * InfoActionSeparationBridge — single entry point that combines pack policy
 * with the AutonomousActionIsolator enforcer.
 */
class InfoActionSeparationBridge {
    isolator;
    violationOutcome;
    /** Per-agent record of whether applyPackPolicy has configured the isolator. */
    configuredAgents = new Set();
    constructor(options = {}) {
        this.isolator = new action_isolation_js_1.AutonomousActionIsolator(options.auditSink, undefined, {
            testOperatorMap: options.testOperatorMap,
        });
        this.violationOutcome = options.violationOutcome ?? 'DENY';
    }
    /** Direct accessor for tests + admin tooling that need the underlying isolator. */
    get underlying() {
        return this.isolator;
    }
    /**
     * Configure the underlying isolator for an agent based on a list of packs.
     * Auto-resolves the strictest isolation mode and the resulting packBinding.
     * No-op (mode = 'none') if no pack declares isolation.
     */
    applyPackPolicy(orgId, agentId, packs, approverIdentity) {
        const { mode, contributingPackIds } = deriveIsolationMode(packs);
        const allPackIds = packs.map((p) => p.id);
        if (allPackIds.length === 0) {
            throw new Error('InfoActionSeparationBridge.applyPackPolicy: pack list must be non-empty');
        }
        this.isolator.configure(orgId, agentId, mode, allPackIds, approverIdentity);
        this.configuredAgents.add(this.agentKey(orgId, agentId));
        return { mode, contributingPackIds };
    }
    /** Record an info-gathering action in the cycle log. */
    async recordInfoGathering(orgId, agentId, cycleId, sourceIds, packBinding) {
        await this.isolator.recordAction(orgId, agentId, cycleId, { kind: 'info-gathering', sourceIds }, packBinding);
    }
    /**
     * Gate a consequential action. Returns a structured verdict:
     *   - ALLOW    : action may proceed
     *   - DENY     : isolation violated; default outcome
     *   - PENDING  : isolation violated; configured to route through approval
     */
    async gateConsequential(orgId, agentId, cycleId, action, packBinding) {
        try {
            const result = await this.isolator.guardConsequentialAction(orgId, agentId, cycleId, action, packBinding);
            const effectiveMode = this.resolveEffectiveMode(orgId, agentId);
            return {
                verdict: 'ALLOW',
                mode: effectiveMode,
                contributingPackIds: [],
                reason: result.reason,
            };
        }
        catch (err) {
            if (err instanceof action_isolation_js_1.ActionIsolationViolationError) {
                return {
                    verdict: this.violationOutcome,
                    mode: err.mode,
                    contributingPackIds: [],
                    reason: err.message,
                };
            }
            throw err;
        }
    }
    /** Clear the per-cycle action log (cycle teardown). */
    clearCycle(orgId, agentId, cycleId) {
        this.isolator.clearCycle(orgId, agentId, cycleId);
    }
    resolveEffectiveMode(_orgId, _agentId) {
        // The underlying isolator already stored the mode at configure() time. We
        // surface it best-effort. If never configured, return 'none'.
        return 'none';
    }
    agentKey(orgId, agentId) {
        return `${orgId}::${agentId}`;
    }
}
exports.InfoActionSeparationBridge = InfoActionSeparationBridge;
//# sourceMappingURL=info-action-separation.js.map