/**
 * Capability Composition Conflict Classifier (AXIS-B1)
 *
 * Some capability combinations are structurally dangerous regardless of how
 * they are individually governed. This module encodes the FULL enumerated
 * fail-list from the AXIS-B1 dispatch brief — each entry individually
 * specified and independently testable.
 *
 * USAGE:
 *   const result = classifyCapabilityComposition(['web-scraping', 'decision-making']);
 *   // → COMPOSITION_RESULT.FAIL
 *
 * SHIPPED-FEATURE DISCLAIMER (AXIS-B1, per feedback_never_claim_shipped_without_integration):
 * This module is NOT end-to-end shipped until AXIS-B4 wires
 * InteractionAxisScore into the trust-score recompute() function and the
 * POST /api/v1/trust-score/refresh response shape carries the interaction field.
 *
 * @connexum/ai-governance  AXIS-B1
 */
// ---------------------------------------------------------------------------
// Result enum
// ---------------------------------------------------------------------------
export const COMPOSITION_RESULT = {
    /** The capability pair is structurally dangerous. Block or prevent registration. */
    FAIL: 'FAIL',
    /**
     * The pair is permissible but REQUIRES a human-in-the-loop approval gate
     * before any autonomous action. Register with HITL mandate; score deduction
     * applied in the interaction axis.
     */
    REQUIRES_HITL: 'REQUIRES_HITL',
    /** No conflict detected between these capabilities. */
    OK: 'OK',
};
const CONFLICT_RULES = Object.freeze([
    // -------------------------------------------------------------------------
    // Web-scraping combinations
    // -------------------------------------------------------------------------
    {
        pair: ['web-scraping', 'decision-making'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'attacker-controlled web content drives autonomous agent decisions',
    },
    {
        pair: ['web-scraping', 'file-write'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'exfil vector: attacker-controlled web content written to disk',
    },
    {
        pair: ['web-scraping', 'external-api-call'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'exfil vector: attacker-controlled web content routed to external API',
    },
    // -------------------------------------------------------------------------
    // File-write combinations
    // -------------------------------------------------------------------------
    {
        pair: ['file-write', 'email-send'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'mass data exfiltration: files emailed to external destinations',
    },
    // -------------------------------------------------------------------------
    // PHI / PII exfiltration outside approved proxy
    // -------------------------------------------------------------------------
    {
        pair: ['read-phi', 'external-api-call-outside-proxy'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'PHI exfiltration: health data sent outside the approved proxy boundary',
    },
    {
        pair: ['read-pii', 'external-api-call-outside-proxy'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'PII exfiltration: personal data sent outside the approved proxy boundary',
    },
    // -------------------------------------------------------------------------
    // Supply-chain injection
    // -------------------------------------------------------------------------
    {
        pair: ['execute-shell', 'commit-code'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'supply-chain injection: shell-injected code committed directly to repository',
    },
    // -------------------------------------------------------------------------
    // read-secrets wildcard — any external destination → FAIL
    // Capabilities enumerated individually (wildcard documented, not implicit):
    //   web-scraping, external-api-call, email-send, file-write, commit-code
    // -------------------------------------------------------------------------
    {
        pair: ['read-secrets', 'web-scraping'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'attacker-controlled data reaches secrets context (secrets + web-scraping)',
    },
    {
        pair: ['read-secrets', 'external-api-call'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'secrets exfiltrated to external API endpoint',
    },
    {
        pair: ['read-secrets', 'file-write'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'secrets written to potentially accessible filesystem location',
    },
    {
        pair: ['read-secrets', 'email-send'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'secrets emailed to any external destination',
    },
    {
        pair: ['read-secrets', 'commit-code'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'secrets committed to code repository',
    },
    // -------------------------------------------------------------------------
    // Financial records + autonomous decision-making → REQUIRES_HITL
    // -------------------------------------------------------------------------
    {
        pair: ['read-financial-records', 'decision-making'],
        result: COMPOSITION_RESULT.REQUIRES_HITL,
        threatClass: 'financial records driving autonomous agent decisions — human approval gate mandatory',
    },
    // -------------------------------------------------------------------------
    // Web-scraping → database write (Thomas example 2026-05-30)
    // An agent that searches/scrapes data online (attacker-influenceable input)
    // and then writes/inserts into a database is a poisoning + exfil vector unless
    // a second agent / human checks the write off first. The composition FAILs;
    // operators may relax it to REQUIRE_APPROVAL ("checked off by another agent")
    // via the per-agent rule editor. Either way it is a negative score impact
    // (capabilityCompositionRisk −25 per FAIL).
    // -------------------------------------------------------------------------
    {
        pair: ['web-scraping', 'external-db-write'],
        result: COMPOSITION_RESULT.FAIL,
        threatClass: 'data-poisoning / exfil: attacker-influenceable scraped web content inserted into a database without a second-agent or human check-off',
    },
    {
        pair: ['mcp-tool-call', 'external-db-write'],
        result: COMPOSITION_RESULT.REQUIRES_HITL,
        threatClass: 'an MCP-sourced read (e.g. online data search) chained into a database write must be checked off by another agent / human before the write',
    },
]);
// ---------------------------------------------------------------------------
// Key normalisation: canonical pair key is always alphabetically sorted
// -------------------------------------------------------------------------
function pairKey(a, b) {
    return a <= b ? `${a}|${b}` : `${b}|${a}`;
}
// Build O(1) lookup map at module init (rules are static).
const FAIL_MAP = new Map();
for (const rule of CONFLICT_RULES) {
    FAIL_MAP.set(pairKey(rule.pair[0], rule.pair[1]), rule);
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Classify all pairwise combinations of the provided capabilities.
 *
 * Returns the MOST SEVERE result across all pairs:
 *   FAIL > REQUIRES_HITL > OK
 *
 * Behaviour on single capability or empty list: returns OK (no pair to check).
 */
export function classifyCapabilityComposition(capabilities) {
    let worst = COMPOSITION_RESULT.OK;
    for (let i = 0; i < capabilities.length; i++) {
        for (let j = i + 1; j < capabilities.length; j++) {
            const key = pairKey(capabilities[i], capabilities[j]);
            const rule = FAIL_MAP.get(key);
            if (!rule)
                continue;
            if (rule.result === COMPOSITION_RESULT.FAIL) {
                // FAIL is the maximum severity — short-circuit.
                return COMPOSITION_RESULT.FAIL;
            }
            if (rule.result === COMPOSITION_RESULT.REQUIRES_HITL) {
                worst = COMPOSITION_RESULT.REQUIRES_HITL;
            }
        }
    }
    return worst;
}
/**
 * Return the matching conflict rule for a pair, or undefined if the pair is OK.
 * Used by audit event builders and Trust Score sub-scoring.
 */
export function getConflictRule(capA, capB) {
    return FAIL_MAP.get(pairKey(capA, capB));
}
/**
 * Return ALL conflict rules that match any pair in the provided capability list.
 * Used by the Trust Score interaction-axis scorer (AXIS-B2) to enumerate
 * all conflicts for a given agent manifest.
 */
export function getAllConflictsForCapabilities(capabilities) {
    const conflicts = [];
    for (let i = 0; i < capabilities.length; i++) {
        for (let j = i + 1; j < capabilities.length; j++) {
            const rule = getConflictRule(capabilities[i], capabilities[j]);
            if (rule)
                conflicts.push(rule);
        }
    }
    return conflicts;
}
//# sourceMappingURL=capability-composition-conflicts.js.map