Files
support_frontend/specs/001-agent-admin-ui/plan.md
T
saqib mirandClaude Sonnet 5 95b5a1e03d feat(001-agent-admin-ui): Setup + Foundational + User Story 0 (sign-in)
Configures both previously-empty test runners (vitest.config.ts,
playwright.config.ts) and adds the typed lib/api client layer (axios +
interceptors), the session-cookie plumbing (lib/auth), TanStack Query
infrastructure (lib/query, providers), and a real sign-in flow consuming
supporthub-api's own login (010-identity-auth) - the true foundation
every other user story in this feature depends on.

Two structural fixes to the existing scaffold, both found only by
running the app rather than by inspection: middleware.ts belongs at
src/middleware.ts under this project's src/ layout, not the repo root;
and next.config.mjs's output:'export' is incompatible with Next.js
Middleware outright (the dev server refuses to start it), so this app
now runs as a standard Next.js server - confirmed with the user before
making that deployment-mode change.

Verified end-to-end with a real, locally-running supporthub-api: all 5
Playwright scenarios (unauthenticated redirect, sign-in, wrong-password
generic error, non-admin role gating, sign-out) pass against a live
backend, not a mock.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 14:27:06 +05:30

11 KiB

Implementation Plan: Agent and Admin UI

Branch: 001-agent-admin-ui | Date: 2026-09-07 | Spec: spec.md

Input: Feature specification from specs/001-agent-admin-ui/spec.md

Summary

Builds the (support)/(admin) portals against the existing Next.js scaffold: a sign-in flow consuming supporthub-api's own login (010-identity-auth, User Story 0 — this feature's true foundation), an agent dashboard and ticket workbench (011-agent-ticket-queue plus the existing ticketing/problem-resolution endpoints), and admin configuration screens for support organization, SLA/calendars, escalation, and (P3) catalog/knowledge governance. Every screen reads and writes through one typed API client layer (lib/api) via TanStack Query — no business logic is computed client-side (Constitution Principle II).

Technical Context

Language/Version: TypeScript 5.5, Node.js 22 (per package.json engines), Next.js 14 (App Router), React 18. next.config.mjs's output: 'export' (static HTML export) is removed by this feature — Next.js Middleware, which FR-000's sign-in guard requires, cannot run under static export (confirmed by the dev server itself refusing to start it); this app now runs as a standard Next.js server (next build && next start), a deployment-mode change, not just a code change.

Primary Dependencies: @tanstack/react-query (server state), axios (wrapped by lib/api), tailwindcss (styling, already configured), clsx/tailwind-merge (already present), lucide-react (icons, already present). New: js-cookie (small, typed cookie read/write for the session token — the codebase has no cookie helper today) and jose (Edge-runtime-safe JWT payload decode for middleware.tsjsonwebtoken depends on Node APIs middleware.ts cannot use).

