Files
Jyotisha/frontend/tests/skill-registry-database.test.ts

588 lines
28 KiB
TypeScript

import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import { readFileSync } from "node:fs";
import test from "node:test";
import { startPostgresFixture } from "./helpers/postgres-fixture.ts";
const runnerPath = fileURLToPath(
new URL("../scripts/db-migrate.mjs", import.meta.url),
);
const migrationSql = readFileSync(
new URL("../supabase/migrations/20260814010000_immutable_skill_registry.sql", import.meta.url),
"utf8",
);
function dockerAvailable(): boolean {
return spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], {
encoding: "utf8",
stdio: "ignore",
}).status === 0;
}
const skipWithoutDocker = dockerAvailable() ? false : "docker unavailable on this host";
const ids = {
user: "66666666-6666-4666-8666-666666666666",
otherUser: "77777777-7777-4777-8777-777777777777",
cascadeUser: "88888888-8888-4888-8888-888888888888",
legacySession: "22222222-2222-4222-8222-222222222222",
legacyCase: "11111111-1111-4111-8111-111111111111",
legacyTurn: "33333333-3333-4333-8333-333333333333",
legacyEvidence: "55555555-5555-4555-8555-555555555555",
legacyResult: "99999999-9999-4999-8999-999999999999",
terminalSession: "22222222-2222-4222-8222-222222222223",
terminalCase: "11111111-1111-4111-8111-111111111112",
verifiedTurn: "33333333-3333-4333-8333-333333333334",
verifiedRequest: "44444444-4444-4444-8444-444444444444",
cascadeSession: "22222222-2222-4222-8222-222222222224",
cascadeCase: "11111111-1111-4111-8111-111111111113",
cascadeTurn: "33333333-3333-4333-8333-333333333335",
cascadeRequest: "44444444-4444-4444-8444-444444444445",
caseDeleteSession: "22222222-2222-4222-8222-222222222225",
caseDeleteCase: "11111111-1111-4111-8111-111111111114",
caseDeleteTurn: "33333333-3333-4333-8333-333333333336",
caseDeleteRequest: "44444444-4444-4444-8444-444444444446",
};
const oldHash = "a".repeat(64);
const newHash = "b".repeat(64);
const adoptionHash = "c".repeat(64);
const sourceCommit = "0fd111d16b45796086a6c1d0945dbd3de6755d8a";
function sqlLiteral(value: string): string {
return `'${value.replaceAll("'", "''")}'`;
}
test("immutable Skill migration enforces RPC-only identity, legacy adoption, and cascade-safe receipts", { skip: skipWithoutDocker }, () => {
const fixture = startPostgresFixture();
const migrate = () =>
spawnSync(process.execPath, [runnerPath], {
encoding: "utf8",
env: {
...process.env,
SCHEMA_DATABASE_URL: fixture.connectionUrl(
"schema_owner",
"schema-owner-test-password",
),
},
});
const serviceSql = (statement: string) =>
fixture
.psqlAs(
"service_runtime",
"service-runtime-test-password",
`set role service_role; ${statement}`,
)
.replace(/^SET\n/, "");
const expectServiceError = (statement: string, pattern: RegExp) => {
assert.throws(() => serviceSql(statement), pattern);
};
const expectOwnerError = (statement: string, pattern: RegExp) => {
assert.throws(
() => fixture.psqlAs(
"schema_owner",
"schema-owner-test-password",
statement,
),
pattern,
);
};
const insertUser = (id: string, email: string) => fixture.psqlAs(
"identity_runtime",
"identity-runtime-test-password",
`insert into identity.users (id, name, email, email_verified, email_verified_at)
values (${sqlLiteral(id)}, 'Skill Registry User', ${sqlLiteral(email)}, true, now());`,
);
const insertSession = (id: string, userId: string) => fixture.psql(`
insert into public.chat_sessions (id, user_id, title, theme, session_type, messages)
values (${sqlLiteral(id)}, ${sqlLiteral(userId)}, '生时校正', 'general',
'birth_time_rectification', '[]'::jsonb);
`);
const insertCase = (input: {
id: string;
userId: string;
sessionId: string;
status?: "draft" | "closed";
hash?: string | null;
}) => fixture.psql(`
insert into public.agentic_rectification_cases (
id, user_id, session_id, status, skill_name, skill_version,
skill_sha256, skill_source_commit, baseline_profile_fingerprint,
baseline_birth_snapshot, candidate_range, completed_at
) values (
${sqlLiteral(input.id)}, ${sqlLiteral(input.userId)}, ${sqlLiteral(input.sessionId)},
${sqlLiteral(input.status ?? "draft")}, 'jyotish-birth-time-rectification', '9.0.0',
${input.hash ? sqlLiteral(input.hash) : "null"},
${input.hash ? sqlLiteral(sourceCommit) : "null"}, ${sqlLiteral(oldHash)},
'{"birth_date":"1997-08-08"}'::jsonb,
'{"start_time":"04:50","end_time":"05:10"}'::jsonb,
${input.status === "closed" ? "now()" : "null"}
);
`);
try {
fixture.psql(`create role historical_runtime_probe noinherit;`);
fixture.psqlAs(
"schema_owner",
"schema-owner-test-password",
`create or replace function public.open_agentic_rectification_case_v2(
uuid, uuid, text, uuid, text, text, text, text, text, jsonb, jsonb
) returns jsonb language sql as $$ select '{}'::jsonb $$;
grant execute on function public.open_agentic_rectification_case_v2(
uuid, uuid, text, uuid, text, text, text, text, text, jsonb, jsonb
) to historical_runtime_probe, service_runtime;`,
);
const first = migrate();
assert.equal(first.status, 0, `${first.stdout}${first.stderr}`);
assert.match(first.stdout, /applied 20260814010000_immutable_skill_registry\.sql/);
const aclCatalog = fixture.psql(`
select string_agg(
case when has_function_privilege('historical_runtime_probe', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when has_function_privilege('service_role', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when has_function_privilege('anon', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when has_function_privilege('authenticated', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when exists (
select 1
from pg_catalog.aclexplode(p.proacl) a
join pg_catalog.pg_roles r on r.oid = a.grantee
where r.rolname = 'service_runtime' and a.privilege_type = 'EXECUTE'
) then 't' else 'f' end,
',' order by p.proname
)
from pg_catalog.pg_proc p
join pg_catalog.pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname in (
'open_agentic_rectification_case_v2',
'get_agentic_rectification_skill_identity',
'get_agentic_rectification_skill_identity_status',
'upgrade_agentic_rectification_skill_v2',
'adopt_agentic_rectification_skill_v1',
'insert_agentic_rectification_skill_run_receipt'
);
`);
assert.equal(aclCatalog, "f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f");
fixture.psql(`
grant execute on function public.open_agentic_rectification_case_v2(
uuid, uuid, text, uuid, text, text, text, text, text, jsonb, jsonb
) to historical_runtime_probe, service_runtime;
grant execute on function public.get_agentic_rectification_skill_identity(uuid, uuid)
to historical_runtime_probe, service_runtime;
grant execute on function public.get_agentic_rectification_skill_identity_status(uuid, uuid)
to historical_runtime_probe, service_runtime;
grant execute on function public.upgrade_agentic_rectification_skill_v2(
uuid, uuid, text, text, text, text
) to historical_runtime_probe, service_runtime;
grant execute on function public.adopt_agentic_rectification_skill_v1(
uuid, uuid, text, text, text, text
) to historical_runtime_probe, service_runtime;
grant execute on function public.insert_agentic_rectification_skill_run_receipt(
uuid, uuid, uuid, uuid, text, text, text, text, text
) to historical_runtime_probe, service_runtime;
`);
fixture.psqlAs(
"schema_owner",
"schema-owner-test-password",
migrationSql,
);
assert.equal(
fixture.psql(`
select string_agg(
case when has_function_privilege('historical_runtime_probe', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when has_function_privilege('service_role', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when exists (
select 1
from pg_catalog.aclexplode(p.proacl) a
join pg_catalog.pg_roles r on r.oid = a.grantee
where r.rolname = 'service_runtime' and a.privilege_type = 'EXECUTE'
) then 't' else 'f' end || ':' ||
case when has_function_privilege('anon', p.oid, 'EXECUTE') then 't' else 'f' end || ':' ||
case when has_function_privilege('authenticated', p.oid, 'EXECUTE') then 't' else 'f' end,
',' order by p.proname
)
from pg_catalog.pg_proc p
join pg_catalog.pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname in (
'open_agentic_rectification_case_v2',
'get_agentic_rectification_skill_identity',
'get_agentic_rectification_skill_identity_status',
'upgrade_agentic_rectification_skill_v2',
'adopt_agentic_rectification_skill_v1',
'insert_agentic_rectification_skill_run_receipt'
);
`),
"f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f,f:t:f:f:f",
);
assert.equal(
fixture.psql("select pg_has_role('service_runtime', 'service_role', 'MEMBER');"),
"t",
);
assert.equal(
serviceSql(`
select string_agg(
case when has_function_privilege(current_user, p.oid, 'EXECUTE') then 't' else 'f' end,
',' order by p.proname
)
from pg_catalog.pg_proc p
join pg_catalog.pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname in (
'open_agentic_rectification_case_v2',
'get_agentic_rectification_skill_identity',
'get_agentic_rectification_skill_identity_status',
'upgrade_agentic_rectification_skill_v2',
'adopt_agentic_rectification_skill_v1',
'insert_agentic_rectification_skill_run_receipt'
);
`),
"t,t,t,t,t,t",
);
const second = migrate();
assert.equal(second.status, 0, `${second.stdout}${second.stderr}`);
assert.match(second.stdout, /already applied 20260814010000_immutable_skill_registry\.sql/);
assert.equal(
fixture.psql(`
select concat_ws(':',
has_table_privilege('service_role', 'public.agentic_rectification_cases', 'SELECT'),
has_table_privilege('service_role', 'public.agentic_rectification_cases', 'INSERT'),
has_table_privilege('service_role', 'public.agentic_rectification_cases', 'UPDATE'),
has_table_privilege('service_role', 'public.agentic_rectification_cases', 'DELETE'),
has_table_privilege('service_role', 'public.agentic_rectification_cases', 'TRUNCATE'),
has_table_privilege('service_role', 'public.agentic_rectification_skill_upgrade_receipts', 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE'),
has_table_privilege('service_role', 'public.agentic_rectification_skill_run_receipts', 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE')
)
`),
"f:f:f:f:f:f:f",
);
const catalog = fixture.psql(`
select p.proname || ':' || pg_catalog.pg_get_userbyid(p.proowner) || ':' ||
p.prosecdef || ':' || coalesce(array_to_string(p.proconfig, ','), '') || ':' ||
has_function_privilege('service_role', p.oid, 'EXECUTE') || ':' ||
has_function_privilege('anon', p.oid, 'EXECUTE') || ':' ||
has_function_privilege('authenticated', p.oid, 'EXECUTE')
from pg_catalog.pg_proc p
join pg_catalog.pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname in (
'open_agentic_rectification_case_v2',
'get_agentic_rectification_skill_identity',
'get_agentic_rectification_skill_identity_status',
'upgrade_agentic_rectification_skill_v2',
'adopt_agentic_rectification_skill_v1',
'insert_agentic_rectification_skill_run_receipt'
)
order by p.proname;
`);
for (const line of catalog.split("\n")) {
assert.match(line, /^[^:]+:schema_owner:true:search_path="":true:f:f$/);
}
assert.equal(catalog.split("\n").length, 6);
assert.equal(
fixture.psql(`
select string_agg(c.relname || ':' || pg_catalog.pg_get_userbyid(c.relowner), ',' order by c.relname)
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relname in (
'agentic_rectification_cases',
'agentic_rectification_skill_upgrade_receipts',
'agentic_rectification_skill_run_receipts'
);
`),
"agentic_rectification_cases:schema_owner,agentic_rectification_skill_run_receipts:schema_owner,agentic_rectification_skill_upgrade_receipts:schema_owner",
);
insertUser(ids.user, "skill-registry@example.com");
insertUser(ids.otherUser, "skill-registry-other@example.com");
insertUser(ids.cascadeUser, "skill-registry-cascade@example.com");
const openedCaseId = serviceSql(`
select public.open_agentic_rectification_case_v2(
${sqlLiteral(ids.user)}::uuid, gen_random_uuid(), 'homepage', null,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(oldHash)},
${sqlLiteral(sourceCommit)}, ${sqlLiteral(oldHash)},
'{"birth_date":"1997-08-08","latitude":25.04,"longitude":121.56,"timezone_offset":8,"birth_time_source":"family_exact"}'::jsonb,
'{"start_time":"04:50","end_time":"05:10"}'::jsonb
)->>'case_id';
`);
assert.match(openedCaseId, /^[0-9a-f-]{36}$/);
assert.equal(
fixture.psql(`select skill_version || ':' || skill_sha256 from public.agentic_rectification_cases where id = ${sqlLiteral(openedCaseId)}`),
`9.0.0:${oldHash}`,
);
expectServiceError(
`insert into public.agentic_rectification_cases (
user_id, session_id, status, skill_name, skill_version,
baseline_profile_fingerprint, baseline_birth_snapshot, candidate_range
) values (${sqlLiteral(ids.user)}, gen_random_uuid(), 'draft',
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(oldHash)}, '{}'::jsonb, '{}'::jsonb);`,
/permission denied for table agentic_rectification_cases/,
);
expectServiceError(
`update public.agentic_rectification_cases set skill_sha256 = ${sqlLiteral(newHash)} where id = ${sqlLiteral(openedCaseId)};`,
/permission denied for table agentic_rectification_cases/,
);
fixture.psql(`
insert into public.agentic_rectification_turns (id, case_id, user_message, status, model_name)
values (${sqlLiteral(ids.verifiedTurn)}, ${sqlLiteral(openedCaseId)}, 'verified run', 'pending', 'fixture-model');
`);
assert.equal(
serviceSql(`select public.insert_agentic_rectification_skill_run_receipt(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(openedCaseId)}::uuid,
${sqlLiteral(ids.verifiedTurn)}::uuid, ${sqlLiteral(ids.verifiedRequest)}::uuid,
'turn', 'jyotish-birth-time-rectification', '9.0.0',
${sqlLiteral(oldHash)}, ${sqlLiteral(sourceCommit)}
)->>'skill_sha256';`),
oldHash,
);
assert.equal(
serviceSql(`select public.upgrade_agentic_rectification_skill_v2(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(openedCaseId)}::uuid,
'jyotish-birth-time-rectification', '9.1.0', ${sqlLiteral(newHash)}, null
)->>'skill_sha256';`),
newHash,
);
assert.equal(
fixture.psql(`select previous_identity_status || ':' || upgrade_kind || ':' || previous_skill_sha256 || ':' || skill_sha256
from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(openedCaseId)}`),
`verified:version_upgrade:${oldHash}:${newHash}`,
);
assert.equal(
serviceSql(`select public.insert_agentic_rectification_skill_run_receipt(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(openedCaseId)}::uuid,
${sqlLiteral(ids.verifiedTurn)}::uuid, gen_random_uuid()::uuid,
'regeneration', 'jyotish-birth-time-rectification', '9.1.0',
${sqlLiteral(newHash)}, null
)->>'run_kind';`),
'regeneration',
);
assert.equal(
fixture.psql(`select count(*) from public.agentic_rectification_skill_run_receipts where turn_id = ${sqlLiteral(ids.verifiedTurn)}`),
'2',
);
expectServiceError(
`select public.adopt_agentic_rectification_skill_v1(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(openedCaseId)}::uuid,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`,
/agentic_rectification_skill_identity_already_verified/,
);
insertSession(ids.legacySession, ids.user);
insertCase({ id: ids.legacyCase, userId: ids.user, sessionId: ids.legacySession, hash: null });
fixture.psql(`
insert into public.agentic_rectification_turns (id, case_id, user_message, status, model_name)
values (${sqlLiteral(ids.legacyTurn)}, ${sqlLiteral(ids.legacyCase)}, 'legacy evidence', 'pending', 'fixture-model');
insert into public.agentic_rectification_evidence (
id, case_id, source_turn_id, user_quote, subject, event_kind, domain, date_precision, summary
) values (
${sqlLiteral(ids.legacyEvidence)}, ${sqlLiteral(ids.legacyCase)}, ${sqlLiteral(ids.legacyTurn)},
'legacy evidence', 'self', 'career_entry', 'career', 'year', 'legacy evidence summary'
);
insert into public.agentic_rectification_results (
id, user_id, session_id, engine_result_id, canonical_input_hash, algorithm_version,
candidate_range, candidates, overall_confidence, selection_allowed, confirmation_allowed,
baseline_birth_date, baseline_latitude, baseline_longitude, baseline_timezone_offset,
case_id, skill_version
) values (
${sqlLiteral(ids.legacyResult)}, ${sqlLiteral(ids.user)}, ${sqlLiteral(ids.legacySession)},
'legacy-engine-result', ${sqlLiteral(oldHash)}, 'legacy-algorithm',
'{"start_time":"04:50","end_time":"05:10"}'::jsonb, '[]'::jsonb,
'low', false, false, '1997-08-08', 25.04, 121.56, 8,
${sqlLiteral(ids.legacyCase)}, '9.0.0'
);
`);
assert.equal(
serviceSql(`select
(public.get_agentic_rectification_skill_identity_status(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid
)->>'skill_identity_status') || ':' ||
(public.get_agentic_rectification_skill_identity_status(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid
)->>'requires_skill_adoption');`),
"legacy_unverifiable:true",
);
expectServiceError(
`select public.get_agentic_rectification_skill_identity(${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid);`,
/agentic_rectification_legacy_skill_identity_unverifiable/,
);
expectServiceError(
`select public.insert_agentic_rectification_skill_run_receipt(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid,
${sqlLiteral(ids.legacyTurn)}::uuid, gen_random_uuid(), 'turn',
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`,
/agentic_rectification_skill_identity_mismatch/,
);
expectServiceError(
`select public.adopt_agentic_rectification_skill_v1(
${sqlLiteral(ids.otherUser)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`,
/agentic_rectification_case_not_found/,
);
insertSession(ids.terminalSession, ids.user);
insertCase({ id: ids.terminalCase, userId: ids.user, sessionId: ids.terminalSession, status: "closed", hash: null });
assert.equal(
serviceSql(`select
(public.get_agentic_rectification_skill_identity_status(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.terminalCase)}::uuid
)->>'skill_identity_status') || ':' ||
(public.get_agentic_rectification_skill_identity_status(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.terminalCase)}::uuid
)->>'requires_skill_adoption');`),
"legacy_unverifiable:false",
);
expectServiceError(
`select public.adopt_agentic_rectification_skill_v1(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.terminalCase)}::uuid,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`,
/agentic_rectification_case_terminal/,
);
const adopted = serviceSql(`select public.adopt_agentic_rectification_skill_v1(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`);
assert.equal(JSON.parse(adopted).idempotent, false);
const replayed = serviceSql(`select public.adopt_agentic_rectification_skill_v1(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.legacyCase)}::uuid,
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)}, ${sqlLiteral(sourceCommit)}
);`);
assert.equal(JSON.parse(replayed).idempotent, true);
assert.equal(
fixture.psql(`select coalesce(previous_skill_sha256, 'NULL') || ':' || previous_identity_status || ':' || upgrade_kind || ':' || skill_sha256
from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(ids.legacyCase)}`),
`NULL:legacy_unverifiable:legacy_adoption:${adoptionHash}`,
);
assert.equal(
fixture.psql(`select count(*) from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(ids.legacyCase)}`),
"1",
);
assert.equal(
fixture.psql(`select concat_ws(':',
(select count(*) from public.agentic_rectification_turns where case_id = ${sqlLiteral(ids.legacyCase)}),
(select count(*) from public.agentic_rectification_evidence where case_id = ${sqlLiteral(ids.legacyCase)}),
(select count(*) from public.agentic_rectification_results where case_id = ${sqlLiteral(ids.legacyCase)})
)`),
"1:1:1",
);
expectServiceError(
`insert into public.agentic_rectification_skill_upgrade_receipts (
case_id, user_id, previous_skill_name, previous_skill_version,
previous_identity_status, upgrade_kind, skill_name, skill_version, skill_sha256
) values (${sqlLiteral(ids.legacyCase)}, ${sqlLiteral(ids.user)},
'jyotish-birth-time-rectification', '9.0.0', 'legacy_unverifiable', 'legacy_adoption',
'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(adoptionHash)});`,
/permission denied for table agentic_rectification_skill_upgrade_receipts/,
);
expectOwnerError(
`update public.agentic_rectification_skill_upgrade_receipts set skill_sha256 = ${sqlLiteral(oldHash)} where case_id = ${sqlLiteral(ids.legacyCase)};`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`delete from public.agentic_rectification_skill_run_receipts where case_id = ${sqlLiteral(openedCaseId)};`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`delete from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(openedCaseId)};`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`truncate table public.agentic_rectification_skill_upgrade_receipts;`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`truncate table public.agentic_rectification_skill_run_receipts;`,
/agentic_rectification_skill_receipts_are_append_only/,
);
expectOwnerError(
`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({
id: ids.caseDeleteCase,
userId: ids.user,
sessionId: ids.caseDeleteSession,
hash: oldHash,
});
fixture.psql(`insert into public.agentic_rectification_turns (id, case_id, user_message, status, model_name)
values (${sqlLiteral(ids.caseDeleteTurn)}, ${sqlLiteral(ids.caseDeleteCase)}, 'case cascade user', 'pending', 'fixture-model');`);
serviceSql(`select public.insert_agentic_rectification_skill_run_receipt(
${sqlLiteral(ids.user)}::uuid, ${sqlLiteral(ids.caseDeleteCase)}::uuid,
${sqlLiteral(ids.caseDeleteTurn)}::uuid, ${sqlLiteral(ids.caseDeleteRequest)}::uuid,
'turn', 'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(oldHash)}, ${sqlLiteral(sourceCommit)}
);`);
fixture.psql(`delete from public.agentic_rectification_cases where id = ${sqlLiteral(ids.caseDeleteCase)};`);
assert.equal(
fixture.psql(`select concat_ws(':',
(select count(*) from public.agentic_rectification_cases where id = ${sqlLiteral(ids.caseDeleteCase)}),
(select count(*) from public.agentic_rectification_turns where id = ${sqlLiteral(ids.caseDeleteTurn)}),
(select count(*) from public.agentic_rectification_skill_run_receipts where case_id = ${sqlLiteral(ids.caseDeleteCase)})
)`),
'0:0:0',
);
fixture.psql(`delete from public.agentic_rectification_turns where id = ${sqlLiteral(ids.verifiedTurn)};`);
assert.equal(
fixture.psql(`select count(*) from public.agentic_rectification_skill_run_receipts where turn_id = ${sqlLiteral(ids.verifiedTurn)}`),
"0",
);
assert.equal(
fixture.psql(`select count(*) from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(openedCaseId)}`),
"1",
);
fixture.psql(`delete from public.agentic_rectification_cases where id = ${sqlLiteral(openedCaseId)};`);
assert.equal(
fixture.psql(`select count(*) from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(openedCaseId)}`),
"0",
);
insertSession(ids.cascadeSession, ids.cascadeUser);
insertCase({ id: ids.cascadeCase, userId: ids.cascadeUser, sessionId: ids.cascadeSession, hash: oldHash });
fixture.psql(`insert into public.agentic_rectification_turns (id, case_id, user_message, status, model_name)
values (${sqlLiteral(ids.cascadeTurn)}, ${sqlLiteral(ids.cascadeCase)}, 'cascade user', 'pending', 'fixture-model');`);
serviceSql(`select public.insert_agentic_rectification_skill_run_receipt(
${sqlLiteral(ids.cascadeUser)}::uuid, ${sqlLiteral(ids.cascadeCase)}::uuid,
${sqlLiteral(ids.cascadeTurn)}::uuid, ${sqlLiteral(ids.cascadeRequest)}::uuid,
'turn', 'jyotish-birth-time-rectification', '9.0.0', ${sqlLiteral(oldHash)}, ${sqlLiteral(sourceCommit)}
);`);
serviceSql(`select public.upgrade_agentic_rectification_skill_v2(
${sqlLiteral(ids.cascadeUser)}::uuid, ${sqlLiteral(ids.cascadeCase)}::uuid,
'jyotish-birth-time-rectification', '9.1.0', ${sqlLiteral(newHash)}, null
);`);
fixture.psqlAs(
"identity_runtime",
"identity-runtime-test-password",
`delete from identity.users where id = ${sqlLiteral(ids.cascadeUser)};`,
);
assert.equal(
fixture.psql(`select concat_ws(':',
(select count(*) from public.agentic_rectification_cases where id = ${sqlLiteral(ids.cascadeCase)}),
(select count(*) from public.agentic_rectification_skill_run_receipts where case_id = ${sqlLiteral(ids.cascadeCase)}),
(select count(*) from public.agentic_rectification_skill_upgrade_receipts where case_id = ${sqlLiteral(ids.cascadeCase)})
)`),
"0:0:0",
);
} finally {
fixture.stop();
}
});