test: harden starter experience quality contract

This commit is contained in:
donghyeon-ka
2026-07-26 00:28:09 +09:00
parent 68d9efbda3
commit 236909be64
17 changed files with 278 additions and 20 deletions
+10 -6
View File
@@ -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
View File
@@ -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.
+69
View File
@@ -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.
+5
View File
@@ -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
+28 -4
View File
@@ -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`.
+7
View File
@@ -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.