Files
OwnCord/Client/CLAUDE.md
T

49 lines
2.7 KiB
Markdown
Raw Normal View History

# OwnCord Client (Tauri v2)
TypeScript frontend (Vite, vanilla TS — no React/Vue) plus a deliberately thin
Rust backend in `src-tauri/` for native APIs only. LiveKit handles voice/video.
## Layout
- `src/stores/` observable stores · `src/lib/` protocol, WS, voice, E2EE ·
`src/pages/`, `src/components/` UI
- `src/lib/protocolTypes.ts` and `src/generated/` are generated — see the root
CLAUDE.md
- `tests/unit`, `tests/integration`, `tests/contract` (vitest, jsdom) ·
`tests/e2e`, `tests/e2e/admin`, `tests/e2e/native` (Playwright) ·
`tests/browser` (vitest browser mode)
- A test whose assertions read, import or execute a **`Server/`-owned**
artifact belongs in `tests/contract`, not `tests/unit``src-tauri/` is
part of this component, so reading it is an ordinary unit test. The rule
is in [docs/contributing.md](../docs/contributing.md#testing)
- `src/platform/` does **not** exist yet. Where the desktop/browser seam will
go, and which 20 files hold the native imports that must move behind it, is
recorded in
[docs/architecture/platform-contracts.md](../docs/architecture/platform-contracts.md).
Building it is B7 — do not start it as a side effect of another change.
## Gotchas
- Node's native Web Storage (Node 22+) shadows jsdom's `localStorage`;
`tests/setup.ts` replaces it with an in-memory shim, so the suite runs on
modern Node without `--no-experimental-webstorage`. If storage tests fail
en masse, suspect that shim before your change. CI pins Node 24.
2026-08-09 11:50:12 +02:00
- `src/lib/dispatcher.ts` is the single WS-event entry point **into the
stores**: server events reach domain stores only through a `ws.on(...)`
subscription registered there. Other modules do register their own
`ws.on(...)` handlers for page-local UI (`main.ts`, `MainPage.ts`,
`ChannelController.ts` — ringing, overlays, slow-mode timers); that is fine
as long as they only _read_ store state. Writing a store from one of those
2026-08-09 11:50:12 +02:00
handlers is the violation, and `local/no-store-write-in-ws-on` now fails the
build on it.
- Voice sessions are superseded, not cancelled. `LiveKitSession` re-entry
points check whether a newer attempt owns the shared state before tearing
anything down, so cleanup in an aborted path must be scoped to that attempt's
own room — a global `leaveVoice()` there kills the live session.
- Voice E2EE is key-holder based with TOFU identity pinning. Anything touching
`livekitE2EE.ts` or `identity.ts` must preserve the epoch/keypair staleness
guards and must never report an unverified peer as verified.
- Do not run `npm run tauri build` locally; the desktop build is CI-only.
- Formatting is prettier-enforced; match the surrounding code rather than
reasoning about style.