Files
Jyotisha/frontend/tests/database-rectification-resume-session-20261023.test.ts
T
jesse-uxandGrok (agent loop) 4a9ad6a1bd fix(rectification): open a new case when an accepted one blocks chat
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)
2026-10-23 01:55:59 +08:00

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();
}
});