diff --git a/tests/control_plane_ts/authority_source.test.ts b/tests/control_plane_ts/authority_source.test.ts index eeb891d2cc..1a19f6f908 100644 --- a/tests/control_plane_ts/authority_source.test.ts +++ b/tests/control_plane_ts/authority_source.test.ts @@ -8,6 +8,7 @@ import {registryAuthoritySourceCheck} from "../../loopx/control_plane/coordinati import { claimLocalCoordinationTodo, createLocalCoordinationTodo, updateLocalCoordinationTodo, terminalLifecycleLocalCoordinationTodo, pollLocalCoordinationMonitor, + LOCAL_COORDINATION_TODO_TERMINAL_LIFECYCLE_REQUEST_SCHEMA, } from "../../loopx/control_plane/coordination/local_authority_runtime.ts"; test("registry witness captures primitive values across awaited request mutation", async t => { @@ -30,7 +31,6 @@ test("registry witness captures primitive values across awaited request mutation const wires = [ {invoke: createLocalCoordinationTodo, prefix: "loopx_local_coordination_todo_create_request", legacy: [0], current: 1}, {invoke: claimLocalCoordinationTodo, prefix: "loopx_local_coordination_todo_claim_request", legacy: [0], current: 1}, - {invoke: terminalLifecycleLocalCoordinationTodo, prefix: "loopx_local_coordination_todo_terminal_lifecycle_request", legacy: [0], current: 1}, {invoke: updateLocalCoordinationTodo, prefix: "loopx_local_coordination_todo_update_request", legacy: [0, 1], current: 2}, {invoke: pollLocalCoordinationMonitor, prefix: "loopx_coordination_monitor_poll_request", legacy: [0, 1], current: 2}, ]; @@ -47,3 +47,24 @@ for (const wire of wires) test(`${wire.prefix}: source obligation cannot silentl assert.match(String(result.reason), /registry_source/u); } }); + +test("terminal lifecycle v3 rejects old wires and requires a registry witness", async () => { + const prefix = "loopx_local_coordination_todo_terminal_lifecycle_request"; + for (const version of [0, 1, 2]) { + const result = await terminalLifecycleLocalCoordinationTodo({ + schema_version: `${prefix}_v${version}`, registry_source: null, + }); + assert.equal(result.status, "failed"); + assert.match(String(result.reason), /schema mismatch/u); + } + for (const source of [undefined, {}, {path: "relative", sha256: "0".repeat(64)}, + {path: "/unused", sha256: "invalid"}]) { + const result = await terminalLifecycleLocalCoordinationTodo({ + schema_version: LOCAL_COORDINATION_TODO_TERMINAL_LIFECYCLE_REQUEST_SCHEMA, + command: "complete", operation_identity: {kind: "explicit", operation_id: "source-wire"}, + registry_source: source, + }); + assert.equal(result.status, "failed"); + assert.match(String(result.reason), /registry_source/u); + } +});