Skip to content

aggregator(feed): isBurnSegment accepts negative tokens, non-date from/to and inverted ranges — garbage burn rows survive sanitizeQuotaView and render as measured history #3428

Closed

Description

@dezren39

Problem

isBurnSegment — the element guard for the quota view's burn history, used by sanitizeQuotaView in pm-stack/aggregator/src/feed.ts:322-331 — checks only types:

typeof v.provider === "string" &&
typeof v.pool === "string" &&
typeof v.from === "string" &&
typeof v.to === "string" &&
isFiniteNumber(v.tokens)

So a segment with a negative token count, a non-date from/to, an impossible calendar date, or an inverted range (from after to) passes the gate, is counted as well-formed, and renders in the "Burn between resets" table (src/render.ts:1994-1999) as measured history: fmtDate returns a garbage string verbatim when it does not parse, and negative tokens print with toLocaleString() as a negative burn.

Evidence (verified this run, main 574c04a)

Laptop probe ~/git/fleet/probe-2026-11-01-laneA-feedquota/ (copies of the real src/ tree, feed.ts md5 e564f17aea918d5281fd37d433a01017, identical to main; bun 1.4.2, real isBurnSegment). Control: a well-formed segment passes. Also passing (isBurnSegment=true):

  • tokens: -12345
  • from: "banana"
  • to: "2026-02-30T01:00:00Z" (a day that never existed; Date.parse rolls it to Mar 2)
  • from: "2026-10-02T00:00:00Z", to: "2026-10-01T01:00:00Z" (inverted range)

The shared strict primitives already exist in the same package — isIsoDate and isNonNegative in src/validate.ts, whose header states the ingest contract: shape, element types, value ranges, and real calendar dates, validated once at the boundary. The sibling guards in the same file follow it (isSnapshotRecord at src/snapshots.ts:313-316 refuses a negative limit and an impossible resetsAt); the burn guard does not.

Why it matters

Burn segments are the historical record the quota page presents as measured throughput between resets. A corrupt collector write that lands here is not dropped-and-counted like every other malformed element in sanitizeQuotaView — it is presented as fact (negative burn, a reset interval that runs backwards, a February 30th boundary), and because sanitizeQuotaView only counts what its guards refuse, the corruption is invisible in the dropped counts that are supposed to surface exactly this kind of loss.

Acceptance criteria

Dedup

Distinct from the quota-window gate gap filed alongside this one (different guard, different consumers — pool state/guidance vs the burn-history table; cross-linked there), #3365 (snapshot rollup guard), #2470 (quota-extract resetsAt emission), and #3364 (coverage census guard). Searched open + closed for isBurnSegment before filing.

Activity

  1. developing-today commented on Nov 1, 2026

    @developing-today
    Contributor
  2. added
    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/lowNice to have; do when convenient
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 1, 2026
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. added
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  5. 8 remaining items

  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/queuedHas a queued task in the Supabase agent queue
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  9. added a commit that references this issue on Nov 2, 2026
  10. 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/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/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