test(skill): enforce schema owner and receipt immutability

This commit is contained in:
Jesse_Chen
2026-08-14 16:52:35 +08:00
parent 5b8b8ac2d4
commit afc8af5b8e
3 changed files with 25 additions and 1 deletions
@@ -3,6 +3,15 @@
-- New Agentic cases bind full identity through the v2 RPC; new Personal Reports
-- bind it through the server-owned persistence service.
do $migration$
begin
if current_user <> 'schema_owner' then
raise exception 'immutable_skill_registry_requires_schema_owner'
using errcode = '42501';
end if;
end
$migration$;
alter table public.agentic_rectification_cases
add column if not exists skill_sha256 text
check (skill_sha256 is null or skill_sha256 ~ '^[0-9a-f]{64}$'),
@@ -492,7 +492,7 @@ test("immutable Skill migration enforces RPC-only identity, legacy adoption, and
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`delete from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(ids.legacyCase)};`,
`delete from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(openedCaseId)};`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
@@ -507,6 +507,14 @@ test("immutable Skill migration enforces RPC-only identity, legacy adoption, and
`truncate table public.agentic_rectification_cases cascade;`,
/agentic_rectification_skill_receipts_are_append_only/,
);
assert.equal(
fixture.psql(`select concat_ws(':',
(select count(*) from public.agentic_rectification_cases where id = ${sqlLiteral(ids.legacyCase)}),
(select count(*) from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(ids.legacyCase)}),
(select count(*) from public.agentic_rectification_skill_run_receipts where case_id = ${sqlLiteral(openedCaseId)})
)`),
'1:1:2',
);
insertSession(ids.caseDeleteSession, ids.user);
insertCase({
@@ -68,6 +68,13 @@ test("run receipt schema repair is safe on repeated execution", () => {
assert.match(migration, /create unique index agentic_rectification_skill_run_receipts_request_idx/);
});
test("immutable Skill migration is restricted to schema_owner", () => {
assert.match(
migration,
/if current_user <> 'schema_owner' then[\s\S]*immutable_skill_registry_requires_schema_owner/,
);
});
test("migration transaction is owned by the migration runner", () => {
assert.doesNotMatch(migration, /^\s*begin\s*;/im);
assert.doesNotMatch(migration, /^\s*commit\s*;/im);