Skip to content

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

Closed

Description

@dezren39

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

Summary

entryState in pm-stack/aggregator/src/quota-current.ts:56-61 decides whether
a gatherer entry may replace a pool's windows:

const t = Date.parse(entry.measuredAt);
return Number.isFinite(t) && nowMs - t <= QUOTA_CURRENT_FRESH_MS ? "ok" : "stale";

The check bounds only the past. A measuredAt in the future gives a negative
age, which is always <= QUOTA_CURRENT_FRESH_MS (20 min) — so a read stamped
an hour, a day, or a month ahead is classified "ok", replaces the pool's
windows in overlayQuotaCurrent, recomputes the pool state and the routing
choices (computeChoices), and keeps doing so on every render until 20
minutes after its future date arrives. The newest-entry sort in the overlay
(Date.parse(b.measuredAt) - Date.parse(a.measuredAt), quota-current.ts:139-141)
also makes a future-dated entry win over every genuinely fresh entry for the
same service.

Evidence (verified on main 3b55904, Bun 1.4.2, real quota-current.ts sha256 c528e1e3 on the laptop)

Probe drove the real overlayQuotaCurrent with a fixed now
(2026-10-27T07:00:00Z), one pool (weekly window at 68%), and one ok entry
carrying a 42% window:

measuredAt result
5m ago (control) state healthy, windows replaced (42), freshness ok
19m ago (control) healthy, windows replaced, freshness ok
21m ago (control) state stale, windows kept (68)
1h in the future healthy, windows replaced (42), freshness ok
30d in the future healthy, windows replaced (42), freshness ok

parseQuotaCurrent (quota-current.ts:41-52) validates only that
measuredAt is a string, so nothing upstream of entryState catches this
either. The existing tests (test/quota-current.test.ts) construct entries
only with past offsets (iso(msAgo)), so the future case is uncovered.

Why it matters

The module's own contract (header, quota-current.ts:7-19) is the dashboard's
data-honesty rule for the quota plane: a read past the freshness bound
"surfaces as the pool's state (error/stale, with the reason) — never as
zeros, and the pool's older windows are never silently presented as
current". A future stamp defeats that rule in the other direction: one
clock-skewed or mis-stamped gatherer write (the gatherer runs on a 15-minute
tick on another host) silently presents its numbers as the freshest truth
for as long as the skew lasts — a month in the verified case — and the
choices computed from those windows steer real session routing.

Acceptance criteria

  • An entry whose measuredAt is more than a small clock-skew tolerance in
    the future (tolerance pinned in triage; it should be minutes, not the
    unbounded current behaviour) is NOT classified fresh-ok: it surfaces as
    stale (or error) with the pool's older windows not replaced.
  • The fresh-ok precedence sort cannot let a future-dated entry outrank a
    genuinely fresh entry for the same service.
  • Regression tests in test/quota-current.test.ts for measuredAt at
    +1h and a far-future date, alongside the existing past-offset controls.
  • No change to the freshness bound or semantics for past-dated reads.

Notes

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/normalOrdinary priority (the default)
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/sSmall: expected under 2 hours of work
    on Oct 28, 2026
  3. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (new-issue-creator-code-b)
    • Session / ID: new-issue-creator-code-b run 2026-10-27 19:38 CDT (2026-10-28T00:52Z)
    • Found via: filed this run
    • Task: Triage the quota-current freshness check: entryState bounds only past age, so a future-dated measuredAt is fresh-ok indefinitely, replaces pool windows, and outranks genuinely fresh entries in the precedence sort.
    • Expectation: effort/s — done when future-dated entries beyond a pinned skew tolerance surface as stale/error without replacing windows, with regression tests at +1h and far-future; past-offset behaviour unchanged.
    • Links: evidence probe (real overlayQuotaCurrent, quota-current.ts sha256 c528e1e3, Bun 1.4.2 on the laptop) in the goal hidden_files probe-2026-10-27-laneB-snapshots/ (probe2-quota-future.ts + out2.log); queue packet packet-1541.json (repo-health-code-pilot, triage)
  4. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 28, 2026
  5. 46 remaining items

  6. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  7. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  8. removed
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    on Oct 28, 2026
  9. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions