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>
5.3 KiB
Data Model: Agent and Admin UI
This feature introduces no persisted frontend data — every "entity" below is a TypeScript type
mirroring a supporthub-api response shape, kept in lib/api/types/. Fields are not re-listed in
full where a backend contract already documents them exactly; each type below names its source
contract instead of duplicating it (Constitution Principle V — never a second, driftable copy of
a shape the backend already owns).
Scoped to this plan's immediate implementation target (Setup + User Stories 0-3). US4-US7's own types follow the identical pattern against their own backend contracts when those stories are built.
Session
The frontend's own type, not mirrored from any single backend response — assembled from
POST /auth/login / GET /auth/me's data.user shape
(specs/010-identity-auth/contracts/identity-auth-contract.md, supporthub-api).
interface Session {
id: string;
email: string;
name: string;
role: 'ADMIN' | 'AGENT';
}
Stored: nowhere as an object — only the raw JWT lives in the sh_session cookie (research.md);
Session is derived at read time via GET /auth/me, never trusted from a locally-decoded JWT
claim for anything but middleware's own UX-only redirect decision.
AssignedTicketSummary
Mirrors specs/011-agent-ticket-queue/contracts/agent-ticket-queue-contract.md's
GET /agents/me/tickets response item exactly (id, code, status, priority, severity, product,
customer, assignedAt, sla) — the Agent Dashboard's (US1) only data source.
Ticket (workbench detail)
Mirrors specs/003-ticketing/contracts/ticket-lifecycle-contract.md's GET /tickets/:ticketId
response, plus:
- Messages:
specs/003-ticketing/contracts/ticket-lifecycle-contract.md's message-list shape (customer/AI/agent messages, internal notes flaggedinternalOnlyor equivalent — see that contract for the exact discriminator field name). - Problem-resolution records (investigation, root cause, solution, verification, resolution):
specs/009-problem-resolution/contracts/problem-resolution-contract.md. - Current assignment:
specs/007-orchestration-assignment/contracts/orchestration-contract.md. - SLA run:
specs/008-sla-escalation/contracts/sla-escalation-contract.md.
The Ticket Workbench (US2) composes these as separate TanStack Query calls (one per concern), not one oversized aggregate endpoint — matches how supporthub-api itself exposes them as separate resources.
Support Organization Editor entities (US3)
Mirrors specs/006-support-organization/contracts/support-org-contract.md exactly: Team,
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 union, derived from a TanStack Query result, never persisted.ApiError:{ code: string; message: string; statusCode: number }— the shape every supporthub-api error response already uses ({success:false,error:{code,message}}), thrown bylib/api/client.ts's response interceptor so a failed mutation'serroris always this shape, never a raw axios error.
Validation / Business Rules
- No screen computes ticket-transition validity, SLA due dates, most-specific-policy resolution, or escalation-rule matching — every such value is read as-is from the API response types above (FR-012).
Session.rolegates which portal renders (FR-011) but is never used to compute a business decision beyond that gate.