From ad93c2dfa64309c1af22f648d09cf67fc4cbf051 Mon Sep 17 00:00:00 2001 From: Robin Bowes Date: Tue, 3 Nov 2026 17:38:02 +0000 Subject: [PATCH 1/2] analytics: scope /facts/status to the caller's organisation checkFactTableFreshness read MAX() over every tenant, so one organisation's admin saw when any other organisation last had activity, and a busy tenant could hide another's stale fact table. Both queries now filter on tenant_id, and a fact table's source must carry it, as the fact table already does. Co-Authored-By: Claude Opus 5.5 --- .../analytics/api/routes/analytics-pages.ts | 2 +- .../analytics/services/fact-tables/CLAUDE.md | 5 ++-- .../services/fact-tables/freshness.ts | 16 +++++++---- .../services/fact-tables/registry.ts | 3 ++- .../tests/api/analytics-pages.test.ts | 16 +++++++++++ .../tests/api/fact-table-refresh.test.ts | 27 ++++++++++++++++++- plugins/analytics/docs/upgrades/unreleased.md | 20 +++++++++++--- 7 files changed, 76 insertions(+), 13 deletions(-) diff --git a/plugins/analytics/apps/web/src/plugins/analytics/api/routes/analytics-pages.ts b/plugins/analytics/apps/web/src/plugins/analytics/api/routes/analytics-pages.ts index 9737671..c92e220 100644 --- a/plugins/analytics/apps/web/src/plugins/analytics/api/routes/analytics-pages.ts +++ b/plugins/analytics/apps/web/src/plugins/analytics/api/routes/analytics-pages.ts @@ -285,7 +285,7 @@ analyticsPagesRouter.post('/templates/recreate', async c => { analyticsPagesRouter.get('/facts/status', async c => { const ctx: RequestCtx = requestCtx(c) guardFactTables(ctx, 'read fact-table status') - return c.json({ items: await checkFactTableFreshness(ctx.db) }) + return c.json({ items: await checkFactTableFreshness(ctx.db, ctx.tenantId) }) }) /** diff --git a/plugins/analytics/apps/web/src/plugins/analytics/services/fact-tables/CLAUDE.md b/plugins/analytics/apps/web/src/plugins/analytics/services/fact-tables/CLAUDE.md index fc51f88..596241a 100644 --- a/plugins/analytics/apps/web/src/plugins/analytics/services/fact-tables/CLAUDE.md +++ b/plugins/analytics/apps/web/src/plugins/analytics/services/fact-tables/CLAUDE.md @@ -12,8 +12,9 @@ read by the `TenantActivityDaily` cube. `DELETE … WHERE tenant_id = $1` then `INSERT INTO t ()