import { type CredentialEvidenceAuthority, type CredentialExecutionBinding, type CredentialExecutionSubject, type CredentialHonoredObservation } from "@claudexor/core"; import type { CredentialUnusableObservation } from "@claudexor/schema"; import { CredentialGeneration } from "./credential-generation.js"; /** * The daemon's bounded, self-expiring memory of typed `credential_unusable` * observations (A7): "this credential is DEAD, not quota-spent". * * Deliberately IN-MEMORY, never journaled: profile readiness is non-durable by * contract (the doctor's projection), the quota poller re-derives vendor * rejections within a poll cycle after a restart, and a restart usually * follows exactly the re-login that heals a dead credential — journaling would * buy rollback-compat risk to preserve evidence that expires anyway. The * `QuotaAbsence` channel is unsuitable on purpose: the registry hides an * absence while ANY live snapshot covers the subject, which is exactly how a * dead credential with a lingering cooldown snapshot would vanish. * * Clearing contract (all three, per the design roast): * 1. self-expiry — every row carries `expires_at`, clamped to 24h max; * 2. a covering dispatch-bound successful model response hides the live * verdict; its bounded negative witnesses remain until expiry, generation * clearing or memory eviction so concurrent refusals keep both boundaries; * 3. a credential-generation change voids the verdicts about the changed * generation: a login/logout clears the WHOLE ledger * (`noteCredentialChange`, wired in claudexord's setup lifecycle), while a * control-API credential mutation (profile enable/disable/create/remove, * secret set/delete) clears PER SUBJECT (`clearSubject` / * `clearDefaultSubjects`, wired beside the daemon's status-cache busting). * Clearing is always fail-open — a lost observation costs at * most one attempt rediscovering a refusal, while a stale one poisons * rotation; * 4. no verdict is recorded while a login may be rewriting that harness's * credential store (the daemon's setup-lifecycle window, #363): it would be * about a credential in flux, and the window's close clears the ledger. */ export declare class CredentialUnusableLedger implements CredentialEvidenceAuthority { private readonly now; private readonly mutating; readonly credentials: CredentialGeneration; private rows; private orders; private successes; constructor(now?: () => Date, mutating?: (harnessId: string) => boolean, credentials?: CredentialGeneration); bind(subject: CredentialExecutionSubject): CredentialExecutionBinding; current(binding: CredentialExecutionBinding): boolean; recordBound(binding: CredentialExecutionBinding, value: CredentialUnusableObservation): void; /** A dispatch cannot heal an observation from a newer concurrent dispatch. */ honorBound(binding: CredentialExecutionBinding, observedModel: string | null, observedAt?: string): void; /** Validate, clamp to the TTL bound, newest-wins per (subject, model). */ record(value: CredentialUnusableObservation): void; private store; /** Unhealed observations; hidden witnesses keep their bounds until expiry. */ live(): readonly CredentialUnusableObservation[]; honored(): readonly CredentialHonoredObservation[]; /** Exported proof obeys the same scope/order checks as row clearing. */ private refusesPositive; private covers; private positivePoints; /** Credential generation changed wholesale (login/logout): every verdict * about the old generation is void. */ noteCredentialChange(): void; /** ONE subject's credential changed (a control-API profile or profile-secret * mutation): only ITS verdicts are void, across every model scope. * `profileId` null = the harness's default subject. */ clearSubject(harnessId: string, profileId: string | null): void; /** A bare managed secret name changed an engine-DEFAULT credential slot. * WHICH harness reads that slot is adapter knowledge the daemon does not * duplicate, so every default subject's verdicts are voided — fail-open by * the clearing contract (costs at most one rediscovered refusal). */ clearDefaultSubjects(): void; private prune; } //# sourceMappingURL=credential-unusable-ledger.d.ts.map