export type PolicyLedgerErrorCode = 'budget-exhausted' | 'idempotency-conflict' | 'invalid-input' | 'invalid-path' | 'invalid-state' | 'legacy-unverifiable' | 'not-found' | 'schema-too-new' | 'unauthorized' | 'version-conflict'; export declare class PolicyLedgerError extends Error { readonly code: PolicyLedgerErrorCode; constructor(code: PolicyLedgerErrorCode, message: string); } export interface PolicyLedgerOptions { path: string; now?: () => number; } /** Shared byte contract for Policy, Delivery, and channel approval rendering. */ export declare const APPROVAL_DISPLAY_BUDGET: Readonly<{ maxTextBytes: number; maxSummaryBytes: 120; renderingReserveBytes: number; maxDiffBytes: number; }>; export interface BudgetReservationInput { scope: string; metric: string; limit: number; amount: number; periodMs: number; idempotencyKey: string; } export interface BudgetReservationResult { reservationId: string; status: 'finalized' | 'released' | 'reserved'; periodStart: number; remaining: number; replayed: boolean; } export interface EmergencyStopState { enabled: boolean; reason: string | undefined; actor: string | undefined; updatedAt: number | undefined; version: number; } export interface ApprovalProposalInput { idempotencyKey: string; requester: string; principal: string; action: string; resource: { kind: string; id: string; }; diff: string; summary: string; ttlMs: number; dispatch?: Readonly; } /** * Durable-domain creation input with an absolute deadline. Unlike `ttlMs`, the * deadline cannot move forward when a process restarts or loses a cross-database * commit acknowledgement. */ export interface ApprovalProposalRecoveryInput { idempotencyKey: string; requester: string; principal: string; action: string; resource: { kind: string; id: string; }; diff: string; summary: string; notAfter: number; dispatch?: Readonly; } export interface ApprovalDispatchRouteV1 { /** Omitted by pre-v2 callers and persisted explicitly as route version 1. */ routeVersion?: 1; sourceId: string; bindingId: string; workspace: string; principal: string; } export interface ApprovalDispatchRouteV2 { routeVersion: 2; sourceId: string; bindingId: string; bindingVersion: number; bindingGeneration: number; workspace: string; principal: string; principalRecordId: string; principalVersion: number; } export type ApprovalDispatchRoute = ApprovalDispatchRouteV1 | ApprovalDispatchRouteV2; export type ApprovalProposalStatus = 'approved' | 'expired' | 'pending' | 'rejected'; /** * Policy fact for an exact owner route. Excludes diff, summary and reason; * caller-owned action/resource metadata still needs source and byte limits. */ export interface ApprovalProposalRouteState { proposalId: string; resource: { kind: string; id: string; }; action: string; /** Pending past its deadline is projected as expired without writing the ledger. */ status: ApprovalProposalStatus; version: number; createdAt: number; expiresAt: number; decidedAt?: number; } export interface ApprovalProposalRouteStates { proposals: readonly ApprovalProposalRouteState[]; truncated: boolean; } export interface ApprovalProposalResult { proposalId: string; status: ApprovalProposalStatus; diffHash: string; expiresAt: number; version: number; replayed: boolean; } export type ApprovalProposalRecoveryResult = Readonly<{ kind: 'proposal'; proposal: ApprovalProposalResult; }> | Readonly<{ kind: 'abandoned'; idempotencyKey: string; notAfter: number; abandonedAt: number; replayed: boolean; }>; export interface ApprovalDecisionInput { proposalId: string; principal: string; expectedVersion: number; decision: 'approved' | 'rejected'; reason: string; } /** * Terminal-decision snapshot of one proposal, exposed so the domain that owns the * pending operation can discover the decision and commit it through its own gate. * Policy never calls back into a domain, so this read seam is the only supported * way to close that loop. */ export interface ApprovalProposalSnapshot { proposalId: string; requester: string; principal: string; action: string; resource: { kind: string; id: string; }; summary: string; status: ApprovalProposalStatus; diffHash: string; expiresAt: number; version: number; decidedBy: string | undefined; decisionReason: string | undefined; } /** * Exact, authority-scoped identity used by a domain to recover a proposal whose * Policy commit may have succeeded before the domain persisted its proposal ID. * This lookup is deliberately read-only and does not accept proposal content or * TTL, so it can never create, replay, or extend a proposal. */ export interface ApprovalProposalLookupInput { idempotencyKey: string; requester: string; principal: string; action: string; resource: { kind: string; id: string; }; } export type ApprovalDispatchState = 'enqueued' | 'pending' | 'quarantined'; /** Stable high-water mark for a pending-dispatch scan. */ export interface ApprovalDispatchCursor { createdAt: number; proposalId: string; } /** * Immutable, policy-derived payload and route for one durable approval delivery. * Callers can choose when to enqueue it, but cannot substitute display content. */ interface ApprovalDispatchSnapshotBase { proposalId: string; requester: string; action: string; resource: { kind: string; id: string; }; summary: string; diff: string; diffHash: string; payloadHash: string; expiresAt: number; proposalVersion: number; state: ApprovalDispatchState; createdAt: number; enqueuedAt: number | undefined; version: number; } export type ApprovalDispatchSnapshot = Readonly; export interface ApprovalDispatchResult { proposalId: string; state: 'enqueued'; payloadHash: string; enqueuedAt: number; version: number; replayed: boolean; } export interface AuditInput { actor: string; action: string; resource: { kind: string; id: string; }; outcome: string; reasonCode: string; details: unknown; } export interface AuditEvent { sequence: number; eventId: string; occurredAt: number; actor: string; action: string; resourceKind: string; resourceHash: string; outcome: string; reasonCode: string; details: unknown; } export declare class PolicyLedger { #private; constructor(options: PolicyLedgerOptions); close(): void; reserve(input: BudgetReservationInput): BudgetReservationResult; finalize(reservationId: string, actualAmount: number): BudgetReservationResult; release(reservationId: string): BudgetReservationResult; /** * Release a still-open reservation addressed by its idempotency key. Used by * hosts during crash recovery when only the deterministic key is available. * A missing row returns undefined; a finalized reservation throws * invalid-state (a charge is never unwound); released replays idempotently. */ releaseByIdempotencyKey(idempotencyKey: string): BudgetReservationResult | undefined; getEmergencyStop(): EmergencyStopState; setEmergencyStop(input: { enabled: boolean; actor: string; reason: string; }): EmergencyStopState; propose(input: ApprovalProposalInput): ApprovalProposalResult; /** * Atomically recover an existing exact proposal, create it under an immutable * absolute deadline, or permanently abandon the idempotency key after that * deadline. `BEGIN IMMEDIATE` serializes this decision across Policy processes, * closing the lookup-then-create orphan-card race. */ recoverOrCreateProposal(input: ApprovalProposalRecoveryInput): ApprovalProposalRecoveryResult; /** Create and decide a fresh, exact owner-request proposal in one write transaction. */ recoverOrCreateOwnerRequestedProposal(input: ApprovalProposalRecoveryInput, reason: string, assertCurrent: () => void): ApprovalProposalRecoveryResult; decideProposal(input: ApprovalDecisionInput): ApprovalProposalResult; /** * Read one proposal's current status without deciding it. A domain reconciler * uses this to learn that its own pending operation was already approved or * rejected elsewhere, then commits that outcome itself. */ getProposal(proposalId: string): ApprovalProposalSnapshot | undefined; /** * Recover an existing proposal by its immutable scoped idempotency identity. * A mismatch is indistinguishable from absence; callers may subsequently try * `propose`, whose normal idempotency conflict check remains fail-closed. */ getProposalByIdempotencyKey(input: ApprovalProposalLookupInput): ApprovalProposalSnapshot | undefined; listPendingApprovalDispatches(limit?: number, after?: Readonly): ApprovalDispatchSnapshot[]; /** Read-only, exact v2 owner-route facts; action/resource remain caller metadata. */ listProposalStatesForRoute(route: ApprovalDispatchRouteV2, limit?: number): ApprovalProposalRouteStates; markApprovalDispatchEnqueued(proposalId: string, expectedVersion: number): ApprovalDispatchResult; expireProposals(limit?: number): number; appendAudit(input: AuditInput): AuditEvent; queryAudit(options?: { afterSequence?: number; limit?: number; }): AuditEvent[]; health(): { lastAuditSequence: number; }; } export {}; //# sourceMappingURL=ledger.d.ts.map