import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { READ_REPORT_CANDIDATE_RANGE_RPC, loadReportCandidateRange, parseReportCandidateRange, reportCandidateRangeErrorCode, } from "../src/lib/report-candidate-range.ts"; import { resolveReportBirthTimeSensitivityInput, } from "../src/lib/personal-report-route-core.ts"; import { REPORT_STABLE_CODES } from "../src/lib/personal-report-codes.ts"; const workerSource = readFileSync( new URL("../src/lib/personal-report-worker.ts", import.meta.url), "utf8", ); const createRoute = readFileSync( new URL("../src/app/api/reports/route.ts", import.meta.url), "utf8", ); const helperSource = readFileSync( new URL("../src/lib/report-candidate-range.ts", import.meta.url), "utf8", ); function capturingWarn() { const reasons: string[] = []; return { reasons, warn: (payload: { event: "report_candidate_range_unavailable"; reason: string }) => { reasons.push(payload.reason); }, }; } test("permission denied, thrown errors, and empty rows all degrade to a null window", async () => { const denied = capturingWarn(); assert.equal( await loadReportCandidateRange( { rpc: async () => ({ data: null, error: { code: "42501", message: "permission denied for table agentic_rectification_cases" }, }), }, { userId: "11111111-1111-4111-8111-111111111111" }, denied.warn, ), null, ); assert.deepEqual(denied.reasons, ["42501"]); const thrown = capturingWarn(); assert.equal( await loadReportCandidateRange( { rpc: async () => { throw new TypeError("rpc exploded"); }, }, { userId: "11111111-1111-4111-8111-111111111111" }, thrown.warn, ), null, ); assert.deepEqual(thrown.reasons, ["TypeError"]); const empty = capturingWarn(); assert.equal( await loadReportCandidateRange( { rpc: async () => ({ data: null, error: null }) }, { userId: "11111111-1111-4111-8111-111111111111" }, empty.warn, ), null, ); assert.deepEqual(empty.reasons, []); }); test("a valid RPC window is returned and extra columns are ignored", async () => { const log = capturingWarn(); assert.deepEqual( await loadReportCandidateRange( { rpc: async (fn, args) => { assert.equal(fn, READ_REPORT_CANDIDATE_RANGE_RPC); assert.equal(args.p_user_id, "11111111-1111-4111-8111-111111111111"); assert.equal(args.p_rectification_case_id, "22222222-2222-4222-8222-222222222222"); return { data: { start_time: "10:00:00", end_time: "10:04:00", user_id: "must-not-leak", candidate_range: { secret: true }, }, error: null, }; }, }, { userId: "11111111-1111-4111-8111-111111111111", rectificationCaseId: "22222222-2222-4222-8222-222222222222", }, log.warn, ), { startTime: "10:00", endTime: "10:04" }, ); assert.deepEqual(log.reasons, []); }); test("degraded candidate windows keep report sensitivity input unwindowed", () => { const input = resolveReportBirthTimeSensitivityInput( {}, "accepted", "10:30", null, ); assert.equal(input.birth_time_accuracy, "provisional"); assert.equal("candidate_range" in input, false); assert.equal(REPORT_STABLE_CODES.calculationUnavailable, "calculation_unavailable"); }); test("error codes never include messages or birth content", () => { assert.equal( reportCandidateRangeErrorCode({ code: "42501", message: "permission denied for table agentic_rectification_cases", }), "42501", ); assert.equal(parseReportCandidateRange({ start_time: "25:00", end_time: "10:00" }), null); assert.doesNotMatch(helperSource, /error\.message|details|hint/); }); test("worker and create route read candidate windows only through the shared RPC helper", () => { for (const source of [workerSource, createRoute]) { assert.match(source, /loadReportCandidateRange/); assert.doesNotMatch(source, /from\("agentic_rectification_cases"\)/); assert.doesNotMatch(source, /from\("birth_time_rectification_cases"\)/); assert.doesNotMatch(source, /\.in\("status", \["confirmed", "completed"\]\)/); } assert.doesNotMatch( workerSource, /loadReportCandidateRange[\s\S]{0,400}calculation_unavailable/, ); });