feat(012-admin-list-views): SLA-run, escalation-event, and product-catalog list endpoints
Adds GET /admin/sla-runs (filterable by status), GET /admin/escalation- events (capped, most-recent-first), and GET /admin/products (with integration status joined in, never the full ProductIntegration row). None of these existed as a single query before - only per-ticket or per-integration-id lookups did. Discovered while planning supporthub-web's 001-agent-admin-ui User Stories 6-7 (SLA/escalation monitoring, product catalog), the same way 011-agent-ticket-queue was discovered for User Story 1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
43158ff0c4
commit
3bd068b031
@@ -40,3 +40,13 @@
|
||||
- Deliberately narrow: read-only, no new persisted entity, no general search/filter API beyond
|
||||
the one filter (`status`) and one cap (`limit`) each list actually needs, per Assumptions.
|
||||
- All items pass; no revision iterations were needed.
|
||||
- **Implementation-time finding**: research.md's plan.md draft had described the existing
|
||||
single-ticket `GET /tickets/:ticketId/sla-run` as "agent-facing (fastify.authenticate)" — it's
|
||||
actually fully ungated (no preHandler at all). Didn't change this feature's own design
|
||||
(`GET /admin/sla-runs`/`GET /admin/escalation-events` still use `fastify.authenticate`, a
|
||||
deliberately more conservative choice than the existing route, matching spec.md's own
|
||||
"agent-usable" wording), but worth correcting for anyone reading research.md later.
|
||||
- No `SLA_RUN_STATUSES` constant existed anywhere before this feature — `SLARun.status` had
|
||||
only ever been written as free strings across the pause/resume/breach-detection code paths.
|
||||
Centralized it in `orchestration/sla/mapper/sla-run-status.ts` since this feature is the first
|
||||
caller that needs to validate against it, not just write it.
|
||||
|
||||
@@ -24,20 +24,20 @@ All file paths are relative to `supporthub-api/` (repo root).
|
||||
|
||||
**Independent Test**: Quickstart Scenario 1.
|
||||
|
||||
- [ ] T001 [P] [US1] Add `SLARunRepository.findAll(status?)` in
|
||||
- [x] T001 [P] [US1] Add `SLARunRepository.findAll(status?)` in
|
||||
`src/modules/orchestration/sla/repository/sla-run.repository.ts` — `include: { ticket:
|
||||
{ select: { id: true, code: true } } }`, optional `where: { status }`
|
||||
- [ ] T002 [US1] Add `SLAService.listAll(status?)` (or directly on the controller if no service
|
||||
- [x] T002 [US1] Add `SLAService.listAll(status?)` (or directly on the controller if no service
|
||||
method is warranted — check existing pattern) validating `status` against
|
||||
`SLA_RUN_STATUSES` (400 on an invalid value) in
|
||||
`src/modules/orchestration/sla/service/sla.service.ts` (depends on T001)
|
||||
- [ ] T003 [US1] Add `GET /admin/sla-runs` (`fastify.authenticate` only) in
|
||||
- [x] T003 [US1] Add `GET /admin/sla-runs` (`fastify.authenticate` only) in
|
||||
`src/modules/orchestration/sla/controller/` + `routes/`, projecting each row to
|
||||
`SlaRunListItem` (data-model.md) (depends on T002)
|
||||
- [ ] T004 [US1] Integration test covering Quickstart Scenario 1 (unfiltered returns all;
|
||||
- [x] T004 [US1] Integration test covering Quickstart Scenario 1 (unfiltered returns all;
|
||||
`status=breached` filters correctly; an invalid status is 400) in
|
||||
`tests/integration/admin-list-views.test.ts`
|
||||
- [ ] T005 [US1] Run Quickstart Scenario 1 locally and confirm all 3 steps pass
|
||||
- [x] T005 [US1] Run Quickstart Scenario 1 locally and confirm all 3 steps pass
|
||||
|
||||
---
|
||||
|
||||
@@ -45,18 +45,18 @@ All file paths are relative to `supporthub-api/` (repo root).
|
||||
|
||||
**Independent Test**: Quickstart Scenario 2.
|
||||
|
||||
- [ ] T006 [P] [US2] Add `EscalationEventRepository.findRecent(limit)` in
|
||||
- [x] T006 [P] [US2] Add `EscalationEventRepository.findRecent(limit)` in
|
||||
`src/modules/orchestration/escalation/repository/escalation-event.repository.ts` —
|
||||
`include: { ticket: { select: { id: true, code: true } } }`, `orderBy: { createdAt:
|
||||
'desc' }`, `take: limit`
|
||||
- [ ] T007 [US2] Add `GET /admin/escalation-events` (`fastify.authenticate` only, `limit` query
|
||||
- [x] T007 [US2] Add `GET /admin/escalation-events` (`fastify.authenticate` only, `limit` query
|
||||
param `z.coerce.number().int().positive().max(200).default(50)`) in
|
||||
`src/modules/orchestration/escalation/controller/` + `routes/`, projecting to
|
||||
`EscalationEventListItem` (depends on T006)
|
||||
- [ ] T008 [US2] Integration test covering Quickstart Scenario 2 (both events appear, most-
|
||||
- [x] T008 [US2] Integration test covering Quickstart Scenario 2 (both events appear, most-
|
||||
recent-first, automatic vs manual distinguished by `ruleId`) in
|
||||
`tests/integration/admin-list-views.test.ts` (same file as T004)
|
||||
- [ ] T009 [US2] Run Quickstart Scenario 2 locally and confirm it passes
|
||||
- [x] T009 [US2] Run Quickstart Scenario 2 locally and confirm it passes
|
||||
|
||||
---
|
||||
|
||||
@@ -64,26 +64,26 @@ All file paths are relative to `supporthub-api/` (repo root).
|
||||
|
||||
**Independent Test**: Quickstart Scenario 3.
|
||||
|
||||
- [ ] T010 [P] [US3] Add `ProductsRepository.findAllWithIntegrationStatus()` in
|
||||
- [x] T010 [P] [US3] Add `ProductsRepository.findAllWithIntegrationStatus()` in
|
||||
`src/modules/catalog/products/repository/products.repository.ts` — `include: {
|
||||
integration: { select: { status: true } } }`, `orderBy: { name: 'asc' }`
|
||||
- [ ] T011 [US3] Add `GET /admin/products` (`fastify.authenticate` + `requireRole('ADMIN')`) in
|
||||
- [x] T011 [US3] Add `GET /admin/products` (`fastify.authenticate` + `requireRole('ADMIN')`) in
|
||||
`src/modules/catalog/products/controller/` + `routes/`, projecting each row to
|
||||
`ProductCatalogListItem` (`integrationStatus: product.integration?.status ?? null` —
|
||||
never the full `ProductIntegration` row, research.md) (depends on T010)
|
||||
- [ ] T012 [US3] Integration test covering Quickstart Scenario 3 (active + no-integration
|
||||
- [x] T012 [US3] Integration test covering Quickstart Scenario 3 (active + no-integration
|
||||
products both correct; non-admin gets 403) in `tests/integration/admin-list-views.test.ts`
|
||||
(same file as T004/T008)
|
||||
- [ ] T013 [US3] Run Quickstart Scenario 3 locally and confirm both steps pass
|
||||
- [x] T013 [US3] Run Quickstart Scenario 3 locally and confirm both steps pass
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Polish & Cross-Cutting Concerns
|
||||
|
||||
- [ ] T014 [P] Update `specs/012-admin-list-views/checklists/requirements.md` Notes with any
|
||||
- [x] T014 [P] Update `specs/012-admin-list-views/checklists/requirements.md` Notes with any
|
||||
implementation-time findings
|
||||
- [ ] T015 Run `npx tsx scripts/check-architecture.ts` and `npm run lint`/`npm run typecheck`
|
||||
- [ ] T016 Full regression: `npm run test:unit` then the full integration suite against real
|
||||
- [x] T015 Run `npx tsx scripts/check-architecture.ts` and `npm run lint`/`npm run typecheck`
|
||||
- [x] T016 Full regression: `npm run test:unit` then the full integration suite against real
|
||||
Docker-provisioned Postgres/Redis, confirming nothing outside this feature regressed
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user