/** * Persistent remediation journal for the two-deploy `forget` orchestration * (drift-remediation plan § 3.2). One JSON file per operation under * `~/.fjall/state/remediation////.json`; * writes are atomic (tmp + rename) against concurrent processes sharing the * directory. * * Unlike the drift-suspect journal (a hint), journal WRITES here fail loudly * — a phase transition that cannot persist aborts the orchestration rather * than mutating without a resume record. READS stay fail-soft: a corrupt or * schema-drifted file reads as `null` (warn-logged) because the AWS-side * `fjall:forget` marker [G3] re-derives the state a lost journal would have * carried. * * Completed records are the audit trail, retained 90 days * (`sweepExpiredRemediationJournals`); the sweep also removes the record's * forensics bundle — the done journal holds the only `forensicsPath` pointer, * so a bundle outliving its journal would accumulate unreferenced forever. */ import { type Result } from "@fjall/generator"; import { type RemediationJournalRecord } from "../../types/remediation.js"; export declare const REMEDIATION_JOURNAL_RETENTION_DAYS = 90; export interface RemediationJournalOptions { /** Override the journal root — tests point this at a temp dir. */ journalDir?: string; } export declare function defaultRemediationJournalDir(): string; /** * opId = digest of stack + logical-ID set (plan §3.2) — order-insensitive so * re-detection reproduces the same id and a re-run resumes instead of forking * a second operation. 16 hex chars keeps it path- and prompt-friendly. */ export declare function computeRemediationOpId(stackName: string, logicalIds: readonly string[]): string; /** * [G5] Verb-accurate done-journal notices, shared by BOTH surgery orchestrators * (`runForgetSurgery` and `runRecreateSurgery` each meet cross-verb DONE * journals — coupled values, one home). Deriving from `journal.verb` keeps a * done RECREATE journal read through the forget arm from reporting "Forget * operation … already completed", and vice versa. */ export declare function formatCompletedOperationNotice(journal: Pick): string; export declare function formatArchivedOperationNotice(journal: Pick): string; /** * Persist the journal record (atomic tmp + rename). Fails loudly — callers * abort the orchestration when the resume record cannot be written. */ export declare function writeRemediationJournal(record: RemediationJournalRecord, options?: RemediationJournalOptions): Promise>; /** * Read one operation's journal. Missing, corrupt, or schema-drifted files * read as `null` (warn-logged) — the fjall:forget marker [G3] re-derives. */ export declare function readRemediationJournal(accountId: string, region: string, stackName: string, opId: string, options?: RemediationJournalOptions): Promise; /** * Archive a COMPLETED journal out of the resume keyspace: renamed to * `.done-.json` in place, it stops matching * `findRemediationJournalByOpId` and the fresh-repair read while remaining a * parseable done record — `listActiveRemediationOps` still excludes it and * the retention sweep still ages it out. Used when a fresh repair meets a * done journal from a prior incarnation of the same opId. */ export declare function archiveCompletedRemediationJournal(record: RemediationJournalRecord, options?: RemediationJournalOptions): Promise>; export interface RemediationJournalContext { accountId: string; region: string; } /** * Locate a journal by opId alone (`fjall drift resume ` has no stack * context). Scans the account/region/stack keyspace for `.json`. The * opId has no account/region component, so the same operation replayed in two * contexts (staging + prod) collides — with multiple matches the one under * the current credentials' account/region wins; when none matches, the * failure enumerates every match so the operator can switch context. */ export declare function findRemediationJournalByOpId(opId: string, context?: RemediationJournalContext, options?: RemediationJournalOptions): Promise>; /** All non-done operations for one stack — the [G2] pre-flight consumes. */ export declare function listActiveRemediationOps(accountId: string, region: string, stackName: string, options?: RemediationJournalOptions): Promise; /** * All non-done operations across EVERY stack in one account/region — the * post-deploy closure sweep consumes (an open recreate journal can live on a * stack the current deploy skipped, and that sweep is the recreate arm's * sole closure point). */ export declare function listActiveRemediationOpsForContext(accountId: string, region: string, options?: RemediationJournalOptions): Promise; /** * Best-effort sweep of completed journals past the 90-day audit retention. * Never fails the caller. */ export declare function sweepExpiredRemediationJournals(options?: RemediationJournalOptions, now?: () => Date): Promise;