test: harden starter experience quality contract
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
# Manual accessibility review checklist
|
||||
|
||||
Automated axe checks do not establish WCAG conformance. A human reviewer must
|
||||
review all three route records in `artifacts/tests/a11y-manual/` against one
|
||||
release candidate and sign them. Copy the template fields exactly; the gate
|
||||
rejects blank identity/timestamp/signature fields, pending verdicts, mismatched
|
||||
release IDs, or missing routes.
|
||||
review all six route records in `artifacts/tests/a11y-manual/` against one
|
||||
release candidate and sign them. The required scope is derived from the route
|
||||
registry: `APP_HOME`, `EXAMPLES_UI`, `EXAMPLES_STATES`, `EXAMPLES_AUTH`,
|
||||
`SAMPLE_RESOURCE_LIST`, and `NOT_FOUND`. Copy the template fields exactly; the
|
||||
gate rejects blank identity/timestamp/signature fields, pending verdicts,
|
||||
mismatched release IDs, or missing routes.
|
||||
|
||||
Allowed item verdicts:
|
||||
|
||||
@@ -43,5 +45,7 @@ The reviewer must verify:
|
||||
- M7: non-essential motion is suppressed with reduced-motion preference
|
||||
- Screen reader: headings, live regions, errors, and actions are announced once
|
||||
|
||||
Passing automated evidence means only that tested pages had no critical or
|
||||
serious axe findings under the recorded browser run.
|
||||
`EXAMPLES_UI` requires real M4 modal and M5 field-error review; those items must
|
||||
not be marked not-applicable on that route. Passing automated evidence means
|
||||
only that tested pages had no critical or serious axe findings under the
|
||||
recorded Chromium, Firefox, and WebKit runs.
|
||||
|
||||
@@ -8,6 +8,8 @@ in `review-ledger.json`, not automatically to edits in this file.
|
||||
flowchart LR
|
||||
Bootstrap[bootstrap / composition root] --> Presentation[presentation]
|
||||
Bootstrap --> Adapters[adapters]
|
||||
Presentation --> Shell[app shell and route surfaces]
|
||||
Shell --> Providers[session and theme providers]
|
||||
Presentation --> Application[application]
|
||||
Adapters --> Application
|
||||
Application --> Domain[domain]
|
||||
@@ -21,3 +23,9 @@ implement application ports, and only the composition root selects concrete
|
||||
adapters. Contract registries are the single named source for routes, API
|
||||
operations, environment values, storage keys, errors, queries, telemetry, and
|
||||
release tokens.
|
||||
|
||||
The executable route tree is mounted only after runtime configuration and
|
||||
release-manifest coherence pass. It receives the composed query client,
|
||||
credential-opaque session port, storage port, telemetry port, and immutable
|
||||
build ID. Visible starter pages depend on those ports and contracts, never on a
|
||||
concrete adapter or the removable sample fixture.
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Starter experience contract
|
||||
|
||||
The repository provides a runnable, domain-neutral application rather than
|
||||
only infrastructure contracts. The starter experience is intentionally
|
||||
replaceable at the page level while the shell, providers, boundaries,
|
||||
primitives, and state surfaces remain reusable.
|
||||
|
||||
## Runtime composition
|
||||
|
||||
```text
|
||||
validated config + coherent release manifest
|
||||
-> concrete adapters
|
||||
-> QueryClientProvider
|
||||
-> ThemeProvider
|
||||
-> SessionProvider
|
||||
-> BrowserRouter
|
||||
-> AppShell
|
||||
-> lazy route boundary
|
||||
```
|
||||
|
||||
Boot stops before product mount when configuration or release coherence fails.
|
||||
Each lazy page renders inside Suspense and a telemetry-aware route boundary.
|
||||
Route changes move focus to the new page heading; the skip link and landmarks
|
||||
remain stable in the shell.
|
||||
|
||||
## Registered routes
|
||||
|
||||
| ID | Path | Access | Surface |
|
||||
| --- | --- | --- | --- |
|
||||
| `APP_HOME` | `/` | public | readiness dashboard |
|
||||
| `EXAMPLES_UI` | `/examples/ui` | public | interactive primitives and tokens |
|
||||
| `EXAMPLES_STATES` | `/examples/states` | public | async and access state matrix |
|
||||
| `EXAMPLES_AUTH` | `/examples/auth` | public | session integration controls |
|
||||
| `SAMPLE_RESOURCE_LIST` | `/sample/resources` | integration-defined | protected integration seam |
|
||||
| `NOT_FOUND` | `*` | public | safe navigation recovery |
|
||||
|
||||
Navigation labels and order come from `ROUTE_REGISTRY`; the sidebar does not
|
||||
maintain a second route list. The client access decision never claims to be
|
||||
authorization.
|
||||
|
||||
## Authentication seam
|
||||
|
||||
The session port exposes state subscription, sign-in start, sign-out,
|
||||
credential attachment, recovery, and unauthenticated notification. Credentials
|
||||
remain opaque to the application and presentation layers.
|
||||
|
||||
- `demo`: local/development-only state transition with no credentials
|
||||
- `external`: delegates to `globalThis.__CA_FRONTEND_AUTH_OWNER__`
|
||||
- missing/invalid external owner: fails closed as `integration-failed`
|
||||
|
||||
An external owner implements `readState`, `subscribe`, `beginSignIn`,
|
||||
`signOut`, `attachCredential`, `recoverSession`, and
|
||||
`notifyUnauthenticated`. It owns token acquisition and storage.
|
||||
|
||||
## Extending the starter
|
||||
|
||||
1. Register the route path, access hint, title, chunk, loading surface, error
|
||||
surface, and optional navigation metadata in `src/contracts/routes.js`.
|
||||
2. Add a lazy page in `src/presentation/` and render it through `RouteSurface`.
|
||||
3. Use application ports or use cases; do not import concrete adapters.
|
||||
4. Use the semantic tokens, UI primitives, and state surfaces before adding a
|
||||
project-specific variant.
|
||||
5. Add component behavior, all-engine E2E, automated axe, and signed manual
|
||||
route evidence.
|
||||
6. Run `test:sample-removal` to prove the visible starter still builds without
|
||||
`src/sample/contract-fixture`.
|
||||
|
||||
Theme preference is the public `COLOR_SCHEME` storage contract. Authentication
|
||||
tokens and other secrets remain forbidden storage keys.
|
||||
@@ -30,6 +30,11 @@ registry: merge evidence through the PR decision, coherent release evidence
|
||||
through the next release promotion, drill evidence through the next production
|
||||
promotion, and field evidence through aggregation.
|
||||
|
||||
Browser-backed merge gates install and execute the pinned Chromium, Firefox,
|
||||
and WebKit engines. This makes route behavior, reflow, native dialog semantics,
|
||||
theme persistence, and automated accessibility a cross-engine contract rather
|
||||
than a Chromium-only smoke check.
|
||||
|
||||
Repository variables required by higher tiers:
|
||||
|
||||
- `HOSTING_BASE_URL` for live header verification
|
||||
|
||||
@@ -1,8 +1,32 @@
|
||||
# Design-token styling contract
|
||||
|
||||
`src/presentation/styles/theme.css` is the styling SSOT. Components consume
|
||||
semantic color, spacing, typography, and radius tokens through static Tailwind
|
||||
classes.
|
||||
semantic color, spacing, typography, status, and radius tokens through static
|
||||
classes. `/examples/ui` is the executable token and primitive gallery.
|
||||
|
||||
## Theme contract
|
||||
|
||||
The supported public preference is the closed set `system`, `light`, and
|
||||
`dark`. `ThemeProvider` reads and writes `COLOR_SCHEME` through the application
|
||||
storage port; it does not access a raw storage key. `system` subscribes to
|
||||
`prefers-color-scheme` changes. Bootstrap applies the persisted preference
|
||||
before React paints.
|
||||
|
||||
Components use semantic tokens such as `--color-panel`, `--color-content`,
|
||||
`--color-border`, `--color-action`, and status surface/content/border triples.
|
||||
They must not hard-code a light-only panel or text color. Both light and dark
|
||||
surfaces are included in automated axe checks.
|
||||
|
||||
## Included primitives
|
||||
|
||||
- `Button`: primary, secondary, danger, and ghost intent
|
||||
- `TextField`: label, help text, required state, and associated validation error
|
||||
- `Card`: labelled surface with optional footer
|
||||
- `Alert` and `Badge`: non-color-only status feedback
|
||||
- `Dialog`: native modal semantics, Escape/backdrop close, and trigger focus
|
||||
restoration
|
||||
- async and access state surfaces: loading, refresh, empty, terminal error,
|
||||
auth required, forbidden, and not found
|
||||
|
||||
Arbitrary-value policy:
|
||||
|
||||
@@ -13,5 +37,5 @@ Arbitrary-value policy:
|
||||
- user-controlled or runtime-composed class strings are forbidden
|
||||
- class variants must be selected from a closed static map
|
||||
|
||||
The removable sample may demonstrate tokens, but product modules must not
|
||||
import from `src/sample/contract-fixture`.
|
||||
The removable sample may demonstrate tokens, but production starter modules do
|
||||
not import from `src/sample/contract-fixture`.
|
||||
|
||||
@@ -12,6 +12,13 @@ Each gate is blocking in its declared scope. Failures are not downgraded with
|
||||
| end-to-end | `pnpm test:e2e` | `artifacts/tests/e2e/` |
|
||||
| accessibility | `pnpm test:a11y` | `artifacts/tests/a11y.json` |
|
||||
|
||||
End-to-end and automated accessibility scenarios run on the pinned Chromium,
|
||||
Firefox, and WebKit engines. The responsive contract explicitly exercises
|
||||
320px reflow, a mobile navigation drawer, and a wide two-column gallery.
|
||||
Theme scenarios verify persistence, operating-system changes, and dark-surface
|
||||
axe results. Native modal focus and validation association are exercised in
|
||||
both component and browser tests.
|
||||
|
||||
A control is verified only when a positive fixture passes and its deliberately
|
||||
failing negative fixture is rejected. Generated evidence is retained by CI;
|
||||
the repository tracks only the evidence directory structure.
|
||||
|
||||
Reference in New Issue
Block a user