// Service role can resume an in-progress case only through the case RPC. // A direct select of agentic_rectification_cases is revoked. Fictional ids only. import assert from "node:assert/strict"; import { randomUUID } from "node:crypto"; import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; import test from "node:test"; import { closeLocalPostgresDataPool, createLocalPostgresDataClient } from "../src/lib/db/local-postgres-client-core.ts"; import { loadResumableRectificationSessionId } from "../src/lib/rectification-resume-session.ts"; import { startPostgresFixture } from "./helpers/postgres-fixture.ts"; const docker = spawnSync("docker", ["version"], { stdio: "ignore" }).status === 0; const runner = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url)); test("service role loads an in-progress rectification session through the case RPC", { skip: !docker && "docker unavailable" }, async () => { const fixture = startPostgresFixture(); const url = fixture.connectionUrl("service_runtime", "service-runtime-test-password"); const userId = randomUUID(); const sessionId = randomUUID(); const caseId = randomUUID(); const snapshot = { birth_date: "2000-06-15", reported_birth_time: "00:10", active_birth_time: null, birth_time_source: "family_exact", birth_time_period: null, uncertainty_before_minutes: 15, uncertainty_after_minutes: 15, latitude: 40, longitude: -74, timezone_id: "America/New_York", timezone_offset: -4, }; const range = { start_time: "23:55", end_time: "00:25", candidate_intervals: [{ start_at: "2000-06-14T23:55", end_at: "2000-06-15T00:25" }], }; try { const migration = spawnSync(process.execPath, [runner], { encoding: "utf8", env: { ...process.env, SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password"), }, }); assert.equal(migration.status, 0, `${migration.stdout}\n${migration.stderr}`); fixture.psqlAs("identity_runtime", "identity-runtime-test-password", ` insert into identity.users(id,name,email,email_verified) values ('${userId}','Synthetic Resume Fixture','${userId}@example.invalid',true); `); fixture.psql(` update public.profiles set birth_date='2000-06-15',reported_birth_time='00:10',birth_time_source='family_exact', birth_time_status='reported',uncertainty_before_minutes=15,uncertainty_after_minutes=15, latitude=40,longitude=-74,timezone_id='America/New_York',timezone_offset=-4 where id='${userId}'; insert into public.chat_sessions(id,user_id,title,theme,session_type,messages) values('${sessionId}','${userId}','Synthetic resume','general','birth_time_rectification','[]'); insert into public.agentic_rectification_cases(id,user_id,session_id,status,skill_name,skill_version, baseline_profile_fingerprint,baseline_birth_snapshot,candidate_range) values('${caseId}','${userId}','${sessionId}','collecting_evidence','jyotish-birth-time-rectification','9.0.0', '${"a".repeat(64)}','${JSON.stringify(snapshot)}','${JSON.stringify(range)}'); `); const service = createLocalPostgresDataClient(url, null, "service_role"); const direct = await service .from("agentic_rectification_cases") .select("session_id") .eq("id", caseId) .maybeSingle(); assert.ok(direct.error, "a direct table read stays revoked for service_role"); assert.match(String(direct.error?.message ?? ""), /permission denied/); assert.equal(await loadResumableRectificationSessionId(service, userId), sessionId); } finally { await closeLocalPostgresDataPool(url); fixture.stop(); } });