fix(moderation): windowValue must not fall back to the 30d total on a null column #97

Merged
whitlocktech merged 1 commits from fix/window-value-null-column into main 2026-07-22 18:15:48 +00:00
Member

Problem

windowValue (moderation dashboard tiles) mapped only the 24h/7d keys and used ?? row.d30 as the fallback:

const col = { '24h': row.d1, '7d': row.d7 }[key] ?? row.d30

Because ?? triggers on null/undefined, a null d1/d7 — which the function's comment says it tolerates — returned the 30-day total instead of 0, inflating the 24h/7d counts.

This is currently unreachable in production: the source rows come from SUM(created_at >= ?), which nulls d1/d7/d30 only in unison (empty set), so whenever d30 is non-null the same rows make d1/d7 a numeric 0. But the contract is wrong, and the existing test used an all-null row ({d1:null, d7:null, d30:null}) that masked it.

Introduced by the code-smell cleanup in 12d50fd; the sibling discordId regex bug from the same commit is #96.

Fix

Map all three window keys explicitly so each reads its own column, and let a null coerce to 0 via Number(col) || 0 (no ?? fallback):

const col = { '24h': row.d1, '7d': row.d7, '30d': row.d30 }[key]
return Number(col) || 0

This stays Sonar-clean (no nested ternary, no cross-column fallthrough).

Test

Adds a regression test that would have caught the original — a null narrow-window column with a non-null d30:

const row = { d1: null, d7: null, d30: 5 }
windowValue(row, '24h') === 0   // was 5 under the old code
windowValue(row, '7d')  === 0   // was 5
windowValue(row, '30d') === 5

Full moderation suite passes (14/14).


AI-assisted: this change was authored with Claude Code.

🤖 Generated with Claude Code

## Problem `windowValue` (moderation dashboard tiles) mapped only the `24h`/`7d` keys and used `?? row.d30` as the fallback: ```js const col = { '24h': row.d1, '7d': row.d7 }[key] ?? row.d30 ``` Because `??` triggers on `null`/`undefined`, a **null `d1`/`d7`** — which the function's comment says it tolerates — returned the **30-day total** instead of `0`, inflating the 24h/7d counts. This is currently **unreachable in production**: the source rows come from `SUM(created_at >= ?)`, which nulls `d1`/`d7`/`d30` only *in unison* (empty set), so whenever `d30` is non-null the same rows make `d1`/`d7` a numeric `0`. But the contract is wrong, and the existing test used an all-null row (`{d1:null, d7:null, d30:null}`) that masked it. Introduced by the code-smell cleanup in `12d50fd`; the sibling `discordId` regex bug from the same commit is #96. ## Fix Map all three window keys explicitly so each reads its own column, and let a null coerce to `0` via `Number(col) || 0` (no `??` fallback): ```js const col = { '24h': row.d1, '7d': row.d7, '30d': row.d30 }[key] return Number(col) || 0 ``` This stays Sonar-clean (no nested ternary, no cross-column fallthrough). ## Test Adds a regression test that would have caught the original — a null narrow-window column with a non-null `d30`: ```js const row = { d1: null, d7: null, d30: 5 } windowValue(row, '24h') === 0 // was 5 under the old code windowValue(row, '7d') === 0 // was 5 windowValue(row, '30d') === 5 ``` Full moderation suite passes (14/14). --- AI-assisted: this change was authored with Claude Code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-07-22 18:14:22 +00:00
fix(moderation): windowValue must not fall back to the 30d total on a null column
All checks were successful
PR Checks / bot-install (pull_request) Successful in 15s
PR Checks / client-build (pull_request) Successful in 24s
PR Checks / server-tests (pull_request) Successful in 39s
c075ab981c
windowValue mapped only the 24h/7d keys and used `?? row.d30` as the fallback:

    const col = { '24h': row.d1, '7d': row.d7 }[key] ?? row.d30

so a null d1/d7 (which the function is documented to tolerate) returned the
30-day count instead of 0, inflating the 24h/7d moderation tiles. It happens to
be masked today because `SUM(created_at >= ?)` nulls d1/d7/d30 only in unison,
but the contract is wrong and the existing test used an all-null row that hid it.

Map all three window keys explicitly so each reads its own column and a null
coerces to 0 via `Number(col) || 0`. Add a regression test with a null narrow
column and a non-null d30.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech approved these changes 2026-07-22 18:15:41 +00:00
whitlocktech merged commit ebfae765d9 into main 2026-07-22 18:15:48 +00:00
whitlocktech deleted branch fix/window-value-null-column 2026-07-22 18:15:49 +00:00
Sign in to join this conversation.
No description provided.