/**
 * BlastRadiusEnforcer -- Per-category, per-cycle blast-radius gate.
 *
 * Complements the autonomy spectrum (PR #24) by adding category-aware
 * impact caps that are enforced at tool-call time. While PR #24's Level 3
 * (Bounded) checks a declared aggregate blast radius (systemsTouched,
 * financialImpactCents, usersAffected) via the agent's own declaration,
 * this enforcer independently counts actual actions by category within the
 * current cycle and rejects calls that would exceed the configured cap for
 * that category at the agent's autonomy level.
 *
 * The key distinction:
 *   PR #24 blast-radius check is DECLARATION-BASED (agent states impact).
 *   This enforcer is COUNT-BASED (system counts actual category invocations).
 *
 * Categories tracked (orthogonal counters; exhausting one does not
 * affect any other):
 *   file-mutations   -- writes, appends, deletes, renames of files/dirs
 *   network-calls    -- HTTP/HTTPS requests to external endpoints
 *   database-writes  -- INSERT, UPDATE, DELETE, schema mutations
 *   secret-reads     -- vault reads, env-var secret access, key material reads
 *   tool-invocations -- total tool calls across all categories
 *
 * Autonomy-level caps (default, operator-tunable):
 *   Level 0 (Manual):       0 / 0 / 0 / 0 / 0   -- no autonomous actions at all
 *   Level 1 (Assisted):     0 / 0 / 0 / 0 / 10  -- read-only; 10 total tools
 *   Level 2 (Conditional):  5 / 2 / 2 / 0 / 25  -- pre-approved classes only
 *   Level 3 (Bounded):     20 / 10 / 10 / 2 / 50 -- within blast limits
 *   Level 4 (Autonomous): 100 / 50 / 50 / 10 / 200 -- widest, still bounded
 *
 * Counter scope: per-cycle. resetCycle() must be called at cycle boundary.
 * Counters for a given (orgId, agentId, cycleId) triple are independent.
 * Calling resetCycle() deletes all counters for that triple.
 *
 * Hook position: fires in PreToolUse, after autonomy-spectrum enforcement.
 * When autonomy-spectrum is not active (main-branch builds without PR #24
 * merged), this enforcer uses the autonomy level passed by the caller;
 * callers not tracking autonomy levels may pass level 4 to get the widest
 * caps or configure custom per-agent caps directly.
 *
 * Audit: every rejection writes a BLAST_RADIUS_CATEGORY_EXCEEDED event
 * with the full packBinding[] to the audit sink. pack-binding primacy is
 * enforced at the entrance of every public method (per
 * feedback_pack_binding_primacy.md): empty packBinding throws
 * UnboundDataError before any counter is incremented.
 *
 * Pen-test gates:
 *   PT-BLAST-1: empty packBinding[] throws UnboundDataError before any
 *     counter increments.
 *   PT-BLAST-2: configured cap of 0 for a category at a given level rejects
 *     all actions in that category.
 *   PT-BLAST-3: tampered config (caps set negative or non-integer) is
 *     rejected at construction time.
 *   PT-BLAST-4: rapid burst of allowed actions followed by a single denied
 *     action produces correct audit-event ordering.
 *
 * Compliance bindings:
 *   HIPAA 164.308(a)(3): Workforce authorization and supervision
 *   HIPAA 164.312(a)(1): Access control -- minimum necessary
 *   SOC 2 CC6.1: Logical access restrictions
 *   GDPR Art. 25: Data protection by design (impact minimisation)
 *   EU AI Act Art. 9: Risk management -- bounded autonomous scope
 *   DORA Art. 16: ICT risk management -- automation limits
 *   NIST 800-53 AC-6: Least privilege
 *   ISO 42001 A.6.1.4: AI resource management
 *
 * Relationship to PR #24 (feat/p3-t1-autonomy-spectrum):
 *   - Does NOT import from autonomy-spectrum.ts; no circular dependency.
 *   - Does NOT duplicate AutonomyLevel type -- defines it locally as the
 *     same numeric union 0|1|2|3|4 for standalone use.
 *   - Does NOT replicate BlastRadius / BlastRadiusLimits types from PR #24;
 *     those capture declared aggregate impact; this file captures actual
 *     per-category invocation counts.
 *   - Both enforcers compose in the PreToolUse chain. Neither replaces the
 *     other. The autonomy spectrum runs first (decides WHAT level); this
 *     enforcer runs alongside/after (counts HOW MANY actions per category).
 *
 * @connexum/ai-governance P3-T2
 */
