# Quality gates — web client LLM-verified gates for `architecture/web-client.md`. Automatic tests: `cbd-web/src/{state,keymap}.rs` (native target), `crabidy-server/src/web.rs`, plus the existing auth-layer suite. ## Parity - [x] Every TUI binding has a web equivalent (keyboard *and* clickable): browse/ascend/dive, marks, `%`/`e`/`d`, `w`/`W`, queue replace/append/queue-next/insert-here, queue select/play/ remove/clear(s)/save, play/pause/restart/next/prev, volume, mute, shuffle, repeat, help overlay. - [x] Semantics ported, not approximated: tracks before children, empty non-creatable nodes not entered, marks win over cursor, per-path cursor memory, capture-progress lines identical, skipped tracks red and flagged, capture deletes ask y/N, cheap deletes do not, mutable roots never cached (`state::is_cacheable` mirrors the TUI rule). - [x] The update stream feeds queue/play-state/volume/mute/mods/ position/capture progress; a broken stream reconnects with backoff and shows a disconnected banner until then. ## Security - [x] The auth layer wraps the gRPC route in both transports: a gRPC-web call without credentials is `UNAUTHENTICATED`, with insufficient role `PERMISSION_DENIED` — verified against a live server. - [x] Static assets are served without auth (public shell), and only via GET/HEAD; nothing under `/crabidy.v1.CrabidyService/` is served statically. - [x] Credentials live in `localStorage` only; never in URLs, never logged to the console; the login form is the only place that reads them back. - [x] `UNAUTHENTICATED` responses open the login dialog instead of a silent failure loop. ## Build & packaging - [x] `cargo build`/`test` (no wasm toolchain) succeeds with the default `web-ui` feature: missing `cbd-web/dist` embeds the placeholder page with the build hint, a present dist embeds the real bundle on the next build (`rerun-if-changed`). - [x] `--no-default-features` yields a gRPC-only server (no embedded assets, no tonic-web), and it still compiles and passes tests. - [x] `devenv shell -- build-web` produces `cbd-web/dist` (RUSTFLAGS cleared: mold breaks rust-lld); `cargo check -p cbd-web --target wasm32-unknown-unknown` and native `cargo test -p cbd-web` both pass. - [x] The TUI's native gRPC still works through the axum server (h2c prior knowledge) — verified live alongside gRPC-web. ## Styling - [x] Pure CSS, no framework, no external requests (fonts, CDNs); everything ships in the bundle. - [x] Light and dark themes: `color-scheme` + `light-dark()` following the OS by default, manual toggle persisted; both themes keep readable contrast for dim text, accent, and the red skipped/danger tones. - [x] The crab orange-red accent is a single custom property (`--accent`), derived tones via `color-mix` — no hard-coded copies. - [x] Usable on a phone viewport (panes stack/switch) and desktop. ## Code shape - [x] Components stay thin; logic lives in `state.rs`/`keymap.rs` with native unit tests. - [x] No panics on server errors: every RPC result is handled (status surfaces in the UI or the console at worst); stream reconnect never busy-loops.