/** * Durable v2-definition -> v3 Saved Workflow migration ledger. * * The legacy definition file is user-authored source material and is never * rewritten. One source identity (canonical real path + workflow id) owns one * stable Saved Workflow. Every semantic legacy revision then maps to an exact * immutable v3 revision. The v2 execution engine is gone; a pending migration * is repaired by re-running the migration command without mutating the legacy * source bytes. */ import { type WorkflowDefinition } from '../definition.js'; import { type SavedWorkflowOwner, type SavedWorkflowScope } from '../v3/library-schema.js'; export declare const LEGACY_MIGRATION_LEDGER_SCHEMA_VERSION: 1; export declare const LEGACY_SOURCE_KEY_RE: RegExp; export declare const LEGACY_MIGRATION_KEY_RE: RegExp; export declare const LEGACY_CONTENT_HASH_RE: RegExp; export declare const LEGACY_CONVERSION_HASH_RE: RegExp; export type LegacyMigrationState = 'pending' | 'committed'; export interface LegacySourceIdentity { path: string; workflowId: string; } export interface LegacyDefinitionIdentity extends LegacySourceIdentity { contentHash: string; } export interface LegacyMigrationTarget { workflowId: string; owner: SavedWorkflowOwner; scope: SavedWorkflowScope; } export type LegacyMigrationSupersedeReason = 'target_latest_changed_before_materialization'; /** Immutable audit row for an explicitly abandoned pending allocation. */ export interface LegacyMigrationSupersededAllocation { conversionHash: string; targetRevisionId: string; targetHumanVersion: number; targetCreatedAt: string; expectedLatestRevision?: string; preparedAt: string; supersededAt: string; reason: LegacyMigrationSupersedeReason; } /** * Allocation frozen before touching the v3 library. It contains enough data * to reconstruct and byte-check the exact immutable revision after any crash. */ export interface LegacyMigrationRevisionRecord { migrationKey: string; state: LegacyMigrationState; contentHash: string; conversionHash: string; targetRevisionId: string; targetHumanVersion: number; targetCreatedAt: string; expectedLatestRevision?: string; preparedAt: string; updatedAt: string; supersededAllocations?: LegacyMigrationSupersededAllocation[]; } export interface LegacyMigrationSourceRecord { sourceKey: string; legacy: LegacySourceIdentity; target: LegacyMigrationTarget; revisions: Record; createdAt: string; updatedAt: string; } export interface LegacyMigrationLedger { schemaVersion: typeof LEGACY_MIGRATION_LEDGER_SCHEMA_VERSION; sources: Record; } export type LegacyMigrationLookup = { kind: 'none'; } | { kind: 'exact'; source: LegacyMigrationSourceRecord; revision: LegacyMigrationRevisionRecord; } | { kind: 'changed_after_migration'; source: LegacyMigrationSourceRecord; currentContentHash: string; }; export declare class LegacyMigrationLedgerError extends Error { constructor(message: string); } export declare function legacyMigrationLedgerPath(dataDir: string): string; export declare function legacyDefinitionIdentity(path: string, definition: WorkflowDefinition): LegacyDefinitionIdentity; export declare function legacySourceKey(identity: LegacySourceIdentity): string; export declare function legacyMigrationKey(identity: LegacyDefinitionIdentity): string; /** Stable across legacy revisions so semantic edits append v3 revisions. */ export declare function migratedSavedWorkflowId(identity: LegacySourceIdentity): string; export declare function computeLegacyConversionHash(value: unknown): string; export declare function validateLegacyMigrationSourceRecord(raw: unknown, expectedSourceKey?: string): LegacyMigrationSourceRecord; export declare function validateLegacyMigrationLedger(raw: unknown): LegacyMigrationLedger; export declare function readLegacyMigrationLedger(dataDir: string): LegacyMigrationLedger; export interface PrepareLegacyMigrationInput { identity: LegacyDefinitionIdentity; target: LegacyMigrationTarget; conversionHash: string; targetRevisionId: string; targetHumanVersion: number; targetCreatedAt: string; expectedLatestRevision?: string; now?: Date; } /** * First durable phase. The exact target allocation is immutable once written. * A repeated call must reproduce it byte-for-byte or fail closed. */ export declare function prepareLegacyMigration(dataDir: string, input: PrepareLegacyMigrationInput): { source: LegacyMigrationSourceRecord; revision: LegacyMigrationRevisionRecord; created: boolean; }; export interface SupersedePendingLegacyMigrationInput extends PrepareLegacyMigrationInput { /** CAS guard: the exact pending allocation the operator inspected. */ previousTargetRevisionId: string; reason: LegacyMigrationSupersedeReason; } /** * Explicit recovery for a pending allocation that was never materialized but * whose optimistic library base moved. The abandoned allocation is retained * as immutable audit evidence; committed rows can never be superseded. * * The service must prove the previous target revision is absent before calling * this ledger seam. A concurrent drift after reallocation is harmless: the * library CAS fails and the operator may explicitly supersede again. */ export declare function supersedePendingLegacyMigration(dataDir: string, input: SupersedePendingLegacyMigrationInput): { source: LegacyMigrationSourceRecord; revision: LegacyMigrationRevisionRecord; }; export declare function commitLegacyMigration(dataDir: string, identity: LegacyDefinitionIdentity, now?: Date): { source: LegacyMigrationSourceRecord; revision: LegacyMigrationRevisionRecord; }; export declare function findLegacyMigration(dataDir: string, identity: LegacyDefinitionIdentity): LegacyMigrationLookup; //# sourceMappingURL=v2-ledger.d.ts.map