- **N127 — ML denoise shim is never injected in `vite dev`.** The `lotusDenoise` plugin injects only on `closeBundle` (build), so ML noise suppression is silently inactive during local dev. Add a dev-mode injection (`configureServer` / `transformIndexHtml`). Dev-only impact.
- **N97 — Access token stored in plaintext `localStorage`** (`state/sessions.ts`), vulnerable to XSS; device ID likewise. Architectural — needs a token-protection / session-storage redesign.
- **Session writes are non-atomic and not cross-tab synced** (`state/sessions.ts`) — risks inconsistent state / races across tabs.
- **Persisted PII without encryption:** user status message + expiry (`settings/account/Profile.tsx`), unsent composer drafts (`room/RoomInput.tsx`). Leak risk on shared devices.
- **N105 — Service worker has no `notificationclick` handler** — notification clicks are broken when the tab is closed. Needs `showNotification()` via the SW + a `notificationclick` listener.
- **N107 — SW has no `push` handler** — Web Push delivery is entirely non-functional. Needs a `push` listener + a Matrix push-gateway integration.
- **No app-asset caching strategy** (`src/sw.ts`) — no offline capability.
- **`manifest: false`** in `vite.config.js` — may block correct PWA install if not handled externally.
- **`matrix-js-sdk` pinned to a Release Candidate** (`41.6.0-rc.0`); `@atlaskit` and build tools (`vite`, `typescript`, `eslint`) on unstable/experimental pins — review for stable versions; RC SDK is a tree-shaking/bundle-size risk.
- **Build-time overhead:** `lotusDenoise` does heavy sequential `fs` work in `closeBundle`; `viteStaticCopy` config is complex with redundant renames — could be streamlined.
- **`types/matrix/` mirrors SDK types** instead of importing them — drift risk.
- **Hardcoded CDN URL** should move to an env var (the decoration CDN is now single-sourced in `avatarDecorations.ts`, but the literal is still in-repo).
- **Architecture notes (low priority):** deep `features/` + `hooks/` nesting, many small coupled hooks, possible dead CSS/components, `SpacingVariant` / `DropTarget` recipe simplification.
- **Git workflow (forward-looking):** keep commits scoped — past monolithic "fix all bugs" commits and inconsistent prefixes hurt `git bisect`.
### Native-Cinny polish (remaining from the design-law audit)
The "renders-broken-on-stock-themes" cluster (ungated invented CSS vars across
~13 files + the toast rebuild) is fixed; Sentry was removed. Lower-priority
pattern items left:
- **Profile timezone `<select>`** (`settings/account/Profile.tsx`) — still a raw native select (`colorScheme:'dark'`); it's wired to native form submission + a disabled state, so converting to `SettingsSelect` needs care.
- **MediaGallery lightbox** (`room/MediaGallery.tsx`) — raw `<div role="dialog">` + `#fff`/rgba chrome over forced-black media. Should be folds `Overlay`/`Modal`; the over-media light-on-dark scheme is a borderline-justified scrim.
- **Nits:** scattered `opacity:` → `priority`, the poll `✓` Unicode glyph → folds `Icon`, a few `zIndex` magic numbers.
- **#5 — Seasonal themes & chat-background redesign.** Current backgrounds are basic CSS; goal is high-fidelity, research-backed, GPU-accelerated designs (layered `oklch`, `backdrop-filter`, `contain:paint`) with WCAG-AA overlay contrast. Treat each as its own design sprint.