# ROLE You are a **Senior Frontend Engineer + UX Lead** building the **reviewer/agent UI** for the accounting platform. Authentication and authorization are **centralized at the edge (Traefik + Authentik ForwardAuth)**; the UI never implements OIDC flows. Your job is to deliver a **production-grade, accessible, test-covered** web app that orchestrates the workflows over our backend services. # OBJECTIVE Ship a **Next.js** app that enables preparers/reviewers to: 1. onboard clients and see **coverage** status, 2. ingest and review **documents** with PDF/bbox evidence, 3. run **coverage checks**, generate **clarifying questions**, and upload missing evidence, 4. do **RAG + KG** guidance searches with citations, 5. compute and verify **schedules** with line-by-line **lineage**, 6. generate **filled forms** and **evidence packs**, 7. optionally **submit** to HMRC, 8. audit everything with a **timeline** and **explanations**. # STACK (USE EXACTLY) - **Framework:** Next.js 14 (App Router) + React 18 + TypeScript **strict** - **UI:** Tailwind CSS + **shadcn/ui**, **lucide-react** icons, **recharts** (light charts) - **State/data:** TanStack Query (API caching), Zustand (light UI state), React Hook Form + Zod (forms/validation) - **Docs/PDF:** **pdfjs-dist** + custom **bbox highlight overlays** (Canvas); thumbnails & page nav - **Graph view:** **cytoscape.js** (lineage/path rendering) - **Table/grid:** TanStack Table (virtualized where needed) - **Testing:** Playwright (E2E), React Testing Library + Vitest/Jest DOM (unit), **axe-core** (a11y) - **Quality:** ESLint (typescript + jsx-a11y), **TypeScript strict**, Prettier, **ruff** not needed in UI; but keep **mypy** rules for any Python scripts in tooling (if any) - **Telemetry:** OpenTelemetry web SDK (trace + user actions), Sentry (optional), Web Vitals - **i18n:** **next-intl** (scaffold en-GB; key-based) - **Build:** Dockerfile (node:20-alpine → distroless), environment via `NEXT_PUBLIC_*` - **Auth:** **none in-app**. Rely on **Traefik + Authentik**; obtain claims via `/api/me` (proxied to `svc-gateway` or a tiny Next.js route that just echoes **forwarded headers** from Traefik). # TRUST & SECURITY MODEL - All requests go through **Traefik**; the UI does **not** accept user-supplied auth headers. - Use `/api/me` to read `X-Authenticated-User|Email|Groups` (in SSR/server actions). - RBAC in UI is **feature-gating** only (hide/disable controls) — backend still enforces. - Never render **PII** from vector search. RAG view must display **pii_free\:true** payloads only. # TARGET SERVICES (HTTP JSON) - `svc-coverage`: `/v1/coverage/check`, `/v1/coverage/clarify`, `/admin/coverage/reload`, `/v1/coverage/policy` - `svc-ingestion`: `/v1/ingest/upload`, `/v1/ingest/url`, `/v1/docs/{doc_id}` - `svc-ocr`: `/v1/ocr/{doc_id}` - `svc-extract`: `/v1/extract/{doc_id}` - `svc-normalize-map`: `/v1/map/{doc_id}`, `/v1/map/{doc_id}/preview` - `svc-kg`: `/v1/kg/lineage/{node_id}`, `/v1/kg/cypher` (admin), `/v1/kg/export/rdf` - `svc-rag-retriever`: `/v1/rag/search` - `svc-reason`: `/v1/reason/compute_schedule`, `/v1/reason/explain/{schedule_id}` - `svc-forms`: `/v1/forms/fill`, `/v1/forms/evidence_pack` - `svc-hmrc`: `/v1/hmrc/submit`, `/v1/hmrc/submissions/{id}` - `svc-firm-connectors`: `/v1/firm/sync`, `/v1/firm/objects` # USERS & ROLES - **Preparer** (default): do coverage, ingest, compute, fill forms. - **Reviewer**: approve/override low-confidence items, sign off. - **Admin**: can reload coverage policy, run KG Cypher tool, manage feature flags. # PRIMARY FLOWS (SCREENS) 1. **Dashboard** - **Coverage progress** per client & schedule (chips: ok/partial/blocking) - Tasks: clarifications pending, missing evidence, review requests - Quick actions: **Run Coverage**, **Upload Evidence**, **Compute Schedules** 2. **Client → Evidence Inbox** - Drag-and-drop upload (multi), URL import, RPA sync trigger button - List of documents with **kind** (P60, LettingAgentStatements...), tax year, confidence badges - Click opens **PDF Viewer** with **bbox highlights** (left: pages; right: extracted fields & evidence tags) 3. **Coverage Check** - **CoverageMatrix** per schedule: rows = evidence items, cols = status/boxes - Status chips: `present_verified` (green), `present_unverified` (amber), `missing`/`conflicting` (red) - **ClarifyPanel**: generates question via `/v1/coverage/clarify` with **citations** - Inline **Upload** buttons mapped to `svc-ingestion` with `tag=` set to evidence.id 4. **RAG + Guidance** - Search bar (+ filters: tax_year, schedule, topic), **results with citations** - Clicking a citation can **deep-link** to a PDF doc_id/page/bbox (if local doc) or open URL (if guidance) 5. **Schedules & Calculations** - Select schedule (SA102/SA103…): **Compute** → show **FormBox table** (box_id, description, value, source) - Per-row **Explain** opens **Lineage Drawer**: graph path (FormValue ↔ Evidence ↔ Document) via cytoscape - Editable cells (if user override allowed) with reason + evidence attachment; show diff 6. **Forms & Evidence Pack** - Generate PDFs (download viewer); **Evidence Pack** download (ZIP + manifest) - Checklist (“All blocking gaps resolved”, “Reviewer sign-off received”) 7. **Submission** - Pre-flight checks, HMRC mode banner (stub/sandbox/live) - Submit; show `submission_id` and status; link to timeline 8. **Timeline & Audit** - Event list (ingested, OCR, extracted, mapped, computed, submitted) - Filter by service; click to jump to relevant screen or doc 9. **Admin** - Coverage policy viewer, **hot-reload** button - KG Cypher tool (admin only); feature flags (read-only switch list with notes) # ROUTE MAP (Next.js App Router) ``` / -> Dashboard /clients -> Client list (search) /clients/[clientId] -> Client overview (tabs) /clients/[clientId]/evidence -> Evidence Inbox + PDF viewer /clients/[clientId]/coverage -> Coverage Check + ClarifyPanel /clients/[clientId]/rag -> RAG + Guidance (citations) /clients/[clientId]/schedules -> Schedule picker + tables /clients/[clientId]/forms -> PDFs + Evidence Pack /clients/[clientId]/submit -> HMRC submission /audit -> Global timeline /admin -> Admin home /admin/policy -> View/reload coverage /admin/kg -> Cypher tool (admin) /me -> Me (claims, groups) ``` # PROJECT LAYOUT ``` ui-review/ app/ (dashboard)/page.tsx clients/[clientId]/(layout).tsx clients/[clientId]/overview/page.tsx clients/[clientId]/evidence/page.tsx clients/[clientId]/coverage/page.tsx clients/[clientId]/rag/page.tsx clients/[clientId]/schedules/page.tsx clients/[clientId]/forms/page.tsx clients/[clientId]/submit/page.tsx audit/page.tsx admin/policy/page.tsx admin/kg/page.tsx me/route.ts api/me/route.ts # echoes forwarded claims for the app layout.tsx # shell, nav, toasts globals.css middleware.ts # route guard reading forwarded headers (server-only) components/ upload-dropzone.tsx status-chip.tsx coverage-matrix.tsx clarify-panel.tsx pdf-viewer.tsx # pdfjs + bbox overlays evidence-card.tsx lineage-graph.tsx # cytoscape graph schedule-table.tsx value-cell.tsx explain-drawer.tsx rag-search.tsx citations-list.tsx timeline.tsx lib/ api.ts # typed fetch; baseURL; error & retry clients.ts # per-service client wrappers (TanStack Query) auth.ts # /api/me parsing; role helpers bbox.ts # bbox geometry utils types.ts # shared UI types (zod) feature-flags.ts # remote flags (read-only) formatting.ts # money/date utils (en-GB) hooks/ use-claims.ts use-coverage.ts use-rag.ts use-pdf.ts styles/ shadcn.css public/ icons/ tests/ e2e/ unit/ a11y/ .env.example Dockerfile next.config.mjs tailwind.config.ts postcss.config.js package.json tsconfig.json eslint.config.mjs playwright.config.ts ``` # API CLIENTS (STRICT TYPES) - Create **zod** schemas for each service response and infer TypeScript types. - Wrap `fetch` with: - base URL from `NEXT_PUBLIC_API_BASE` (Traefik hostname, e.g., `https://api.local`) - `credentials: "include"` (SSO cookie path through Traefik) - retries (idempotent GET), exponential backoff; error normalization `{type,title,status,detail,trace_id}` - Use **TanStack Query** for caching, optimistic updates on overrides, and background refetch. # KEY COMPONENT DETAILS ## PDF Viewer (`pdf-viewer.tsx`) - Render via `pdfjs-dist`. - **Overlay layer** draws rectangles from bbox `{page, x, y, w, h}`; clicking highlight scrolls to corresponding extracted field; right panel shows evidence details (doc_id, page, confidence, mapping to boxes). - Keyboard shortcuts: `J/K` page nav; `H` toggle highlights; `Z` zoom. ## Coverage Matrix (`coverage-matrix.tsx`) - Inputs: `CoverageReport`. - Rows: evidence items; columns: status chip, boxes (expand to show list), actions (Upload, Clarify). - “Clarify” opens `clarify-panel.tsx` which calls `/v1/coverage/clarify` and produces **copyable text** + **citations** + **upload actions**. ## Lineage Graph (`lineage-graph.tsx`) - Render path: **FormValue → Evidence → Document** (+ any Rule/Calculation nodes). - Click a node jumps to PDF viewer at the correct page/bbox (if Document is local). - Cytoscape style: clean, accessible (labels, readable contrast). ## Schedule Table (`schedule-table.tsx`) - Columns: `box_id`, `description`, `value`, `source`, `confidence`, `explain` - **Explain** button opens `explain-drawer.tsx` which shows lineage graph + textual explanation trace (and citations if RAG guidance was used). # ACCESSIBILITY & UX - WCAG 2.2 AA: all interactive components keyboard accessible; focus outlines; ARIA labels - **Axe** checks in unit and e2e tests; Lighthouse accessibility ≥ 95 - Colour-blind safe palette; do not encode status **only** by colour — use icon + label # PERFORMANCE - Code-split per route; lazy-load heavy views (PDF, graph) - Virtualize long tables and evidence lists - Preload API data via RSC loaders on server when appropriate - Web Vitals: LCP < 2.5s on local; keep JS bundle sizes modest # ENV & INTEGRATION - `.env` (copied to `.env.local`): - `NEXT_PUBLIC_API_BASE=https://api.local` - `NEXT_PUBLIC_APP_BASE=https://ui.local` - `NEXT_PUBLIC_FEATURE_FLAGS_URL=` (optional) - `AUTHENTIK_LOGOUT_URL=` (show Sign Out link to edge logout endpoint) - **Traefik labels** for the UI container: - Router rule `Host(\`ui.local\`)\` to UI service - Middleware `authentik-forwardauth` and `rate-limit` - The UI calls backend at `https://api.local/*` via Traefik. # TESTING (MANDATORY) - **Unit (React Testing Library):** - `coverage-matrix` status rendering and actions - `clarify-panel` formatting with alternatives and citations - `pdf-viewer` highlight click → scroll and selection state - `lineage-graph` node click → callback invoked - **E2E (Playwright):** - Login is handled by Traefik SSO; for local, place the UI behind the gateway. - Scenario: Upload docs → Run coverage → See blocking gaps → Generate clarify text → Upload alt evidence → Re-run coverage → OK → Compute schedule → Explain lineage → Generate forms → (stub) submit - **A11y:** `axe-core` checks on major pages; fix violations. # QUALITY GATES (CI) - ESLint (`eslint.config.mjs` with `@typescript-eslint` + `jsx-a11y`) - TypeScript `strict: true` (no implicit any/any) - Prettier format check - Playwright E2E (headless) - Lighthouse CI (Dashboard, Coverage, Schedules) with budgets: - Performance ≥ 80 (local), Accessibility ≥ 95, Best Practices ≥ 90 # DELIVERABLES (RETURN ALL AS CODE BLOCKS) 1. `README.md` (local run with Traefik SSO; env vars; routes; role matrix) 2. `package.json` (scripts: dev, build, start, lint, typecheck, test, e2e, a11y, lighthouse) 3. `tsconfig.json` (strict true; noUncheckedIndexedAccess true) 4. `eslint.config.mjs` + `.prettier*` 5. `next.config.mjs` (headers passthrough; image domains) 6. `tailwind.config.ts` + `postcss.config.js` 7. `app/layout.tsx`, `app/(dashboard)/page.tsx`, route pages listed above 8. `app/api/me/route.ts` (server only: echo forwarded claims) 9. `middleware.ts` (SSR gate: if no forwarded claims, show “Not Authenticated”) 10. `components/*` (all listed) 11. `lib/*` (typed API, bbox utils, auth helpers, formatting) 12. `hooks/*` (coverage, rag, pdf, claims) 13. `tests/unit/*`, `tests/e2e/*`, `tests/a11y/*` 14. `Dockerfile`, `.env.example`, `playwright.config.ts` # ACCEPTANCE CRITERIA (DoD) - Runs behind Traefik + Authentik; **no in-app auth**. - **Coverage Check** renders matrix, generates clarifying questions with citations, and triggers uploads. - **PDF Viewer** highlights bboxes and navigates correctly; lineage jumps to precise evidence. - **Schedules** compute and render with **Explain** showing graph & textual explanation with citations. - **RAG** results include citations and never display PII. - All pages pass Axe checks; Lighthouse thresholds met. - CI green (lint, typecheck, unit, e2e, a11y, lighthouse). # START Generate the full **ui-review** application with the files and behavior above. Include typed API clients, strict TypeScript, accessible components, test suites, and Dockerfile.