/**
 * Autonomy level 0-4. Mirrors the same union from PR #24 without importing
 * from that file so this module works on main before that PR merges.
 */
export type AutonomyLevel = 0 | 1 | 2 | 3 | 4;
/**
 * The five orthogonal blast-radius categories. Counters are independent;
 * exhausting one does not affect another.
 */
export type BlastCategory = 'file-mutations' | 'network-calls' | 'database-writes' | 'secret-reads' | 'tool-invocations';
export declare const ALL_BLAST_CATEGORIES: BlastCategory[];
/**
 * Per-category cap set. A cap of 0 means the category is completely blocked.
 * Caps must be non-negative integers; the constructor validates this.
 */
export interface CategoryCaps {
    'file-mutations': number;
    'network-calls': number;
    'database-writes': number;
    'secret-reads': number;
    'tool-invocations': number;
}
/**
 * Per-autonomy-level default caps. Operators may override any or all levels
 * in BlastRadiusEnforcerConfig.
 */
export type LevelCaps = Record<AutonomyLevel, CategoryCaps>;
/**
 * Default caps per autonomy level. Designed so each higher level has equal
 * or wider caps in every category. Operators tune these in deployment config.
 */
export declare const DEFAULT_LEVEL_CAPS: LevelCaps;
/**
 * Thrown when an operation is called without a non-empty packBinding[].
 * Pack-binding primacy invariant: every action must declare which compliance
 * packs govern it. Counters are never incremented when this fires.
 */
export declare class UnboundDataError extends Error {
    constructor(operation: string);
}
/**
 * Thrown when the enforcer is constructed with invalid cap values (negative
 * or non-integer). PT-BLAST-3.
 */
export declare class InvalidBlastCapError extends Error {
    readonly level: AutonomyLevel;
    readonly category: BlastCategory;
    readonly value: unknown;
    constructor(level: AutonomyLevel, category: BlastCategory, value: unknown);
}
/**
 * Thrown when a tool call would exceed the configured cap for a category
 * at the agent's current autonomy level. The action is rejected; the
 * rejection is written to the audit chain.
 */
export declare class BlastRadiusCategoryExceededError extends Error {
    readonly orgId: string;
    readonly agentId: string;
    readonly cycleId: string;
    readonly category: BlastCategory;
    readonly level: AutonomyLevel;
    readonly count: number;
    readonly cap: number;
    readonly packBinding: string[];
    constructor(opts: {
        orgId: string;
        agentId: string;
        cycleId: string;
        category: BlastCategory;
        level: AutonomyLevel;
        count: number;
        cap: number;
        packBinding: string[];
    });
}
export type BlastRadiusEventType = 'BLAST_RADIUS_CATEGORY_EXCEEDED' | 'BLAST_RADIUS_ACTION_ALLOWED' | 'BLAST_RADIUS_CYCLE_RESET';
export interface BlastRadiusAuditEvent {
    type: BlastRadiusEventType;
    severity: 'INFO' | 'WARN' | 'ERROR';
    orgId: string;
    agentId: string;
    cycleId: string;
    timestamp: string;
    /** SHA-256 of previous audit event for this (orgId, agentId) pair. */
    prevHash: string;
    /** SHA-256 of this event's canonical payload. */
    currentHash: string;
    data: Record<string, unknown>;
}
export type BlastRadiusAuditSink = (event: BlastRadiusAuditEvent) => void;
export interface BlastRadiusEnforcerConfig {
    /**
     * Level caps to apply. Defaults to DEFAULT_LEVEL_CAPS.
     * Only specified levels/categories are overridden; omitted entries fall back
     * to DEFAULT_LEVEL_CAPS. Validated at construction: all provided cap values
     * must be non-negative integers (PT-BLAST-3).
     */
    levelCaps?: Partial<Record<AutonomyLevel, Partial<CategoryCaps>>>;
    /**
     * Per-agent autonomy level. Agents not listed use defaultAutonomyLevel.
     * Map of agentId -> AutonomyLevel (0-4).
     */
    agentLevels?: Record<string, AutonomyLevel>;
    /**
     * Default autonomy level for agents not in agentLevels. Default: 1.
     */
    defaultAutonomyLevel?: AutonomyLevel;
    /**
     * Audit sink. All EXCEEDED events are emitted. ALLOWED events are emitted
     * only if emitAllowedEvents is true. Default: no-op.
     */
    auditSink?: BlastRadiusAuditSink;
    /**
     * If true, emit BLAST_RADIUS_ACTION_ALLOWED for every allowed action.
     * Useful for dense audit trails; off by default for performance.
     */
    emitAllowedEvents?: boolean;
}
interface CycleCounters {
    'file-mutations': number;
    'network-calls': number;
    'database-writes': number;
    'secret-reads': number;
    'tool-invocations': number;
}
/**
 * Blast-radius enforcement gate with per-category, per-cycle counters and
 * per-autonomy-level caps. Designed to be instantiated once per
 * governance-server instance and shared across agents/cycles.
 *
 * Usage in PreToolUse hook:
 *
 *   const enforcer = new BlastRadiusEnforcer(config);
 *   // At cycle start, no reset needed -- new cycleId is clean.
 *
 *   // On each tool call:
 *   enforcer.check({
 *     orgId, agentId, cycleId,
 *     category: 'file-mutations',
 *     packBinding: ['hipaa'],
 *   });
 *   // Throws BlastRadiusCategoryExceededError if cap exceeded.
 *
 *   // At cycle end (or on cycle reset):
 *   enforcer.resetCycle(orgId, agentId, cycleId, packBinding);
 */
