/**
 * PerAgentDailyBudgetEnforcer -- Per-(orgId, agentId) 24-hour rolling token
 * budget with hard FREEZE on breach.
 *
 * Freeze semantics (different from per-cycle pause):
 *   - Pause (CycleTokenBudgetEnforcer, PR #12): a single cycle is held. An
 *     operator can extend the cycle budget and resume. The agent keeps running.
 *   - Freeze (this module): the AGENT is frozen. All in-flight cycles are
 *     terminated. No new cycles can start. No re-extension is allowed.
 *     The freeze persists until either (a) the 24-hour window elapses and
 *     auto-thaw applies (lenient packs only), or (b) an OPERATOR_ADMIN
 *     unfreezes with a documented attestation.
 *
 * Rationale: a per-cycle overrun is a recoverable operational event. A
 * per-agent-daily overrun signals systemic misuse and warrants a harder stop
 * that surfaces to a human with documented reasoning before the agent resumes.
 *
 * Rolling 24-hour window (NOT calendar-day):
 *   Window start = first usage timestamp recorded in the current 24h period.
 *   Avoids the midnight-UTC cliff that would allow an agent to spend its full
 *   budget just before and just after midnight, doubling effective spend within
 *   minutes. Rolling windows are timezone-neutral for international operators.
 *
 * Auto-thaw after 24h:
 *   For lenient packs: when now > windowStartsAt + 24h the window resets and
 *   the freeze clears automatically.
 *   For strict packs (HIPAA, GDPR, PCI DSS, HMDA, DORA): the freeze REMAINS
 *   even after the daily window elapses. An OPERATOR_ADMIN must unfreeze with
 *   a documented attestation. Rationale: in regulated environments an agent
 *   that burned its entire daily budget is a compliance event. Auto-resuming
 *   it after midnight would be a gap auditors would flag -- the human must
 *   review the root cause before re-enabling the agent.
 *
 * v0 storage: in-memory map. State is lost on process restart.
 * v1 plan: persist agent state snapshots to a durable KV store (Redis or a
 *   lightweight SQLite sidecar) on every write. On startup, hydrate from
 *   store. Freeze state must survive process restart in regulated deployments
 *   because a frozen agent that auto-resumes after a pod restart is a
 *   compliance bypass. The v1 store key: `agent-daily-budget:{orgId}:{agentId}`.
 *
 * P3-T2 coverage gap: BUILD_PLAN_V3_FULL_LIFECYCLE.md line 273.
 *
 * Compliance bindings:
 *   - HIPAA 164.312(b): Audit Controls -- bounded inference spend per agent
 *   - HIPAA 164.308(a)(5): Security Awareness -- agent-level budget as
 *     anomaly signal
 *   - SOC 2 CC6.1: Access control / resource limits
 *   - EU AI Act Art. 9: Risk management (bounded daily agent scope)
 *   - ISO 42001 A.6.1.4: Resource management for AI systems
 *   - DORA Art. 17: ICT incident management -- freeze as incident trigger
 *   - PCI DSS Req 7: Restrict agent resource access by business need
 *
 * @connexum/ai-governance
 */
/** 24-hour window in milliseconds. */
export declare const DAILY_WINDOW_MS: number;
/**
 * Strict packs require explicit operator unfreeze even after the daily window
 * elapses. Auto-thaw is blocked for these pack IDs.
 */
