Files
voice-cat/CLAUDE.md
Talon 694494a5be feat(M2): UDP voice/media plane -- SFU relay, Opus, AEAD, jitter buffer
Adds the full voice pipeline: 14-byte binary frame header, ChaCha20-Poly1305
AEAD keyed from the TLS exporter, libopus encode/decode with FEC/PLC/DTX,
an adaptive per-ssrc jitter buffer, a miniaudio capture/playback engine, an
APM passthrough stub, and the UdpBinding/StreamAnnounce signaling chain
wired through ConnSession/SessionRegistry into a new server-side SFU
(MediaRelay) that decrypts and re-encrypts frames per channel member.

Exit criterion verified: test_m2_voice — two headless clients relay 50
encrypted Opus frames through the server; ctest --preset m1-dev is 9/9
green. Also corrects protocol.md's UdpBinding diagram, which described the
UDP-side binding packet as AEAD-sealed when it is in fact a plaintext
bootstrap frame (separate from the TCP/TLS UdpBinding ack).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 01:31:14 +02:00

143 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md — agent hub for VoiceCat
Auto-loaded each session. This is the **map**: build commands, architecture at a glance, and
where everything is. For the *working method* read [`AGENTS.md`](AGENTS.md); for *what's done
and what's next* read [`PROGRESS.md`](PROGRESS.md); for *design* read [`docs/`](docs/).
> **One-line status:** M2 voice/media plane is complete and verified (`ctest --preset m1-dev`
> green — 9/9 tests including UDP relay, AEAD, Opus round-trip, and the M2 exit criterion
> `test_m2_voice`). Next up is **M3** (multi-stream, per-channel tuning, listener-side NR).
> See [`PROGRESS.md`](PROGRESS.md).
VoiceCat = self-hosted native voice & text chat (TeamSpeak/Mumble-style). Plain TCP (control)
+ UDP (media), no WebRTC, encrypted by default. A shared C++ core (`libvoicecat`) drives
native clients (Swift on macOS/iOS, C# on Windows) and the server.
---
## Build & test commands
The **M0 skeleton builds with no third-party dependencies** — just CMake + Ninja + a C++20
compiler. Deps (vcpkg) are off until a subsystem needs them.
```bash
# Configure + build the skeleton (default; no vcpkg needed)
cmake --preset dev
cmake --build --preset dev
# Run the tests (behavior smoke test today; grows per milestone)
ctest --preset dev # or: ctest --test-dir build/dev --output-on-failure
# Run the binaries (Windows adds .exe; Linux/macOS no extension)
./build/dev/bin/vccli # headless test client
./build/dev/bin/voicecat-server --help
./build/dev/bin/voicecat-server --name "My Server"
# Build a single target / be verbose
cmake --build --preset dev --target vccli
cmake --build --preset dev --verbose
# Clean
rm -rf build/dev # nuke; or:
cmake --build --preset dev --target clean
```
When you start a subsystem that needs real libraries (mbedTLS, libsodium, opus, protobuf, …),
turn vcpkg deps on:
```bash
# one-time: git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh (.bat on Windows)
export VCPKG_ROOT=/path/to/vcpkg # works on Linux / macOS / Windows
cmake --preset server-release # auto-installs deps pinned in vcpkg.json
cmake --build --preset server-release
```
Other useful toggles (pass with `-D` at configure time):
```bash
cmake --preset dev -DVOICECAT_BUILD_SHARED=ON # build libvoicecat as a .dll/.so/.dylib (for the C# client)
cmake --preset dev -DVOICECAT_BUILD_SERVER=OFF # core + tools only
cmake --preset dev -DVOICECAT_BUILD_TESTS=OFF
```
Formatting: `clang-format` config is `.clang-format` (Google base, 100 cols, 4-space).
```bash
git ls-files '*.cpp' '*.h' | xargs clang-format -i
```
---
## Architecture at a glance
Full detail: [`docs/architecture.md`](docs/architecture.md). The short version:
```
Swift (macOS/iOS) ─┐ ┌─ C# (Windows)
├──▶ libvoicecat (C ABI: voicecat.h) ◀──┤
voicecat-server ───┘ net · crypto · codec · protocol · └─ all UIs are thin
(links core) session · audio the core owns audio
```
- **One core, many faces.** Protocol, Opus, crypto, networking, jitter buffer, and mixing
live once in C++. Clients call the **C ABI** (`core/include/voicecat.h`); the server links
the same core, so framing/crypto never drift between ends.
- **Two transports.** TCP + **TLS 1.3** (control, protobuf `Envelope`) and UDP + **exported-key
ChaCha20-Poly1305 AEAD** (media, fixed binary voice frame). Encryption is mandatory.
- **Threading.** Real-time audio threads never allocate/lock/block; they exchange data with
the net thread via lock-free ring buffers; a worker pool absorbs blocking work.
### Subsystem map (code ↔ design doc)
| Path | Subsystem | Design |
|------|-----------|--------|
| `core/include/voicecat.h` | The C ABI (client/server contract) | architecture.md §4 |
| `core/proto/voicecat.proto` | Control-plane wire format (source of truth) | protocol.md |
| `core/src/net/` | Asio TCP/UDP transport, `[u32 len][payload]` framing | protocol.md §1, voice.md §2 |
| `core/src/crypto/` | TLS 1.3 (mbedTLS), media AEAD (libsodium), anti-replay | security.md |
| `core/src/codec/` | Opus encode/decode, FEC/DTX | voice.md §34 |
| `core/src/protocol/` | Envelope (de)serialize, request/response, dispatch | protocol.md |
| `core/src/session/` | Channels, users, streams, permissions, ephemeral text | protocol.md §5 |
| `core/src/audio/` | miniaudio I/O, APM DSP, jitter buffer, mixer | voice.md §811 |
| `core/src/core/` | `vc_client` — the handle behind the C ABI | architecture.md §4 |
| `server/` | Connection mgr, session registry, SFU relay, SQLite | architecture.md §5 |
| `tools/vccli/` | Headless client that drives/verifies the protocol | — |
| `clients/apple/`, `clients/windows/` | Native GUIs (M4) | architecture.md §4 |
---
## Documentation index (source of truth)
Read [`docs/`](docs/) before changing behavior. Order:
1. [docs/README.md](docs/README.md) — overview, locked decisions, glossary
2. [docs/architecture.md](docs/architecture.md) — core, C ABI, threading, server
3. [docs/protocol.md](docs/protocol.md) — control plane, Envelope, message catalog
4. [docs/voice.md](docs/voice.md) — UDP media, Opus, multi-stream, two-sided NR, VAD/PTT
5. [docs/security.md](docs/security.md) — mandatory encryption, TLS+AEAD, accounts, threat model
6. [docs/tech-stack.md](docs/tech-stack.md) — libraries, permissive-license rule, tooling
7. [docs/deployment.md](docs/deployment.md) — zero-config self-host (Docker / binary / source)
8. [docs/roadmap.md](docs/roadmap.md) — milestones + resolved decisions
---
## Keeping track of progress
**[`PROGRESS.md`](PROGRESS.md) is the living status file.** When you finish a task, check it
off there and note the next step, so the next agent can pick up instantly. Treat it as part of
the work, not an afterthought — update it in the same commit as the code.
---
## House rules (hard constraints)
- **A clean compile is the floor, not the goal.** "Done" = the milestone's observable exit
criterion in [`docs/roadmap.md`](docs/roadmap.md) passes (e.g. M1 = two `vccli` actually chat
over TLS). Encode it as a test. See [`AGENTS.md`](AGENTS.md).
- **No GPL/LGPL dependencies, ever** (closed-source redistribution is a goal). docs/tech-stack.md §5.
- **Encryption is mandatory** — never add a plaintext transport path. docs/security.md.
- **Real-time audio threads** never allocate, lock, or block. docs/architecture.md §3.
- **Keep docs + code in sync.** Changing a wire format (`voicecat.proto`) or the C ABI
(`voicecat.h`) is a deliberate, versioned act — update the doc in the same commit (protocol.md §8).
- Every commit must build (`cmake --build --preset dev`) and pass `ctest --preset dev`.