Repository navigation
Description
Problem
parseDbSize and parseRequestCount in pm-stack/supabase-export/supabase-quota-export.mjs convert string values with bare Number(...) and then check only finiteness / sign — so strings that are not decimal integer literals are accepted as real measurements:
parseDbSize(:91-98):const n = typeof bytes === "string" ? Number(bytes) : bytes;thenNumber.isFinite(n) && n >= 0.parseRequestCount(:101-105): the same conversion forcount.
pg_database_size returns an integer byte count and the api-requests-count endpoint returns an integer count; neither can legitimately be empty, hexadecimal, scientific-notation, or fractional. But:
""/" "→0— an empty/drifted db-size row is published as a measured 0-byte database (buildMetricsstampsused: 0, detail0 bytes, and the run counts it as measured, so the tick does not fail or even leave the metric null). An empty request count is likewise recorded as "0 API requests observed" in the egress detail."0x10"→16,"1e3"→1000— non-decimal spellings are silently reinterpreted."1.5"(string or number) →1.5— a fractional byte/request count passes.
This breaks the file's own fail-closed contract: the header says an endpoint that answers "a shape this parser does not know" is unparseable (exit 6), parseDbSize throws for "nope" / negative rows, parseRequestCount returns null for "nope" / missing rows, and the existing test parsers reject shape drift pins that intent — it just never tries the coercion edge cases. The fleet has hit this exact Number("") === 0 trap before in pkgs/id's world-seed parser (#707: only a run of decimal digits counts).
Evidence (verified this run, main 72545cb9)
Laptop probe (~/git/fleet/probe-2026-10-30-laneB-supacount/probe.mjs, real module imported from the laptop clone at the same HEAD; module md5 68a77fe41d96785c23b5a72c068c0da5 matches the sandbox clone):
dbSize control "123" => 123
dbSize control 123 => 123
dbSize "" => 0 (expected: throw unparseable)
dbSize " " => 0 (expected: throw unparseable)
dbSize "0x10" => 16 (expected: throw unparseable)
dbSize "1e3" => 1000 (expected: throw unparseable)
dbSize "1.5" / 1.5 => 1.5 (expected: throw unparseable)
dbSize "nope" / "-5" => THROWS unparseable (correct)
reqCount control "12" => 12
reqCount "" / " " => 0 (expected: null)
reqCount "0x10" / "1e3" => 16 / 1000 (expected: null)
reqCount "1.5" => 1.5 (expected: null)
reqCount "nope" / missing => null (correct)
Dedup: #2492 covers billedFromAddons in the same file (per-addon price shapes) and cites parseDbSize only as the fail-closed contrast for "nope"-style inputs; the empty/hex/scientific/fractional coercion acceptance here is not covered by it or by any other open/closed issue found in title+keyword search.
Why it matters
The db-size metric is the exporter's primary Free-plan wedge measure and carries the paid-trigger flag. A shape-drifted SQL row that reads as a measured 0 hides real usage behind the strongest trust marker the format has, instead of surfacing as unparseable / a null metric the way every other drift in this file does. The request count feeds the egress detail text the same way.
Acceptance criteria
-
parseDbSizethrowsExportError("unparseable", 6, …)for byte values that are not non-negative integers: empty/whitespace strings, non-decimal spellings (0x10,1e3), and fractional values (string or number). Well-formed integer strings and numbers are unchanged. -
parseRequestCountreturnsnullfor the same classes of count values; well-formed integer strings and numbers are unchanged. - Tests extend the existing
parsers reject shape driftcase with these inputs for both parsers; the existing test suite still passes. - Triage pins the exact strictness (e.g. decimal-digits-only string form vs integer-valued check) — either is acceptable as long as the cases above fail closed.
Activity
dezren39 commentedon Oct 30, 2026
🤖 Agent note · filed
dezren39 commentedon Oct 31, 2026
🤖 Design-architect pass 25 (2026-10-31) — agent note: this issue is ADOPTED as Phase 3 (with #2791) of design #3005 (a measurement is a plain decimal), linked as its sub-issue and labelled
source/design-architect. Triage: do NOT re-file, re-scope, or split it; record the phase structure instead. The design generalises the landed sibling gate (meta-exporter via #2789, CLOSED) toparseDbSize/parseRequestCount: plain-decimal spellings only, with this exporter's existing not-measured outcome on refusal. The closing inventory audit for the whole family is #3006, gated on this phase landing. Flag genuine blockers on #3005.8 remaining items
dezren39 commentedon Nov 1, 2026
🤖 Agent note · done
developing-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 6814 (small_fix, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
parseDbSizeandparseRequestCounton issue supabase-export: parseDbSize/parseRequestCount accept empty, hex, scientific and fractional strings as real measurements — Number("") reads a drifted db-size row as a measured 0-byte database #2743.dezren39 commentedon Nov 3, 2026
🤖 Agent note · done (PR opened)
bun test pm-stack/supabase-export/supabase-quota-export.test.mjs— 12 passed, 65 assertions;git diff --check— passed.