export declare const STRICT_PACK_IDS: Set<string>;
export declare class AgentFrozenError extends Error {
    readonly orgId: string;
    readonly agentId: string;
    readonly frozenSince: string;
    readonly frozenReason: string;
    readonly packBinding: string[];
    constructor(opts: {
        orgId: string;
        agentId: string;
        frozenSince: string;
        frozenReason: string;
        packBinding: string[];
    });
}
export declare class UnfreezePermissionError extends Error {
    readonly operatorId: string;
    readonly reason: string;
    constructor(operatorId: string, reason: string);
}
export declare class UnfreezeNonceReplayError extends Error {
    readonly nonce: string;
    constructor(nonce: string);
}
export declare class EmptyPackBindingError extends Error {
    readonly operation: string;
    constructor(operation: string);
}
export type DailyBudgetEventType = 'AGENT_DAILY_BUDGET_CONFIGURED' | 'AGENT_DAILY_BUDGET_FROZEN' | 'AGENT_DAILY_BUDGET_UNFROZEN' | 'AGENT_DAILY_BUDGET_WINDOW_RESET' | 'AGENT_SELF_UNFREEZE_ATTEMPT' | 'CYCLE_TERMINATED_BY_DAILY_FREEZE' | 'TOKEN_COUNT_ANOMALY';
export type AuditSeverity = 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL';
export interface DailyBudgetAuditEvent {
    type: DailyBudgetEventType;
    severity: AuditSeverity;
    orgId: string;
    agentId: string;
    packBinding: string[];
    timestamp: string;
    prevSha?: string;
    /** Additional payload fields. */
    [key: string]: unknown;
}
export interface PerAgentDailyBudgetConfig {
    /**
     * Daily token budget (total input + output tokens per 24-hour window).
     * Must be > 0.
     */
    dailyBudgetTokens: number;
    /**
     * Pack IDs bound to this agent configuration. Must be non-empty.
     * Used to determine whether auto-thaw is permitted after the window elapses.
     */
    packBinding: string[];
    /**
     * Identity of the operator who configured this budget.
     * Must hold governance.configure permission.
     */
    configuredBy: string;
    /** ISO timestamp when this configuration was set. */
    configuredAt: string;
}
export declare class PerAgentDailyBudgetEnforcer {
    /**
     * Agent configurations. Key: `${orgId}::${agentId}`
     */
    private readonly configs;
    /**
     * Runtime state. Key: `${orgId}::${agentId}`
     *
     * v0: in-memory only. v1 plan: hydrate from durable store on startup,
     * persist on every write. Freeze state must survive process restart.
     */
    private readonly state;
    /**
     * Set of operator IDs that hold ADMIN role.
     * The enforcer maintains its own ADMIN set rather than calling out to
     * OperatorRoles to avoid runtime coupling -- callers are expected to pass
     * admin IDs at construction time or via registerAdmin().
     *
     * Alternatively, inject an OperatorRoles.checkPermission function.
     */
    private readonly adminOperatorIds;
    /**
     * Audit event callback. Called for every event emitted by this enforcer.
     */
    private readonly onAudit;
    /**
     * Seen unfreeze nonces -- replay prevention.
     * Key: nonce string. Value: timestamp it was used.
     */
    private readonly usedNonces;
    /**
     * SHA chain state (simple in-memory chain for the enforcer's own events).
     * In production wire to the external AuditIntegrity chain.
     */
    private lastSha;
    constructor(opts?: {
        /**
         * Callback invoked for every audit event. Wire to AuditIntegrity.append()
         * in production. Must not throw (errors are swallowed).
         */
        onAudit?: (event: DailyBudgetAuditEvent) => void;
        /**
         * Optional permission check function.
         * If provided, called for configure/unfreeze to verify admin role.
         * Signature mirrors OperatorRoles.checkPermission.
         */
        checkPermission?: (operatorId: string, action: string) => {
            allowed: boolean;
            reason: string;
        };
        /**
         * Pre-seeded admin operator IDs. Supplemented by registerAdmin().
         */
        adminOperatorIds?: string[];
    });
    /** Optional injected permission checker. */
    private _checkPermission?;
    /** Register an operator ID as having ADMIN authority over this enforcer. */
    registerAdmin(operatorId: string): void;
    /**
     * Configure the daily token budget for an agent.
     *
     * Operator-only. Verifies the approverIdentity holds governance.configure
     * permission (ADMIN role). Empty packBinding throws EmptyPackBindingError.
     *
     * @param orgId           Tenant / organization ID.
     * @param agentId         Agent identifier.
     * @param dailyBudgetTokens  Daily token budget (input + output).
     * @param approverIdentity   Operator identity performing this configuration.
     * @param packBinding     Non-empty compliance pack binding.
     */
    configure(orgId: string, agentId: string, dailyBudgetTokens: number, approverIdentity: string, packBinding: string[]): void;
    /**
     * Record token usage after an LLM call.
     *
     * Called post-LLM-call alongside the per-cycle counter. Returns remaining
     * tokens and current status. If the budget is exceeded on this call, the
     * agent is FROZEN, all in-flight cycles are terminated, and
     * AGENT_DAILY_BUDGET_FROZEN + CYCLE_TERMINATED_BY_DAILY_FREEZE events are
     * emitted.
     *
     * PT-DAILY-FREEZE-2 (token-count understatement): if the reported output
     * token count is below the byte-length / 8 floor, the byte-derived estimate
     * is used and a TOKEN_COUNT_ANOMALY WARNING event is emitted.
     *
     * @param orgId         Tenant / organization ID.
     * @param agentId       Agent identifier.
     * @param inputTokens   Input token count for this LLM call.
     * @param outputTokens  Output token count for this LLM call.
     * @param packBinding   Non-empty compliance pack binding.
     * @param cycleId       Optional cycle ID to register as active.
     * @param outputBytes   Optional byte length of LLM output (for anomaly detection).
     */
    recordUsage(orgId: string, agentId: string, inputTokens: number, outputTokens: number, packBinding: string[], cycleId?: string, outputBytes?: number): {
        remainingTokens: number;
        status: 'ok' | 'frozen';
    };
    /**
     * Pre-call gate. Call before each LLM request.
     *
     * Throws AgentFrozenError if the agent is currently frozen.
     * Returns { allowed: true } otherwise.
     *
     * Position in the hook chain: AFTER cycle-level gates (per-cycle token
     * budget, cycle wall-clock timeout, tool rate limit) but BEFORE the LLM
     * call. Per-cycle gates have tighter scope and fire first; the daily budget
     * is the broader bound that survives across multiple cycles.
     *
     * @param orgId       Tenant / organization ID.
     * @param agentId     Agent identifier.
     * @param packBinding Non-empty compliance pack binding.
     */
    guardPreCall(orgId: string, agentId: string, packBinding: string[]): {
        allowed: true;
    };
    /**
     * Operator-attested unfreeze.
     *
     * Only OPERATOR_ADMIN identities may call this. Agent-runtime identities
     * are explicitly rejected and an AGENT_SELF_UNFREEZE_ATTEMPT audit event
     * (severity ERROR) is emitted.
     *
     * Attestation must be non-empty. Each unfreeze call carries a unique nonce
     * (PT-DAILY-FREEZE-3 replay prevention).
     *
     * Emits AGENT_DAILY_BUDGET_UNFROZEN with severity ERROR (unfreezing a
     * frozen agent is itself a notable posture change).
     *
     * @param orgId           Tenant / organization ID.
     * @param agentId         Agent identifier.
     * @param approverIdentity  Operator identity performing the unfreeze.
     * @param attestation     Non-empty explanation of why the agent is being
     *                        unfrozen (e.g., root-cause summary, mitigation steps).
     * @param packBinding     Non-empty compliance pack binding.
     * @param nonce           Unique nonce for this unfreeze action. Must not
     *                        have been used in a prior unfreeze call.
     */
    unfreeze(orgId: string, agentId: string, approverIdentity: string, attestation: string, packBinding: string[], nonce?: string): void;
    /**
     * Return current status for monitoring and tests.
     */
    getStatus(orgId: string, agentId: string): {
        frozen: boolean;
        dailyBudget: number | null;
        consumedToday: number;
        windowStartsAt: string | null;
        windowEndsAt: string | null;
        frozenSince: string | null;
        frozenReason: string | null;
        activeCycleCount: number;
        configured: boolean;
    };
    /**
     * Register a cycle ID as active for the given agent.
     * Called by the cycle management layer when a new cycle starts.
     */
    registerCycle(orgId: string, agentId: string, cycleId: string): void;
    /**
     * Deregister a cycle ID (called when a cycle ends normally).
     */
    deregisterCycle(orgId: string, agentId: string, cycleId: string): void;
    private stateKey;
    private getOrCreateState;
    private requireConfig;
    /**
     * Check whether the daily window has elapsed and, if so, apply auto-thaw
     * logic for lenient packs (strict packs do NOT auto-thaw).
     */
    private maybeResetWindow;
    /**
     * PT-DAILY-FREEZE-2: resolve effective output token count.
     * If the reported count is below byte_length / 8, emit TOKEN_COUNT_ANOMALY
     * and use the byte-derived estimate.
     */
    private resolveOutputTokens;
    /**
     * PT-DAILY-FREEZE-1: window-start immutability.
     *
     * The windowStartMs is stored in the private state map and can only be
     * written by this class. It cannot be overwritten by runtime context,
     * agent messages, or external callers -- the Map key is derived from
     * orgId + agentId and the state reference is never exposed.
     *
     * This method exists for documentation and is called by tests to verify
     * that the immutability contract holds.
     */
    getWindowStartMs(orgId: string, agentId: string): number | null;
    /**
     * Determine if a given identity is an agent-runtime identity rather than
     * an operator identity. Heuristic: agent-runtime IDs are prefixed with
     * 'agent:' or 'runtime:'. Operators use 'op_' prefix (per OperatorRoles).
     *
     * In production wire to OperatorRoles.getOperator() for a hard check.
     */
    private isAgentRuntimeIdentity;
    /**
     * Assert that the given operator holds admin permission.
     * Uses injected checkPermission if available, falls back to the local
     * adminOperatorIds set.
     */
    private assertAdminPermission;
    /**
     * Emit an audit event with SHA chaining.
     * Swallows errors from the onAudit callback to avoid breaking the
     * enforcement path.
     */
    private emit;
}
//# sourceMappingURL=per-agent-daily-budget.d.ts.map