From 792f5b7ba7702adee0cf31a0190ea1c032649234 Mon Sep 17 00:00:00 2001 From: mptyl Date: Tue, 11 Aug 2026 23:02:09 +0200 Subject: [PATCH] test: fix addressed registry step11 regressions --- backend/test/routes-workspaces.test.ts | 9 ++- ...ace-registry-addressed-publication.test.ts | 81 ++++++++++++++++++- backend/test/workspace-registry.test.ts | 5 +- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/backend/test/routes-workspaces.test.ts b/backend/test/routes-workspaces.test.ts index fa17b06e..bd5878a9 100644 --- a/backend/test/routes-workspaces.test.ts +++ b/backend/test/routes-workspaces.test.ts @@ -312,8 +312,11 @@ test("reports missing Evidence binding through the real test route without chang policy: { max_chunk_chars: 4_000, retain_published_generations: 3 }, }, }; - const read = vi.fn(async () => ({ workspace: evidenceWorkspace, revision })); - const registry = registryFake({ read }); + const readPinned = vi.fn(async () => ({ + workspace: evidenceWorkspace, + workspaceConfigPath: revision.snapshotPath, + })); + const registry = registryFake({ readPinned }); const app = appFor(registry, createProductionWorkspaceDiagnoser(100)); const variable = "THT_WS_PSD_CLINICAL_EVIDENCE_SIGNED_URLS_FILE"; const previous = process.env[variable]; @@ -330,7 +333,7 @@ test("reports missing Evidence binding through the real test route without chang field: "evidence.source.authentication", variable, })])); - expect(read).toHaveBeenCalledTimes(1); + expect(readPinned).toHaveBeenCalledTimes(1); expect(registry.publishAddressed).not.toHaveBeenCalled(); expect(revision).toMatchObject({ commit: "a".repeat(40), blob: "b".repeat(40) }); } finally { diff --git a/backend/test/workspace-registry-addressed-publication.test.ts b/backend/test/workspace-registry-addressed-publication.test.ts index ba22bd75..8f9d0e2d 100644 --- a/backend/test/workspace-registry-addressed-publication.test.ts +++ b/backend/test/workspace-registry-addressed-publication.test.ts @@ -1,2 +1,79 @@ -import {describe,expect,it} from "vitest"; import {RegistryAddressedPublicationStore,canonicalBootstrapRequestDigest} from "../src/workspaces/registry-publication.js"; import {mkdtemp} from "node:fs/promises"; import {join} from "node:path"; -describe("addressed publication",()=>{it("claims and advances a durable job",async()=>{const root=await mkdtemp(join(process.env.TMPDIR??"/tmp","thoth-pub-")); const base={kind:"bootstrap" as const,installation:{installationId:"i",digest:"a".repeat(64)},repository:{remote:"r",branch:"main",head:"",digest:"b".repeat(64)},remote:{remote:"r",head:"",digest:"c".repeat(64)},workspaceIds:[] as string[]}; const req={...base,requestDigest:canonicalBootstrapRequestDigest(base)}; const s=new RegistryAddressedPublicationStore(root); const x=await s.claim(req); expect((await s.transition(x.runId,"target_advertised")).phase).toBe("target_advertised");});}); +import { describe, expect, it } from "vitest"; +import { mkdtemp } from "node:fs/promises"; +import { join } from "node:path"; +import { + RegistryAddressedPublicationStore, + type RegistryAddressedRequestV1, +} from "../src/workspaces/registry-publication.js"; + +describe("addressed publication", () => { + it("claims a complete pull context and advances only through legal phases", async () => { + const root = await mkdtemp(join(process.env.TMPDIR ?? "/tmp", "thoth-pub-")); + const runId = "a".repeat(32); + const baseCommit = "b".repeat(40); + const targetCommit = "c".repeat(40); + const base = { + commit: baseCommit, + manifestSha256: "d".repeat(64), + workspaces: [{ + workspaceId: "workspace-a" as any, + revision: "e".repeat(40) as any, + descriptorBlob: "f".repeat(40) as any, + manifestSha256: "0".repeat(64) as any, + }], + }; + const request: RegistryAddressedRequestV1 = { + mode: "create", + operation: "registry_pull", + runId: runId as any, + requestSha256: "1".repeat(64) as any, + installationIdentitySha256: "2".repeat(64) as any, + repositoryIdentitySha256: "3".repeat(64) as any, + expectedBaseCommit: baseCommit as any, + remoteRefIdentitySha256: "4".repeat(64) as any, + }; + const store = new RegistryAddressedPublicationStore(root); + + const claimed = await store.claim(request, base); + expect(claimed).toMatchObject({ + operation: "registry_pull", + baseCommit, + baseManifestSha256: base.manifestSha256, + baseWorkspaces: base.workspaces, + phase: "request_claimed", + }); + const advertised = await store.transition(runId as any, "target_advertised", { + advertisedTargetCommit: targetCommit as any, + immutableTargetRef: `refs/thoth/addressed-runs/${runId}/target`, + }); + expect(advertised.phase).toBe("target_advertised"); + const fetched = await store.transition(runId as any, "target_fetched", { + fetchedTargetCommit: targetCommit as any, + }); + expect(fetched.phase).toBe("target_fetched"); + const planned = await store.transition(runId as any, "planned", { + targetCommit: targetCommit as any, + targetManifestSha256: "5".repeat(64) as any, + targetWorkspaces: [], + changedWorkspaceIds: ["workspace-a" as any], + changedSetSha256: "6".repeat(64) as any, + changedSetRule: "symmetric_base_target_workspace_difference", + planSha256: "7".repeat(64) as any, + }); + expect(planned.phase).toBe("planned"); + expect((await store.transition(runId as any, "participants_prepared", { + participantsSha256: "8".repeat(64) as any, + synchronizersSha256: "9".repeat(64) as any, + })).phase).toBe("participants_prepared"); + expect((await store.transition(runId as any, "publication_intent_durable", { + publicationIntentSha256: "a".repeat(64) as any, + })).phase).toBe("publication_intent_durable"); + expect((await store.transition(runId as any, "target_published", { + publishedActiveStateSha256: "b".repeat(64) as any, + })).phase).toBe("target_published"); + expect((await store.transition(runId as any, "terminal_durable", { + terminalResultSha256: "c".repeat(64) as any, + terminalPublication: "target", + })).phase).toBe("terminal_durable"); + }); +}); diff --git a/backend/test/workspace-registry.test.ts b/backend/test/workspace-registry.test.ts index a5019e8b..fb928d32 100644 --- a/backend/test/workspace-registry.test.ts +++ b/backend/test/workspace-registry.test.ts @@ -455,11 +455,10 @@ test("workspace registry exposes only the addressed lifecycle and snapshot/sessi "rootLeaseFactory", "lifecycleOwner", "participants", "synchronizers", ]); expect(Object.getOwnPropertyNames(WorkspaceRegistry.prototype)).toEqual([ - "constructor", "ensureBootstrapAddressed", "publishAddressed", "listRetainedSnapshots", - "read", "acquireSessionRevision", "readPinned", + "constructor", "ensureBootstrapAddressed", "publishAddressed", ]); const pointerNames = Object.getOwnPropertyNames(WorkspaceRegistry.prototype) - .filter((name) => !["constructor", "ensureBootstrapAddressed", "publishAddressed", "listRetainedSnapshots", "read", "acquireSessionRevision", "readPinned"].includes(name)); + .filter((name) => !["constructor", "ensureBootstrapAddressed", "publishAddressed"].includes(name)); expect(pointerNames).toEqual([]); });