Files
support_backend/specs/015-reporting-dashboards/tasks.md
T
saqib mirandClaude Sonnet 5 d65683641a feat(015-reporting-dashboards): four real reporting/analytics endpoints
Wires the pre-scaffolded, unused platform/reports module (ReportsService
.generateSummaryReport previously returned {}) into four real, admin-
gated dashboards matching docs/09-testing-observability-cicd.md's own
table:

- GET /admin/reports/management: total cases, AI-resolved, human-
  escalated, resolved/open, SLA compliance/breaches, escalation count,
  average response/resolution time.
- GET /admin/reports/product/:externalProductId: support volume,
  problem-category breakdown, recurring problems, AI-resolution/human-
  escalation rate, top error codes.
- GET /admin/reports/support: current per-agent workload, SLA at-risk/
  breached counts, escalation count, response/resolution performance.
- GET /admin/reports/ai: AI resolution/human-handoff rate, failed-
  troubleshooting-then-escalated rate, knowledge-match rate, confidence
  distribution (reusing 005-ai-support's own decideConfidenceBand),
  tool invocation success/failure.

Every rate/average is number|null -- null means no qualifying data in
range, never a computed NaN or a misleading 0. Adds one new durable
table, ErrorCodeLookup, since 014-full-observability's own equivalent
metric is a process-lifetime Prometheus counter unusable for a
historical "top errors" report.

Verified end-to-end against real Postgres/Redis: every figure checked
against hand-computed expected values, including a no-activity range
(all-zero counts, all-null rates) and cross-product isolation.

Also fixes a real regression the new ErrorCodeLookup FK caused in the
pre-existing known-issues.test.ts (its afterAll deleted ErrorCode rows
before the now-referencing lookup rows).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 11:59:38 +05:30

9.4 KiB

description
description
Task list for 015-reporting-dashboards

Tasks: Reporting and Analytics Dashboards

Input: Design documents from specs/015-reporting-dashboards/

Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/reports-api-contract.md, quickstart.md

Organization: Tasks are grouped by user story (US1 = P1 Management, US2 = P1 Product, US3 = P2 Support, US4 = P2 AI). All four share the Foundational phase (schema, config, shared helpers, module scaffolding) but are otherwise independent of each other.

Format: [ID] [P?] [Story] Description

All file paths are relative to supporthub-api/ (repo root).


Phase 1: Foundational (Blocking Prerequisites)

  • T001 Add REPORTING_DEFAULT_WINDOW_DAYS (default 30), REPORTING_SLA_RISK_THRESHOLD_MINUTES (default 60), and REPORTING_TOP_N_LIMIT (default 10) to src/config/env.ts, exposed via a new reportingConfig in src/config/reporting.ts (or added to an existing config file, matching this codebase's own per-feature config-file convention)
  • T002 Add the ErrorCodeLookup model to prisma/schema.prisma per data-model.md, generate the migration via prisma migrate diff --from-url <db-url> --to-schema-datamodel ./prisma/schema.prisma --script, hand-write it into prisma/migrations/<timestamp>_add_error_code_lookup/migration.sql, apply via prisma migrate deploy against the throwaway test database (depends on T001 only in that both are Foundational — no code dependency)
  • T003 Add ai-support/knowledge/repository/error-code-lookup.repository.tscreate(errorCodeId, productId), exported from the knowledge module's repository index (depends on T002)
  • T004 [P] Call the new repository's create(...) from ai-support/knowledge/service/error-codes.service.ts's existing findKnownIssuesByErrorCode, alongside (not replacing) 014's own knownErrorLookupsCounter.inc(...) call at that same call site (depends on T003)
  • T005 [P] Add platform/reports/mapper/date-range.ts — parses/validates from/to query params, defaulting via T001's reportingConfig.defaultWindowDays, throwing ValidationError when from > to (depends on T001)
  • T006 [P] Add platform/reports/mapper/rate.ts — a shared computeRate(numerator, denominator): number | null and computeAverageSeconds(durations: number[]): number | null pair, both returning null (never NaN/0) when there's no qualifying data (research.md §3) — no dependency, pure functions
  • T007 Scaffold platform/reports/schema/ (query-param zod schema using T005's date-range parsing), platform/reports/controller/reports.controller.ts (empty methods to be filled in per user story below), platform/reports/routes/reports.routes.ts registering all four routes behind requireRole('ADMIN'), and update platform/reports/index.ts to export the new public surface, replacing generateSummaryReport's stub entirely (depends on T005, T006)

Checkpoint: Config, schema, shared helpers, and module scaffolding in place. Each dashboard can now be built independently.


Phase 2: User Story 1 - Management sees organization-wide support health (Priority: P1)

Goal: GET /admin/reports/management returns real figures per data-model.md's ManagementDashboard shape.

Independent Test: Quickstart Scenario 1.

Tests for User Story 1

  • T008 [P] [US1] Unit tests for T006's computeRate/computeAverageSeconds (empty input -> null; a real mix -> the correct value) in tests/unit/platform/reports/rate-helpers.test.ts

Implementation for User Story 1

  • T009 [US1] Add platform/reports/repository/management.repository.ts — one method per research.md §2's Management table row (ticket counts by status, SLA-run outcome counts, response/resolution duration row-fetches for T006 to average) (depends on T007)
  • T010 [US1] Add ReportsService.getManagementDashboard(range) composing T009's repository calls into the ManagementDashboard shape, reusing the Resolution.resolvedBy convention (research.md §4) for the AI-vs-human split (depends on T009)
  • T011 [US1] Wire GET /admin/reports/management to the controller/service (depends on T010)
  • T012 [US1] Integration test covering Quickstart Scenario 1 (real tickets in various terminal states, a met and a breached SLA run, verified figure-by-figure; a no-activity range returns all-zero counts and all-null rates) in tests/integration/platform-reports/management-dashboard.test.ts (depends on T011)

Checkpoint: Quickstart Scenario 1 passes.


Phase 3: User Story 2 - See support broken down by product (Priority: P1)

Goal: GET /admin/reports/product/:externalProductId returns real figures per ProductDashboard.

Independent Test: Quickstart Scenario 2.

Implementation for User Story 2

  • T013 [P] [US2] Add platform/reports/repository/product.repository.ts — ticket/problem queries scoped by productId, plus a query against T003's ErrorCodeLookup table for the top-N ranking (reportingConfig.topNLimit) (depends on T007)
  • T014 [US2] Add ReportsService.getProductDashboard(externalProductId, range), 404-ing via NotFoundError when the product doesn't resolve (FR-006) before running any aggregation query (depends on T013)
  • T015 [US2] Wire GET /admin/reports/product/:externalProductId (depends on T014)
  • T016 [US2] Integration test covering Quickstart Scenario 2 (two products' data never cross-contaminating each other's figures; an unknown product 404s) in tests/integration/platform-reports/product-dashboard.test.ts (depends on T015)

Checkpoint: Quickstart Scenario 2 passes.


Phase 4: User Story 3 - Support sees team workload and performance (Priority: P2)

Goal: GET /admin/reports/support returns real figures per SupportDashboard.

Independent Test: Quickstart Scenario 3.

Implementation for User Story 3

  • T017 [P] [US3] Add platform/reports/repository/support.repository.ts — current Assignment workload-by-agent query, SLARun at-risk/breached queries (resolutionDueAt within reportingConfig.slaRiskThresholdMinutes of now, per research.md §2) (depends on T007)
  • T018 [US3] Add ReportsService.getSupportDashboard(range) (depends on T017)
  • T019 [US3] Wire GET /admin/reports/support (depends on T018)
  • T020 [US3] Integration test covering Quickstart Scenario 3 (real per-agent assignment counts; a near-due-but-not-breached run counted as at-risk, distinct from breached) in tests/integration/platform-reports/support-dashboard.test.ts (depends on T019)

Checkpoint: Quickstart Scenario 3 passes.


Phase 5: User Story 4 - See how well the AI is performing (Priority: P2)

Goal: GET /admin/reports/ai returns real figures per AiDashboard.

Independent Test: Quickstart Scenario 4.

Tests for User Story 4

  • T021 [P] [US4] Unit test: the confidence-distribution bucketing reuses decideConfidenceBand (005-ai-support) against aiConfig defaults, not a reimplemented threshold check, in tests/unit/platform/reports/confidence-distribution.test.ts

Implementation for User Story 4

  • T022 [US4] Add platform/reports/repository/ai.repository.tsAISupportSession outcome counts, AIDiagnosis confidence fetch, AIKnowledgeReference presence-per-session query, AIAction/AIActionResult outcome counts (depends on T007)
  • T023 [US4] Add ReportsService.getAiDashboard(range), bucketing confidence via decideConfidenceBand + aiConfig.defaultHighConfidence/defaultLowConfidence (research.md §7) (depends on T022, T021)
  • T024 [US4] Wire GET /admin/reports/ai (depends on T023)
  • T025 [US4] Integration test covering Quickstart Scenario 4 (real AI sessions to mixed outcomes, mixed tool results, a spread of diagnosis confidence values) in tests/integration/platform-reports/ai-dashboard.test.ts (depends on T024)

Checkpoint: Quickstart Scenario 4 passes. All four dashboards work independently and together — this feature's full scope.


Phase 6: Polish & Cross-Cutting Concerns

  • T026 [P] Update specs/015-reporting-dashboards/checklists/requirements.md Notes with any implementation-time findings
  • T027 Run npx tsx scripts/check-architecture.ts and npm run lint/npm run typecheck
  • T028 Full regression: npm run test:unit then the full integration suite against real Docker-provisioned Postgres/Redis, confirming nothing outside this feature regressed (particularly error-codes.service.ts's own existing tests, now touched by T004)

Dependencies & Execution Order

  • Foundational (Phase 1): No dependencies — BLOCKS all four user stories
  • User Story 1 (Phase 2): Depends on Foundational — independent of US2/US3/US4
  • User Story 2 (Phase 3): Depends on Foundational — independent of US1/US3/US4
  • User Story 3 (Phase 4): Depends on Foundational — independent of US1/US2/US4
  • User Story 4 (Phase 5): Depends on Foundational — independent of US1/US2/US3
  • Polish (Phase 6): Depends on all four user stories