Problem
loadUpstreamStatus treats a ruleset snapshot as current when generatedAt is missing or malformed. Date.parse returns NaN, the stale comparison is false, and operators see a fresh upstream status on corrupted snapshot data.
Expected behavior
Unparseable or missing generatedAt should resolve to stale (fail-closed), matching the guard pattern already used in src/github/backfill.ts (Number.isFinite(ageMs)).
Scope
- Add a shared staleness helper in
src/upstream/ruleset.ts
- Update
loadUpstreamStatus status resolution
- Regression tests in
test/unit/upstream-ruleset.test.ts for garbage ISO, empty string, and valid timestamps
Acceptance criteria
Problem
loadUpstreamStatustreats a ruleset snapshot as current whengeneratedAtis missing or malformed.Date.parsereturnsNaN, the stale comparison is false, and operators see a fresh upstream status on corrupted snapshot data.Expected behavior
Unparseable or missing
generatedAtshould resolve to stale (fail-closed), matching the guard pattern already used insrc/github/backfill.ts(Number.isFinite(ageMs)).Scope
src/upstream/ruleset.tsloadUpstreamStatusstatus resolutiontest/unit/upstream-ruleset.test.tsfor garbage ISO, empty string, and valid timestampsAcceptance criteria
generatedAt→status: "stale"(when no drift reports)status: "current"UPSTREAM_STALE_MS→status: "stale"npm run test:cigreen