Frontend User Stories — Overview & Conventions
This section documents the sharded, INVEST + Gherkin-formatted product backlog for the AMTP
web frontend. The application is a pure React SPA; all routing is client-side
(React Router), environment variables are baked at build time or fetched via /config,
and no Node.js runtime logic exists in the frontend bundle.
Personas
| Persona | Abbrev. | Primary Goals | RBAC Summary |
|---|---|---|---|
| Business User | BU |
Connect repos, trigger runs, review PRs and artifacts | Create/edit projects, trigger runs, view history and artifacts, manage notification preferences |
| Approver | AP |
Decide on awaiting_approval gates with full context |
View and action approval inboxes; no project/run mutation beyond approval decisions |
| Operator / Admin | OP |
Maintain system health, GitHub App credentials, tenant roster, rate-limit config | Full admin surface; can terminate workflows, rotate secrets, manage tenants and roles |
| Auditor | AU |
Read-only compliance and audit access with zero mutation side-effects | Read-only everywhere; mutating controls hidden; sensitive fields pre-redacted; clipboard copy intercepted and redacted |
Reading Conventions
Story shape
### Story X.Y — <Imperative title>
**As a** <persona abbrev>
**I want** <capability>
**So that** <user outcome>
**Acceptance criteria**
- **Scenario: <label>**
- **Given** …
- **And** …
- **When** …
- **Then** …
- **And** …
Gherkin grammar
Given— precondition (DB state, session state, or role)When— user action or system eventThen— observable UI changeAnd— continuation of preconditions or outcomesScenario:label is mandatory; one label per scenario
Optimistic mutations additionally require a mutation addendum block in each mutating story.
Any mutation Gherkin that lacks a prior_state clone in the Given/And block fails PR review.
Source citation format
**Source**
- `@/c:/ZT_AMTP/docs/AMTP_Docs_Website/<page>.html#<anchor>` — purpose
Endpoint map grammar
**Endpoint map**
- `<METHOD> /<path>` — purpose
- `<SSE|WS> /<path>` — streamed payload description
- DB: `<table>.<column>` — state read or written
Cross-Cutting NFRs
These requirements apply to every story across all 15 epics. They are declared here and inherited; epics do not repeat them.
Accessibility
WCAG 2.1 AA — visible focus rings on all interactive elements, full keyboard reachability, semantic landmark regions
(<main>, <nav>, <aside>), aria-live regions for all
SSE/streaming updates, colour contrast ≥ 4.5:1 for body text, interactive element hit-targets ≥ 44 × 44 CSS px.
Theming
prefers-color-scheme parity with the AMTP docs site. Palette: OKLCH, ZagTrader blue hue 240–241°,
accent oklch(63% 0.20 241). Fonts: Chakra Petch (headings) + Hanken Grotesk (body). Callouts use full
border: 1px solid + background tint — no accent left-stripes. No hard-coded colour values outside the
design-token layer.
Internationalisation & Logical Properties
Copy externalised to i18n resource files. RTL-readiness (Arabic) is mandatory. Physical CSS direction properties are forbidden. CI enforcement is automated and blocks merge with no override path.
| Forbidden | Required |
|---|---|
margin-left / margin-right | margin-inline-start / margin-inline-end |
padding-left / padding-right | padding-inline-start / padding-inline-end |
left: / right: (layout) | inset-inline-start / inset-inline-end |
border-left / border-right | border-inline-start / border-inline-end |
text-align: left|right | text-align: start|end |
Reduced Motion
prefers-reduced-motion: reduce disables stage-timeline animations, skeleton shimmer, and all transition effects;
static representations replace them.
Security
- No LLM context or run telemetry stored client-side beyond the OTel browser SDK envelope
- OAuth scope minimisation — request only scopes required for the operation
- CSRF tokens on every state-changing request
- Strict CORS and
Content-Security-Policywith nounsafe-inlinefor scripts - No third-party analytics scripts on authenticated routes
Privacy — Redaction Filter (dual-mode)
The Redaction Filter (RedactionFilter) operates in two modes:
| Mode | Surfaces | Strategy |
|---|---|---|
| Heuristic | Epics 5, 8 | Regex/pattern catalogue — catches tokens, JWTs, PEM markers, emails, SSNs |
| Schema-Strict | Epic 15 | JSON-pointer allow-list of known-sensitive keys per audit-event schema |
Every redaction emits a typed breadcrumb to the structured client log and OTel browser SDK envelope. The breadcrumb never carries the value, a prefix, a hash, or any reversible derivative.
Auditor copy/cut/drag interception: On the Artifact Viewer (Epic 5) and Audit Log (Epic 15), the UI intercepts
copy, cut, and dragstart events for the Auditor persona, calls
event.preventDefault(), runs the selection through the appropriate Redaction Filter mode, and writes only
the redacted projection to event.clipboardData/DataTransfer.
Performance Budget
- Time-to-interactive on the run-detail page ≤ 2.5 s p75 on broadband
- SSE first-event latency ≤ 1 s after subscribe
Dev-Prod Parity (Error Provenance)
Every error surface distinguishes between local infra failures (Docker daemon down, missing PEM, Postgres not
bootstrapped, Valkey unreachable) and production API failures (GitHub API 5xx, OpenAI provider degradation,
OAuth IdP outage). The deciding axis is the VITE_ENV build flag, resolved by the EnvProvenance module.
PR reviewers reject error copy that conflates the two.
Traceability — Correlation Chip + Last-Synced Badge
Correlation Chip (CorrelationChip): Every error toast, banner, modal, and empty state renders
the Correlation chip showing run_id (when scoped) and request_id from the X-Request-ID
response header, copyable to clipboard.
Last-Synced Badge (LastSyncedBadge): Any view rendered from a reconciliation snapshot,
prior_state rollback, or SSE Circuit-Breaker stall must display Synced at: <ISO local time> · Snapshot
beside the Correlation chip. When the live SSE/WS stream is healthy, the badge reads Live.
Shared Frontend Modules
| Canonical name | Description | Owner epic(s) |
|---|---|---|
RedactionFilter | Dual-mode filter (Heuristic / Schema-Strict) + redactSelection() clipboard helper | 5, 8, 15 |
audit-export-worker.ts | Web Worker for non-blocking audit blob processing | 15 |
ReconnectController | SSE/WS reconnect manager with Circuit-Breaker (3 disconnects / 60 s → Manual Reconnect Only) | 4 |
ReconciliationFetcher | GET /runs/{id} post-reconnect re-sync; suppressed in Manual Reconnect Only | 4 |
TemporalLifecycleDetector | Distinguishes Network Idle from Activity Heartbeat Timeout | 4 |
SessionRefreshController | Single-flight 401 → POST /auth/refresh → retry + in-flight form preservation | 1 |
ReturnToValidator | Whitelist + HMAC verification; anti-Open-Redirect | 1 |
OptimisticMutationHelper | prior_state capture / restore; persists x-idempotency-key for retry replay | 2, 3 |
EnvProvenance | Resolves development / staging / production build flag | All |
CorrelationChip | Renders copyable run_id / request_id chip on all error surfaces | All error surfaces |
LastSyncedBadge | Live vs Synced at: <time> · Snapshot indicator on streamed / snapshot views | 4+ |
design-tokens | Single source of truth for palette, typography, callout shapes | All |
Failure-Class Distribution
| Failure class | Owning epic | Trigger surface |
|---|---|---|
| Rate-limit rejection (Valkey) | Epic 3 | Submit-run form, pre-flight 429 |
MalformedLlmOutput | Epic 4 | Stage card error state + retry counter |
SchemaValidationError | Epic 4 | Stage card error state + artifact link disabled |
BranchProtectionViolation | Epic 6 | Approval gate banner + decision form |
StaleBaseBranch | Epic 7 | Terminal failure card on PR delivery view |
PR-lock contention (pr_lock) | Epic 7 | “Waiting for repository lock” status |
| GitHub App auth failure | Epic 13 | Install status panel + remediation wizard |
| OTel/Tempo/Prometheus down | Epic 14 | Service map degraded badges |
| Artifact JSON oversize/binary | Epic 5 | Viewer fallback + download-only mode |
Zero-State Ownership
The cold-start onboarding flow (empty tenant → first project → GitHub App install → first run trigger) is owned by Epic 2 — Project Management. Epics 1 and 3 cross-link to this flow and do not duplicate empty-state acceptance criteria.
Epic Link Tree
| Epic | One-line summary |
|---|---|
| Epic 1 — Authentication | OAuth login, silent token refresh, deep-link re-auth, Open-Redirect protection |
| Epic 2 — Project Management | Project CRUD, soft-delete/restore, running-state guard, onboarding zero-state |
| Epic 3 — Run Triggering | Manual run trigger, client-side idempotency key, rate-limit rejection |
| Epic 4 — Live Run Timeline | SSE/WS timeline, circuit-breaker, reconciliation, Temporal lifecycle detection |
| Epic 5 — Artifact Inspection | JSON viewer, diff, sanitizer staleness warning, Auditor redaction |
| Epic 6 — Approval Workflow | Approval inbox, approve/reject, 7-day pause, BranchProtectionViolation |
| Epic 7 — Pull Request Delivery | PR cards, idempotent re-PR, StaleBaseBranch, pr_lock contention |
| Epic 8 — Run History & Search | Global/project history, filters, full-text search, Auditor masking |
| Epic 9 — In-App Observability | Per-run token usage, latency, MCP cache-hit ratio, Grafana deep-links |
| Epic 10 — Notifications | In-app + email/Slack subscriptions, quiet hours, theme/locale |
| Epic 11 — Quota & Rate Limits | Read-only quota visibility, concurrency gauge, pr_lock wait queue |
| Epic 12 — Admin: Tenancy | Org CRUD, role assignment, invitations, SSO mapping |
| Epic 13 — Admin: GitHub App | App install status, PEM rotation wizard, auth-failure remediation |
| Epic 14 — Admin: System Health | Service map, Temporal task-queue backlog, Operator panic-button |
| Epic 15 — Audit Log | Immutable feed, Web Worker export, non-persistence guarantee, redaction |
Glossary
Core terms are defined at Concepts & Primer.
| Term | Short definition |
|---|---|
| Run | One end-to-end pipeline execution (runs table, V2) |
| Stage | One Temporal activity invocation within a run (stages table, V3) |
| Artifact | Structured JSON output persisted between agent boundaries (artifacts table, V4) |
| Approval | Human or automated decision gate for a stage (approvals table, V5) |
depth_level | Pipeline thoroughness tier: smoke / core / standard / deep |
pr_lock | Advisory lock preventing concurrent PR delivery for the same repository |
heartbeat_timeout | Per-stage maximum inter-event silence before an Activity Heartbeat Timeout is declared |
| Sanitizer | Per-artifact schema-normalisation version recorded in artifacts.content.meta.sanitizer |