# Apple clients `VoiceCat.Mac` and `VoiceCat.iOS` are .NET 10 AppKit and UIKit clients over the shared managed core. The ReplayKit upload extension under `native/apple/broadcast` remains Swift because it runs under the extension memory limit and writes the versioned shared audio ring. Build on macOS with Xcode and the pinned .NET workloads: ```bash ./scripts/build-native.ps1 ./scripts/build-native-ios.sh dotnet restore clients/apple/VoiceCat.Apple.slnx dotnet build clients/apple/VoiceCat.Apple.slnx -c Debug --no-restore ``` Use `publish-macos.sh --dry-run` to validate a local ad-hoc macOS bundle. The dry-run build does not enable hardened runtime because ad-hoc signatures have no Team ID and cannot satisfy macOS library validation. The script normalizes nested signatures and installs the verified bundle at both `VoiceCat.Mac/bin/Release/net10.0-macos27.0/osx-arm64/VoiceCat.app` and `VoiceCat.Mac/bin/Release/distribution/VoiceCat.app`. Distribution builds remain hardened and require `VOICECAT_CODESIGN_IDENTITY`; optional notarization uses `APPLE_ID`, `APPLE_TEAM_ID`, and `APPLE_APP_PASSWORD`. For a physical iOS device, use `build-ios-device.sh` and `deploy-ios-device.sh`. The host and ReplayKit extension require signing profiles with App Group `group.me.iamtalon.voicecat`. Hardware validation must cover VoiceOver, background and lock behavior, interruptions, route changes, Bluetooth, ReplayKit, and iOS 27 ScreenCaptureKit audio. App Store builds use the same device builder with `--configuration Release`. Set `VOICECAT_BUILD_NUMBER`, `VOICECAT_DISPLAY_VERSION`, `VOICECAT_DEVELOPMENT_TEAM`, the host `VOICECAT_CODESIGN_KEY`/`VOICECAT_CODESIGN_PROVISION` pair, and the extension `VOICECAT_BROADCAST_CODESIGN_KEY`/`VOICECAT_BROADCAST_CODESIGN_PROVISION` pair. The host and extension profiles must both be App Store Connect profiles and include the shared App Group. The complete TestFlight workflow is documented in `docs/apple-ios-release.md`. The shared ring contract is documented in `docs/broadcast-ring-format.md`.