docs(001-agent-admin-ui): task breakdown for Setup + User Stories 0-3
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
273e73be07
commit
326859e27b
@@ -0,0 +1,261 @@
|
||||
---
|
||||
description: "Task list for 001-agent-admin-ui (Setup + User Stories 0-3, this plan's immediate scope)"
|
||||
---
|
||||
|
||||
# Tasks: Agent and Admin UI (Setup + User Stories 0-3)
|
||||
|
||||
**Input**: Design documents from `specs/001-agent-admin-ui/`
|
||||
|
||||
**Prerequisites**: [plan.md](./plan.md), [spec.md](./spec.md), [research.md](./research.md),
|
||||
[data-model.md](./data-model.md), [contracts/api-client-contract.md](./contracts/api-client-contract.md),
|
||||
[quickstart.md](./quickstart.md)
|
||||
|
||||
**Scope note**: Per plan.md's own Technical Context, this task list covers Setup + User Stories
|
||||
0-3 (the P1 MVP) only. User Stories 4-7 (P2/P3) get their own tasks.md continuation once this
|
||||
scope is verified — the identical pattern established here (lib/api function → TanStack Query
|
||||
hook → feature component → page) applies directly.
|
||||
|
||||
**Organization**: Tasks are grouped by user story. US0 blocks every other story (no session, no
|
||||
data). US1-US3 are independent of each other once US0 exists.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
All file paths are relative to `supporthub-web/` (repo root).
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Setup
|
||||
|
||||
- [ ] T001 [P] Add `js-cookie` + `@types/js-cookie` and `jose` to `package.json`
|
||||
- [ ] T002 [P] Populate `src/lib/env/index.ts` — typed accessor over the existing
|
||||
`NEXT_PUBLIC_*` env vars (zod-validated, matching supporthub-api's own `env.ts` pattern),
|
||||
exporting `env.apiUrl` etc.
|
||||
- [ ] T003 [P] Configure `vitest.config.ts` (currently empty) — `environment: 'jsdom'`, path
|
||||
aliases matching `tsconfig.json`, `tests/unit` + `tests/integration` include globs
|
||||
- [ ] T004 [P] Configure `playwright.config.ts` (currently empty) — base URL from
|
||||
`NEXT_PUBLIC_APP_URL`, `tests/e2e` test dir
|
||||
- [ ] T005 [P] Add `@testing-library/react`, `@testing-library/jest-dom`, `jsdom` as dev
|
||||
dependencies (needed by T003's `jsdom` environment; not yet present in `package.json`)
|
||||
|
||||
**Checkpoint**: Both test runners actually run (even with zero tests) and `env` is typed.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: The typed client layer, session plumbing, and query infrastructure every user
|
||||
story is built on.
|
||||
|
||||
**⚠️ CRITICAL**: No user-story work can begin until this phase is complete.
|
||||
|
||||
- [ ] T006 Add `lib/auth/session-cookie.ts` — `getSessionToken()`/`setSessionToken(token)`/
|
||||
`clearSessionToken()` using `js-cookie` (`sh_session`, `Secure` in production,
|
||||
`SameSite=Lax`) (depends on T001)
|
||||
- [ ] T007 Add `lib/api/client.ts` — axios instance (`baseURL: env.apiUrl`), a request
|
||||
interceptor attaching `Authorization: Bearer <token>` from T006, a response interceptor
|
||||
throwing a typed `ApiError` (data-model.md) and clearing the session + redirecting to
|
||||
`/sign-in` on `401` (depends on T002, T006)
|
||||
- [ ] T008 [P] Add `lib/api/types/` — `Session`, `ApiError`, `AssignedTicketSummary` (011's
|
||||
contract), and the ticket/message/problem-resolution/team/agent/hierarchy types
|
||||
data-model.md names, each referencing its source backend contract in a comment
|
||||
- [ ] T009 Add `lib/api/auth.ts` — `login`, `getCurrentSession`, `logout` per
|
||||
contracts/api-client-contract.md (depends on T007, T008)
|
||||
- [ ] T010 Add `lib/query/query-client.ts` (the shared `QueryClient` instance) and
|
||||
`lib/query/query-state.ts` (research.md's `'loading'|'empty'|'error'|'ready'`
|
||||
discriminated union helper, taking a `UseQueryResult` and an optional
|
||||
`isEmpty(data)` predicate)
|
||||
- [ ] T011 Add `providers/query-provider.tsx` (`QueryClientProvider` wrapping T010's client) and
|
||||
`providers/session-provider.tsx` (calls `getCurrentSession` on mount via TanStack Query,
|
||||
exposes `useSession()`; the query's own `onError` for a `401` clears the session and
|
||||
redirects, per contracts/api-client-contract.md's "Session guard contract") (depends on
|
||||
T009, T010)
|
||||
- [ ] T012 Wire both providers into `src/app/layout.tsx` (currently the root layout with no
|
||||
providers)
|
||||
- [ ] T013 Write `middleware.ts` (currently empty) — no `sh_session` cookie on a
|
||||
`(support)`/`(admin)` path → redirect to `/sign-in?from=<path>`; cookie present but
|
||||
`jose`-decoded `role` isn't `ADMIN` on an `(admin)` path → redirect to
|
||||
`/support/dashboard` (research.md's unverified-decode decision) (depends on T001)
|
||||
|
||||
**Checkpoint**: A session can be established, read, and cleared; every subsequent API call
|
||||
carries it; an unauthenticated or wrongly-roled request never reaches portal content.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 0 - An agent or admin signs in (Priority: P1)
|
||||
|
||||
**Goal**: A real sign-in screen and the redirect/guard behavior FR-000 requires.
|
||||
|
||||
**Independent Test**: Quickstart Scenario 0.
|
||||
|
||||
### Tests for User Story 0
|
||||
|
||||
- [ ] T014 [P] [US0] Unit test for `lib/query/query-state.ts`'s discriminated-union logic
|
||||
(loading/empty/error/ready, each input combination) in `tests/unit/lib/query-state.test.ts`
|
||||
- [ ] T015 [US0] Integration test (mocked `lib/api/auth.ts`) covering Quickstart Scenario 0
|
||||
steps 2-3 (successful sign-in redirects and stores a session; wrong credentials show one
|
||||
generic error) in `tests/integration/auth/sign-in.test.tsx` (depends on T009)
|
||||
- [ ] T016 [US0] Playwright E2E covering Quickstart Scenario 0 end-to-end against a real
|
||||
supporthub-api (redirect-when-unauthenticated, sign-in, role-gated redirect, sign-out) in
|
||||
`tests/e2e/agent-sign-in-and-resolve.spec.ts` — this is also Constitution Principle VII's
|
||||
journey (B), continued by User Story 2's own steps once that story is built
|
||||
|
||||
### Implementation for User Story 0
|
||||
|
||||
- [ ] T017 [US0] Add `features/auth/sign-in-form.tsx` + `features/auth/use-login.ts` (a
|
||||
TanStack `useMutation` wrapping `lib/api/auth.ts`'s `login`, redirecting to a
|
||||
role-appropriate landing page on success) (depends on T009, T011)
|
||||
- [ ] T018 [US0] Add the `/sign-in` page (`src/app/sign-in/page.tsx`, new — outside every
|
||||
existing route group, since it's neither an admin nor support surface) rendering T017's
|
||||
form
|
||||
- [ ] T019 [US0] Add a sign-out action (`features/auth/use-logout.ts`, wrapping
|
||||
`lib/api/auth.ts`'s `logout`) wired into both `(support)/layout.tsx` and
|
||||
`(admin)/layout.tsx`'s existing nav shells (depends on T009, T011)
|
||||
- [ ] T020 [US0] Run Quickstart Scenario 0 locally and confirm all 5 steps pass
|
||||
|
||||
**Checkpoint**: A real session exists end-to-end. Every other user story can now consume one.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 1 - An agent sees and opens their assigned work (Priority: P1)
|
||||
|
||||
**Goal**: The agent dashboard, backed by 011's new endpoint.
|
||||
|
||||
**Independent Test**: Quickstart Scenario 1.
|
||||
|
||||
### Tests for User Story 1
|
||||
|
||||
- [ ] T021 [P] [US1] Integration test (mocked `lib/api/tickets.ts`) covering Quickstart
|
||||
Scenario 1's three states (populated list, empty state, list reflects reassignment after
|
||||
refetch) in `tests/integration/tickets/agent-dashboard.test.tsx`
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [ ] T022 [US1] Add `lib/api/tickets.ts`'s `getMyAssignedTickets` (depends on T007, T008)
|
||||
- [ ] T023 [US1] Add `features/tickets/use-my-tickets.ts` (TanStack `useQuery` +
|
||||
`query-state.ts`) and `features/tickets/agent-dashboard.tsx` (the list itself — customer/
|
||||
product/priority/status/SLA time-remaining per row, per FR-001) (depends on T010, T022)
|
||||
- Sub-note: a `404` from `getMyAssignedTickets` (011's "no linked agent" rejection) renders
|
||||
as its own distinct message, not the generic empty state (contracts/api-client-
|
||||
contract.md)
|
||||
- [ ] T024 [US1] Replace the placeholder `src/app/(support)/support/dashboard/page.tsx` with
|
||||
T023's component (depends on T023)
|
||||
- [ ] T025 [US1] Run Quickstart Scenario 1 locally and confirm all 3 steps pass
|
||||
|
||||
**Checkpoint**: An agent has a real, live dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 2 - An agent works a ticket end-to-end (Priority: P1)
|
||||
|
||||
**Goal**: The ticket workbench — messages, status transitions, the full problem-resolution
|
||||
workflow — surfacing every backend rejection verbatim.
|
||||
|
||||
**Independent Test**: Quickstart Scenario 2.
|
||||
|
||||
### Tests for User Story 2
|
||||
|
||||
- [ ] T026 [P] [US2] Integration test (mocked `lib/api/tickets.ts` + `lib/api/problems.ts`)
|
||||
covering Quickstart Scenario 2's three steps, including the `409` precondition-rejection
|
||||
case rendered verbatim, in `tests/integration/tickets/workbench.test.tsx`
|
||||
- [ ] T027 [US2] Extend `tests/e2e/agent-sign-in-and-resolve.spec.ts` (T016) with the full
|
||||
investigation→root-cause→solution→implementation→verification→resolution flow against a
|
||||
real supporthub-api ticket already in `HUMAN_ESCALATION`
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [ ] T028 [US2] Add `lib/api/tickets.ts`'s `getTicket`/`getTicketMessages`/`postMessage`/
|
||||
`updateTicketStatus`/`escalateTicket` and `lib/api/problems.ts`'s full set (per
|
||||
contracts/api-client-contract.md) (depends on T007, T008)
|
||||
- [ ] T029 [US2] Add `features/tickets/ticket-header.tsx` (status, priority, SLA, escalate
|
||||
action) and `features/tickets/message-thread.tsx` (customer/AI/agent messages + internal
|
||||
notes, visually distinct, per FR-002) (depends on T028)
|
||||
- [ ] T030 [US2] Add `features/problems/investigation-form.tsx` through
|
||||
`features/problems/resolution-form.tsx` (one per stage, FR-003) — each renders its own
|
||||
`409` precondition rejection from `ApiError` verbatim, never a client-side pre-check of
|
||||
"is there an investigation on file yet" (depends on T028)
|
||||
- [ ] T031 [US2] Replace the placeholder
|
||||
`src/app/(support)/support/agent-tickets/[ticketId]/page.tsx` composing T029-T030
|
||||
(depends on T029, T030)
|
||||
- [ ] T032 [US2] Run Quickstart Scenario 2 locally and confirm all 3 steps pass
|
||||
|
||||
**Checkpoint**: An agent can resolve a real customer problem end-to-end from the UI alone.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: User Story 3 - An admin sets up the support organization (Priority: P1)
|
||||
|
||||
**Goal**: Teams/agents/skills/hierarchy admin screens, replacing every placeholder under
|
||||
`(admin)/admin/{teams,agents,hierarchy}`.
|
||||
|
||||
**Independent Test**: Quickstart Scenario 3.
|
||||
|
||||
### Tests for User Story 3
|
||||
|
||||
- [ ] T033 [P] [US3] Integration test (mocked `lib/api/teams.ts` + `lib/api/hierarchy.ts`)
|
||||
covering Quickstart Scenario 3's three steps, including the cycle-detection rejection
|
||||
rendered verbatim, in `tests/integration/teams/support-org-admin.test.tsx`
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [ ] T034 [US3] Add `lib/api/teams.ts` and `lib/api/hierarchy.ts` per
|
||||
contracts/api-client-contract.md, including 011's `linkAgentAccount` (depends on T007, T008)
|
||||
- [ ] T035 [US3] Add `features/teams/team-roster.tsx` (create team, add agent, upsert skill,
|
||||
link an agent's account per FR-005) (depends on T034)
|
||||
- [ ] T036 [US3] Add `features/orchestration/hierarchy-editor.tsx` (create/view a node with
|
||||
scope/skills/strategy, rendered as a tree by `parentId`, per FR-005) (depends on T034)
|
||||
- [ ] T037 [US3] Replace the placeholder `src/app/(admin)/admin/teams/page.tsx` and
|
||||
`src/app/(admin)/admin/hierarchy/page.tsx` with T035/T036 (depends on T035, T036)
|
||||
- [ ] T038 [US3] Run Quickstart Scenario 3 locally and confirm all 3 steps pass
|
||||
|
||||
**Checkpoint**: All four Phase 3-6 stories (US0-US3, this plan's full immediate scope) work
|
||||
independently and together — this is the feature's P1 MVP.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Polish & Cross-Cutting Concerns (this scope's own)
|
||||
|
||||
- [ ] T039 [P] Update `specs/001-agent-admin-ui/checklists/requirements.md` Notes with any
|
||||
implementation-time findings
|
||||
- [ ] T040 Run `npm run typecheck` and `npm run lint`
|
||||
- [ ] T041 Run `npm run test` (all unit + integration) and `npm run test:e2e` (both Playwright
|
||||
journeys) against a real, locally-running supporthub-api
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
- **Setup (Phase 1)**: No dependencies
|
||||
- **Foundational (Phase 2)**: Depends on Setup — BLOCKS every user story
|
||||
- **User Story 0 (Phase 3)**: Depends on Foundational — BLOCKS User Stories 1-3 (no session, no
|
||||
data)
|
||||
- **User Stories 1-3 (Phases 4-6)**: Each depends on US0 only — independent of each other,
|
||||
parallelizable once US0 is done
|
||||
- **Polish (Phase 7)**: Depends on all of Phases 3-6
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- T001-T005 (Setup, all independent)
|
||||
- T008 (types) alongside T006-T007 (client plumbing) once T002 exists
|
||||
- Once US0 (Phase 3) is complete: Phases 4, 5, and 6 can proceed in parallel — they touch
|
||||
disjoint `features/*` subdirectories and disjoint page files
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 0 alone is not shippable — it has no destination)
|
||||
|
||||
1. Setup + Foundational (T001-T013)
|
||||
2. User Story 0 (T014-T020) → a real session exists
|
||||
3. **STOP and VALIDATE**: Quickstart Scenario 0 passes end-to-end against a real
|
||||
supporthub-api, including the redirect-on-401 path (contracts/api-client-contract.md's
|
||||
"Session guard contract" — this is the one behavior that can't be verified by a mocked-API
|
||||
integration test alone).
|
||||
4. User Stories 1-3 (T021-T038), in any order or in parallel — this plan's full P1 MVP
|
||||
5. Polish (T039-T041)
|
||||
|
||||
### Continuing past this plan's scope
|
||||
|
||||
User Stories 4-7 (SLA/calendar config, escalation config, monitoring views, catalog/knowledge
|
||||
governance) follow the identical `lib/api` function → TanStack Query hook → `features/*`
|
||||
component → page pattern established above, against their own backend contracts
|
||||
(`specs/008-sla-escalation`, `specs/004-product-knowledge` in supporthub-api) — deferred to a
|
||||
tasks.md continuation once this scope is verified, per plan.md's own Technical Context.
|
||||
Reference in New Issue
Block a user