fix: route workspace CRUD through addressed publication
This commit is contained in:
@@ -116,7 +116,7 @@ const revision: WorkspaceRevision = {
|
||||
snapshotPath: "/registry/snapshots/psd-clinical.yaml",
|
||||
};
|
||||
|
||||
type RegistryFake = Pick<WorkspaceRegistry, "bootstrap" | "pull" | "list" | "read" | "publish"> & { ensureBootstrapAddressed: ReturnType<typeof vi.fn>; publishAddressed: ReturnType<typeof vi.fn> };
|
||||
type RegistryFake = Pick<WorkspaceRegistry, "read" | "recoveryIdentity"> & { ensureBootstrapAddressed: ReturnType<typeof vi.fn>; publishAddressed: ReturnType<typeof vi.fn>; snapshotPath: ReturnType<typeof vi.fn> };
|
||||
|
||||
function registryFake(overrides: Partial<RegistryFake> = {}): RegistryFake {
|
||||
return {
|
||||
@@ -128,9 +128,10 @@ function registryFake(overrides: Partial<RegistryFake> = {}): RegistryFake {
|
||||
})),
|
||||
list: vi.fn(async () => [revision]),
|
||||
read: vi.fn(async () => ({ workspace, revision })),
|
||||
publish: vi.fn(async () => revision),
|
||||
recoveryIdentity: vi.fn(() => ({ operation: "registry_bootstrap", requestSha256: "c".repeat(64), installationIdentitySha256: "d".repeat(64), repositoryIdentitySha256: "e".repeat(64), remoteRefIdentitySha256: "f".repeat(64) })),
|
||||
ensureBootstrapAddressed: vi.fn(async () => ({ kind: "already_active", snapshot: { schemaVersion: 1, commit: revision.commit, manifestSha256: "a".repeat(64), workspaces: [{ workspaceId: revision.id, revision: revision.commit, descriptorBlob: revision.blob, manifestSha256: "b".repeat(64) }] } })),
|
||||
publishAddressed: vi.fn(async () => ({ plan: { targetCommit: revision.commit, targetManifestSha256: "a".repeat(64), targetWorkspaces: [{ workspaceId: revision.id, revision: revision.commit, descriptorBlob: revision.blob, manifestSha256: "b".repeat(64) }] } })),
|
||||
snapshotPath: vi.fn(() => revision.snapshotPath),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
@@ -278,7 +279,7 @@ test.each([
|
||||
});
|
||||
expect(response.body).not.toMatch(/migration_required|schema version/i);
|
||||
}
|
||||
expect(registry.publish).not.toHaveBeenCalled();
|
||||
expect(registry.publishAddressed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("runs diagnostics for a schema v3 workspace without external semantic bindings", async () => {
|
||||
@@ -332,7 +333,7 @@ test("reports missing Evidence binding through the real test route without chang
|
||||
variable,
|
||||
})]));
|
||||
expect(read).toHaveBeenCalledTimes(1);
|
||||
expect(registry.publish).not.toHaveBeenCalled();
|
||||
expect(registry.publishAddressed).not.toHaveBeenCalled();
|
||||
expect(revision).toMatchObject({ commit: "a".repeat(40), blob: "b".repeat(40) });
|
||||
} finally {
|
||||
if (previous === undefined) delete process.env[variable];
|
||||
@@ -352,7 +353,7 @@ test("returns a 409 field conflict instead of overwriting a changed workspace",
|
||||
remote: { ...workspace, workspace: { ...workspace.workspace, description: "Remote description" } },
|
||||
},
|
||||
);
|
||||
const registry = registryFake({ publish: vi.fn(async () => { throw conflict; }) });
|
||||
const registry = registryFake({ publishAddressed: vi.fn(async () => { throw conflict; }) });
|
||||
const app = appFor(registry);
|
||||
const staleUpdate = {
|
||||
action: "update",
|
||||
@@ -378,7 +379,7 @@ test("returns a 409 field conflict instead of overwriting a changed workspace",
|
||||
|
||||
test("maps a stale registry commit to HTTP 409 without conflict payloads", async () => {
|
||||
const registry = registryFake({
|
||||
publish: vi.fn(async () => {
|
||||
publishAddressed: vi.fn(async () => {
|
||||
throw new WorkspaceRegistryError("workspace_stale", "Workspace revision is stale");
|
||||
}),
|
||||
});
|
||||
@@ -395,6 +396,18 @@ test("maps a stale registry commit to HTTP 409 without conflict payloads", async
|
||||
expect(res.json()).toEqual({ code: "workspace_stale", message: "Workspace revision is stale." });
|
||||
});
|
||||
|
||||
test("publishes accepted CRUD through the addressed request and returns its terminal revision", async () => {
|
||||
const publishAddressed = vi.fn(async (request: any) => ({
|
||||
plan: { targetCommit: revision.commit, targetManifestSha256: "a".repeat(64), targetWorkspaces: [{ workspaceId: request.mutation.workspace.workspace.id, revision: revision.commit, descriptorBlob: revision.blob, manifestSha256: "b".repeat(64) }] },
|
||||
}));
|
||||
const registry = registryFake({ publishAddressed });
|
||||
const app = appFor(registry);
|
||||
const response = await app.inject({ method: "POST", url: "/workspaces/publish", payload: { action: "create", workspace, baseCommit: revision.commit } });
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json()).toEqual({ revision: { id: workspace.workspace.id, commit: revision.commit, blob: revision.blob, snapshotPath: revision.snapshotPath } });
|
||||
expect(publishAddressed).toHaveBeenCalledWith(expect.objectContaining({ mode: "create", operation: "registry_pull", mutation: expect.objectContaining({ action: "create", baseCommit: revision.commit }) }));
|
||||
});
|
||||
|
||||
test("exports generated public artifacts without secret values", async () => {
|
||||
const app = appFor(registryFake());
|
||||
|
||||
@@ -415,7 +428,7 @@ test("rejects a zip-slip import without publishing or writing a checkout file",
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.json()).toMatchObject({ code: "workspace_invalid" });
|
||||
expect(registry.publish).not.toHaveBeenCalled();
|
||||
expect(registry.publishAddressed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("imports an exact generated bundle only as a browser draft", async () => {
|
||||
@@ -426,7 +439,7 @@ test("imports an exact generated bundle only as a browser draft", async () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.json()).toMatchObject({ draft: { workspace } });
|
||||
expect(registry.publish).not.toHaveBeenCalled();
|
||||
expect(registry.publishAddressed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user