Files
Jyotisha/frontend/tests/database-rectification-block-scan.test.ts
T
jesse-uxandClaude Code 8d0359fc62
Independent Staging Quality Gate / validate (push) Successful in 10m4s
Independent Staging Quality Gate / publish (push) Successful in 10m26s
fix(rectification): enforce trusted result identity and preserve receipt provenance
Unify minute and block cache identity, keep unverifiable historical results read-only across server tools and write entrypoints, and aggregate completed receipt sources chronologically through a compatible function migration.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-20 18:03:38 +08:00

279 lines
13 KiB
TypeScript

import assert from "node:assert/strict";
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 { startPostgresFixture } from "./helpers/postgres-fixture.ts";
const runnerPath = fileURLToPath(
new URL("../scripts/db-migrate.mjs", import.meta.url),
);
function dockerAvailable(): boolean {
const probe = spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], {
encoding: "utf8",
stdio: "ignore",
});
return probe.status === 0;
}
const skipWithoutDocker = dockerAvailable() ? false : "docker unavailable on this host";
function rpcError(error: unknown): string {
if (!error || typeof error !== "object") return "";
const value = error as { message?: unknown };
return typeof value.message === "string" ? value.message : "";
}
const snapshot = {
birth_date: "1998-03-15",
birth_place_label: "北京市",
latitude: 39.9042,
longitude: 116.4074,
timezone_id: "Asia/Shanghai",
timezone_offset: 8,
birth_time_source: "unknown",
reported_birth_time: null,
active_birth_time: null,
birth_time_period: null,
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
};
const fingerprint = "b".repeat(64);
const fullDay = { start_time: "00:00", end_time: "23:59" };
const skillName = "jyotish-birth-time-rectification";
const skillVersion = "9.0.0";
const blocks = {
blocks: [
{ period: "early_morning", start_time: "04:00", end_time: "07:59", relative_support: 12 },
{ period: "morning", start_time: "08:00", end_time: "11:59", relative_support: 41 },
{ period: "afternoon", start_time: "12:00", end_time: "17:59", relative_support: 28 },
{ period: "evening", start_time: "18:00", end_time: "22:59", relative_support: 11 },
{ period: "late_night", start_time: "23:00", end_time: "03:59", relative_support: 8 },
],
};
test("block_scan RPCs are service_role-only and advance a declared period", { skip: skipWithoutDocker }, async () => {
const fixture = startPostgresFixture();
const schemaUrl = fixture.connectionUrl("schema_owner", "schema-owner-test-password");
try {
const migration = spawnSync(process.execPath, [runnerPath], {
encoding: "utf8",
env: { ...process.env, SCHEMA_DATABASE_URL: schemaUrl },
});
assert.equal(migration.status, 0, migration.stderr);
fixture.psqlAs(
"identity_runtime",
"identity-runtime-test-password",
`
insert into identity.users (name, email, email_verified, email_verified_at)
values ('Unknown', 'unknown-time@example.com', true, now());
`,
);
const userId = fixture.psql(
"select id from identity.users where email = 'unknown-time@example.com'",
);
fixture.psql(`
update public.profiles
set birth_date = '1998-03-15',
reported_birth_time = null,
birth_time_source = 'unknown',
latitude = 39.9042, longitude = 116.4074, timezone_offset = 8,
birth_time_status = 'reported'
where id = '${userId}';
`);
fixture.psql(`
with provider as (
insert into public.model_providers (code, name, provider_type, encrypted_api_key, enabled)
values ('block-scan-test', 'Block Scan Test', 'openai', 'test-ciphertext', true)
returning id
), config as (
insert into public.model_configs (model_id)
values ('block-scan-default-model')
returning id
)
insert into public.model_config_versions (
config_id, version, provider_id, label, provider_model, enabled, is_default, status, published_at
)
select config.id, 1, provider.id, 'Default', 'gpt-test', true, true, 'published', now()
from config cross join provider;
`);
const service = createLocalPostgresDataClient(
fixture.connectionUrl("service_runtime", "service-runtime-test-password"),
null,
"service_role",
);
const opened = await service.rpc("open_agentic_rectification_case", {
p_user_id: userId,
p_request_id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
p_intent: "homepage",
p_session_id: null,
p_skill_name: skillName,
p_skill_version: skillVersion,
p_baseline_profile_fingerprint: fingerprint,
p_baseline_birth_snapshot: snapshot,
p_candidate_range: fullDay,
});
assert.equal(opened.error, null, rpcError(opened.error));
const caseId = String((opened.data as Record<string, unknown>).case_id);
// BUG-984: identities belong to completed results, never deployment/start rows.
// All rows are synthetic; the timestamp/id order, not the version text, wins.
const turnId = fixture.psql(`
insert into public.agentic_rectification_turns (case_id, status, model_name, assistant_message)
values ('${caseId}', 'completed', 'fixture', 'fixture') returning id;
`).split("\n")[0];
const receipt = async (owner = userId, turn = turnId) => service.rpc("get_agentic_rectification_turn_receipt", {
p_user_id: owner, p_case_id: caseId, p_turn_id: turn,
});
const addReceipt = (id: string, status: string, version: string | null, second: number, attempt: string | null = null, tool = "rectification-compare-candidates") => fixture.psql(`
insert into public.agentic_rectification_tool_receipts
(id, case_id, turn_id, tool_name, public_phase, status, engine_version, started_at, attempt_id)
values ('${id}', '${caseId}', '${turnId}', '${tool}', 'candidates.updated', '${status}',
${version ? `'${version}'` : "null"}, '2026-09-20 00:00:${String(second).padStart(2, "0")}+00',
${attempt ? `'${attempt}'` : "null"});
`);
const version = (n: number) => `rectification-v5-matrix-scoring-${n}`;
addReceipt("10000000-0000-4000-8000-000000000001", "started", version(8), 1);
addReceipt("10000000-0000-4000-8000-000000000002", "completed", version(7), 2);
assert.equal((await receipt()).data?.engine_version, version(7));
addReceipt("10000000-0000-4000-8000-000000000003", "completed", version(9), 3);
addReceipt("10000000-0000-4000-8000-000000000004", "completed", version(10), 4, null, "rectification-read-diagnostics");
addReceipt("10000000-0000-4000-8000-000000000005", "failed", version(99), 5);
assert.equal((await receipt()).data?.engine_version, version(10));
// Same timestamp: stable id tie-break, independent of insertion/lexical version order.
addReceipt("10000000-0000-4000-8000-000000000006", "completed", version(11), 4);
assert.equal((await receipt()).data?.engine_version, version(11));
const attempt1 = fixture.psql(`
insert into public.agentic_rectification_run_attempts (case_id, turn_id, attempt_number, status, completed_at)
values ('${caseId}', '${turnId}', 1, 'completed', now()) returning id;
`).split("\n")[0];
addReceipt("10000000-0000-4000-8000-000000000007", "completed", version(10), 6, attempt1);
fixture.psql(`update public.agentic_rectification_turns set successful_attempt_id = '${attempt1}' where id = '${turnId}'`);
const attempt2 = fixture.psql(`
insert into public.agentic_rectification_run_attempts (case_id, turn_id, attempt_number, status, completed_at)
values ('${caseId}', '${turnId}', 2, 'failed', now()) returning id;
`).split("\n")[0];
addReceipt("10000000-0000-4000-8000-000000000008", "failed", version(99), 7, attempt2);
assert.equal((await receipt()).data?.engine_version, version(10), "failed retry cannot replace successful attempt");
fixture.psql(`update public.agentic_rectification_turns set successful_attempt_id = null where id = '${turnId}'`);
assert.equal((await receipt()).data?.engine_version, null, "latest failed-only attempt has no result provenance");
assert.match(rpcError((await receipt("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")).error), /case_not_found/);
assert.match(rpcError((await receipt(userId, "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")).error), /turn_not_found/);
assert.equal(fixture.psql(`select engine_version from public.agentic_rectification_tool_receipts where id = '10000000-0000-4000-8000-000000000002'`), version(7), "historical rows are not relabelled");
assert.equal(fixture.psql(`select has_function_privilege('authenticated', 'public.get_agentic_rectification_turn_receipt(uuid,uuid,uuid)', 'EXECUTE')`), "f");
const staged = await service.rpc("set_agentic_rectification_case_stage", {
p_user_id: userId,
p_case_id: caseId,
p_stage: "block_scan",
});
assert.equal(staged.error, null, rpcError(staged.error));
const written = await service.rpc("write_agentic_rectification_block_scan", {
p_user_id: userId,
p_case_id: caseId,
p_block_scan: blocks,
});
assert.equal(written.error, null, rpcError(written.error));
const dossier = await service.rpc("get_agentic_rectification_case_dossier", {
p_user_id: userId,
p_case_id: caseId,
});
assert.equal(dossier.error, null, rpcError(dossier.error));
const caseRow = (dossier.data as { case?: { stage?: string; block_scan?: unknown } }).case;
assert.equal(caseRow?.stage, "block_scan");
assert.ok(caseRow?.block_scan);
const advanced = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "08:00",
p_end_time: "11:59",
});
assert.equal(advanced.error, null, rpcError(advanced.error));
assert.equal((advanced.data as { stage?: string }).stage, "block_scan");
assert.deepEqual((advanced.data as { candidate_range?: unknown }).candidate_range, {
start_time: "08:00",
end_time: "11:59",
});
assert.equal(
fixture.psql(`select stage from public.agentic_rectification_cases where id = '${caseId}'`),
"block_scan",
);
const outside = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "04:50",
p_end_time: "05:10",
});
assert.match(rpcError(outside.error), /agentic_rectification_invalid_block_window/);
const narrowed = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "08:00",
p_end_time: "09:00",
});
assert.equal(narrowed.error, null, rpcError(narrowed.error));
assert.equal((narrowed.data as { stage?: string }).stage, "minute");
const invalidPeriod = await service.rpc("advance_agentic_rectification_case_from_block_scan", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "08:00",
p_end_time: "09:00",
});
assert.match(rpcError(invalidPeriod.error), /agentic_rectification_not_block_scan/);
const widened = await service.rpc("widen_agentic_rectification_case_window", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "07:30",
p_end_time: "09:30",
});
assert.equal(widened.error, null, rpcError(widened.error));
assert.deepEqual((widened.data as { candidate_range?: unknown }).candidate_range, {
start_time: "07:30",
end_time: "09:30",
});
assert.equal(
fixture.psql(`select adopted_credible_range is null from public.agentic_rectification_cases where id = '${caseId}'`),
"t",
);
const shrink = await service.rpc("widen_agentic_rectification_case_window", {
p_user_id: userId,
p_case_id: caseId,
p_start_time: "08:00",
p_end_time: "09:00",
});
assert.match(rpcError(shrink.error), /agentic_rectification_invalid_widen_window/);
const privileges = fixture.psql(`
select concat_ws(':',
has_function_privilege('service_role', 'public.set_agentic_rectification_case_stage(uuid,uuid,text)', 'EXECUTE'),
has_function_privilege('anon', 'public.set_agentic_rectification_case_stage(uuid,uuid,text)', 'EXECUTE'),
has_function_privilege('authenticated', 'public.write_agentic_rectification_block_scan(uuid,uuid,jsonb)', 'EXECUTE'),
has_function_privilege('service_role', 'public.advance_agentic_rectification_case_from_block_scan(uuid,uuid,text,text)', 'EXECUTE'),
has_function_privilege('service_role', 'public.widen_agentic_rectification_case_window(uuid,uuid,text,text)', 'EXECUTE'),
has_function_privilege('anon', 'public.widen_agentic_rectification_case_window(uuid,uuid,text,text)', 'EXECUTE')
)
`);
assert.equal(privileges, "t:f:f:t:t:f");
} finally {
try {
await closeLocalPostgresDataPool(
fixture.connectionUrl("service_runtime", "service-runtime-test-password"),
);
} finally {
fixture.stop();
}
}
});