supporthub-api's 010-identity-auth (built after this spec's initial approval) established that agent/admin login is supporthub-api's own authentication, never SaaS-delegated — this spec and the project constitution's Principle I still assumed the opposite. Adds User Story 0 (sign-in, P1) and FR-000/SC-006 for the login screen and session-guard this frontend must now own, and rewords FR-011/the affected Edge Case to reference the supporthub-api session role instead of a "SaaS-provided role." Only end-customer identity remains SaaS-delegated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
135 lines
8.6 KiB
Markdown
135 lines
8.6 KiB
Markdown
<!--
|
|
Sync Impact Report
|
|
Version change: 1.0.0 → 1.1.0
|
|
Modified principles:
|
|
- I. Renamed from "SaaS Is the Sole Identity & Access Authority" to "Each Identity Has
|
|
Exactly One Authority, and the Frontend Is Never It" — corrects a mis-scoping in the
|
|
original text, which treated agent/admin identity as SaaS-delegated. supporthub-api's
|
|
010-identity-auth (built after this constitution's initial ratification) established that
|
|
agent/admin login is supporthub-api's own authentication, never SaaS-delegated — mirroring
|
|
supporthub-api's own Principle I, which was itself clarified during that same feature's
|
|
planning. Only end-customer identity remains SaaS-delegated.
|
|
Added sections: none
|
|
Removed sections: none
|
|
Deferred items: none
|
|
Templates requiring follow-up: specs/001-agent-admin-ui/spec.md's FR-011 and Edge Cases still
|
|
say "SaaS-provided role" for agent/admin access — needs the same correction before that
|
|
feature's plan.md is written.
|
|
-->
|
|
|
|
# SupportHub Web Constitution
|
|
|
|
## Core Principles
|
|
|
|
### I. Each Identity Has Exactly One Authority, and the Frontend Is Never It (NON-NEGOTIABLE)
|
|
supporthub-web MUST NOT implement its own user authentication, session management, or
|
|
role-based access control for either identity this project serves. It reads, and only reads,
|
|
whichever authority already owns that identity: for end-customers, that's the parent SaaS host,
|
|
via the documented token mechanism (`X-SaaS-User-Token`, per README.md); for agents/admins,
|
|
that's supporthub-api's own login (`POST /auth/login`, specs/010-identity-auth in
|
|
supporthub-api) — SupportHub is the sole authority for its own support-org structure and staff
|
|
accounts, exactly as supporthub-api's own Principle I defines, and was never SaaS-delegated.
|
|
Neither identity's role or session state is ever re-derived, cached as a second source of
|
|
truth, or locally overridden by this frontend. Rationale: an authentication or role system
|
|
duplicated on the frontend is worse than none — it creates a second place authorization can
|
|
silently disagree with whichever backend already decided it, and conflating the two identities'
|
|
different authorities is exactly the kind of drift Principle I exists to prevent.
|
|
|
|
### II. The Backend Is the Sole Source of Business Logic
|
|
supporthub-web MUST NOT re-implement ticket lifecycle state machines, SLA due-date or
|
|
pause/resume math, escalation rule evaluation, assignment/routing logic, or any other business
|
|
rule supporthub-api already owns. The frontend renders the state the API returns and calls the
|
|
API to change it — it never computes a business decision the backend is authoritative for, even
|
|
as a "just for the UI" shortcut (e.g. a client-side guess at whether a status transition is
|
|
valid). Rationale: two implementations of the same rule (one in Fastify, one in React) will
|
|
drift the moment either one changes; the API is already the tested, audited source of truth.
|
|
|
|
### III. Strict Portal Boundaries
|
|
The four route groups — `(public)`, `(customer)`, `(support)`, `(admin)` — are distinct
|
|
surfaces with different audiences and trust levels. Components, data, and navigation MUST NOT
|
|
leak across portal boundaries: an admin-only data shape (e.g. escalation policy internals) MUST
|
|
NOT be fetched or rendered from a customer-facing route, and customer-portal code MUST NOT
|
|
import agent- or admin-portal features. Shared UI primitives live in `components/ui` and are
|
|
portal-agnostic; portal-specific composition lives under each route group or its matching
|
|
`features/` module. Rationale: this is the frontend analogue of supporthub-api's module
|
|
boundaries (its own Principle III) — without an enforced seam, a support-agent-only view of a
|
|
ticket inevitably ends up reachable from the customer portal by accident.
|
|
|
|
### IV. Typed API Boundary, No Ad Hoc Fetching
|
|
Every call to supporthub-api goes through a single typed API client layer (`lib/api`), with
|
|
request/response shapes kept in sync with the backend's own contracts
|
|
(`specs/*/contracts/*.md` in supporthub-api). Components and `features/` modules MUST NOT call
|
|
`fetch`/`axios` directly — all server state flows through TanStack Query hooks built on that
|
|
client layer, giving one consistent place for auth headers, error handling, and retry/caching
|
|
policy. Rationale: a typed, single-entry-point client is what keeps a contract change on the
|
|
backend from becoming a silent runtime break scattered across dozens of components.
|
|
|
|
### V. Configuration Over Hardcoding
|
|
Anything the backend exposes as admin-configurable — SLA policies, escalation rules,
|
|
routing/assignment strategy, support hierarchy — MUST be rendered and edited generically from
|
|
what the API returns, never hardcoded as frontend constants or duplicated enums that could drift
|
|
from the backend's own validated values (e.g. root-cause types, verification methods,
|
|
escalation trigger types). Rationale: mirrors supporthub-api's own Principle II — a value the
|
|
business can change from an admin screen must never require a frontend deploy to keep it in
|
|
sync with the backend's own enum.
|
|
|
|
### VI. Accessible, Responsive, Enterprise-Grade UI
|
|
Every screen MUST be usable via keyboard, meet WCAG AA contrast, and remain usable down to a
|
|
reasonable minimum viewport. This is an enterprise support tool used for hours at a time by
|
|
agents and admins, not a marketing site — interaction patterns (tables, forms, workflows) MUST
|
|
prioritize density and speed of task completion over decorative polish. Rationale: an
|
|
inaccessible or slow-to-use agent workspace directly costs support throughput and SLA
|
|
compliance — this is a productivity tool first.
|
|
|
|
### VII. Testing Gates
|
|
Required test categories: unit tests (Vitest) for hooks, utilities, and business-facing
|
|
component logic; integration tests for each portal's critical flows; Playwright E2E for the two
|
|
cross-cutting journeys that matter most — (A) a customer submitting and tracking a ticket
|
|
through to resolution/confirmation, and (B) an agent working an escalated ticket through
|
|
investigation to resolution. Typecheck and lint MUST be clean before any feature is considered
|
|
done, matching supporthub-api's own quality-gate discipline. Rationale: a frontend regression
|
|
that silently breaks the agent workspace or the customer submission flow is a direct support-
|
|
capacity or customer-trust incident, not a cosmetic bug.
|
|
|
|
## Technology & Platform Constraints
|
|
|
|
- Stack: Next.js 14 (App Router), React 18, TypeScript, TanStack Query, Tailwind CSS, axios
|
|
(wrapped by the typed client layer, Principle IV), Vitest, Playwright.
|
|
- Architecture style: route groups as portals (`(public)`, `(customer)`, `(support)`,
|
|
`(admin)`), domain-organized `features/` modules, portal-agnostic `components/ui`. Do not
|
|
introduce a second frontend framework or a competing state-management paradigm without a
|
|
constitution amendment — one server-state layer (TanStack Query) and one client-state
|
|
approach (`stores/`) keep data flow predictable.
|
|
- Every environment (`development`, `test`, `production`) has its own `.env.*` file, matching
|
|
the existing convention — no secrets committed to the repository.
|
|
|
|
## Development Workflow & Quality Gates
|
|
|
|
- `npm run typecheck` and `npm run lint` MUST pass before a feature is considered done.
|
|
- `npm run test` (Vitest) covers unit/integration-level logic; `npm run test:e2e` (Playwright)
|
|
covers the two cross-cutting journeys named in Principle VII, plus any portal-specific
|
|
critical flow a feature's own spec identifies.
|
|
- New pages/features are built against the existing scaffold (route groups, `features/`
|
|
modules) — replacing a placeholder page's content, not restructuring the route tree, unless a
|
|
spec explicitly calls for a structural change.
|
|
|
|
## Governance
|
|
|
|
This constitution supersedes ad hoc conventions and undocumented team habits for
|
|
supporthub-web. All PRs and code reviews MUST verify compliance with the principles above
|
|
before merge.
|
|
|
|
Amendments require: a documented rationale for the change, a version bump under the semantic
|
|
versioning rule below, and an updated Sync Impact Report prepended to this file. MAJOR = a
|
|
backward-incompatible principle removal or redefinition. MINOR = a new principle added, or
|
|
existing guidance materially expanded. PATCH = clarification, wording, or typo fixes with no
|
|
semantic change. Any exception to a MUST/MUST NOT rule requires explicit written justification
|
|
in the relevant PR description and is expected to be rare, not routine.
|
|
|
|
This project is a sibling to, and a pure consumer of, `supporthub-api` — that project's own
|
|
constitution and `docs/00-INDEX.md` through `docs/10-implementation-roadmap.md` remain the
|
|
authority for backend and product-domain design; this constitution governs only how
|
|
supporthub-web is engineered.
|
|
|
|
**Version**: 1.1.0 | **Ratified**: 2026-09-07 | **Last Amended**: 2026-09-07
|