export declare class BlastRadiusEnforcer {
    private readonly resolvedCaps;
    private readonly agentLevels;
    private readonly defaultLevel;
    private readonly auditSink;
    private readonly emitAllowed;
    /**
     * Counters keyed by `${orgId}:${agentId}:${cycleId}`.
     * Isolated per triple; resetCycle() deletes the entry.
     */
    private readonly counters;
    /**
     * SHA-256 audit chain state keyed by `${orgId}:${agentId}`.
     * Persists across cycles so the chain is continuous per agent.
     */
    private readonly chainState;
    constructor(config?: BlastRadiusEnforcerConfig);
    /**
     * Pre-tool-call gate. Call this before dispatching any tool.
     *
     * Increments the category counter for the cycle and rejects the call if
     * the autonomy-level cap for that category is exceeded.
     *
     * Also always increments tool-invocations regardless of the primary
     * category supplied, so that the total-invocations cap is always enforced.
     *
     * @param opts.orgId      Organisation identifier.
     * @param opts.agentId    Agent identifier.
     * @param opts.cycleId    Cycle identifier (resets counters when new).
     * @param opts.category   Blast-radius category of the action being taken.
     * @param opts.packBinding Non-empty compliance pack IDs governing this action.
     * @param opts.level      Optional override for the agent's autonomy level.
     *                        When omitted, the level from agentLevels config or
     *                        defaultAutonomyLevel is used.
     *
     * @throws UnboundDataError             packBinding is empty.
     * @throws BlastRadiusCategoryExceededError  cap exceeded for the category or
     *                                           for tool-invocations.
     */
    check(opts: {
        orgId: string;
        agentId: string;
        cycleId: string;
        category: BlastCategory;
        packBinding: string[];
        level?: AutonomyLevel;
    }): void;
    /**
     * Reset all counters for the given cycle. Call at cycle end.
     * The audit chain state is preserved so the chain remains continuous
     * across cycle boundaries.
     *
     * @throws UnboundDataError if packBinding is empty.
     */
    resetCycle(orgId: string, agentId: string, cycleId: string, packBinding: string[]): void;
    /**
     * Return the current counters for an (orgId, agentId, cycleId) triple.
     * Returns all-zero counters if the cycle has not started yet or was reset.
     * Useful for monitoring dashboards.
     */
    getCounters(orgId: string, agentId: string, cycleId: string): Readonly<CycleCounters>;
    /**
     * Return the resolved caps for a given autonomy level.
     * Useful for surfacing configured limits in dashboards or audit docs.
     */
    getCaps(level: AutonomyLevel): Readonly<CategoryCaps>;
    /**
     * Return the effective autonomy level for an agent (from agentLevels config
     * or defaultAutonomyLevel).
     */
    getLevel(agentId: string): AutonomyLevel;
    private buildResolvedCaps;
    private counterKey;
    private chainKey;
    private getOrCreateCounters;
    private zeroCounters;
    private getChainState;
    private advanceChain;
    private emitRejection;
    private emitAllowed_event;
}
export {};
//# sourceMappingURL=blast-radius-enforcer.d.ts.map