Skip to content

pm-stack(aggregator): applyCloudflareExport accepts negative used values — Supabase overlay refuses them #4942

Closed

Description

@dezren39

pm-stack(aggregator): applyCloudflareExport accepts negative used values — the Supabase overlay refuses them

Evidence

pm-stack/aggregator/src/saas-extract.ts, applyCloudflareExport (line ~831): the export-metric filter accepts any finite used:

.filter((m) => m && typeof m.id === "string" && typeof m.used === "number" && Number.isFinite(m.used))

The sibling overlay in the same file, applySupabaseExport (lines ~941-947), explicitly drops negative measurements:

!(typeof m.used === "number" && m.used < 0) &&
!(typeof m.limit === "number" && m.limit < 0),

and the Supabase billing gate in the same function also requires billedUsd >= 0 (line ~982). The Cloudflare path has no equivalent guard, so a negative used from the file-export document is copied onto the card and its percent is derived from it (line ~843: percent: ... Math.round((live.used / m.limit) * 1000) / 10), and the card is stamped sourceClass = "api" — presented as live measured data.

Verified this run (laptop bun probe at origin/main 115fe4f)

Fresh, in-cycle Cloudflare export doc with workers-requests: used = -500 (control kv-reads: used = 1420):

workers-requests used= -500 percent= -0
kv-reads used= 1420 percent= 0
sourceClass= api

The negative measurement is stored on the service card. With a larger magnitude (e.g. used = -5,000,000 against the 10M limit) the derived percent is -50 — a negative usage percentage rendered as measured fact.

Why it matters

The export document is produced by an external collector writing a file; a buggy or drifted collector value flows straight through this overlay onto the usage card as authoritative "live" data. The Supabase overlay in the same file already encodes the house rule — negative usage/limit measurements are not measurements and are dropped, keeping the tracker prose fallback. The Cloudflare overlay is the inconsistent half of the pair.

Acceptance criteria

  • applyCloudflareExport drops export metrics with used < 0 (mirroring applySupabaseExport's filter), so the affected metric keeps its prose/null state instead of a negative measured value.
  • A regression test in pm-stack/aggregator/test/cloudflare-export.test.ts: a fresh doc carrying a negative used leaves that metric unchanged (and does not set a negative percent), while other valid metrics in the same doc still overlay.
  • Existing cloudflare-export and saas test suites pass.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    source/creatorFiled by the new-issue-creator job
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    on Nov 3, 2026
  2. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: filed

    • Agent: new-issue-creator job (lane B, new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b run 2026-11-03 07:50 CST
    • Found via: filed this run
    • Task: applyCloudflareExport (saas-extract.ts) accepts negative used from the Cloudflare export doc and stores it on the card with a derived negative percent, while sibling applySupabaseExport in the same file explicitly drops negative used/limit metrics. Verified by laptop bun probe at origin/main 115fe4f: used=-500 stored, percent=-0, card stamped sourceClass=api.
    • Expectation: effort s — mirror the Supabase filter (drop used<0 metrics) + regression test in cloudflare-export.test.ts; done when negative metrics keep prose fallback and suites pass.
    • Links: queue packet packet-4942-fix.json (repo-health-code-pilot)
  3. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  4. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  5. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  6. 6 remaining items

  7. 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 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  11. added a commit that references this issue on Nov 4, 2026
  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  13. dezren39 commented on Nov 4, 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/pm-stackpm-stack (Pad/Grist) in developing-today/codekind/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/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