Files
voice-cat/docs/architecture.md
Talon 08e6c5930a
Build and test / test (macos-latest) (push) Canceled after 0s
Build and test / test (ubuntu-24.04) (push) Canceled after 0s
Build and test / test (windows-latest) (push) Canceled after 0s
Build and test / apple-client (push) Canceled after 0s
Retire legacy implementations and flatten managed layout
2026-09-21 00:11:32 +02:00

3.7 KiB

Architecture

VoiceCat is a .NET 10 client/server application with a deliberately narrow native media boundary. The managed implementation is authoritative.

Runtime components

Windows WinForms ─┐
macOS AppKit ─────┼─ VoiceCat.Core ─ VoiceCat.Audio ─ native media shim
iOS UIKit ────────┘       │
                          ├─ VoiceCat.Protocol
                          └─ VoiceCat.Crypto

VoiceCat.Server ──────────── VoiceCat.Protocol + VoiceCat.Crypto + SQLite

The server terminates TLS control sessions and relays authenticated encrypted Opus packets. It does not decode, mix, or transcode media. Clients own capture, encoding, jitter/loss recovery, decoding, mixing, and playback.

Managed projects

  • VoiceCat.Protocol: generated protobuf types and bounded length-prefixed framing.
  • VoiceCat.Crypto: BouncyCastle TLS 1.3, exporter-derived media secrets, certificate TOFU, Ed25519 server identity, ChaCha20-Poly1305, replay windows, and Argon2id.
  • VoiceCat.Codec: safe ownership around fixed Opus shim handles.
  • VoiceCat.Dsp: RNNoise and energy-VAD ownership.
  • VoiceCat.Audio: streams, packet-loss recovery, jitter buffers, mixing, PCM rings, and activation policy.
  • VoiceCat.Core: connection lifecycle, authentication, state snapshots/events, requests, stream negotiation, encrypted UDP, reconnect, and administration helpers.
  • VoiceCat.Server: listener/session ownership, SQLite state, permissions, moderation, channel management, encrypted UDP routing, and process administration commands.
  • VoiceCat.Cli: interactive client and deterministic text/voice behavior driver.

Leaf UI projects reference the managed core; platform audio objects translate between native device buffers and bounded PCM rings owned by VoiceCat.Audio.

Native boundary

native/media builds voicecat_media for desktop and static Apple targets. It contains only fixed C entry points for Opus/DRED and RNNoise. Vendored RNNoise is under native/rnnoise. Networking, TLS, media encryption, session state, jitter, and mixing do not live in native code.

native/apple/broadcast is a Swift ReplayKit upload extension. It captures application audio, converts it to 48 kHz stereo int16 PCM, and writes the frozen App Group ring documented in broadcast-ring-format.md. The managed iOS host drains that ring and performs encoding and networking. The extension deliberately has no managed runtime or VoiceCat protocol stack.

The iOS host also has small Objective-C bridges in its managed project for platform APIs that need direct native entry points. These are platform adapters, not a second core.

Ownership and concurrency

  • A VoiceCatClient owns one TLS control connection, one media session, and its audio engine.
  • Control/TLS operations have one serialized owner. UI code submits requests and observes events; it does not call TLS concurrently.
  • The server publishes immutable routing state to its UDP loop. The UDP loop owns endpoint binding, packet authentication, replay checks, and recipient resealing.
  • Audio callbacks consume or produce preallocated ring-buffer memory. They never allocate, lock, block, log, or access sockets.
  • Teardown establishes a quiescence barrier before callback-owned state is released.
  • Blocking file, database, TLS, and device lifecycle work stays off real-time callbacks.

Data and contracts

  • proto/voicecat.proto is the control-plane schema.
  • Media uses the fixed header and AEAD construction described in protocol.md and security.md.
  • SQLite is the server's persistent store; schema changes require explicit migrations.
  • Client profiles and TOFU pins are local platform data.
  • The ReplayKit ring layout is separately versioned and frozen.