105 lines
4.9 KiB
Markdown
105 lines
4.9 KiB
Markdown
# Implementation Plan: Admin List Views
|
|||
|
|
|
||
|
|
**Branch**: `012-admin-list-views` | **Date**: 2026-09-07 | **Spec**: [spec.md](./spec.md)
|
||
|
|
|
||
|
|
**Input**: Feature specification from `specs/012-admin-list-views/spec.md`
|
||
|
|
|
||
|
|
## Summary
|
||
|
|
|
||
|
|
Adds three read-only endpoints, each a straightforward `findMany` on an already-existing model
|
||
|
|
plus a small ticket-id/code projection: `GET /admin/sla-runs` (optional `?status=`),
|
||
|
|
`GET /admin/escalation-events` (optional `?limit=`), and `GET /admin/products` (products joined
|
||
|
|
to their integration's status). No new persisted entity, no write capability.
|
||
|
|
|
||
|
|
## Technical Context
|
||
|
|
|
||
|
|
**Language/Version**: TypeScript 5.4 / Node.js 20+ (unchanged).
|
||
|
|
|
||
|
|
**Primary Dependencies**: None new — Prisma only.
|
||
|
|
|
||
|
|
**Storage**: PostgreSQL via Prisma. No schema change — every field already exists; these are
|
||
|
|
projections over `SLARun`, `EscalationEvent`, and `Product`/`ProductIntegration`.
|
||
|
|
|
||
|
|
**Testing**: Vitest — integration tests against real Postgres/Redis for each endpoint's filter/
|
||
|
|
ordering/projection behavior, plus one admin-role-gating check for `GET /admin/products`.
|
||
|
|
|
||
|
|
**Target Platform**: Same Fastify modular monolith. Modifies `orchestration/sla` (new route +
|
||
|
|
repository method), `orchestration/escalation` (new route + repository method), and
|
||
|
|
`catalog/products` (new admin route + repository method) — no new module, each list lives in
|
||
|
|
the module that already owns its underlying model.
|
||
|
|
|
||
|
|
**Project Type**: Backend service — single project.
|
||
|
|
|
||
|
|
**Performance Goals**: Each list is one indexed/simple query — `SLARun` has no per-status
|
||
|
|
index today (status is a small string column, not indexed), acceptable at this stage per
|
||
|
|
spec.md's own "no general search API" scoping; revisit if a future feature's data volume
|
||
|
|
demands one.
|
||
|
|
|
||
|
|
**Constraints**: FR-004 — read-only, no new write path. The product-catalog list must not leak
|
||
|
|
`ProductIntegration.credentialRef` (encrypted secret) or any other sensitive integration field
|
||
|
|
— only `status` is projected.
|
||
|
|
|
||
|
|
**Scale/Scope**: Three new GET routes across three existing modules, three new repository
|
||
|
|
methods, no new module, no schema migration. Explicitly excludes: pagination (spec.md
|
||
|
|
Assumptions — `limit` only on the escalation-event list), and any filter beyond `status`/`limit`.
|
||
|
|
|
||
|
|
## Constitution Check
|
||
|
|
|
||
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||
|
|
|
||
|
|
| Principle / Section | Check | Result |
|
||
|
|
|---|---|---|
|
||
|
|
| I. SaaS Is the Sole Identity & Access Authority | Purely internal SupportHub domain (SLA/escalation/product-catalog monitoring) — no SaaS/customer identity involved. | PASS — N/A |
|
||
|
|
| II. Configuration Over Hardcoding | No new configurable values. | PASS — N/A |
|
||
|
|
| III. Layered Architecture With Enforced Module Boundaries | Each list lives in the module that already owns its model (`orchestration/sla`, `orchestration/escalation`, `catalog/products`) — no cross-module reach-through; the ticket id/code projection reads `ticketsRepository`'s own public surface via `ticketing/tickets`'s existing `index.ts`. | PASS |
|
||
|
|
| IV. AI Recommends, Deterministic Policy Decides | Not applicable. | PASS — N/A |
|
||
|
|
| V. Evidence-Based Verification | Not applicable. | PASS — N/A |
|
||
|
|
| VI. Durable Audit & History | Not applicable — no new mutable state. | PASS — N/A |
|
||
|
|
| VII. Concurrency-Safe, Durable Job Handling | Read-only queries; no concurrency concern. | PASS |
|
||
|
|
| VIII. Problem and Ticket Are Separate, Related Entities | Not applicable. | PASS — N/A |
|
||
|
|
| Technology & Platform Constraints | No new dependencies or infrastructure. | PASS |
|
||
|
|
|
||
|
|
No violations requiring Complexity Tracking justification.
|
||
|
|
|
||
|
|
## Project Structure
|
||
|
|
|
||
|
|
### Documentation (this feature)
|
||
|
|
|
||
|
|
```text
|
||
|
|
specs/012-admin-list-views/
|
||
|
|
├── plan.md
|
||
|
|
├── research.md
|
||
|
|
├── data-model.md
|
||
|
|
├── quickstart.md
|
||
|
|
├── contracts/
|
||
|
|
└── tasks.md
|
||
|
|
```
|
||
|
|
|
||
|
|
### Source Code (repository root)
|
||
|
|
|
||
|
|
```text
|
||
|
|
supporthub-api/
|
||
|
|
└── src/
|
||
|
|
└── modules/
|
||
|
|
├── orchestration/
|
||
|
|
│ ├── sla/ # MODIFIED — GET /admin/sla-runs
|
||
|
|
│ │ ├── controller/ routes/
|
||
|
|
│ │ └── repository/ (new findAll(status?) method)
|
||
|
|
│ └── escalation/ # MODIFIED — GET /admin/escalation-events
|
||
|
|
│ ├── controller/ routes/
|
||
|
|
│ └── repository/ (new findRecent(limit?) method)
|
||
|
|
└── catalog/
|
||
|
|
└── products/ # MODIFIED — GET /admin/products
|
||
|
|
├── controller/ routes/
|
||
|
|
└── repository/ (new findAllWithIntegrationStatus() method)
|
||
|
|
└── tests/
|
||
|
|
└── integration/ # one new test file per endpoint's own scenarios
|
||
|
|
```
|
||
|
|
|
||
|
|
**Structure Decision**: Single project, no new module — each endpoint extends the module that
|
||
|
|
already owns its underlying data, matching 011-agent-ticket-queue's own precedent.
|
||
|
|
|
||
|
|
## Complexity Tracking
|
||
|
|
|
||
|
|
*No constitution violations — table intentionally omitted.*
|