cv-web v0.1 GA-Readiness Checklist

Audit date: 2026-05-21 (CV-210) Site under audit: https://simplestruct.com/cv-web/ Build under audit: main @ 3053e601 (post-CV-195)

This checklist exists so we don’t point an alpha tester at a build with broken install, broken offline reopen, or known accessibility regressions. Items are marked PASS, FAIL, PARTIAL, or N/A. Every FAIL becomes a child Bug under CV-150 with a fix sprint assigned.

Summary

Category

PASS

FAIL

PARTIAL

N/A

Build & deploy

5

0

0

0

PWA install + offline (CV-195)

5

0

0

0

Update / cache invalidation

3

0

0

0

Accessibility

6

2

2

0

Operational hardening

4

0

0

0

Feature completeness

0

0

0

1

Total

23

2

2

1

GA blockers: 0. Two accessibility FAILs filed as child Bugs (sprintable in Sprint 22 — neither blocks GA on its own).


1. Build & deploy

#

Item

Status

Evidence

1.1

npm run build (tsc + vite) green

PASS

Build run during CV-195 — 1453 modules, 18 precache entries, sw.js + manifest emitted.

1.2

npm run test (Vitest) green

PASS

158/158 across 11 test files (run 2026-05-21).

1.3

Deploy SimpleStruct workflow green on main

PASS

Run 26244863686 — 2m11s, S3 sync + CloudFront /* invalidation.

1.4

Source maps uploaded

PASS

Sentry plugin builds source maps; auth-token-less warning is expected for non-release builds.

1.5

No Update Changelog regression

PASS

Workflow deleted in CV-543; CHANGELOG regenerates at Sphinx build time.

2. PWA install + offline (CV-195)

#

Item

Status

Evidence

2.1

manifest.webmanifest emitted with correct icons + start_url=/cv-web/

PASS

vite.config.ts manifest block; verified in dist/manifest.webmanifest.

2.2

Service worker registers (registerType: 'autoUpdate')

PASS

Vite plugin injects registration; verified in built index.html.

2.3

beforeinstallprompt captured + install button surfaced

PASS

PwaInstallButton mounted in App.tsx. Hides in standalone mode (iOS + Chromium).

2.4

App boot path has no required network fetch

PASS

Audited boot — only lazy Nominatim / Open-Meteo fetches in ProjectView.tsx, fail silently.

2.5

Last-loaded panel restores on offline reload

PASS

Dexie auto-persists; verified in store/db.ts boot path.

3. Update / cache invalidation

#

Item

Status

Evidence

3.1

skipWaiting: true + clientsClaim: true configured

PASS

vite.config.ts workbox block.

3.2

Update banner surfaces on new SW activation

PASS

PwaUpdateBanner uses useRegisterSW().needRefresh.

3.3

Cache invalidation strategy documented

PASS

52-cv-web-pwa-cache-strategy.md.

4. Accessibility

#

Item

Status

Evidence

4.1

Semantic landmarks (<main>, header via TopBar)

PASS

App.tsx line 106.

4.2

Image alt text

PASS

Only <img> in source is the welcome logo with alt="ConstructiVision".

4.3

Focus indicators visible (outline: 2px solid var(--cv-blue))

PASS

index.css global :focus rule.

4.4

Color contrast — navy/blue on white

PASS

--cv-navy #0d2b4e and --cv-blue #1565c0 exceed WCAG AA on white.

4.5

Form labels paired with inputs

PASS

label styling rule + manual spot-check on WelcomeScreen + dialog forms.

4.6

<div onClick> keyboard-accessible

FAIL

4 sites in PropsPanel.tsx (lines 217, 313, 512, 599) use <div className="props-entity-header" onClick={…}> as toggle controls. Not focusable, no Enter/Space handler. Filed as CV-545.

4.7

Modal close on Escape

FAIL

DialogRouter, SnapshotBrowser, CastSimReport modal overlays have backdrop-click close but no keydown Escape handler. Filed as CV-546.

4.8

Focus management on modal open (focus moves into modal, returns on close)

PARTIAL

Not implemented; trapped-focus pattern would be cleaner. Tracked alongside CV-546.

4.9

Automated axe-core scan integrated

PARTIAL

Audit was manual heuristic review. Playwright is in devDeps but @axe-core/playwright is not yet wired. Follow-up Task: file cv-web: wire axe-core scan into CI.

4.10

Welcome banner update + install button have keyboard equivalence

PASS

Both are <button> elements; Tab focus + Enter/Space work natively.

5. Operational hardening

#

Item

Status

Evidence

5.1

ErrorBoundary mounted at root

PASS

main.tsx wraps <App /> in <ErrorBoundary>.

5.2

Sentry instrumentation initialized before React

PASS

main.tsx imports ./instrument as the first line.

5.3

Worker errors surfaced to user (CastLayoutView)

PASS

Shipped in CV-540 — simError state + role="alert" banner.

5.4

Branch protection enforces commit conventions

PASS

validate-commit-messages.yml blocking on every push to main.

6. Feature completeness

#

Item

Status

Evidence

6.1

Share a panel book by URL

N/A

CV-203 (Sprint 25). Not GA-blocking for v0.1 alpha but blocks v1.0.


Filed FAIL items

  • CV-545 — [Internal] cv-web: PropsPanel section headers not keyboard-accessible (Bug, Sprint 22) — Replace <div className="props-entity-header" onClick> with <button> + aria-expanded. Four sites in PropsPanel.tsx.

  • CV-546 — [Internal] cv-web: modal overlays missing Escape key close handler (Bug, Sprint 22) — Add keydown listener for Escape to DialogRouter, SnapshotBrowser, CastSimReport. Trap focus inside open modal; return focus to opener on close.

Follow-up Tasks (not GA-blocking)

  • cv-web: wire @axe-core/playwright into CI — install dep, add a smoke test that boots the preview server and asserts no critical or serious axe violations. Sprint 23 or later.

Re-audit triggers

Re-run this checklist when:

  • Any of vite.config.ts, App.tsx, main.tsx, index.html, or instrument.ts changes materially.

  • New top-level routes or modal patterns are added.

  • CloudFront cache rules change.

  • New external-network calls are introduced on the boot path.

References

  • Acceptance: CV-210 — cv-web v0.1 GA-readiness check

  • Parent: CV-150 — cv-web Browser App With Field Round-Trip

  • Companion docs: 52-cv-web-pwa-cache-strategy.md, 47-gtm-plan.md