docs(001-agent-admin-ui): extend data model, contract, and tasks for User Stories 4-7
Backed by supporthub-api's new 012-admin-list-views feature (SLA-run, escalation-event, product-catalog, and knowledge-governance list endpoints) - the same lib/api function -> TanStack Query hook -> features/* component -> page pattern established for User Stories 0-3 applies directly, so no new Foundational work or fresh research decisions are needed for this continuation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b20bcc7aff
commit
f1dc7494d5
@@ -55,6 +55,48 @@ basic form completeness (required-field presence), matching Principle II.
|
||||
A `400 CYCLE_DETECTED` from `createHierarchyNode`/its update equivalent is rendered as-is (US3
|
||||
acceptance scenario 3) — the frontend never pre-checks for a cycle itself.
|
||||
|
||||
## `lib/api/sla.ts` / `lib/api/calendars.ts` (User Story 4)
|
||||
|
||||
| Function | Calls | Body/Query |
|
||||
|---|---|---|
|
||||
| `listSlaPolicies()` / `createSlaPolicy(body)` | `GET`/`POST /admin/sla-policies` | `{name, productId?, categoryId?, problemTypeId?, priority?, firstResponseMinutes, investigationMinutes?, resolutionMinutes, customerResponseMinutes?, businessCalendarId?}` |
|
||||
| `listCalendars()` / `createCalendar(body)` | `GET`/`POST /admin/business-calendars` | `{name, timezone, workingHours: {mon?..sun?: {start,end}}}` |
|
||||
| `addHoliday(calendarId, body)` | `POST /admin/business-calendars/:id/holidays` | `{date, description?}` |
|
||||
|
||||
US4 acceptance scenario 3 ("indicates which policy is more specific"): the frontend sorts/badges
|
||||
by specificity using only which optional scope fields (`productId`/`categoryId`/
|
||||
`problemTypeId`/`priority`) are non-null on each policy — it never re-derives the backend's own
|
||||
most-specific-match *resolution* (which policy actually applies to a given ticket), only a
|
||||
display ordering over already-fetched policies (Constitution Principle II).
|
||||
|
||||
## `lib/api/escalation.ts` (User Story 5)
|
||||
|
||||
| Function | Calls | Body |
|
||||
|---|---|---|
|
||||
| `listEscalationPolicies()` / `createEscalationPolicy(name, productId?)` | `GET`/`POST /admin/escalation-policies` | `{name, productId?}` |
|
||||
| `createEscalationRule(policyId, body)` | `POST /admin/escalation-policies/:id/rules` | `{triggerType, condition, targetNodeId, notify, active?}` — `triggerType` is one of the 10 values in `specs/008-sla-escalation/contracts/sla-escalation-contract.md`, not re-declared as a separate frontend enum (Principle V) |
|
||||
|
||||
Manual escalation (`escalateTicket`, already in `lib/api/tickets.ts`) is this same story's own
|
||||
US2-surfaced action — a stale `targetNodeId` shows the backend's own rejection (US5 scenario 3).
|
||||
|
||||
## `lib/api/monitoring.ts` (User Story 6)
|
||||
|
||||
| Function | Calls |
|
||||
|---|---|
|
||||
| `listSlaRuns(status?)` | `GET /admin/sla-runs` (012-admin-list-views) |
|
||||
| `listEscalationEvents(limit?)` | `GET /admin/escalation-events` (012-admin-list-views) |
|
||||
|
||||
Both reflect live backend state on every fetch/refetch (US6's own "not a snapshot that goes
|
||||
stale") — no client-side caching beyond TanStack Query's own normal `staleTime` behavior.
|
||||
|
||||
## `lib/api/catalog.ts` / `lib/api/knowledge.ts` (User Story 7)
|
||||
|
||||
| Function | Calls |
|
||||
|---|---|
|
||||
| `listProductCatalog()` | `GET /admin/products` (012-admin-list-views) |
|
||||
| `listKnowledgeEntries(externalProductId)` | `GET /admin/products/:externalProductId/knowledge` (012-admin-list-views follow-up — NOT `GET /knowledge/retrieve`, which is published-only and would hide the very drafts this screen exists to publish) |
|
||||
| `publishKnowledgeEntry(code, effectiveDate?)` / `unpublishKnowledgeEntry(code)` | `PATCH /admin/knowledge/:code/publish` / `.../unpublish` |
|
||||
|
||||
## Session guard contract (`middleware.ts`, `SessionProvider`)
|
||||
|
||||
- No `sh_session` cookie on a `(support)`/`(admin)` request → redirect to `/sign-in?from=<path>`.
|
||||
|
||||
@@ -58,6 +58,39 @@ Mirrors `specs/006-support-organization/contracts/support-org-contract.md` exact
|
||||
`Agent` (including the `userId` link from 011), `AgentSkill`, `AgentAvailability`,
|
||||
`HierarchyNode` (with `productScope`, `skills`, `assignmentStrategy`, `parentId`).
|
||||
|
||||
## SLA & Calendar Configuration entities (US4)
|
||||
|
||||
Mirrors `specs/008-sla-escalation/contracts/sla-escalation-contract.md`: `SLAPolicy` (`name`,
|
||||
`productId?`, `categoryId?`, `problemTypeId?`, `priority?`, `firstResponseMinutes`,
|
||||
`investigationMinutes?`, `resolutionMinutes`, `customerResponseMinutes?`,
|
||||
`businessCalendarId?`), `BusinessCalendar` (`name`, `timezone`, `workingHours` keyed
|
||||
`mon`..`sun` each `{start,end}` in `"HH:mm"`), `BusinessCalendarHoliday` (`date`,
|
||||
`description?`).
|
||||
|
||||
## Escalation Configuration entities (US5)
|
||||
|
||||
Mirrors the same contract: `EscalationPolicy` (`name`, `productId?`), `EscalationRule`
|
||||
(`triggerType` — one of the 10 values in that contract, `condition`, `targetNodeId`, `notify`,
|
||||
`active`).
|
||||
|
||||
## Monitoring Views entities (US6)
|
||||
|
||||
Mirrors `specs/012-admin-list-views/contracts/admin-list-views-contract.md` exactly:
|
||||
`SlaRunListItem` (`ticketId`, `ticketCode`, `status`, `firstResponseDueAt`, `resolutionDueAt`,
|
||||
`breachedAt`, `firstResponseBreachedAt`), `EscalationEventListItem` (`ticketId`, `ticketCode`,
|
||||
`reason`, `ruleId`, `triggeredBy`, `toNodeId`, `createdAt`).
|
||||
|
||||
## Catalog & Knowledge Governance entities (US7)
|
||||
|
||||
`ProductCatalogListItem` mirrors `specs/012-admin-list-views/contracts/admin-list-views-
|
||||
contract.md` exactly (`id`, `externalProductId`, `name`, `status`, `supportEnabled`,
|
||||
`integrationStatus`). `KnowledgeEntry` mirrors `specs/004-product-knowledge/contracts/
|
||||
knowledge-contract.md`: `code`, `feature?`, `type`, `problem?`, `symptoms?`, `errorCode?`,
|
||||
`cause?`, `recommendedSolution?`, `verificationSteps?`, `escalationGuidance?`,
|
||||
`categoryScope?`, `owner?`, `source?`, plus lifecycle fields (`status`/`validationStatus`/
|
||||
`effectiveDate`/`version` — exact names confirmed against the controller at implementation
|
||||
time, not guessed).
|
||||
|
||||
## Frontend-only derived state
|
||||
|
||||
- **`QueryState`**: `'loading' | 'empty' | 'error' | 'ready'` — research.md's discriminated
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
---
|
||||
description: "Task list for 001-agent-admin-ui, continuation: User Stories 4-7 (P2/P3)"
|
||||
---
|
||||
|
||||
# Tasks: Agent and Admin UI — User Stories 4-7
|
||||
|
||||
**Input**: Design documents from `specs/001-agent-admin-ui/` (plan.md, spec.md, research.md,
|
||||
data-model.md — extended with US4-7 entities, contracts/api-client-contract.md — extended with
|
||||
US4-7 functions, quickstart.md)
|
||||
|
||||
**Prerequisites**: `tasks.md` (Setup + Foundational + User Stories 0-3) already complete. This
|
||||
continuation needs no new Foundational work — every US4-7 story follows the identical `lib/api`
|
||||
function → TanStack Query hook → `features/*` component → page pattern already established.
|
||||
|
||||
**Backend dependency**: 012-admin-list-views (supporthub-api) — SLA-run/escalation-event/
|
||||
product-catalog list endpoints, plus its own follow-up commit adding the knowledge-governance
|
||||
list endpoint. Both already merged into this feature's own contracts before these tasks began.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
All file paths are relative to `supporthub-web/` (repo root).
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 4 - SLA policies and business calendars (Priority: P2)
|
||||
|
||||
**Independent Test**: Quickstart Scenario 4 (see quickstart.md addendum below).
|
||||
|
||||
- [ ] T042 [P] [US4] Add `lib/api/sla.ts` (`listSlaPolicies`, `createSlaPolicy`) and
|
||||
`lib/api/calendars.ts` (`listCalendars`, `createCalendar`, `addHoliday`) per
|
||||
contracts/api-client-contract.md
|
||||
- [ ] T043 [US4] Add `lib/api/types/sla.ts` (`SlaPolicy`, `BusinessCalendar`,
|
||||
`BusinessCalendarHoliday` — data-model.md) and export from `lib/api/types/index.ts`
|
||||
- [ ] T044 [US4] Add `features/settings/calendar-editor.tsx` (create a calendar with per-weekday
|
||||
working hours + add a holiday, US4 scenario 1) (depends on T042, T043)
|
||||
- [ ] T045 [US4] Add `features/settings/sla-policy-editor.tsx` (create a policy scoped to a
|
||||
product/category/priority with a calendar reference; each row in the list badges its own
|
||||
specificity — which optional scope fields are set — per contracts/api-client-
|
||||
contract.md's own note, US4 scenarios 2-3) (depends on T042, T043)
|
||||
- [ ] T046 [US4] Replace the placeholder `src/app/(admin)/admin/sla-policies/page.tsx` composing
|
||||
T044+T045 (both calendars and SLA policies live here — Key Entities' own "SLA & Calendar
|
||||
Configuration" grouping) (depends on T044, T045)
|
||||
- [ ] T047 [US4] Integration test (mocked `lib/api/sla.ts`/`lib/api/calendars.ts`) covering
|
||||
Quickstart Scenario 4 in `tests/integration/settings/sla-calendar-admin.test.tsx`
|
||||
- [ ] T048 [US4] Run Quickstart Scenario 4 locally against a real supporthub-api and confirm it
|
||||
passes
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: User Story 5 - Escalation policies and rules (Priority: P2)
|
||||
|
||||
**Independent Test**: Quickstart Scenario 5.
|
||||
|
||||
- [ ] T049 [P] [US5] Add `lib/api/escalation.ts` (`listEscalationPolicies`,
|
||||
`createEscalationPolicy`, `createEscalationRule`) per contracts/api-client-contract.md
|
||||
- [ ] T050 [US5] Add `lib/api/types/escalation.ts` (`EscalationPolicy`, `EscalationRule`,
|
||||
`ESCALATION_TRIGGER_TYPES` — data-model.md) and export from `lib/api/types/index.ts`
|
||||
- [ ] T051 [US5] Add `features/escalation/escalation-policy-editor.tsx` (create a policy, add a
|
||||
rule with trigger type + target node, both clearly shown in the list, US5 scenario 1)
|
||||
(depends on T049, T050)
|
||||
- [ ] T052 [US5] Replace the placeholder `src/app/(admin)/admin/escalation-policies/page.tsx`
|
||||
with T051 (depends on T051)
|
||||
- [ ] T053 [US5] Integration test (mocked `lib/api/escalation.ts`) covering Quickstart Scenario
|
||||
5's policy/rule creation, plus a stale-`targetNodeId` manual escalation from the ticket
|
||||
workbench (already-built `TicketHeader`, US5 scenario 3) rendering the backend's own
|
||||
rejection, in `tests/integration/escalation/escalation-admin.test.tsx`
|
||||
- [ ] T054 [US5] Run Quickstart Scenario 5 locally against a real supporthub-api and confirm it
|
||||
passes, including a manual escalation from a real ticket appearing in that ticket's own
|
||||
history (scenario 2)
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: User Story 6 - SLA and escalation monitoring views (Priority: P2)
|
||||
|
||||
**Independent Test**: Quickstart Scenario 6.
|
||||
|
||||
- [ ] T055 [P] [US6] Add `lib/api/monitoring.ts` (`listSlaRuns`, `listEscalationEvents`) per
|
||||
contracts/api-client-contract.md (012-admin-list-views)
|
||||
- [ ] T056 [US6] Add `features/reports/sla-monitor.tsx` (every SLA run, filterable by status,
|
||||
each row linking to its ticket via `ticketCode`/`ticketId`, US6 scenario 1) (depends on
|
||||
T055)
|
||||
- [ ] T057 [US6] Add `features/reports/escalation-matrix.tsx` (recent escalation events, each
|
||||
showing reason + rule-or-actor + target node, US6 scenario 2) (depends on T055)
|
||||
- [ ] T058 [US6] Replace the placeholder `src/app/(admin)/admin/reports/page.tsx` composing
|
||||
T056+T057 (depends on T056, T057)
|
||||
- [ ] T059 [US6] Integration test (mocked `lib/api/monitoring.ts`) covering Quickstart Scenario
|
||||
6 (status filter, automatic-vs-manual distinction) in
|
||||
`tests/integration/reports/monitoring-views.test.tsx`
|
||||
- [ ] T060 [US6] Run Quickstart Scenario 6 locally against a real supporthub-api and confirm it
|
||||
passes, using real SLA runs/escalation events from earlier stories' own test data
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: User Story 7 - Product catalog and knowledge base governance (Priority: P3)
|
||||
|
||||
**Independent Test**: Quickstart Scenario 7.
|
||||
|
||||
- [ ] T061 [P] [US7] Add `lib/api/catalog.ts` (`listProductCatalog`) and `lib/api/knowledge.ts`
|
||||
(`listKnowledgeEntries`, `publishKnowledgeEntry`, `unpublishKnowledgeEntry`) per
|
||||
contracts/api-client-contract.md
|
||||
- [ ] T062 [US7] Add `lib/api/types/catalog.ts`/`lib/api/types/knowledge.ts` (data-model.md) and
|
||||
export from `lib/api/types/index.ts`
|
||||
- [ ] T063 [US7] Add `features/products/product-catalog.tsx` (each product's integration status
|
||||
visible, US7 scenario 1) (depends on T061, T062)
|
||||
- [ ] T064 [US7] Add `features/knowledge/knowledge-governance.tsx` (list entries for a selected
|
||||
product including drafts, publish/unpublish action, status update reflected immediately,
|
||||
US7 scenario 2) (depends on T061, T062)
|
||||
- [ ] T065 [US7] Replace the placeholder `src/app/(admin)/admin/products/page.tsx` with T063 and
|
||||
`src/app/(admin)/admin/knowledge/page.tsx` with T064 (depends on T063, T064)
|
||||
- [ ] T066 [US7] Integration test (mocked `lib/api/catalog.ts`/`lib/api/knowledge.ts`) covering
|
||||
Quickstart Scenario 7 in `tests/integration/products/catalog-and-knowledge.test.tsx`
|
||||
- [ ] T067 [US7] Run Quickstart Scenario 7 locally against a real supporthub-api and confirm it
|
||||
passes
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Polish & Cross-Cutting Concerns (this continuation's own)
|
||||
|
||||
- [ ] T068 [P] Update `specs/001-agent-admin-ui/checklists/requirements.md` Notes with any
|
||||
implementation-time findings from User Stories 4-7
|
||||
- [ ] T069 Run `npm run typecheck` and `npm run lint`
|
||||
- [ ] T070 Run `npm run test` (all unit + integration) and confirm Setup/US0-3's own tests still
|
||||
pass (no regression from US4-7's additions)
|
||||
- [ ] T071 Real end-to-end verification: run the app against a live, locally-running
|
||||
supporthub-api and manually (or via a Playwright addition) confirm all four of this
|
||||
continuation's Quickstart scenarios, matching Setup/US0-3's own established discipline of
|
||||
never claiming a scenario done without exercising it against real infrastructure
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
- **User Stories 4-7 (Phases 5-8)**: Each depends only on User Story 0 (a session) — independent
|
||||
of each other and of Phases 5-8's own siblings, parallelizable in any order (matches the
|
||||
original tasks.md's own US1-3 independence)
|
||||
- **Polish (Phase 9)**: Depends on all four
|
||||
|
||||
## Quickstart Addenda (this continuation's own scenarios)
|
||||
|
||||
**Scenario 4 — SLA policies and business calendars**: Create a business calendar with working
|
||||
hours and a holiday; create an SLA policy referencing it, scoped to a product. Confirm both
|
||||
retrievable/editable exactly as configured, and that a second, more general policy is visibly
|
||||
marked less specific than a product-scoped one.
|
||||
|
||||
**Scenario 5 — escalation policies and rules**: Create an escalation policy and a
|
||||
`resolution_breach` rule targeting a specific node. Confirm it's retrievable. From an existing
|
||||
ticket's workbench, manually escalate to that node with a reason; confirm the escalation appears
|
||||
in that ticket's own history. Attempt escalating to a nonexistent node; confirm the rejection is
|
||||
shown clearly.
|
||||
|
||||
**Scenario 6 — SLA and escalation monitoring**: With SLA runs in different states and a recent
|
||||
escalation event, open the SLA monitor and filter by status; open the escalation matrix and
|
||||
confirm the triggering reason/rule-or-actor/target node are all shown.
|
||||
|
||||
**Scenario 7 — catalog and knowledge governance**: View the product list with integration
|
||||
status visible. Open the knowledge governance screen for a product, publish a draft entry,
|
||||
confirm its status updates immediately.
|
||||
Reference in New Issue
Block a user