# VoiceCat .NET rewrite The first slice targets .NET 10: protobuf, control framing, voice headers, and media encryption, TLS 1.3, persisted TOFU pins, and server credentials. Server/client state, audio, and UI migration are next. The existing C++ implementation remains the conformance oracle. From the repository root: ```powershell dotnet restore dotnet/VoiceCat.slnx --locked-mode dotnet build dotnet/VoiceCat.slnx -c Release --no-restore dotnet test dotnet/VoiceCat.slnx -c Release --no-build ``` Dependencies are pinned in project files and lock files. Generated protobuf is build output; the schema remains `core/proto/voicecat.proto`. Production dependencies are Google.Protobuf (BSD-3-Clause), BouncyCastle.Cryptography (MIT), and the build-only Grpc.Tools (Apache-2.0). No GPL/LGPL dependencies are permitted. ## C# conventions Use file-scoped namespaces, standard .NET naming, immutable values where useful, and spans for binary data. Invalid arguments throw; invalid network packets use parsing results or protocol exceptions. Async APIs accept cancellation tokens. Comments explain constraints that cannot be made clear in code. Avoid banners, implementation history, and narration. Keep durable design explanations in `docs/`. ## Regenerating C++ fixtures The optional oracle target calls the existing C++ protobuf, header serializer, and libsodium media implementation. From the root, with the development dependencies: ```powershell cmake --preset dev -DVOICECAT_BUILD_DOTNET_ORACLE=ON cmake --build --preset dev --target voicecat-dotnet-oracle New-Item -ItemType Directory -Force dotnet/tests/VoiceCat.Tests/Fixtures ./build/dev/bin/voicecat-dotnet-oracle.exe dotnet/tests/VoiceCat.Tests/Fixtures/cpp-wire.json git diff -- dotnet/tests/VoiceCat.Tests/Fixtures/cpp-wire.json ``` On Linux/macOS, omit `.exe` and create the directory with `mkdir -p`. The oracle writes deterministic JSON directly, avoiding shell output encoding. Fixtures contain a framed ClientHello and media packets at counters 0, 1, 65535, and 65536. Keys contain bytes 0–31; payload bytes count upward from zero. The 20-byte header has type 1, marker flag, codec 0, SSRC `0xcafebabe`, timestamp 960. Both managed crypto backends must match these bytes. ## TLS interoperability The optional TLS oracle uses the existing mbedTLS context and libsodium media crypto. The test authenticates an encrypted challenge in both directions, proving exporter compatibility without sending raw keys. It also loads the C++ server's credential files. ```powershell cmake --build --preset dev --target voicecat-dotnet-tls-oracle $env:VOICECAT_TLS_ORACLE = (Resolve-Path build/dev/bin/voicecat-dotnet-tls-oracle.exe).Path dotnet test dotnet/VoiceCat.slnx -c Release --no-restore ``` On Linux/macOS, set `VOICECAT_TLS_ORACLE` to the absolute executable path without `.exe`. Without that variable, only this native interoperability test is skipped; managed TLS loopback, rejection, persistence, and wire tests still run. CI's C++ conformance job requires the native test. See `docs/api-dotnet.md` for ownership and certificate acceptance requirements. ## Next checkpoint Port codec/DSP wrappers and their native packaging per Phase 3 of the porting plan. The managed server follows, tested first with the existing C++ CLI.