From c075ab981c9190bb5d72b969ef6e14c6ceaf8cb4 Mon Sep 17 00:00:00 2001 From: wtclaude Date: Wed, 22 Jul 2026 13:14:02 -0500 Subject: [PATCH] fix(moderation): windowValue must not fall back to the 30d total on a null column 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 --- server/src/model/moderation/moderation.pure.js | 2 +- server/test/moderation.test.js | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/server/src/model/moderation/moderation.pure.js b/server/src/model/moderation/moderation.pure.js index 34ac9f4..2d606b0 100644 --- a/server/src/model/moderation/moderation.pure.js +++ b/server/src/model/moderation/moderation.pure.js @@ -40,7 +40,7 @@ function reshapeWindows(rows) { // { d1, d7, d30 } sum row, coercing to a number and tolerating a null row. function windowValue(row, key) { if (!row) return 0 - const col = { '24h': row.d1, '7d': row.d7 }[key] ?? row.d30 + const col = { '24h': row.d1, '7d': row.d7, '30d': row.d30 }[key] return Number(col) || 0 } diff --git a/server/test/moderation.test.js b/server/test/moderation.test.js index 9104a5b..d320cf7 100644 --- a/server/test/moderation.test.js +++ b/server/test/moderation.test.js @@ -87,3 +87,12 @@ test('windowValue: null row (no rows in window) yields 0', () => { test('windowValue: null sum column yields 0', () => { assert.strictEqual(moderation.windowValue({ d1: null, d7: null, d30: null }, '7d'), 0) }) + +test('windowValue: a null narrow-window column never falls back to the 30d total', () => { + // Regression: an earlier rewrite used `{...}[key] ?? row.d30`, so a null d1/d7 + // returned the 30-day count instead of 0 — inflating the 24h/7d tiles. + const row = { d1: null, d7: null, d30: 5 } + assert.strictEqual(moderation.windowValue(row, '24h'), 0) + assert.strictEqual(moderation.windowValue(row, '7d'), 0) + assert.strictEqual(moderation.windowValue(row, '30d'), 5) +})