/**
 * SuspendStateCache — local per-agent suspend state cache with best-effort
 * background refresher for SDK-embedded deployments (ASI-10 SDK kill-switch).
 *
 * Design rationale
 * ────────────────
 * The operator kill-switch (POST /api/v1/agents/:id/suspend) writes
 * `operatorSuspended=true` to the governance-server. An SDK-embedded agent
 * running in the customer's process with no proxy must learn about the
 * suspension through a different channel — it cannot rely on the proxy's
 * forceOpen() shortcut because there is no proxy in its traffic path.
 *
 * This cache solves the problem without violating any Locked Invariant:
 *
 * Invariant 2 — advisory, never authoritative:
 *   The refresh network call is NEVER on the PreToolUse hot path. The cache
 *   is queried synchronously; the refresh runs asynchronously in the
 *   background. If the governance server is unreachable the agent continues
 *   operating on last-known state (provision-allow / provision-deny depending
 *   on the last-known value).
 *
 * Invariant 3 — graceful degradation:
 *   On network error / timeout, the cache keeps its last-known entry and does
 *   NOT throw. Other agents are completely unaffected — each agentId has an
 *   independent cache entry.
 *
 * Invariant 10 — push-receive only:
 *   The refresher POLLS an existing GET endpoint (GET /api/v1/agents/:id) on
 *   the governance server — we are pulling status for an agent we ourselves
 *   registered. This is not scanning customer infrastructure; it is checking
 *   our own platform's published registry data for an agent that opted in.
 *
 * Enforcement boundary
 * ────────────────────
 * Enforcement requires the @connexum/ai-governance runtime/hook to be
 * installed (the standard SDK install path). If the customer removes the
 * runtime hook entirely there is nothing to enforce on the client side — this
 * is inherent to any client-side control and is an accepted, documented gap
 * (see SECURITY.md §ASI-10-SDK-boundary).
 *
 * Usage
 * ─────
 *   const cache = new SuspendStateCache({
 *     agentId: 'agent-xyz',
 *     governanceServerUrl: 'https://api.my-cc.io',
 *     authToken: '<ORG_KEY>',
 *     circuitBreaker,          // root SDK CircuitBreaker instance
 *     ttlMs: 30_000,           // optional, default 30 s
 *     refreshTimeoutMs: 5_000, // optional, default 5 s
 *   });
 *   await cache.start();       // boots with an immediate fetch, then polls
 *   // ... agent runs; cache refreshes in background ...
 *   cache.stop();              // clears the poll interval
 *
 * @connexum/ai-governance  ASI-10 SDK kill-switch
 */
import { CircuitBreaker } from './circuit-breaker.js';
export interface SuspendStateCacheConfig {
    /** Stable agent ID as registered on the governance server. */
    agentId: string;
    /**
     * Base URL of the governance server
     * (e.g. 'https://api.my-cc.io' or 'http://localhost:3000').
     * Must NOT end with a trailing slash.
     */
    governanceServerUrl: string;
    /**
     * Bearer token sent in the Authorization header when calling
     * GET /api/v1/agents/:id. Should be an ORG_KEY or ORG_VIEWER token
     * scoped to the org that owns the agent.
     */
    authToken: string;
    /**
     * Root SDK CircuitBreaker instance that will be updated when suspend
     * state changes are detected:
     *   operatorSuspended=true  → circuitBreaker.forceOpen(agentId)
     *   operatorSuspended=false → circuitBreaker.resetForced(agentId)
     */
    circuitBreaker: CircuitBreaker;
    /**
     * How often to re-fetch the agent's suspend state from the governance
     * server (milliseconds). Default: 30_000 (30 s).
     */
    ttlMs?: number;
    /**
     * HTTP request timeout for each refresh call (milliseconds).
     * Kept short so a slow governance server does not block the background loop.
     * Default: 5_000 (5 s).
     */
    refreshTimeoutMs?: number;
}
export interface SuspendEntry {
    /** Current suspend state as last reported by the governance server. */
    suspended: boolean;
    /** ISO timestamp of when this entry was last fetched successfully. */
    fetchedAt: string;
}
export declare class SuspendStateCache {
    private readonly agentId;
    private readonly governanceServerUrl;
    private readonly authToken;
    private readonly cb;
    private readonly ttlMs;
    private readonly refreshTimeoutMs;
    /** Per-agent cache entry. null = never successfully fetched yet. */
    private entry;
    /** NodeJS timer reference; null when not running. */
    private timer;
    constructor(config: SuspendStateCacheConfig);
    /**
     * Start the cache: perform an immediate fetch then schedule periodic
     * refreshes. The initial fetch failure is silently swallowed so boot
     * continues even if the governance server is temporarily unreachable.
     *
     * Returns `this` to allow chaining.
     */
    start(): Promise<this>;
    /**
     * Stop the background refresh interval.
     * Safe to call multiple times.
     */
    stop(): void;
    /**
     * Return the last-known suspend entry, or null if never fetched.
     * Does NOT trigger a network call. Purely synchronous.
     */
    getEntry(): SuspendEntry | null;
    /**
     * Trigger an immediate out-of-band refresh (beyond the normal TTL).
     * Useful after the customer's code observes a suspend signal through
     * another channel and wants to synchronise immediately.
     *
     * Returns the updated entry, or null if the fetch failed.
     * Never throws.
     */
    refresh(): Promise<SuspendEntry | null>;
    /**
     * Fetch GET /api/v1/agents/:id from the governance server and update the
     * local cache and circuit breaker.
     *
     * Invariant 3 compliance: ALL error paths are swallowed. The method NEVER
     * throws. On any failure the last-known cache entry is preserved unchanged.
     */
    private _refresh;
}
//# sourceMappingURL=suspend-state-cache.d.ts.map