Repository navigation
Description
Problem
pm-stack/aggregator/src/quota-current.ts gates the gatherer's quota-current.json with parseQuotaCurrent. In the same two gate functions, some date fields are held to the shared real-calendar rule and the most load-bearing one is not:
- window
resetsAtmust passisIsoDate(quota-current.ts:61) - entry
credentialExpiresAtmust passisIsoDate(quota-current.ts:80) - entry
measuredAtis onlytypeof value.measuredAt === "string"(quota-current.ts:75) - window
measuredAtis onlytypeof value.measuredAt === "string"(quota-current.ts:62)
measuredAt is the field the whole overlay runs on: entryState (quota-current.ts:137) classifies an entry fresh/stale from Date.parse(entry.measuredAt), newestFirst (quota-current.ts:161) picks the winning entry by it, and applyEntry (quota-current.ts:208) stamps it verbatim onto the pool as its displayed freshness.
Date.parse rolls day-overflow dates over and accepts non-ISO strings, so a gatherer entry stamped 2026-02-30T12:00:00.000Z passes the gate, parses as March 2, and — at a wall-clock time near March 2 — classifies as a fresh "ok" read: its windows replace the pool's windows, the pool recomputes healthy, and the freshness stamp shown for the pool is a date that never existed. A stamp of March 2, 2026 passes the same way. Every sibling date field in the same gate, and the shared validate.ts contract (parseIsoDate/isIsoDate: impossible calendar dates FAIL instead of rolling over), say this input is malformed.
Verified this run (laptop bun probe, origin/main 314fbbe)
Probe /tmp/probe-qc.ts on the laptop (log /tmp/probe-qc.log), driving parseQuotaCurrent and overlayQuotaCurrent directly:
impossible-entry+window 2026-02-30 providersKept=1 dropped=0 winKept=1
noniso-entry "March 2, 2026" providersKept=1 dropped=0 winKept=1
contrast credentialExpiresAt 2026-02-30 (measuredAt valid) providersKept=null (entry refused)
contrast window resetsAt 2026-02-30 (measuredAts valid) providersKept=1 winKept=0 (window dropped)
control leap 2024-02-29 providersKept=1 dropped=0 winKept=1
overlay freshness={"measuredAt":"2026-02-30T12:00:00.000Z","source":"probe","state":"ok"} poolState=healthy windows=1
The overlay case: an entry stamped 2026-02-30T12:00:00.000Z, viewed at 2026-03-02T12:05:00Z, is classified fresh, replaces the pool's windows, sets the pool healthy, and displays the impossible stamp verbatim as the pool's freshness.
Why it matters
quota-current.json is written by an external gatherer process on a 15-minute tick; a skewed, hand-edited, or drifted write is exactly what this gate exists to isolate (the file's own history: #1541 future-dated reads, #2253 garbage stamps winning the stale-path pick, #2416 malformed windows). Those fixes finite-gated the consumers of measuredAt, but the gate still admits stamps that name no real instant — and the rollover makes them more dangerous than garbage: a garbage stamp parses to NaN and loses, while an impossible stamp parses to a real, possibly-fresh instant and wins, wearing a freshness label that never existed.
Acceptance criteria
isQuotaCurrentEntryrefuses (drops, per the gate's existing per-entry isolation) an entry whosemeasuredAtis not a real ISO calendar date/time, using the sharedisIsoDateprimitive fromvalidate.ts— e.g.2026-02-30T12:00:00.000Z,2026-04-31T12:00:00.000Z,March 2, 2026are refused; this matches the existing treatment ofcredentialExpiresAtin the same function.isQuotaCurrentWindowapplies the same rule to a window'smeasuredAt, matching its existingresetsAtrule — a malformed window drops without dropping its entry's valid windows.- Real timestamps still validate, including leap dates (
2024-02-29T12:00:00.000Z) and thenew Date().toISOString()shapes the gatherer writes — the existing tests inpm-stack/aggregator/test/quota-current.test.tsstay green. - New tests in
pm-stack/aggregator/test/quota-current.test.tscover the impossible-date and non-ISO refusals for both the entry and the window, plus a leap-date control that is kept.
Dedup / related
- Distinct from closed aggregator: a future-dated gatherer read is 'fresh' forever until its date passes — quota-current freshness has no upper bound, so one skewed measuredAt pins a pool's windows for weeks #1541 / aggregator(quota-current): stale-path newest pick is not finite-gated — a garbage or far-future measuredAt wins the pool's displayed freshness #2253 (future-dated and garbage stamps at the freshness/newest-pick consumers — finite-gating, not calendar validity at the gate) and from closed aggregator(feed): isQuotaWindow accepts any string as resetsAt and any finite used/limit/percent — an impossible reset date is clocked as Mar 2 in guidance, a -50% window reads healthy and a 15000% window walls a pool #3427 (
feed.tsisQuotaWindow, a different gate). - Distinct from open pm-stack(aggregator): isCredentialLifecycleRow accepts garbage and impossible dates — measuredAt is typeof-only and expiresAt is Date.parse-only, unlike the isIsoDate gates in the same sanitize pass #4955 (
credential-lifecycle.tsrow gate) and open pm-stack(aggregator): normalizeResetAt accepts impossible and non-ISO reset dates — its string branch is Date.parse-only, rolling 2026-02-30 to Mar 2 instead of returning null #4968 (quota-gather-map.tsnormalizeResetAt): same defect class, different files and gates.
Activity
dezren39 commentedon Nov 3, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
fix(aggregator): gate quota-current measuredAt with isIsoDate (#4987) (…
dezren39 commentedon Nov 3, 2026
🤖 Agent note · done — fixed and merged
measuredAtinpm-stack/aggregator/src/quota-current.tsnow go throughisIsoDate, matching theresetsAt/credentialExpiresAtgates in the same functions.test/quota-current.test.ts(impossible/non-ISO entry dropped with siblings surviving; impossible/non-ISO window dropped without dropping valid windows; leap date 2024-02-29 still validates). Laptopbun test test/quota-current.test.ts: 42 pass, 0 fail. Codex review failed on usage limits with zero findings (disposition on PR fix(aggregator): gate quota-current measuredAt with isIsoDate (#4987) #4996); CodeRabbit skipped.