From a3e2276bef550d16cf6318e0d40f1cd2958cb145 Mon Sep 17 00:00:00 2001 From: mptyl Date: Wed, 12 Aug 2026 00:23:17 +0200 Subject: [PATCH] fail closed before resumed publication side effects --- backend/src/workspaces/registry.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/workspaces/registry.ts b/backend/src/workspaces/registry.ts index f7effcff..4e2038d5 100644 --- a/backend/src/workspaces/registry.ts +++ b/backend/src/workspaces/registry.ts @@ -387,6 +387,12 @@ export class WorkspaceRegistry { } target = state.fetchedTargetCommit ?? target; if (!target) throw new WorkspaceRegistryError("registry_bootstrap_recovery_conflict", "Bootstrap recovery is ambiguous or corrupt"); + // Do not reacquire participant leases or run side effects when a restart finds a + // target-published job whose active pointer has drifted. + if (state.phase === "target_published") { + const active = await this.#tryActiveState(); + if (!active || active.head !== target || registryDigest(active) !== state.targetManifestSha256) throw new WorkspaceRegistryError("registry_bootstrap_recovery_conflict", "Active registry target drifted"); + } // Once advertised, the run-specific ref is immutable evidence. Every resume after // the fetch barrier revalidates it before reading or publishing any bytes. if (state.phase !== "target_advertised" && state.phase !== "request_claimed") {