Storage: N/A (server state is supporthub-api's; the only client-side state is the session cookie itself, research.md).

Testing: Vitest (unit — hooks, lib/api functions, the query-state helper; integration — per-portal critical flows against a mocked API layer) + Playwright (E2E — the two journeys Constitution Principle VII names, plus this feature's own: an agent signing in and resolving a ticket end-to-end, User Stories 0-2). vitest.config.ts and playwright.config.ts are both currently empty stubs — this feature is the first to configure either.

Target Platform: Browser (desktop-first, responsive down to a reasonable minimum per Principle VI), served by the existing Next.js app.

Project Type: Web frontend — single Next.js project, consuming a separately-deployed supporthub-api.

Performance Goals: SC-001 — dashboard-open to message-post in under 15 seconds of active use (excluding backend response time), meaning the UI itself must not introduce avoidable extra round trips or re-renders on that path.

Constraints: FR-012/Principle II — no business decision (transition validity, SLA due dates, most-specific-policy resolution, escalation matching) is computed client-side, only rendered from what the API returns. FR-000/Principle I — this frontend never verifies a JWT signature itself (research.md); the unverified middleware decode is UX-only.

Scale/Scope: Eight user stories (US0 sign-in + US1-US7), against ~30 existing placeholder page.tsx files across four route groups, all of lib/api/lib/auth/lib/query/hooks/ stores/providers/features/* currently empty. Given the size, this plan's own Project Structure section scopes Phase 1 (Setup) and User Stories 0-3 (the P1 MVP: sign-in, dashboard, ticket workbench, support-org admin) as the immediate implementation target; User Stories 4-7 (P2/P3) follow the identical pattern once the MVP is verified, per the Implementation Strategy below — matching this project's own established phase-by-phase, checkpoint-then-continue discipline (mirrors supporthub-api's own MVP-first pattern, e.g. 010's own tasks.md).

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Principle Check Result
I. Each Identity Has Exactly One Authority US0 consumes supporthub-api's own login (010) for agent/admin identity, never re-implementing or re-deriving it; the (public)/(customer) portals (SaaS-delegated identity) are explicitly out of scope for this feature (Assumptions), so no conflict between the two identities' authorities arises here. PASS
II. The Backend Is the Sole Source of Business Logic FR-012 is this principle restated as a testable requirement; every user story's Acceptance Scenarios that touch a business-rule rejection (US2 scenario 2, US3 scenario 3, US5 scenario 3) exist specifically to keep it enforced. PASS
III. Strict Portal Boundaries This feature only touches (support)/(admin)(public)/(customer) are untouched (Assumptions). Shared primitives stay in components/ui; portal-specific composition lives in features/* and each route group. PASS
IV. Typed API Boundary, No Ad Hoc Fetching lib/api is the single client layer (research.md); every features/* module consumes it only through TanStack Query hooks. PASS
V. Configuration Over Hardcoding Support hierarchy, SLA policies, escalation rules, and skills are rendered/edited generically from what the API returns — no frontend-duplicated enum for root-cause types, verification methods, escalation trigger types, etc. PASS
VI. Accessible, Responsive, Enterprise-Grade UI Existing components/ui primitives (already built, this session's earlier scaffold work) are the basis for every new screen; density/keyboard-usability is a per-task acceptance bar, not a separate follow-up. PASS
VII. Testing Gates This plan's Testing section above configures both currently-empty test runners as part of Setup, not deferred — Vitest unit/integration plus the two Playwright E2E journeys (one of which, agent resolving an escalated ticket, is this feature's own US0-US2). PASS

No violations requiring Complexity Tracking justification.

Post-Design Constitution Re-check

All gates above remain PASS after Phase 1 design (data-model.md, contracts, quickstart.md). One principle is worth restating post-design: Principle I's redefinition (this session's own constitution amendment, 1.0.0 → 1.1.0) is what makes User Story 0 exist at all — without it, this plan would have wrongly assumed no sign-in screen was needed.

Project Structure

Documentation (this feature)

specs/001-agent-admin-ui/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md

Source Code (repository root)

supporthub-web/
├── src/middleware.ts                      # MODIFIED (was an empty file at repo root — moved
│                                              under src/, required by this project's src/
│                                              directory layout) — session presence + role
│                                              redirect for (support)/(admin), FR-000/research.md
├── vitest.config.ts                       # MODIFIED (was empty) — first real test config
├── playwright.config.ts                   # MODIFIED (was empty) — first real E2E config
├── src/
│   ├── lib/
│   │   ├── env/index.ts                   # MODIFIED (was empty) — typed env accessor
│   │   ├── auth/                          # MODIFIED (was empty) — session cookie read/write/
│   │   │   │                                 clear, decode-for-display helpers
│   │   │   └── (session.ts, use-session.ts)
│   │   ├── api/                           # MODIFIED (was empty) — axios instance + interceptors
│   │   │   │                                 (client.ts) + one file per domain (auth.ts,
│   │   │   │                                 agents.ts, tickets.ts, teams.ts, hierarchy.ts,
│   │   │   │                                 sla.ts, escalation.ts, problems.ts, ...)
│   │   │   └── types/                      # response/request shapes, kept in sync with
│   │   │                                     supporthub-api's own contracts/*.md
│   │   └── query/                         # MODIFIED (was empty) — QueryClient config,
│   │       │                                 query-state.ts (research.md's discriminated union)
│   │       └── keys.ts                     # centralized TanStack Query key factory
│   ├── providers/                         # MODIFIED — QueryClientProvider, SessionProvider
│   ├── hooks/                              # MODIFIED — use-session, use-query-state re-exports
│   ├── features/
│   │   ├── auth/                          # NEW — sign-in form + its own mutation hook (US0)
│   │   ├── tickets/                        # MODIFIED (was empty) — dashboard list, workbench
│   │   │                                     detail, message thread, status/escalate actions
│   │   ├── problems/                       # MODIFIED — investigation/root-cause/solution/
│   │   │                                     verification/resolution recording (US2)
│   │   ├── teams/                          # MODIFIED — team/agent/skill admin (US3)
│   │   ├── orchestration/                  # MODIFIED — hierarchy-node admin (US3)
│   │   ├── settings/                       # MODIFIED — SLA/calendar admin (US4, deferred)
│   │   └── ...                             # escalation/reports/knowledge/products: US5-US7,
│   │                                          deferred past this plan's immediate MVP scope
│   └── app/
│       ├── (support)/
│       │   ├── layout.tsx                 # MODIFIED — session-aware shell (nav, sign-out)
│       │   └── support/
│       │       ├── dashboard/page.tsx     # MODIFIED (was a placeholder) — US1
│       │       └── agent-tickets/[ticketId]/page.tsx  # MODIFIED — US2
│       └── (admin)/
│           ├── layout.tsx                 # MODIFIED — admin-only shell
│           └── admin/
│               ├── teams/page.tsx         # MODIFIED — US3
│               └── hierarchy/page.tsx     # MODIFIED — US3
└── tests/
    ├── unit/                              # lib/api functions, query-state, session helpers
    ├── integration/                       # per-portal critical flows (mocked API layer)
    └── e2e/                               # Playwright — Principle VII's two journeys

Structure Decision: Single Next.js project, built entirely against the existing scaffold (no new route groups or top-level directories) per the constitution's own Development Workflow rule — replacing placeholder pages, not restructuring the route tree. This plan's own immediate implementation scope is Setup + User Stories 0-3 (P1 MVP); features/ subdirectories for US4-US7 are named above for completeness but not built until those stories' own turn.

Complexity Tracking

No constitution violations — table intentionally omitted.