Repository navigation
Description
aggregator: SnapshotStore accepts records it can never read back — non-finite estimate pairs and non-ISO timestamps pass validation, append reports success, and dedupe never sees them
Summary
isSnapshotRecord (pm-stack/aggregator/src/snapshots.ts:26-42) is the shared
structural validator for the usage snapshot store: the store's own
readAll/append, the feed ingest in sources/live.ts (which appends
feed.snapshots into the local store), and the writer scripts
(collect-fleet-feed.ts, gather-quota.ts, append-usage-snapshots.ts) all
gate on it. Two classes of record pass that validator but can never be read
back by the store, so SnapshotStore.append reports them as written, they
never appear in history, and — because dedupe is computed from readAll —
re-appending the same record appends it again every time.
Evidence (verified on main 3b55904, Bun 1.4.2, verbatim snapshots.ts sha256 49b14289 on the laptop)
Probe: probe-2026-10-27-laneB-snapshots (real snapshots.ts, only the
type-only model.ts import stubbed).
- Estimate pairs skip the finiteness check scalars get. Scalar
value: NaN→isSnapshotRecordfalse (line 34:Number.isFinite), but
value: { low: NaN, high: 10 }→ true, and{ low: Infinity, high: 10 }
→ true (lines 35-38 check onlytypeof === "number"). An inverted
pair{ low: 50, high: 10 }also passes.append([NaN-pair])returns 1; the stored line has
"value":{"low":null,"high":10}(JSON.stringify turns NaN into null),
whichreadAllthen rejects —readAll()returns 0 records.append([same NaN-pair])again returns 1 (not 0): dedupe is built
fromreadAll(snapshots.ts:99), which never sees the stored line, so
every re-run of a writer appends another dead line and reports it as a
new observation. The monthly file grows with records no reader will
ever return.
- Any
Date.parse-abletspasses, but file routing assumes an ISO
prefix.snapshotFileFor(snapshots.ts:20-22) routes by
ts.slice(0, 7), andreadAllonly reads files matching
usage-(\d{4}-\d{2})\.jsonl(line 17). A record with
ts: "October 20, 2026"passesisSnapshotRecord(line 29 only requires
Date.parseto succeed),appendreturns 1 and writes it to
usage-October.jsonl— a filereadAllfilters out, soreadAll()
returns 0. Same silent-loss + no-dedupe shape as (1). - Control: a normal ISO record with a finite pair appends once, the
second append returns 0 (dedupe works), andreadAllreturns 1.
Why it matters
The snapshot store is the append-only usage history the hub's history views
are built from, and its contract (module header, snapshots.ts:1-10) is that
writers and the backfill are "safe to re-run" because dedupe makes appends
idempotent. Records in either class above break that contract silently:
append counts them as stored history, no surface ever shows them, and every
writer re-run adds another copy. The pair case is reachable from any writer
whose estimate arithmetic can produce NaN/Infinity (e.g. a division by a
zero denominator upstream) — the validator is exactly the boundary that is
supposed to keep such values out, and it already does so for scalar values.
Acceptance criteria
isSnapshotRecordrejects estimate pairs whoseloworhighis not a
finite number (mirroring the scalar branch), and rejects a pair with
low > high.isSnapshotRecordrejects atswhose first 7 characters are not a
YYYY-MMmonth the store can route (or, equivalently,snapshotFileFor
output is guaranteed to match thereadAllfile pattern for every
accepted record).- Regression tests: appending a NaN/Infinity-pair record and a non-ISO-ts
record each append 0 and write nothing; the existing finite-pair control
still appends once and dedupes on re-append. - No change to the on-disk format or to the dedupe key for valid records.
Notes
- Deliberately not self-solved by the creator lane: the
low > highruling
and the exact ts shape to require (full ISO vsYYYY-MMprefix) are small
contract decisions for triage, and this validator is shared by four
writer/reader paths. - Related, different defect: aggregator: concurrent writes to the JSON stores share one temp path — most fail with ENOENT (returned as '400 invalid'), and persisted records don't match the calls that succeeded #1509 (concurrent JSON-store writes in the
aggregator) — same app, unrelated module and mechanism.
Activity
developing-today commentedon Oct 28, 2026
CODE-594
dezren39 commentedon Oct 28, 2026
🤖 Agent note · filed
3 remaining items
dezren39 commentedon Oct 31, 2026
🤖 Agent note · picked up
Merge pull request #2925 from developing-today/queue/1812-1540-snapsh…
dezren39 commentedon Oct 31, 2026
🤖 Agent note · done — fixed & merged