/** * Policy-as-Code registry. * * Manages versioned policy bundles with promote/rollback semantics. * Enforces the rule that no bundle may move to enforcement without * prior simulation evidence and a passing divergence gate. * * Bundle lifecycle: * loaded → simulating → promoting (gate check) → active (enforced) * * At any time: * - `current` , the bundle whose rules are actively enforced * - `candidate`, a loaded bundle awaiting simulation before promotion * - `history` , previous active bundles, kept for rollback */ import type { PolicyRule } from './types.js'; import type { SignedPolicyBundle } from './policy-signer.js'; import type { PolicyBundlePayload, BundleProvenance, PolicyLoadResult, PolicyLoaderOptions } from './policy-loader.js'; import type { DivergenceReport, SimulationMode } from './types.js'; import type { EnforceGateResult } from './divergence-dashboard.js'; /** * Lifecycle state of a policy bundle version. * * - `loaded` , Bundle loaded as candidate; not yet simulated. * - `simulating`, Simulation pipeline is active; divergence being collected. * - `promoting` , Gate check in progress; simulation evidence collected. * - `active` , Bundle is the enforced policy. * - `rolled-back`: Bundle was superseded by a rollback operation. */ export type BundleLifecycleState = 'loaded' | 'simulating' | 'promoting' | 'active' | 'rolled-back'; /** * A versioned policy bundle entry in the registry. */ export interface PolicyBundleVersion { /** The signed bundle as loaded from disk/inline. */ bundle: SignedPolicyBundle; /** Provenance record from the loader. */ provenance: BundleProvenance; /** The extracted rules (only populated when load succeeded). */ rules: PolicyRule[]; /** Lifecycle state for this version. */ state: BundleLifecycleState; /** ISO 8601 timestamp when this version was loaded. */ loadedAt: string; /** ISO 8601 timestamp when this version became active, if ever. */ activatedAt?: string | undefined; /** ISO 8601 timestamp when this version was rolled back, if applicable. */ rolledBackAt?: string | undefined; /** Simulation report collected before promotion, if any. */ simulationReport?: DivergenceReport | undefined; /** The gate result that was evaluated at promotion time, if any. */ gateResult?: EnforceGateResult | undefined; } /** * Result of a diff between two policy bundle versions. */ export interface PolicyDiffResult { /** ID of the "from" bundle (current or named). */ fromBundleId: string; /** ID of the "to" bundle (candidate or named). */ toBundleId: string; /** Rules present in `from` but not in `to` (removed). */ removed: PolicyRule[]; /** Rules present in `to` but not in `from` (added). */ added: PolicyRule[]; /** Rules whose `id` matches but whose payload differs. */ changed: Array<{ ruleId: string; from: PolicyRule; to: PolicyRule; }>; /** Rules identical in both bundles. */ unchanged: PolicyRule[]; /** Total count of changed rules (added + removed + modified). */ totalChanges: number; } /** * Result of a promote operation. */ export interface PromoteResult { /** Whether the promotion succeeded. */ ok: boolean; /** The gate result evaluated at promotion time. */ gate?: EnforceGateResult | undefined; /** Human-readable explanation when promotion is blocked. */ error?: string | undefined; /** The bundle that was promoted, if successful. */ bundleId?: string | undefined; } /** * Result of a rollback operation. */ export interface RollbackResult { /** Whether the rollback succeeded. */ ok: boolean; /** The bundle ID restored to active state. */ restoredBundleId?: string | undefined; /** Human-readable error when rollback fails. */ error?: string | undefined; } /** * Configuration for the PolicyRegistry. */ export interface PolicyRegistryConfig { /** * Maximum number of historical (non-active) bundle versions to retain. * Oldest entries are dropped when the limit is exceeded. * Defaults to 10. */ maxHistorySize?: number | undefined; /** * Options forwarded to `loadPolicyBundle()` for every bundle load. */ loaderOptions?: PolicyLoaderOptions | undefined; } /** * PolicyRegistry, Versioned policy bundle manager. * * Maintains the full bundle lifecycle: loaded → simulating → promoting → active. * Enforces that promotion to `active` (enforcement mode) requires: * 1. A simulation report to have been attached (evidence of simulation). * 2. The divergence gate to be passing (rate below threshold). * * Usage: * ```ts * const registry = new PolicyRegistry(); * * // Load a new candidate bundle * const loadResult = registry.loadCandidate(signedBundle); * * // After simulation, attach the report * registry.attachSimulationReport(divergenceReport, gateResult); * * // Promote when gate passes * const promoteResult = registry.promote(); * * // Rollback if something goes wrong * registry.rollback(); * ``` */ export declare class PolicyRegistry { private _current; private _candidate; private _history; readonly DEFAULT_HISTORY_SIZE = 10; private readonly _maxHistorySize; private readonly _loaderOptions; constructor(config?: PolicyRegistryConfig); /** * loadCandidate, Load a signed policy bundle as the pending candidate. * * Replaces any existing candidate. The candidate must be simulated and * have its gate checked before it can be promoted to active. * * @param bundle , The signed bundle to load. * @returns `PolicyLoadResult` indicating success or validation failure. */ loadCandidate(bundle: SignedPolicyBundle): PolicyLoadResult; /** * markSimulating, Transition candidate to `simulating` state. * * Called by the `/policy simulate` command when a simulation pipeline * is started. Validates that a candidate is loaded and in `loaded` state. * * @returns true if the state was successfully advanced. */ markSimulating(): boolean; /** * attachSimulationReport, Attach divergence report and gate result to candidate. * * Advances the candidate to `promoting` state, which is a prerequisite for * calling `promote()`. * * @param report , The divergence report from the simulation run. * @param gateResult, The gate evaluation at report time. * @returns true if the evidence was attached. */ attachSimulationReport(report: DivergenceReport, gateResult: EnforceGateResult): boolean; /** * promote, Promote the candidate bundle to active enforcement. * * Blocked unless: * - A candidate exists in `promoting` state (simulation evidence attached). * - The attached gate result is `passing`. * * On success, the previous active bundle moves to history. * * @param force, Skip gate check. Use only for testing; not for production use. */ promote(force?: boolean): PromoteResult; /** * rollback, Restore the previous active bundle. * * Moves the current active bundle to history and restores the most recent * previously-active bundle from history. * * @returns `RollbackResult` indicating success or failure. */ rollback(): RollbackResult; /** * diff, Produce a structural diff between two bundle rule sets. * * Compares `from` (defaults to current active) and `to` (defaults to candidate). * Rules are matched by `id` field. * * @param fromRules, Override the "from" rule set (defaults to current active). * @param toRules , Override the "to" rule set (defaults to candidate). */ diff(fromRules?: PolicyRule[], toRules?: PolicyRule[]): PolicyDiffResult | null; /** Returns the currently active bundle version, or null if none loaded. */ getCurrent(): PolicyBundleVersion | null; /** Returns the candidate bundle version, or null if none loaded. */ getCandidate(): PolicyBundleVersion | null; /** Returns the bundle history (previous active bundles), oldest first. */ getHistory(): PolicyBundleVersion[]; /** * getSimulationMode, Returns the recommended simulation mode based on * whether the candidate has simulation evidence. * * This is a hint for the command handler; callers choose the actual mode. */ getSimulationMode(): SimulationMode; private _archiveVersion; } //# sourceMappingURL=policy-registry.d.ts.map