"use strict";
/**
 * RED-GREEN tests for F-NEW-PRODUCT-PER-AGENT-OVERRIDE-AUTHORITY (W1.9).
 *
 * Thomas directive 2026-05-12: "individual agents can be overridden by the
 * developer or CISO to allow MCP usage or to delete a database... we're not
 * going to restrict them. We'll just notify them if they override it and an
 * accident happens, as long as we have the incident recorded and we have
 * approval for an employee to change the requirement."
 *
 * Validates:
 *   - Override RELAXES a baseline BLOCK on a specific agent
 *   - OverrideEvent is emitted with full provenance (approver / justification /
 *     baseline action / relaxed action / overrideId)
 *   - Override requires approver + justification + approvedAt (fail-closed)
 *   - Overrides do NOT affect agents without that override (cross-agent isolation)
 *   - Without override, strictest-wins still applies
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-PER-AGENT-OVERRIDE-AUTHORITY
 */
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 });
const node_test_1 = require("node:test");
const assert = __importStar(require("node:assert/strict"));
const pack_inheritance_1 = require("./pack-inheritance");
const capability_classes_1 = require("./capability-classes");
const pack_evaluator_1 = require("./pack-evaluator");
const index_1 = require("../packs/index");
const event_bus_1 = require("../audit/event-bus");
const index_2 = require("../adapters/index");
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
function evalActionWithPack(pack, toolName, input = {}) {
    const registry = new index_1.PackRegistry();
    registry.register(pack);
    registry.activate(pack.id);
    const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-'));
    const bus = new event_bus_1.EventBus({ eventDir: dir, agentName: 'ov-test' });
    const evaluator = new pack_evaluator_1.PackEvaluator(registry, bus, { ttlMs: 60_000, enableCache: false });
    const ac = (0, index_2.createActionContext)(toolName, input, { name: 'agent-x', orgId: 'org-x' });
    return evaluator.evaluate('org-x', 'agent-x', ac);
}
(0, node_test_1.describe)('F-NEW-PRODUCT-PER-AGENT-OVERRIDE-AUTHORITY (W1.9)', () => {
    (0, node_test_1.it)('override RELAXES baseline BLOCK on a specific agent', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const composed = (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-mcp-allowed',
            name: 'agent allowed MCP via override',
            orgId: 'org-x',
            agentId: 'agent-mcp-allowed',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.MCP,
                    action: 'LOG', // relaxed from BLOCK -> LOG
                    approver: 'cto-bob',
                    justification: 'Agent integrates with internal MCP server; vetted by Security Council 2026-05-12.',
                    approvedAt: '2026-05-12T10:00:00.000Z',
                },
            ],
        });
        const verdict = evalActionWithPack(composed, 'mcp__list_resources');
        assert.equal(verdict.verdict, 'ALLOW', 'override LOG action allows the MCP call (was BLOCK without override)');
    });
    (0, node_test_1.it)('override emits an OverrideEvent with full provenance', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.EXTERNAL_DB_WRITE, action: 'BLOCK' }],
        });
        const events = [];
        (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-db-allowed',
            name: 'agent allowed DB writes',
            orgId: 'org-x',
            agentId: 'agent-db-allowed',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.EXTERNAL_DB_WRITE,
                    action: 'REQUIRE_APPROVAL',
                    approver: 'ciso-alice',
                    justification: 'DB writes required for nightly batch ETL; gated by approval workflow.',
                    approvedAt: '2026-05-12T11:00:00.000Z',
                    overrideId: 'ov-db-001',
                },
            ],
        }, { onOverride: (ev) => events.push(ev) });
        assert.equal(events.length, 1);
        const ev = events[0];
        assert.equal(ev.overrideId, 'ov-db-001');
        assert.equal(ev.capability, capability_classes_1.CAPABILITY_CLASS.EXTERNAL_DB_WRITE);
        assert.equal(ev.baselineAction, 'BLOCK');
        assert.equal(ev.relaxedAction, 'REQUIRE_APPROVAL');
        assert.equal(ev.approver, 'ciso-alice');
        assert.equal(ev.agentId, 'agent-db-allowed');
        assert.equal(ev.orgId, 'org-x');
        assert.ok(ev.composedAt.length > 0);
    });
    (0, node_test_1.it)('override without approver throws fail-closed', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        assert.throws(() => (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-bad',
            name: 'agent bad',
            orgId: 'org-x',
            agentId: 'agent-bad',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.MCP,
                    action: 'LOG',
                    approver: '', // empty -- fail-closed
                    justification: 'ok',
                    approvedAt: '2026-05-12T10:00:00.000Z',
                },
            ],
        }), /missing an approver/i);
    });
    (0, node_test_1.it)('override without justification throws fail-closed', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        assert.throws(() => (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-bad',
            name: 'agent bad',
            orgId: 'org-x',
            agentId: 'agent-bad',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.MCP,
                    action: 'LOG',
                    approver: 'cto-bob',
                    justification: '',
                    approvedAt: '2026-05-12T10:00:00.000Z',
                },
            ],
        }), /missing a justification/i);
    });
    (0, node_test_1.it)('override invalid approvedAt throws fail-closed', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        assert.throws(() => (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-bad',
            name: 'agent bad',
            orgId: 'org-x',
            agentId: 'agent-bad',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.MCP,
                    action: 'LOG',
                    approver: 'cto-bob',
                    justification: 'ok',
                    approvedAt: 'not-a-timestamp',
                },
            ],
        }), /invalid approvedAt/i);
    });
    (0, node_test_1.it)('no overrides -> strictest-wins still applies (unchanged W1.3 behavior)', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const composed = (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-no-override',
            name: 'no override',
            orgId: 'org-x',
            agentId: 'agent-no-override',
            rules: [],
        });
        const v = evalActionWithPack(composed, 'mcp__list_resources');
        assert.equal(v.verdict, 'DENY', 'baseline BLOCK survives in absence of override');
    });
    (0, node_test_1.it)('cross-agent isolation: override on agent A does not affect agent B', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const packA = (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-a-pack',
            name: 'A',
            orgId: 'org-x',
            agentId: 'agent-a',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.MCP,
                    action: 'LOG',
                    approver: 'cto-bob',
                    justification: 'Agent A only',
                    approvedAt: '2026-05-12T10:00:00.000Z',
                },
            ],
        });
        const packB = (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-b-pack',
            name: 'B',
            orgId: 'org-x',
            agentId: 'agent-b',
            rules: [],
        });
        const vA = evalActionWithPack(packA, 'mcp__list_resources');
        const vB = evalActionWithPack(packB, 'mcp__list_resources');
        assert.equal(vA.verdict, 'ALLOW', 'A has override -> ALLOW');
        assert.equal(vB.verdict, 'DENY', 'B has no override -> baseline BLOCK -> DENY');
    });
    (0, node_test_1.it)('override action REQUIRE_APPROVAL produces PENDING at runtime', () => {
        const baseline = (0, pack_inheritance_1.buildOrgBaselinePack)({
            orgId: 'org-x',
            rules: [{ capability: capability_classes_1.CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
        });
        const composed = (0, pack_inheritance_1.composeAgentPack)(baseline, {
            id: 'agent-shell-via-approval',
            name: 'shell via approval',
            orgId: 'org-x',
            agentId: 'agent-shell-via-approval',
            rules: [],
            overrides: [
                {
                    capability: capability_classes_1.CAPABILITY_CLASS.SHELL_EXEC,
                    action: 'REQUIRE_APPROVAL',
                    approver: 'cto-bob',
                    justification: 'Operator allowed shell exec gated by per-call approval.',
                    approvedAt: '2026-05-12T10:00:00.000Z',
                },
            ],
        });
        const v = evalActionWithPack(composed, 'Bash', { command: 'ls' });
        assert.equal(v.verdict, 'PENDING');
    });
});
//# sourceMappingURL=per-agent-override.test.js.map