{"version":3,"file":"execution-lease.d.ts","sourceRoot":"","sources":["../../../src/core/mission-domain/execution-lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,gFAAgF;AAChF,eAAO,MAAM,mCAAmC,QAAc,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC9B,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAElF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAE3E;AAED,MAAM,MAAM,2BAA2B,GACpC,eAAe,GACf,kBAAkB,GAClB,uBAAuB,GACvB,gBAAgB,GAChB,uBAAuB,GACvB,eAAe,GACf,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,uBAAuB,CAAC;AAE3B;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpD,YAAY,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAKzG;CACD","sourcesContent":["/**\n * Execution Lease + Fencing (2.7.0).\n *\n * First-class durable execution ownership for a single durable mission.\n *\n * The local file-backed store already guarantees an atomic record swap and an\n * atomic cross-process mutation critical section. This module models the\n * *long-lived* ownership contract layered on top of that short critical\n * section:\n *\n *   - `ExecutionLease` identifies the single current execution owner.\n *   - `fencingToken` is the monotonic ownership epoch for that mission. It is\n *     stored on the durable record itself (not only inside the lease) so it\n *     survives lease clearing and can never move backward across takeover or\n *     recovery revocation.\n *   - `ExecutionLeaseProof` is the small credential a live owner presents on\n *     every execution-authoritative mutation.\n *\n * The file mutation lock is deliberately NOT this lease: the lock protects\n * milliseconds-long record swaps, the lease protects minutes/hours-long\n * ownership. A stale lock and an expired lease are different failure domains.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport * as os from \"node:os\";\n\n/** Default execution-ownership lease lifetime. Configurable per coordinator. */\nexport const DEFAULT_EXECUTION_LEASE_DURATION_MS = 30 * 60_000;\n\nexport interface ExecutionLease {\n\t/** Opaque, non-PID-derived executor owner identity. Stable for one ownership lifetime. */\n\townerId: string;\n\t/** Unique acquisition identity for this ownership instance. */\n\tleaseId: string;\n\t/** Monotonic ownership epoch; strictly increases on every acquisition and recovery revocation. */\n\tfencingToken: number;\n\tacquiredAtMs: number;\n\trenewedAtMs: number;\n\texpiresAtMs: number;\n}\n\n/** Minimal proof a live owner presents for execution-authoritative mutation. */\nexport interface ExecutionLeaseProof {\n\tleaseId: string;\n\tfencingToken: number;\n}\n\n/** True while the lease still authorizes execution-authoritative mutation. */\nexport function isExecutionLeaseActive(lease: ExecutionLease, now: number): boolean {\n\treturn lease.expiresAtMs > now;\n}\n\n/**\n * Stable executor owner identity. Deliberately not PID-derived (PIDs are\n * reusable) and never contains secrets. Host + random UUID are sufficient for\n * diagnosable, opaque, process-lifetime-stable identity.\n */\nexport function newExecutorOwnerId(hostname: string = os.hostname()): string {\n\treturn `owner_${hostname}_${randomUUID()}`;\n}\n\nexport type ExecutionOwnershipErrorCode =\n\t| \"MISSION_OWNED\"\n\t| \"MISSION_TERMINAL\"\n\t| \"MISSION_NOT_RESUMABLE\"\n\t| \"STALE_REVISION\"\n\t| \"STALE_EXECUTION_OWNER\"\n\t| \"LEASE_EXPIRED\"\n\t| \"LEASE_NOT_FOUND\"\n\t| \"LEASE_CONFLICT\"\n\t| \"LOCK_TIMEOUT\"\n\t| \"CORRUPT_LOCK_METADATA\";\n\n/**\n * Structured ownership error. Core logic never relies on message string\n * matching; consumers switch on `code`.\n */\nexport class ExecutionOwnershipError extends Error {\n\treadonly code: ExecutionOwnershipErrorCode;\n\treadonly detail?: Readonly<Record<string, unknown>>;\n\n\tconstructor(code: ExecutionOwnershipErrorCode, message: string, detail?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message);\n\t\tthis.name = \"ExecutionOwnershipError\";\n\t\tthis.code = code;\n\t\tthis.detail = detail ? Object.freeze({ ...detail }) : undefined;\n\t}\n}\n"]}