fix(rectification): enforce trusted result identity and preserve receipt provenance
Unify minute and block cache identity, keep unverifiable historical results read-only across server tools and write entrypoints, and aggregate completed receipt sources chronologically through a compatible function migration. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,52 @@ test("block_scan RPCs are service_role-only and advance a declared period", { sk
|
||||
assert.equal(opened.error, null, rpcError(opened.error));
|
||||
const caseId = String((opened.data as Record<string, unknown>).case_id);
|
||||
|
||||
// BUG-984: identities belong to completed results, never deployment/start rows.
|
||||
// All rows are synthetic; the timestamp/id order, not the version text, wins.
|
||||
const turnId = fixture.psql(`
|
||||
insert into public.agentic_rectification_turns (case_id, status, model_name, assistant_message)
|
||||
values ('${caseId}', 'completed', 'fixture', 'fixture') returning id;
|
||||
`).split("\n")[0];
|
||||
const receipt = async (owner = userId, turn = turnId) => service.rpc("get_agentic_rectification_turn_receipt", {
|
||||
p_user_id: owner, p_case_id: caseId, p_turn_id: turn,
|
||||
});
|
||||
const addReceipt = (id: string, status: string, version: string | null, second: number, attempt: string | null = null, tool = "rectification-compare-candidates") => fixture.psql(`
|
||||
insert into public.agentic_rectification_tool_receipts
|
||||
(id, case_id, turn_id, tool_name, public_phase, status, engine_version, started_at, attempt_id)
|
||||
values ('${id}', '${caseId}', '${turnId}', '${tool}', 'candidates.updated', '${status}',
|
||||
${version ? `'${version}'` : "null"}, '2026-09-20 00:00:${String(second).padStart(2, "0")}+00',
|
||||
${attempt ? `'${attempt}'` : "null"});
|
||||
`);
|
||||
const version = (n: number) => `rectification-v5-matrix-scoring-${n}`;
|
||||
addReceipt("10000000-0000-4000-8000-000000000001", "started", version(8), 1);
|
||||
addReceipt("10000000-0000-4000-8000-000000000002", "completed", version(7), 2);
|
||||
assert.equal((await receipt()).data?.engine_version, version(7));
|
||||
addReceipt("10000000-0000-4000-8000-000000000003", "completed", version(9), 3);
|
||||
addReceipt("10000000-0000-4000-8000-000000000004", "completed", version(10), 4, null, "rectification-read-diagnostics");
|
||||
addReceipt("10000000-0000-4000-8000-000000000005", "failed", version(99), 5);
|
||||
assert.equal((await receipt()).data?.engine_version, version(10));
|
||||
// Same timestamp: stable id tie-break, independent of insertion/lexical version order.
|
||||
addReceipt("10000000-0000-4000-8000-000000000006", "completed", version(11), 4);
|
||||
assert.equal((await receipt()).data?.engine_version, version(11));
|
||||
const attempt1 = fixture.psql(`
|
||||
insert into public.agentic_rectification_run_attempts (case_id, turn_id, attempt_number, status, completed_at)
|
||||
values ('${caseId}', '${turnId}', 1, 'completed', now()) returning id;
|
||||
`).split("\n")[0];
|
||||
addReceipt("10000000-0000-4000-8000-000000000007", "completed", version(10), 6, attempt1);
|
||||
fixture.psql(`update public.agentic_rectification_turns set successful_attempt_id = '${attempt1}' where id = '${turnId}'`);
|
||||
const attempt2 = fixture.psql(`
|
||||
insert into public.agentic_rectification_run_attempts (case_id, turn_id, attempt_number, status, completed_at)
|
||||
values ('${caseId}', '${turnId}', 2, 'failed', now()) returning id;
|
||||
`).split("\n")[0];
|
||||
addReceipt("10000000-0000-4000-8000-000000000008", "failed", version(99), 7, attempt2);
|
||||
assert.equal((await receipt()).data?.engine_version, version(10), "failed retry cannot replace successful attempt");
|
||||
fixture.psql(`update public.agentic_rectification_turns set successful_attempt_id = null where id = '${turnId}'`);
|
||||
assert.equal((await receipt()).data?.engine_version, null, "latest failed-only attempt has no result provenance");
|
||||
assert.match(rpcError((await receipt("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")).error), /case_not_found/);
|
||||
assert.match(rpcError((await receipt(userId, "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")).error), /turn_not_found/);
|
||||
assert.equal(fixture.psql(`select engine_version from public.agentic_rectification_tool_receipts where id = '10000000-0000-4000-8000-000000000002'`), version(7), "historical rows are not relabelled");
|
||||
assert.equal(fixture.psql(`select has_function_privilege('authenticated', 'public.get_agentic_rectification_turn_receipt(uuid,uuid,uuid)', 'EXECUTE')`), "f");
|
||||
|
||||
const staged = await service.rpc("set_agentic_rectification_case_stage", {
|
||||
p_user_id: userId,
|
||||
p_case_id: caseId,
|
||||
|
||||
Reference in New Issue
Block a user