An accepted rectification no longer counts as in progress at the chat entry, so an explicit request starts a new case and the offer card can return. An unfinished case still resumes through the case RPC. A failed lookup is logged without personal data and opens a new case. Self-test: tsc 0, lint 0 errors, 47 targeted tests, test:db failures match the Windows list, next build with / static. Co-Authored-By: Grok (agent loop)
78 lines
3.7 KiB
TypeScript
78 lines
3.7 KiB
TypeScript
// 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();
|
|
}
|
|
});
|