From 103acc70dfaa4bf1f7f757f28585023b0f250403 Mon Sep 17 00:00:00 2001 From: ddonaldson130 Date: Thu, 9 Jul 2026 03:15:17 -0400 Subject: [PATCH] fix(dashboard): scope reliability endpoints by projectId (FUX-042) Reliability GET and reset endpoints were always using the server's root store, ignoring projectId. Mirror the Command Center pattern by using getProjectIdFromRequest and getScopedStore so multi-project servers report per-project reliability stats. Refs FUX-042 --- packages/dashboard/src/server.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/dashboard/src/server.ts b/packages/dashboard/src/server.ts index 3ed2acf85..124c588fa 100644 --- a/packages/dashboard/src/server.ts +++ b/packages/dashboard/src/server.ts @@ -1595,6 +1595,8 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT }); app.get("/api/health/reliability", async (req, res) => { + const projectId = getProjectIdFromRequest(req); + const scopedStore = projectId ? await getScopedStore(projectId) : store; const rawWindowDays = req.query.windowDays; const parsedWindowDays = rawWindowDays === undefined ? 7 : Number.parseInt(String(rawWindowDays), 10); @@ -1606,7 +1608,7 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT return; } - const settings = await store.getSettings(); + const settings = await scopedStore.getSettings(); const resetAt = typeof settings.reliabilityStatsResetAt === "string" ? settings.reliabilityStatsResetAt : null; const nowMs = Date.now(); @@ -1617,11 +1619,11 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT const endIso = new Date(nowMs).toISOString(); const [runAuditEvents, enteredByDay, bouncedByDay, durationEvents, mergedTaskIds] = await Promise.all([ - Promise.resolve(store.getRunAuditEvents({ startTime: startIso, endTime: endIso, limit: 50_000 })), - store.getTaskMovedCountsByDay({ since: startIso, until: endIso, toColumn: "in-review" }), - store.getTaskMovedCountsByDay({ since: startIso, until: endIso, fromColumn: "in-review", toColumn: "in-progress" }), - store.getInReviewDurationEvents({ since: startIso, until: endIso }), - store.getTaskMergedTaskIds({ since: startIso, until: endIso }), + Promise.resolve(scopedStore.getRunAuditEvents({ startTime: startIso, endTime: endIso, limit: 50_000 })), + scopedStore.getTaskMovedCountsByDay({ since: startIso, until: endIso, toColumn: "in-review" }), + scopedStore.getTaskMovedCountsByDay({ since: startIso, until: endIso, fromColumn: "in-review", toColumn: "in-progress" }), + scopedStore.getInReviewDurationEvents({ since: startIso, until: endIso }), + scopedStore.getTaskMergedTaskIds({ since: startIso, until: endIso }), ]); const postMergeByDay = postMergeAuditFailuresPerDay(runAuditEvents, effectiveStartMs, nowMs); @@ -1698,9 +1700,11 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT }); }); - app.post("/api/health/reliability/reset", async (_req, res) => { + app.post("/api/health/reliability/reset", async (req, res) => { + const projectId = getProjectIdFromRequest(req); + const scopedStore = projectId ? await getScopedStore(projectId) : store; const resetAt = new Date().toISOString(); - await store.updateSettings({ reliabilityStatsResetAt: resetAt }); + await scopedStore.updateSettings({ reliabilityStatsResetAt: resetAt }); res.json({ resetAt }); });