Files
Jyotisha/frontend/tests/account-api.test.ts
T
jesse-ux b85c4a686a
Independent Staging Quality Gate / validate (push) Successful in 13m27s
Independent Staging Quality Gate / publish (push) Failing after 1h0m1s
fix(rectification): anchor candidate windows to civil dates across midnight
Carry explicit local date intervals instead of inferring the day from clock
order. Cluster width, delivery, adoption, and reports keep the actual civil
date; adopted date is stored separately from the reported birth_date.

Algorithm identity is scoring-9 / spec-v5. Scoring weights, confirmation
thresholds, and Skill version are unchanged. Isolated Linux final-3 gates
passed; four pre-existing Python failures remain. This is not a production
release.
2026-09-21 02:55:00 +08:00

579 lines
22 KiB
TypeScript

import assert from "node:assert/strict";
import { existsSync, readFileSync } from "node:fs";
import test from "node:test";
import {
accountProfilePatchSchema,
resolveAccountBirthTimeApplicationPatch,
resolveAppliedAccountBirthTime,
} from "../src/lib/account-profile-patch.ts";
const source = readFileSync(new URL("../src/app/api/account/route.ts", import.meta.url), "utf8");
const patchSource = readFileSync(new URL("../src/lib/account-profile-patch.ts", import.meta.url), "utf8");
const reportedStatusMigration = readFileSync(
new URL("../supabase/migrations/20260726010000_backfill_reported_birth_time_status.sql", import.meta.url),
"utf8",
);
const acceptedExactFamilyMigration = readFileSync(
new URL("../supabase/migrations/20260816010000_accept_exact_family_birth_times.sql", import.meta.url),
"utf8",
);
const selfHostedMigrator = readFileSync(
new URL("../scripts/db-migrate.mjs", import.meta.url),
"utf8",
);
test("account API reads and returns the server-configured rectification price", () => {
assert.match(source, /parseRectificationPriceCredits\(\s*process\.env\.RECTIFICATION_PRICE_CREDITS,?\s*\)/);
assert.match(source, /rectificationPriceCredits/);
assert.doesNotMatch(source, /RECTIFICATION_PRICE_CREDITS[^\n]*\?\?\s*["']1["']/);
});
test("account API separates engine confirmation from an accepted usable chart time", () => {
assert.match(source, /hasConfirmedBirthTime:\s*profile\.birth_time_status === "confirmed"/);
assert.match(source, /hasUsableBirthTime:\s*\(profile\.birth_time_status === "accepted" \|\| profile\.birth_time_status === "confirmed"\)/);
});
test("account API routes staging admins to the configured exact admin host", () => {
assert.match(source, /readSelfHostedIdentityConfig\(process\.env\)\.adminOrigin/);
assert.match(source, /const adminUrl = isAdmin \? adminEntryUrl\(\) : null/);
assert.match(source, /adminUrl,/);
assert.doesNotMatch(source, /NEXT_PUBLIC_ADMIN|AUTH_ADMIN_ORIGIN/);
});
test("account GET falls back when global birthplace columns are not migrated yet", () => {
const getSource = source.slice(source.indexOf("export async function GET"), source.indexOf("export async function PATCH"));
assert.match(getSource, /profileError && isMissingProfileColumn\(profileError\)/);
assert.match(getSource, /select\("credits,active_birth_time[^"]*timezone_offset(?:,[^"]*)?"\)/);
assert.match(getSource, /birth_place_label: undefined/);
assert.match(getSource, /timezone_id: undefined/);
assert.match(getSource, /timezone_source,ayanamsa,name,birth_time,rectification_case_id/);
});
test("account API no longer reads or returns retired rectification cases", () => {
assert.doesNotMatch(source, /birth_time_rectification_v4_cases|birth_time_rectification_cases/);
assert.doesNotMatch(source, /rectificationCase/);
});
test("profile patch schema validates calendar, clock, source requirements, and location bounds", () => {
const valid = {
name: "岳辰",
birth_date: "2000-02-29",
reported_birth_time: "05:30",
birth_time_source: "family_exact",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 0,
uncertainty_after_minutes: 0,
country_code: "CN",
province_code: "130000",
city_code: "130400",
district_code: "130406",
latitude: 36.420487,
longitude: 114.209936,
timezone_offset: 8,
};
assert.equal(accountProfilePatchSchema.safeParse(valid).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, uncertainty_before_minutes: 10, uncertainty_after_minutes: 10 }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, birth_date: "2001-02-29" }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, reported_birth_time: "24:00" }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, uncertainty_before_minutes: 7, uncertainty_after_minutes: 7 }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
birth_time_source: "approximate",
uncertainty_before_minutes: 120,
uncertainty_after_minutes: 120,
}).success, true);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
birth_time_source: "approximate",
uncertainty_before_minutes: 90,
uncertainty_after_minutes: 90,
}).success, false);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, latitude: 91 }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({ reported_birth_time: "05:30" }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({ ...valid, longitude: null }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
timezone_offset: null,
birth_place_label: "New York, New York, United States",
birth_place_type: "place",
birth_place_provider: "mapbox",
birth_place_provider_id: "place.123",
timezone_id: "America/New_York",
timezone_source: "iana_historical",
}).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ name: "只改称呼" }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ayanamsa: "lahiri" }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ayanamsa: "kp" }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ayanamsa: "true_pushya" }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ayanamsa: "raman" }).success, true);
assert.equal(accountProfilePatchSchema.safeParse({ ayanamsa: "fagan" }).success, false);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: null,
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
}).success, false);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: "evening",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
}).success, true);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: null,
declared_window_start: "14:30",
declared_window_end: "15:00",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
}).success, true);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: null,
declared_window_start: "14:30",
declared_window_end: "14:30",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
}).success, false);
assert.equal(accountProfilePatchSchema.safeParse({
...valid,
reported_birth_time: null,
birth_time_source: "unknown",
birth_time_period: "morning",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
}).success, false);
});
test("ordinary declaration edits clear stale candidate application but never overwrite confirmed active time", () => {
const candidate = {
birth_date: "1997-08-08",
reported_birth_time: "05:30",
birth_time_source: "approximate",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 30,
uncertainty_after_minutes: 30,
active_birth_time: "05:18",
birth_time: "05:18",
birth_time_status: "candidate",
rectification_case_id: "11111111-1111-4111-8111-111111111111",
latitude: 36.420487,
longitude: 114.209936,
timezone_offset: 8,
} as const;
const edited = {
birth_date: candidate.birth_date,
reported_birth_time: "06:10",
birth_time_source: candidate.birth_time_source,
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 30,
uncertainty_after_minutes: 30,
} as const;
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(candidate, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(candidate, {
district_code: "130407",
}), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
for (const coordinatePatch of [
{ latitude: 36.420488 },
{ longitude: 114.209937 },
{ timezone_offset: 9 },
]) {
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(candidate, coordinatePatch), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
}
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
birth_time_status: "accepted",
}, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
birth_time_status: "confirmed",
}, edited), {});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
birth_time_status: "confirmed",
}, { ayanamsa: "lahiri" }), {});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
active_birth_time: null,
birth_time_status: "reported",
}, { timezone_offset: 7 }), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
active_birth_time: null,
birth_time: null,
birth_time_status: null,
rectification_case_id: null,
}, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
active_birth_time: null,
birth_time: null,
birth_time_status: null,
rectification_case_id: null,
reported_birth_time: edited.reported_birth_time,
}, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(null, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
birth_time_status: "accepted",
}, edited), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
birth_time_status: "confirmed",
}, edited), {});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...candidate,
active_birth_time: null,
birth_time_status: null,
reported_birth_time: edited.reported_birth_time,
}, edited), {});
});
test("zero-uncertainty family exact time becomes an accepted usable chart time", () => {
const exactDeclaration = {
birth_date: "1997-08-08",
reported_birth_time: "05:00",
birth_time_source: "family_exact",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 0,
uncertainty_after_minutes: 0,
} as const;
const reportedExactProfile = {
...exactDeclaration,
reported_birth_time: "05:00:00",
active_birth_time: null,
birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
} as const;
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(null, exactDeclaration), {
active_birth_time: "05:00",
birth_time_status: "accepted",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(reportedExactProfile, exactDeclaration), {
active_birth_time: "05:00",
birth_time_status: "accepted",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...reportedExactProfile,
active_birth_time: "05:00:00",
birth_time_status: "accepted",
}, {
...exactDeclaration,
reported_birth_time: "05:40",
}), {
active_birth_time: "05:40",
birth_time_status: "accepted",
rectification_case_id: null,
});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...reportedExactProfile,
active_birth_time: "05:00:00",
birth_time_status: "confirmed",
}, {
...exactDeclaration,
reported_birth_time: "05:40",
}), {});
assert.deepEqual(resolveAccountBirthTimeApplicationPatch({
...reportedExactProfile,
active_birth_time: "05:00:00",
birth_time: "05:00:00",
birth_time_status: null,
}, {
...exactDeclaration,
reported_birth_time: "05:40",
}), {});
});
test("account PATCH answers with the birth-time truth it derived server-side", () => {
const exactDeclaration = {
birth_date: "1997-08-08",
reported_birth_time: "05:00",
birth_time_source: "family_exact",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 0,
uncertainty_after_minutes: 0,
} as const;
const reportedExactProfile = {
...exactDeclaration,
reported_birth_time: "05:00:00",
active_birth_time: null,
birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
} as const;
// A client that keeps the declaration it submitted would consult as
// unverified_birth_time and be rejected by the consultation truth check.
assert.deepEqual(
resolveAppliedAccountBirthTime(
null,
resolveAccountBirthTimeApplicationPatch(null, exactDeclaration),
),
{ status: "accepted", activeTime: "05:00" },
);
assert.deepEqual(
resolveAppliedAccountBirthTime(
reportedExactProfile,
resolveAccountBirthTimeApplicationPatch(reportedExactProfile, exactDeclaration),
),
{ status: "accepted", activeTime: "05:00" },
);
const periodDeclaration = {
...exactDeclaration,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: "early_morning",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
} as const;
assert.deepEqual(
resolveAppliedAccountBirthTime(
reportedExactProfile,
resolveAccountBirthTimeApplicationPatch(reportedExactProfile, periodDeclaration),
),
{ status: "reported", activeTime: null },
);
// An untouched application keeps the stored truth, including a legacy confirmed minute.
const confirmedProfile = {
...reportedExactProfile,
active_birth_time: "05:18:00",
birth_time_status: "confirmed",
} as const;
assert.deepEqual(
resolveAppliedAccountBirthTime(
confirmedProfile,
resolveAccountBirthTimeApplicationPatch(confirmedProfile, { district_code: "130407" }),
),
{ status: "confirmed", activeTime: "05:18" },
);
const legacyProfile = {
...reportedExactProfile,
birth_time: "05:18:00",
birth_time_status: null,
} as const;
assert.deepEqual(
resolveAppliedAccountBirthTime(
legacyProfile,
resolveAccountBirthTimeApplicationPatch(legacyProfile, { district_code: "130407" }),
),
{ status: "confirmed", activeTime: "05:18" },
);
assert.deepEqual(
resolveAppliedAccountBirthTime(null, resolveAccountBirthTimeApplicationPatch(null, { name: "岳辰" })),
{ status: null, activeTime: null },
);
assert.match(source, /\.\.\.resolveAppliedAccountBirthTime\(currentProfile, applicationPatch\)/);
assert.match(source, /activeDate: data\.active_birth_date \?\? null/);
assert.match(source, /activeTimezoneOffset: data\.active_birth_timezone_offset \?\? null/);
});
test("only a strict family exact zero-uncertainty declaration is auto-accepted", () => {
const base = {
birth_date: "1997-08-08",
reported_birth_time: "05:00",
birth_time_source: "family_exact",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 0,
uncertainty_after_minutes: 0,
} as const;
const declarations = [
{ ...base, uncertainty_before_minutes: 5, uncertainty_after_minutes: 5 },
{ ...base, uncertainty_before_minutes: 10, uncertainty_after_minutes: 10 },
{ ...base, uncertainty_before_minutes: 15, uncertainty_after_minutes: 15 },
{ ...base, birth_time_source: "approximate", uncertainty_before_minutes: 30, uncertainty_after_minutes: 30 },
{
...base,
reported_birth_time: null,
birth_time_source: "period_only",
birth_time_period: "morning",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
},
{
...base,
reported_birth_time: null,
birth_time_source: "unknown",
uncertainty_before_minutes: null,
uncertainty_after_minutes: null,
},
] as const;
for (const declaration of declarations) {
assert.deepEqual(resolveAccountBirthTimeApplicationPatch(null, declaration), {
active_birth_time: null,
birth_time_status: "reported",
rectification_case_id: null,
});
}
});
test("reported birth-time status repair is forward-only and applied by the self-hosted migrator", () => {
assert.match(reportedStatusMigration, /birth_time_status is null/);
assert.match(reportedStatusMigration, /birth_time_status = 'reported'/);
assert.match(reportedStatusMigration, /active_birth_time is null/);
assert.match(reportedStatusMigration, /rectification_case_id is null/);
// Staging and production migrations run through db-migrate.mjs, which applies
// frontend/supabase/migrations as the compatibility directory; the repair file
// must stay there rather than in a retired workflow's explicit file list.
assert.ok(
existsSync(new URL("../supabase/migrations/20260726010000_backfill_reported_birth_time_status.sql", import.meta.url)),
);
assert.match(selfHostedMigrator, /"\.\.\/supabase\/migrations"/);
assert.match(selfHostedMigrator, /supabaseCompatibilityDirectory,/);
});
test("profile ayanamsa is added by the self-hosted migrator with Raman as the default", () => {
const ayanamsaMigration = readFileSync(
new URL("../supabase/migrations/20260903010000_profile_ayanamsa.sql", import.meta.url),
"utf8",
);
assert.match(ayanamsaMigration, /add column if not exists ayanamsa text not null default 'raman'/);
assert.match(ayanamsaMigration, /'raman', 'lahiri', 'kp', 'true_pushya'/);
assert.equal(
existsSync(new URL("../db/migrations/20260903010000_profile_ayanamsa.sql", import.meta.url)),
false,
);
});
test("existing exact family declarations are forward-repaired without claiming confirmation", () => {
assert.match(acceptedExactFamilyMigration, /update public\.profiles/);
assert.match(acceptedExactFamilyMigration, /active_birth_time = reported_birth_time/);
assert.match(acceptedExactFamilyMigration, /birth_time_status = 'accepted'/);
assert.match(acceptedExactFamilyMigration, /birth_time_source = 'family_exact'/);
assert.match(acceptedExactFamilyMigration, /uncertainty_before_minutes = 0/);
assert.match(acceptedExactFamilyMigration, /uncertainty_after_minutes = 0/);
assert.match(acceptedExactFamilyMigration, /birth_time_status = 'reported'/);
assert.match(acceptedExactFamilyMigration, /active_birth_time is null/);
assert.match(acceptedExactFamilyMigration, /rectification_case_id is null/);
assert.doesNotMatch(acceptedExactFamilyMigration, /birth_time_status = 'confirmed'/);
assert.equal(
existsSync(new URL("../db/migrations/20260816010000_accept_exact_family_birth_times.sql", import.meta.url)),
false,
);
});
test("account PATCH uses the shared validator and never writes client birth_time over account truth", () => {
assert.match(source, /accountProfilePatchSchema\.safeParse/);
assert.match(source, /resolveAccountBirthTimeApplicationPatch/);
assert.match(patchSource, /birthTimeSource[\s\S]*birth_time_status: "reported"/);
assert.doesNotMatch(source, /birth_time:\s*nullableString\(payload\.birth_time\)/);
assert.match(source, /invalidatesUnconfirmedApplication/);
assert.match(patchSource, /"birth_time_status"/);
assert.match(patchSource, /"active_birth_time"/);
assert.match(source, /latitude,longitude,timezone_offset/);
assert.match(source, /birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source/);
assert.match(source, /payload\.ayanamsa !== undefined \? \{ ayanamsa: payload\.ayanamsa \}/);
assert.match(patchSource, /ayanamsa: z\.enum\(AYANAMSA_VALUES\)\.optional\(\)/);
const declarationBlock = patchSource.slice(
patchSource.indexOf("const declarationFields"),
patchSource.indexOf("const concurrencyFields"),
);
assert.doesNotMatch(declarationBlock, /ayanamsa/);
assert.match(source, /applyAccountProfileConcurrencyGuards/);
assert.match(source, /最新确认结果已保留/);
});
test("candidate invalidation compares coordinates and timezone in the conditional write", async () => {
const { applyAccountProfileConcurrencyGuards } = await import("../src/lib/account-profile-patch.ts");
const calls: Array<["eq" | "is", string, unknown]> = [];
const query = {
eq(column: string, value: unknown) {
calls.push(["eq", column, value]);
return this;
},
is(column: string, value: null) {
calls.push(["is", column, value]);
return this;
},
};
const current = {
birth_date: "1997-08-08",
reported_birth_time: "05:30",
birth_time_source: "approximate",
birth_time_period: null,
birth_time_clue: null,
uncertainty_before_minutes: 30,
uncertainty_after_minutes: 30,
active_birth_time: "05:18",
birth_time: "05:18",
birth_time_status: "candidate",
rectification_case_id: "11111111-1111-4111-8111-111111111111",
country_code: "CN",
province_code: "130000",
city_code: "130400",
district_code: "130406",
latitude: 36.420487,
longitude: 114.209936,
timezone_offset: 8,
};
applyAccountProfileConcurrencyGuards(query, current);
assert.deepEqual(calls.filter((call) => ["latitude", "longitude", "timezone_offset"].includes(call[1])), [
["eq", "latitude", 36.420487],
["eq", "longitude", 114.209936],
["eq", "timezone_offset", 8],
]);
assert.deepEqual(calls.find((call) => call[1] === "active_birth_time"), ["eq", "active_birth_time", "05:18"]);
assert.deepEqual(calls.find((call) => call[1] === "birth_time_status"), ["eq", "birth_time_status", "candidate"]);
});