Skip to content

aggregator(quota-current): parseQuotaCurrent never checks windows entries — one null entry crashes the whole gatherer overlay and provenance still claims it applied #2416

Closed

Description

@dezren39

Problem

parseQuotaCurrent never checks the entries inside a provider's windows array, so one malformed entry crashes the whole Stage-2 quota overlay — and the live source's fail-soft catch then silently drops the gatherer data for every pool while its provenance still claims the gatherer was applied.

  • parseQuotaCurrent (pm-stack/aggregator/src/quota-current.ts:49-62) is the structural check for the gatherer's quota-current.json. For each provider it checks id/state/measuredAt/source types and that windows is an array (:60) — it never checks that the array's entries are objects.
  • pctWindows (quota-current.ts:85-97) dereferences every entry in its filter: typeof w.pctOfLimit === "number" (:87). A null entry throws TypeError: null is not an object (evaluating 'w.pctOfLimit'). A string entry survives the filter (its pctOfLimit is undefined), but an entry with a numeric pctOfLimit and a non-string name or a non-string resetsAt passes both layers verbatim into the pool's windows.
  • The live caller (src/sources/live.ts:775-782) appends · gatherer <generatedAt> to provenance.quota before calling overlayQuotaCurrent, inside a try/catch whose catch is commented "base view stands". When the overlay throws, the base view is indeed served — but with provenance claiming the gatherer overlay was applied, and with the fresh reads of every other, well-formed provider discarded too: one null in one provider's windows disables the whole overlay.

Evidence (verified this run on main 5a34fa70)

Sandbox Bun probe importing the real quota-current.ts (probe at /tmp/probe-laneB-aa/probe2.ts):

  • A v1 doc whose single provider has windows:[null], state ok, fresh measuredAt → parseQuotaCurrent returns non-null; overlayQuotaCurrent on a matching pool throws TypeError: null is not an object (evaluating 'w.pctOfLimit').
  • A window {name: 42, pctOfLimit: 50, resetsAt: {bad: true}} → passes parseQuotaCurrent; the overlay emits a pool window with name: 42 and resetsAt: {bad: true} verbatim.
  • Control (from the module's own tests/semantics): well-formed windows overlay normally — the defect is only the missing entry-level gate.

Why it matters

quota-current.json is rewritten every 15 minutes by a gatherer on another host; the parser is the trust boundary for that file, exactly like the feed section gates. Today a single corrupt entry produces the worst of both worlds: all fresh gatherer data is silently lost (pools fall back to dated reads with no signal anything is wrong) while the page's provenance asserts the gatherer was applied. Per-entry validation — drop or reject only the bad entry/provider — keeps one provider's corruption from taking the other providers' fresh reads down with it.

Acceptance criteria

  • parseQuotaCurrent (or pctWindows) validates window entries: non-object entries (including null) can never reach the pctOfLimit dereference; a bad entry is dropped or its provider rejected, without discarding other providers' entries.
  • Window name and resetsAt are type-checked before they can enter a pool's windows (string name; string-or-null resetsAt), matching the QuotaCurrentWindow contract in model.ts.
  • The live quota path's provenance only claims the gatherer overlay when it was actually applied (or the overlay can no longer throw on gate-passing input — either pin is acceptable, triage decides).
  • Regression tests pin: windows:[null] does not throw and the remaining providers still overlay; a numeric-name/object-resetsAt window is refused or normalized; well-formed files overlay unchanged.

Dedup

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. added
    queue/queuedHas a queued task in the Supabase agent queue
    effort/xsTrivial: expected under 30 minutes of work
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    on Oct 29, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: filed

    • Agent: new-issue-creator job (new-issue-creator-code-b, lane B)
    • Session / ID: cron job new-issue-creator-code-b, run 2026-10-29 14:50 CDT
    • Found via: filed this run
    • Task: Filed after verifying on main 5a34fa7 that parseQuotaCurrent (quota-current.ts:49-62) passes a windows:[null] entry and overlayQuotaCurrent then throws in pctWindows (:87), silently dropping the whole gatherer overlay at the live caller while provenance claims it applied; a triage packet is being enqueued to repo-health-code-pilot.
    • Expectation: effort/xs triage — pin per-entry validation depth and the provenance fix, then route a small_fix.
    • Links: evidence body in goal hidden_files/issue-code-quotacurrent-windows-body.md; probe /tmp/probe-laneB-aa/probe2.ts (sandbox Bun, real quota-current.ts)
  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  6. 95 remaining items

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    on Nov 2, 2026
  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — parked
    Agent: repo-worker-code (OpenChamber scheduled lane)
    Task: repo-health-code-pilot task 5318
    At: 2026-11-02T12:52:20Z
    State: parked
    Fresh evidence: #2416 OPEN and assigned to dezren39; canonical PR #4182 OPEN, non-draft, authored/assigned to dezren39.
    Disposition: parked for 30 minutes at the Drew-owned hard stop. No checks, diff, branch, worktree, or source inspected. work/assigned remains set.
    Resume: explicit Drew release/handoff or PR disposition; revalidate fresh before action.
    Links: #2416 · #4182 · task 5318

  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  10. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  11. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  12. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  13. dezren39 commented on Nov 2, 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)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/xsTrivial: expected under 30 minutes 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/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions