docs(p0): compact MVP spec for Android Oboe focus
This commit is contained in:
@@ -1,664 +0,0 @@
|
||||
# Building Chanora v0.2.0-beta.1 on iOS via macOS host
|
||||
|
||||
**Document type:** Release / Platform Build Instructions
|
||||
**Version:** 0.1.0
|
||||
**Status:** Draft
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
**Repo path:** `docs/release/ios-build.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document gives exact step-by-step instructions for building the
|
||||
Chanora `v0.2.0-beta.1` Internal Beta on an Apple macOS host. It
|
||||
exists because the development host is Linux x86_64; the entire
|
||||
iOS toolchain (Xcode, `xcrun`, `codesign`, `xcodebuild`, the
|
||||
`iPhoneOS` SDK) is macOS-only under Apple licence and cannot be
|
||||
cross-compiled from Linux. Even projects like `xcbuild` or
|
||||
`cctools-port` cannot produce a signed `.ipa` that an iOS device's
|
||||
`installd` will accept.
|
||||
|
||||
After following this doc you will have:
|
||||
|
||||
- `Runner.app` — the iOS app bundle.
|
||||
- `libchanora_bridge.a` and/or an XCFramework containing both
|
||||
device (arm64) and simulator (arm64+x86_64) slices of the Rust
|
||||
cdylib.
|
||||
- A `Runner.ipa` archive suitable for ad-hoc / TestFlight / App
|
||||
Store distribution depending on the provisioning profile you sign
|
||||
with.
|
||||
|
||||
The doc assumes you have:
|
||||
|
||||
- A macOS host (physical Mac or rental — see §3 for options).
|
||||
- An Apple Developer account ($99/year). A free Apple ID can build
|
||||
for personal devices via Xcode automatic signing, but profiles
|
||||
expire in 7 days; the paid account is strongly recommended.
|
||||
- Permission to enrol a test iPhone or iPad in the developer team.
|
||||
- The Chanora source code (this repository), reachable from the
|
||||
Mac (git remote, scp, or AirDrop).
|
||||
|
||||
---
|
||||
|
||||
## 2. Toolchain versions pinned for this build
|
||||
|
||||
| Tool | Version | Why |
|
||||
|---|---|---|
|
||||
| macOS | 14 Sonoma or 15 Sequoia | Xcode 26 requires macOS 14+ at minimum |
|
||||
| Xcode | **26 or newer** (DEC-021) | Required to upload to App Store Connect on or after 2026-04-28. Beta builds for internal devices also pin to 26+ for parity. |
|
||||
| iOS SDK | **26 or newer** (DEC-021) | Bundled with Xcode 26+. |
|
||||
| iOS deployment target | **iOS 13** (DEC-003) | Matches Flutter 3.41.9's baseline support. The Podfile and Runner.xcodeproj must set this. |
|
||||
| Command Line Tools | Latest stable (`xcode-select --install` or via Xcode) | Provides `xcrun`, `xcodebuild`, `codesign`. |
|
||||
| Flutter SDK | 3.41.9 stable | Same pin as Linux/Android/Windows builds. |
|
||||
| Dart SDK | 3.11.5 | Bundled with Flutter. |
|
||||
| Rust toolchain | stable 1.95 (or newer) | Workspace `rust-version = "1.95"`. |
|
||||
| Rust targets | `aarch64-apple-ios`, `aarch64-apple-ios-sim`, `x86_64-apple-ios` | Device + Apple-silicon simulator + Intel-Mac simulator. |
|
||||
| `cbindgen` (optional) | 0.27+ | Only if you wire a C header for the bridge; FRB does not require it. |
|
||||
| `cargo-lipo` (legacy) | not required | `cargo-lipo` was deprecated for multi-arch iOS in favor of `cargo build --target <triple>` + `xcodebuild -create-xcframework`. |
|
||||
| CocoaPods | 1.16+ | Required by Flutter iOS builds (Podfile in `apps/chanora_flutter/ios/`). |
|
||||
| Opus library | bundled via `audiopus_sys` build script with iOS-specific CMake toolchain | Apple does not ship libopus; we cross-compile it per Rust target. |
|
||||
| Apple Developer ID + certificate | one-time | Required to sign the .ipa. Free Apple ID OK for personal-device install (7-day profile). |
|
||||
|
||||
> **Why not Xcode 15 or 16?** Apple's App Store Connect upload gate
|
||||
> (DEC-021) requires the iOS 26 SDK on or after 2026-04-28. Even for
|
||||
> internal Beta where you don't upload, we pin Xcode 26+ so the same
|
||||
> archive can be re-signed for TestFlight without re-building.
|
||||
|
||||
---
|
||||
|
||||
## 3. macOS host options
|
||||
|
||||
### 3.1 Owned Apple hardware (cheapest long-term)
|
||||
|
||||
| Hardware | Min spec | Notes |
|
||||
|---|---|---|
|
||||
| Mac mini (M2, 2023+) | 16 GiB RAM, 256 GiB SSD | Best price/perf; ~USD $799 new |
|
||||
| MacBook Air / Pro (M2+) | 16 GiB RAM | Portable; ~USD $1099+ new |
|
||||
| Used Intel Mac (2018+) | 16 GiB RAM | Will need macOS 14+; check Apple's compatibility list |
|
||||
|
||||
Apple's licence forbids running macOS on non-Apple hardware
|
||||
("Hackintoshes") for any commercial purpose. Don't.
|
||||
|
||||
### 3.2 macOS rental (no hardware purchase)
|
||||
|
||||
| Provider | Cost | Notes |
|
||||
|---|---|---|
|
||||
| MacStadium | USD ~$79+/month for an M-series Mac mini | Dedicated host; supports Xcode + signing |
|
||||
| MacinCloud | USD ~$30+/month "Pay-As-You-Go" or "Dedicated Server" plans | Shared options exist; choose Dedicated for full Xcode access |
|
||||
| Scaleway Apple silicon (EU) | EUR ~0.13/hour for Mac mini M2 | Hourly billing; cheap for short builds |
|
||||
| AWS EC2 Mac (`mac1.metal`, `mac2.metal`) | USD ~$1.08/hour with a 24h minimum allocation | Most expensive; use only if you need AWS integration |
|
||||
|
||||
> Apple's licence permits cloud hosts that comply with their terms.
|
||||
> All of the above explicitly meet that requirement.
|
||||
|
||||
### 3.3 Borrowed Mac
|
||||
|
||||
Find a friend or coworker with a Mac that can run Xcode 26. Install
|
||||
your dev certificate to their Keychain locally for the build session
|
||||
only, then remove it. This is the cheapest option if you have access.
|
||||
|
||||
---
|
||||
|
||||
## 4. Install the toolchain (one-time per Mac)
|
||||
|
||||
All commands assume a normal user account; only the Xcode install
|
||||
needs an Administrator password.
|
||||
|
||||
### 4.1 Xcode + Command Line Tools
|
||||
|
||||
Either:
|
||||
|
||||
```bash
|
||||
# Easiest: install Xcode from the Mac App Store.
|
||||
# (Or download the .xip from https://developer.apple.com/download/all/)
|
||||
open "https://apps.apple.com/app/xcode/id497799835"
|
||||
|
||||
# Then accept the licence and install Command Line Tools.
|
||||
sudo xcodebuild -license accept
|
||||
xcode-select --install # idempotent; skip if already done
|
||||
|
||||
# Verify.
|
||||
xcodebuild -version # expect Xcode 26.x
|
||||
xcrun --version
|
||||
xcrun simctl list runtimes | head
|
||||
```
|
||||
|
||||
If you already have Xcode 16 or 17 installed, **add** Xcode 26
|
||||
side-by-side (don't replace) and switch via `sudo xcode-select -s
|
||||
/Applications/Xcode-26.app`.
|
||||
|
||||
### 4.2 Homebrew + Rust + Flutter + CocoaPods
|
||||
|
||||
```bash
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
# Rust (managed by rustup, not brew)
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal
|
||||
source "$HOME/.cargo/env"
|
||||
|
||||
# Add the three iOS targets.
|
||||
rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
|
||||
|
||||
# Flutter — pinned to 3.41.9 stable to match the Linux / Android
|
||||
# builds.
|
||||
brew install --cask flutter
|
||||
flutter --version | head -3
|
||||
flutter precache --ios
|
||||
|
||||
# CocoaPods.
|
||||
brew install cocoapods
|
||||
pod --version # expect 1.16 or newer
|
||||
```
|
||||
|
||||
> If your Mac is Apple-silicon and Homebrew installs to
|
||||
> `/opt/homebrew`, make sure that's on `PATH` for new shells:
|
||||
> `eval "$(/opt/homebrew/bin/brew shellenv)"`.
|
||||
|
||||
### 4.3 Opus
|
||||
|
||||
`audiopus_sys` ships an Opus source tree and tries to build it via
|
||||
CMake. On iOS the cmake-crate's generated build sometimes confuses
|
||||
the iOS toolchain. We use the same pre-built libopus strategy that
|
||||
the Android build uses:
|
||||
|
||||
```bash
|
||||
# Get the audiopus_sys-bundled libopus source after a first cargo
|
||||
# fetch (it gets unpacked into the registry).
|
||||
cd ~/chanora
|
||||
cargo fetch
|
||||
OPUS_SRC=$(find ~/.cargo/registry/src -path '*audiopus_sys-*/opus' -type d | head -1)
|
||||
mkdir -p /tmp/opus-ios
|
||||
cp -R "$OPUS_SRC"/* /tmp/opus-ios/
|
||||
|
||||
# Helper: build libopus.a for one iOS arch.
|
||||
build_opus_ios() {
|
||||
local ARCH=$1 # arm64 | x86_64 | arm64-simulator
|
||||
local SDK=$2 # iphoneos | iphonesimulator
|
||||
local OUT=/tmp/opus-ios-${ARCH}
|
||||
rm -rf /tmp/opus-ios/build && mkdir /tmp/opus-ios/build
|
||||
cd /tmp/opus-ios/build
|
||||
cmake .. \
|
||||
-DCMAKE_SYSTEM_NAME=iOS \
|
||||
-DCMAKE_OSX_SYSROOT=$(xcrun --sdk "$SDK" --show-sdk-path) \
|
||||
-DCMAKE_OSX_ARCHITECTURES="${ARCH%-simulator}" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DOPUS_BUILD_PROGRAMS=OFF \
|
||||
-DOPUS_BUILD_TESTING=OFF \
|
||||
-DCMAKE_INSTALL_PREFIX="$OUT" \
|
||||
-G "Unix Makefiles"
|
||||
make -j8 install
|
||||
# Wrap so LIBOPUS_LIB_DIR appends /lib correctly.
|
||||
mkdir -p "$OUT-wrap/lib"
|
||||
cp "$OUT/lib/libopus.a" "$OUT-wrap/lib/"
|
||||
cd /tmp/opus-ios
|
||||
}
|
||||
|
||||
build_opus_ios arm64 iphoneos # device
|
||||
build_opus_ios arm64-simulator iphonesimulator # Apple-silicon Mac sim
|
||||
build_opus_ios x86_64 iphonesimulator # Intel Mac sim
|
||||
```
|
||||
|
||||
You should end up with three wrap dirs each containing `lib/libopus.a`:
|
||||
|
||||
```
|
||||
/tmp/opus-ios-arm64-wrap/lib/libopus.a
|
||||
/tmp/opus-ios-arm64-simulator-wrap/lib/libopus.a
|
||||
/tmp/opus-ios-x86_64-wrap/lib/libopus.a
|
||||
```
|
||||
|
||||
### 4.4 Cargo target linker config
|
||||
|
||||
iOS targets need explicit linker config to find the SDK. Create
|
||||
`~/.cargo/config.toml`:
|
||||
|
||||
```toml
|
||||
[target.aarch64-apple-ios]
|
||||
rustflags = ["-C", "link-arg=-fembed-bitcode"]
|
||||
|
||||
[target.aarch64-apple-ios-sim]
|
||||
rustflags = ["-C", "link-arg=-fembed-bitcode"]
|
||||
|
||||
[target.x86_64-apple-ios]
|
||||
rustflags = ["-C", "link-arg=-fembed-bitcode"]
|
||||
```
|
||||
|
||||
Rust's built-in iOS targets already drive the right linker via
|
||||
`xcrun`, so usually no further config is needed. If you hit a
|
||||
"-platform_version not supported" error, ensure Xcode CLI tools are
|
||||
fresh: `sudo xcode-select --reset`.
|
||||
|
||||
### 4.5 (Optional) `flutter_rust_bridge_codegen`
|
||||
|
||||
Only needed if you modify `crates/chanora_bridge/src/api.rs` on the
|
||||
Mac. The bindings shipped in the repo are platform-agnostic Dart +
|
||||
Rust source and do **not** need regenerating per platform.
|
||||
|
||||
```bash
|
||||
cargo install flutter_rust_bridge_codegen --version "=2.12.0"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Get the source onto the Mac
|
||||
|
||||
Same two options as the Windows doc:
|
||||
|
||||
### Option A — git remote
|
||||
|
||||
```bash
|
||||
# On Linux dev host: push to a private remote.
|
||||
cd /home/milkice/chanora
|
||||
git remote add origin git@github.com:<your-user>/chanora.git
|
||||
git push --all
|
||||
git push --tags
|
||||
```
|
||||
|
||||
```bash
|
||||
# On the Mac:
|
||||
cd ~
|
||||
git clone https://github.com/<your-user>/chanora.git
|
||||
cd chanora
|
||||
git checkout v0.2.0-beta.1
|
||||
```
|
||||
|
||||
### Option B — zip / AirDrop
|
||||
|
||||
```bash
|
||||
# On Linux:
|
||||
git -C /home/milkice/chanora archive --format=zip \
|
||||
--output=/tmp/chanora-v0.2.0-beta.1.zip v0.2.0-beta.1
|
||||
|
||||
# Transfer the zip to the Mac (AirDrop, scp, USB), then:
|
||||
cd ~
|
||||
unzip /Volumes/.../chanora-v0.2.0-beta.1.zip -d chanora
|
||||
cd chanora
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Add the iOS platform to the Flutter app
|
||||
|
||||
The product Flutter app was scaffolded with `--platforms=linux,android`,
|
||||
so the `ios/` folder does not yet exist. Add it once on the Mac:
|
||||
|
||||
```bash
|
||||
cd ~/chanora/apps/chanora_flutter
|
||||
flutter create --platforms=ios .
|
||||
```
|
||||
|
||||
This creates `apps/chanora_flutter/ios/` containing:
|
||||
|
||||
```
|
||||
ios/
|
||||
Runner/
|
||||
AppDelegate.swift
|
||||
Info.plist
|
||||
Runner-Bridging-Header.h
|
||||
Assets.xcassets/
|
||||
Runner.xcodeproj/
|
||||
Runner.xcworkspace/
|
||||
Podfile
|
||||
Flutter/
|
||||
```
|
||||
|
||||
> **Important:** Do **not** commit this `ios/` folder back to the
|
||||
> repo from the Mac unless you also do the corresponding edits the
|
||||
> source-of-truth host uses (icons, bundle ID, signing config).
|
||||
> For Beta it is fine to keep it Mac-only.
|
||||
|
||||
### 6.1 Set the iOS deployment target
|
||||
|
||||
Edit `apps/chanora_flutter/ios/Podfile`'s first line to:
|
||||
|
||||
```ruby
|
||||
platform :ios, '13.0' # DEC-003
|
||||
```
|
||||
|
||||
And in Xcode (`open Runner.xcworkspace`):
|
||||
|
||||
- Project → Runner → General → Minimum Deployments → iOS 13.0
|
||||
- Project → Runner → Signing & Capabilities → set your Team
|
||||
|
||||
### 6.2 Add iOS-required entitlements + Info.plist keys
|
||||
|
||||
Chanora's audio engine needs the microphone. Edit
|
||||
`apps/chanora_flutter/ios/Runner/Info.plist` to include:
|
||||
|
||||
```xml
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Chanora uses the microphone for voice chat with TeamSpeak-compatible servers.</string>
|
||||
|
||||
<!-- Background-mode audio so playback continues when the screen
|
||||
locks. Optional for Beta; required for a real release. -->
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
|
||||
<!-- Allow plain HTTP only for development. Remove before release.
|
||||
The protocol layer itself uses UDP, not HTTP, but Flutter's hot
|
||||
reload talks HTTP. -->
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
```
|
||||
|
||||
The bundle identifier should be set to a reverse-DNS string under
|
||||
your developer team, e.g. `app.chanora.chanora_flutter`. Update it
|
||||
in Xcode → Runner → General → Identity → Bundle Identifier.
|
||||
|
||||
---
|
||||
|
||||
## 7. Build the Rust libraries for iOS
|
||||
|
||||
We build three flavors and combine them into an XCFramework that
|
||||
Xcode can link against from both device and simulator slices.
|
||||
|
||||
```bash
|
||||
cd ~/chanora
|
||||
export LIBOPUS_STATIC=1
|
||||
export LIBOPUS_NO_PKG=1
|
||||
|
||||
build_bridge_for_ios() {
|
||||
local TARGET=$1 # aarch64-apple-ios | aarch64-apple-ios-sim | x86_64-apple-ios
|
||||
local OPUS_DIR=$2 # /tmp/opus-ios-*-wrap
|
||||
export LIBOPUS_LIB_DIR="$OPUS_DIR"
|
||||
|
||||
# Wipe audiopus_sys build cache so LIBOPUS_LIB_DIR is re-read.
|
||||
rm -rf target/$TARGET/release/build/audiopus_sys-*
|
||||
|
||||
cargo build --release --target "$TARGET" -p chanora_bridge
|
||||
}
|
||||
|
||||
build_bridge_for_ios aarch64-apple-ios /tmp/opus-ios-arm64-wrap
|
||||
build_bridge_for_ios aarch64-apple-ios-sim /tmp/opus-ios-arm64-simulator-wrap
|
||||
build_bridge_for_ios x86_64-apple-ios /tmp/opus-ios-x86_64-wrap
|
||||
```
|
||||
|
||||
Expected static-lib outputs (the `[lib]` section in
|
||||
`crates/chanora_bridge/Cargo.toml` already declares `staticlib`):
|
||||
|
||||
```
|
||||
target/aarch64-apple-ios/release/libchanora_bridge.a (~25 MiB, device)
|
||||
target/aarch64-apple-ios-sim/release/libchanora_bridge.a (~25 MiB, M-series simulator)
|
||||
target/x86_64-apple-ios/release/libchanora_bridge.a (~25 MiB, Intel simulator)
|
||||
```
|
||||
|
||||
### 7.1 Build the simulator universal binary with `lipo`
|
||||
|
||||
The simulator side needs both arches in one `.a` for Xcode to pick
|
||||
the host architecture automatically:
|
||||
|
||||
```bash
|
||||
mkdir -p target/universal-ios-sim
|
||||
lipo -create \
|
||||
target/aarch64-apple-ios-sim/release/libchanora_bridge.a \
|
||||
target/x86_64-apple-ios/release/libchanora_bridge.a \
|
||||
-output target/universal-ios-sim/libchanora_bridge.a
|
||||
file target/universal-ios-sim/libchanora_bridge.a
|
||||
```
|
||||
|
||||
### 7.2 Build the XCFramework
|
||||
|
||||
```bash
|
||||
rm -rf target/ChanoraBridge.xcframework
|
||||
xcodebuild -create-xcframework \
|
||||
-library target/aarch64-apple-ios/release/libchanora_bridge.a \
|
||||
-library target/universal-ios-sim/libchanora_bridge.a \
|
||||
-output target/ChanoraBridge.xcframework
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
target/ChanoraBridge.xcframework/
|
||||
Info.plist
|
||||
ios-arm64/libchanora_bridge.a
|
||||
ios-arm64_x86_64-simulator/libchanora_bridge.a
|
||||
```
|
||||
|
||||
### 7.3 Link the XCFramework from the Flutter iOS app
|
||||
|
||||
Open `apps/chanora_flutter/ios/Runner.xcworkspace` in Xcode.
|
||||
|
||||
1. Drag `target/ChanoraBridge.xcframework` into the Runner project
|
||||
(Embed: "Do Not Embed" — it's a static lib).
|
||||
2. Project → Runner → Build Phases → Link Binary with Libraries →
|
||||
ensure `ChanoraBridge.xcframework` is listed.
|
||||
3. The FRB Dart loader expects to find the symbols in the main app
|
||||
binary on iOS (static linkage). The generated
|
||||
`apps/chanora_flutter/lib/src/rust/frb_generated.io.dart` should
|
||||
look up via `DynamicLibrary.process()` on iOS — this is the
|
||||
default for FRB v2 when the Rust crate type is `staticlib`.
|
||||
|
||||
If the dart-side loader expects a separate dylib, regenerate
|
||||
bindings with the iOS target hint:
|
||||
|
||||
```bash
|
||||
flutter_rust_bridge_codegen generate
|
||||
```
|
||||
|
||||
(The repo's bindings already target this style; no change usually
|
||||
needed.)
|
||||
|
||||
---
|
||||
|
||||
## 8. Regenerate the FRB bindings (optional)
|
||||
|
||||
Skip unless you've modified `crates/chanora_bridge/src/api.rs` on
|
||||
the Mac. The bindings are platform-agnostic Dart + Rust source.
|
||||
|
||||
```bash
|
||||
cd ~/chanora
|
||||
flutter_rust_bridge_codegen generate
|
||||
```
|
||||
|
||||
Takes ~5–10 minutes on first run (cargo expand).
|
||||
|
||||
---
|
||||
|
||||
## 9. Build the iOS app via Flutter
|
||||
|
||||
```bash
|
||||
cd ~/chanora/apps/chanora_flutter
|
||||
flutter pub get
|
||||
cd ios && pod install && cd ..
|
||||
flutter build ios --release --no-codesign
|
||||
```
|
||||
|
||||
`flutter build ios --no-codesign` produces an unsigned `Runner.app`.
|
||||
For signed `.ipa` for TestFlight or device install, use:
|
||||
|
||||
```bash
|
||||
flutter build ipa --release --export-method development
|
||||
# or: --export-method ad-hoc | enterprise | app-store
|
||||
```
|
||||
|
||||
This requires:
|
||||
|
||||
- A configured Team and Bundle Identifier (set in Xcode in §6.1).
|
||||
- A matching provisioning profile in your Keychain (Xcode's
|
||||
Automatic Signing usually handles this if you've signed into
|
||||
your Apple ID in Xcode → Settings → Accounts).
|
||||
|
||||
Expected output locations:
|
||||
|
||||
| Variant | Path |
|
||||
|---|---|
|
||||
| Unsigned app bundle | `apps/chanora_flutter/build/ios/iphoneos/Runner.app/` |
|
||||
| Signed `.ipa` | `apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa` |
|
||||
|
||||
---
|
||||
|
||||
## 10. Install on a physical iPhone/iPad
|
||||
|
||||
### 10.1 Wired install (USB or USB-C)
|
||||
|
||||
```bash
|
||||
# List paired devices.
|
||||
xcrun devicectl list devices
|
||||
|
||||
# Install the ipa.
|
||||
xcrun devicectl device install app --device <UDID> \
|
||||
apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa
|
||||
|
||||
# Launch it.
|
||||
xcrun devicectl device process launch \
|
||||
--device <UDID> --terminate-existing \
|
||||
app.chanora.chanora_flutter
|
||||
```
|
||||
|
||||
### 10.2 TestFlight (wireless to many testers)
|
||||
|
||||
```bash
|
||||
xcrun altool --upload-app \
|
||||
--type ios \
|
||||
--file apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa \
|
||||
--username "<your-apple-id>" \
|
||||
--password "<app-specific-password>"
|
||||
```
|
||||
|
||||
Then in App Store Connect:
|
||||
|
||||
1. Wait for processing (10–30 minutes).
|
||||
2. Add the build to a TestFlight test group.
|
||||
3. Invite testers by Apple ID email.
|
||||
|
||||
Testers install via the TestFlight app on their device.
|
||||
|
||||
---
|
||||
|
||||
## 11. Smoke test on the iPhone/iPad
|
||||
|
||||
Open the installed Chanora app:
|
||||
|
||||
1. **Banner**: "Beta build — voice in/out wired; not production
|
||||
ready."
|
||||
2. **Form**: pre-populated with `cn.teamspeak.app` + `ChanoraBeta`.
|
||||
3. **Connect**.
|
||||
|
||||
> **Known limitation (same as Android):** the protocol layer's
|
||||
> `hickory-resolver` cannot resolve hostnames on iOS by default. If
|
||||
> Connect times out, enter the literal IP. For `cn.teamspeak.app`
|
||||
> that is currently `175.178.125.23`. A proper fix wires the iOS
|
||||
> system resolver into hickory; Beta+ work.
|
||||
|
||||
4. Once connected, the channel tree appears.
|
||||
5. **Start audio** → grant microphone permission when prompted.
|
||||
6. **Hold to talk** → frame counter increments under PTT.
|
||||
|
||||
If audio fails to start, check:
|
||||
|
||||
- Microphone permission granted in Settings → Chanora → Microphone.
|
||||
- Device not in silent mode (output side only).
|
||||
- iOS Audio Session category — by default Flutter uses
|
||||
`AVAudioSessionCategoryPlayback`. Voice transmission needs
|
||||
`PlayAndRecord` with `voiceChat` mode. **Beta+ work.**
|
||||
|
||||
---
|
||||
|
||||
## 12. Package the release artefact
|
||||
|
||||
`flutter build ipa` already produces a single `.ipa`. Stamp it with
|
||||
the build identifier:
|
||||
|
||||
```bash
|
||||
cd ~/chanora/apps/chanora_flutter
|
||||
cp build/ios/ipa/chanora_flutter.ipa \
|
||||
"$HOME/chanora-v0.2.0-beta.1-ios.ipa"
|
||||
shasum -a 256 "$HOME/chanora-v0.2.0-beta.1-ios.ipa"
|
||||
```
|
||||
|
||||
Typical size: 60–90 MiB (includes Flutter engine + Dart AOT +
|
||||
Rust static lib + bundled libopus + iOS resources).
|
||||
|
||||
---
|
||||
|
||||
## 13. Download to your local host
|
||||
|
||||
If on a rental Mac:
|
||||
|
||||
```bash
|
||||
# From the Mac, copy back to Linux dev host.
|
||||
scp "$HOME/chanora-v0.2.0-beta.1-ios.ipa" \
|
||||
user@your-linux-host:/home/milkice/
|
||||
```
|
||||
|
||||
Or pull from the rental's web file manager. Keep the `.ipa`
|
||||
re-installable indefinitely if the provisioning profile is
|
||||
ad-hoc/enterprise; for development profiles it expires in 7 days.
|
||||
|
||||
---
|
||||
|
||||
## 14. Final artefact paths (what you actually produce)
|
||||
|
||||
On the Mac, after a successful build:
|
||||
|
||||
| Artefact | Path |
|
||||
|---|---|
|
||||
| Rust device static lib | `~/chanora/target/aarch64-apple-ios/release/libchanora_bridge.a` |
|
||||
| Rust Apple-silicon sim lib | `~/chanora/target/aarch64-apple-ios-sim/release/libchanora_bridge.a` |
|
||||
| Rust Intel sim lib | `~/chanora/target/x86_64-apple-ios/release/libchanora_bridge.a` |
|
||||
| Lipo'd simulator lib | `~/chanora/target/universal-ios-sim/libchanora_bridge.a` |
|
||||
| XCFramework | `~/chanora/target/ChanoraBridge.xcframework/` |
|
||||
| Unsigned app bundle | `~/chanora/apps/chanora_flutter/build/ios/iphoneos/Runner.app/` |
|
||||
| Signed `.ipa` | `~/chanora/apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa` |
|
||||
| Renamed release `.ipa` | `~/chanora-v0.2.0-beta.1-ios.ipa` |
|
||||
|
||||
---
|
||||
|
||||
## 15. After the build — deallocate (rental hosts)
|
||||
|
||||
| Provider | Deallocate command |
|
||||
|---|---|
|
||||
| MacStadium | Suspend / shut down via control panel |
|
||||
| MacinCloud | "Stop" the session in account dashboard |
|
||||
| Scaleway | `scw instance server stop <id>` |
|
||||
| AWS EC2 Mac | Stop the host; release the dedicated host if at end of 24h minimum |
|
||||
|
||||
Always verify the billing dashboard shows the instance as stopped,
|
||||
not just shut down at the OS level.
|
||||
|
||||
---
|
||||
|
||||
## 16. Known issues and caveats
|
||||
|
||||
| Issue | Workaround |
|
||||
|---|---|
|
||||
| `audiopus_sys` cmake-build fails with "no member named '__int128_t'" | Re-export `LIBOPUS_LIB_DIR` to a pre-built `.a` directory (§4.3); never let cargo's cmake-build attempt to compile Opus on iOS. |
|
||||
| `hickory-resolver` cannot resolve hostnames on iOS | Use literal IP. Fix: wire `dns-via-system` resolver into `chanora_protocol`. Beta+ work. |
|
||||
| Microphone permission prompt never appears | The `NSMicrophoneUsageDescription` is missing from Info.plist. See §6.2. |
|
||||
| Audio plays but no transmission | iOS AVAudioSession category likely set to `Playback` not `PlayAndRecord`. Configure the session in Swift before Flutter loads, or via a small plugin. Beta+ work. |
|
||||
| Code signing fails with "No signing certificate" | Open Xcode → Settings → Accounts → add your Apple ID, then close and reopen `Runner.xcworkspace` to refresh. |
|
||||
| `flutter build ipa` complains about missing entitlements | Make sure the provisioning profile in Apple Developer console includes the App ID with microphone capability enabled. |
|
||||
| TestFlight upload rejected: "Invalid bundle. Apple silicon support" | Build with `flutter build ipa --release` (not `--debug`); debug AOT is JIT-only and not allowed in TestFlight. |
|
||||
| App crashes on launch with `dyld: Library not loaded: libchanora_bridge.dylib` | The bridge is built as `staticlib`, not `cdylib`, on iOS — FRB's loader uses `DynamicLibrary.process()`. If you accidentally built a `cdylib`, the loader path won't match. Stick to staticlib. |
|
||||
| First `flutter build ios` takes > 30 minutes | Normal — first Pod install + CocoaPods cache. |
|
||||
|
||||
---
|
||||
|
||||
## 17. Reproducibility note
|
||||
|
||||
Like the Windows build, the iOS build is **not bit-reproducible**:
|
||||
|
||||
- `xcodebuild` embeds a creation timestamp in the `.ipa`.
|
||||
- `audiopus_sys` picks the cmake-discovered Xcode toolchain version.
|
||||
- Dart AOT compilation embeds a Dart kernel hash.
|
||||
- Code-signing inherently makes every signed `.ipa` unique.
|
||||
|
||||
If true reproducibility is required for a future External Beta or
|
||||
MVP Public release, that is Beta+ work; the build above is
|
||||
sufficient for an Internal Beta milestone per DEC-001.
|
||||
|
||||
---
|
||||
|
||||
## 18. Change History
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.1.0 | 2026-05-14 | Initial iOS build instructions for Chanora `v0.2.0-beta.1`. Targets a macOS 14+ host running Xcode 26+ (DEC-021), Rust 1.95 stable with `aarch64-apple-ios` + `aarch64-apple-ios-sim` + `x86_64-apple-ios` targets, Flutter 3.41.9 stable, `flutter_rust_bridge` 2.12.0. Produces `Runner.app` + `chanora_flutter.ipa` via `flutter build ipa --release`. iOS deployment target pinned to 13.0 (DEC-003). Surface caveat: DEC-011.1 iOS audio remains Deferred — `cpal`'s iOS backend has not been empirically verified, and AVAudioSession category configuration is required for voice transmission. |
|
||||
@@ -1,83 +0,0 @@
|
||||
# Rel Platform Release Policy
|
||||
|
||||
**Document type:** Release / Platform Release Policy
|
||||
**Version:** 0.9.2
|
||||
**Status:** Baseline Candidate
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
**Repo path:** `docs/release/platform-release-policy.md` ---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document separates runtime deployment targets from app-store upload build-SDK gates.
|
||||
|
||||
## 2. iOS / iPadOS Policy
|
||||
|
||||
| Policy item | Decision |
|
||||
|---|---|
|
||||
| Runtime deployment target | iOS 13 or later unless Flutter, plugin, audio, or product constraints require raising it. |
|
||||
| App Store Connect upload build-SDK gate | For upload on or after 2026-04-28, use Xcode 26 or later and the iOS 26 / iPadOS 26 SDK or later, unless Apple publishes a newer applicable requirement before upload. |
|
||||
| Internal Alpha / local development | May use development toolchains suitable for internal testing if no App Store Connect upload is performed. |
|
||||
| TestFlight / App Store upload | Must satisfy the active Apple App Store Connect upload requirement. |
|
||||
|
||||
## 3. Android Policy
|
||||
|
||||
| Policy item | Decision |
|
||||
|---|---|
|
||||
| Runtime minimum | Android API 24 or later unless Flutter, plugin, audio, or product constraints require raising it. |
|
||||
| Store upload target API | Target the Google Play-required API level on the upload date. |
|
||||
| Internal Alpha / sideload testing | May use internal build configuration suitable for internal testing, but release readiness must state whether Google Play rules apply. |
|
||||
|
||||
## 4. Release Readiness Rule
|
||||
|
||||
The Go/No-Go record shall record:
|
||||
|
||||
- runtime minimum versions;
|
||||
- store upload build/toolchain gates;
|
||||
- build number;
|
||||
- commit SHA;
|
||||
- tag;
|
||||
- artifact hashes;
|
||||
- platform-specific release status;
|
||||
- whether the release is internal-only or store-uploaded.
|
||||
|
||||
## 5. Traceability
|
||||
|
||||
| Policy | Traceability |
|
||||
|---|---|
|
||||
| iOS runtime minimum | SysRS-286 -> SysDes-133 -> SRS-185 -> SAD-061 -> SDD-071 |
|
||||
| Apple App Store Connect upload SDK gate | SysRS-287 -> SysDes-134 -> SRS-186 -> SAD-062 -> SDD-072 |
|
||||
| Android runtime and target API policy | SysRS-288/289 -> SysDes-135 -> SRS-187/188 -> SAD-063 -> SDD-073 |
|
||||
|
||||
## 6. Change History
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.2 | 2026-05-14 | Initial platform release policy separating runtime targets from store upload build-SDK gates. |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.2 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate to 2026-04-28 and checked full-package naming, references, and coverage. |
|
||||
|
||||
|
||||
## Desktop Push-to-Talk Release Policy Addendum (Baseline Candidate 0.9.3)
|
||||
|
||||
Per SysDes-148 the release readiness record shall carry, for every desktop release artefact, the following per-platform evidence:
|
||||
|
||||
| Field | Source | Acceptance |
|
||||
|---|---|---|
|
||||
| Detected `PttCapabilityLevel` | Live runtime measurement on the verification host. | Must equal the level the release notes claim. |
|
||||
| Active backend identifier | `DesktopPttBackend::backend_id()` reported by the live measurement. | Must equal the backend the release notes claim. |
|
||||
| Focused fallback exercised | Manual verification step. | Must record "yes" with a re-measurement of the same backend identifier after the user revokes the relevant permission / blocks the relevant input path. |
|
||||
| Capability badge UI | Screenshot or platform-test trace. | Must match the runtime capability. |
|
||||
|
||||
Release notes shall not claim Global PTT support on a platform when the live measurement returned `L0Focused`. Release notes shall not claim mouse-side-button support on a platform when the live measurement did not include a side-button binding (per DEC-026 the Linux portal may not expose side-button bindings on every session).
|
||||
|
||||
Per DEC-025 the only officially-tested Linux environment for the first public release is GNOME on Wayland. Other Linux environments are supported at the `L0Focused` capability only; the release notes shall not claim Global PTT support outside the tested compositor.
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.3 | 2026-05-15 | Added desktop PTT release-policy evidence requirements: per-platform capability level + backend identifier + fallback-exercised + capability badge UI screenshot must be recorded before release notes may claim Global PTT support. |
|
||||
@@ -1,51 +0,0 @@
|
||||
# Release Artifact Policy
|
||||
|
||||
**Document type:** Release / Artifact Policy
|
||||
**Version:** 0.1.0
|
||||
**Status:** Draft
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
**Repo path:** `docs/release/release-artifact-policy.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document defines the expected release artifact metadata before a release is approved.
|
||||
|
||||
## 2. Required Artifact Metadata
|
||||
|
||||
| Field | Required |
|
||||
|---|---|
|
||||
| Release version | Yes |
|
||||
| Build number | Yes |
|
||||
| Git commit SHA | Yes |
|
||||
| Git tag | Yes |
|
||||
| Build timestamp | Yes |
|
||||
| Build environment | Yes |
|
||||
| Platform | Yes |
|
||||
| Artifact filename | Yes |
|
||||
| SHA-256 hash | Yes |
|
||||
| Signing status | Required for public/store release |
|
||||
| Notarization status | Required for macOS public release |
|
||||
| Store upload status | Required for store release |
|
||||
|
||||
## 3. Artifact Types
|
||||
|
||||
| Platform | Expected artifact |
|
||||
|---|---|
|
||||
| Windows | Installer or packaged app artifact |
|
||||
| macOS | Signed/notarized app bundle or installer |
|
||||
| Linux | AppImage, Flatpak, deb, rpm, or selected package |
|
||||
| Android | AAB/APK |
|
||||
| iOS / iPadOS | App Store Connect/TestFlight upload artifact |
|
||||
|
||||
## 4. Rule
|
||||
|
||||
Release artifacts shall not be treated as approved until the Release Readiness / Go-No-Go record is completed.
|
||||
|
||||
## 5. Change History
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.1.0 | 2026-05-14 | Initial release artifact policy. |
|
||||
@@ -1,234 +0,0 @@
|
||||
|
||||
# CHANORA_REL_Release_Readiness_Go_NoGo_Record_v0.9.2.2.1
|
||||
|
||||
**Document type:** Release Readiness Checklist / Go-No-Go Record
|
||||
**Version:** 0.9.2
|
||||
**Status:** Baseline Candidate
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
**Repo path:** `docs/release/release-readiness-go-nogo-record.md` ---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document records the auditable release readiness decision for a Chanora release.
|
||||
|
||||
Design documents alone do not authorize release. A release requires an explicit readiness decision based on scope, build identity, requirement completion, verification evidence, security review, platform readiness, legal/privacy readiness, known risks, and approval.
|
||||
|
||||
## 2. Release Identity
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Release name | TBD by Product Owner |
|
||||
| Release type | TBD: Internal Alpha / External Beta / MVP Public / Store Release |
|
||||
| Release version | TBD |
|
||||
| Release candidate ID | TBD |
|
||||
| Release date target | TBD |
|
||||
| Release owner | TBD |
|
||||
| Product owner | TBD |
|
||||
| Engineering owner | TBD |
|
||||
| QA / verification owner | TBD |
|
||||
| Security reviewer | TBD |
|
||||
| Legal / compliance reviewer | TBD |
|
||||
|
||||
## 3. Build Identity
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Git repository | TBD |
|
||||
| Git branch | TBD |
|
||||
| Git commit SHA | TBD |
|
||||
| Git tag | TBD |
|
||||
| iOS App Store Connect upload SDK gate | Xcode 26+ and iOS 26 / iPadOS 26 SDK+ for upload on or after 2026-04-28 |
|
||||
| Platform release policy included | Yes |
|
||||
| Build number | TBD |
|
||||
| CI pipeline ID | TBD |
|
||||
| Build timestamp | TBD |
|
||||
| Windows artifact | TBD |
|
||||
| macOS artifact | TBD |
|
||||
| Linux artifact | TBD |
|
||||
| Android artifact | TBD |
|
||||
| iOS artifact | TBD |
|
||||
| Artifact hash method | SHA-256 unless otherwise specified |
|
||||
| Artifact hashes | TBD |
|
||||
|
||||
## 4. Scope Readiness
|
||||
|
||||
| Question | Answer | Evidence | Owner |
|
||||
|---|---|---|---|
|
||||
| Is this release scope defined? | TBD | Release scope statement | Product Owner |
|
||||
| Is this release Internal Alpha, External Beta, MVP Public, or Store Release? | TBD | Release scope statement | Product Owner |
|
||||
| Are included features listed? | TBD | Release notes / scope list | Product Owner |
|
||||
| Are excluded/deferred features listed? | TBD | Deferred requirements list | Product Owner |
|
||||
| Are target platforms listed? | TBD | Platform readiness table | Engineering Owner |
|
||||
| Are known limitations documented? | TBD | Known issue register | Product Owner / QA |
|
||||
|
||||
## 5. Requirements Readiness
|
||||
|
||||
| Requirement group | Status | Evidence | Deferred items / waiver |
|
||||
|---|---|---|---|
|
||||
| P0 / MVP connection requirements | TBD | SRS/SWE.6 evidence | TBD |
|
||||
| P0 / MVP channel and state requirements | TBD | SRS/SWE.6 evidence | TBD |
|
||||
| P0 / MVP voice requirements | TBD | SRS/SWE.6 evidence | TBD |
|
||||
| Audio processing requirements | TBD | SWE.4/SWE.5/SWE.6 evidence | TBD |
|
||||
| Storage and secure storage requirements | TBD | SWE.4/SWE.5/SWE.6 evidence | TBD |
|
||||
| Diagnostics and redaction requirements | TBD | SWE.4/SWE.5/SWE.6 evidence | TBD |
|
||||
| Material 3 / UI requirements | TBD | SWE.6 evidence | TBD |
|
||||
| Accessibility requirements | TBD | SWE.6 evidence | TBD |
|
||||
| Platform behavior requirements | TBD | SYS.4/SWE.6 evidence | TBD |
|
||||
| i18n / Unicode requirements | TBD | SWE.4/SWE.5/SWE.6 evidence | TBD |
|
||||
| Traceability requirements | TBD | Validation report | TBD |
|
||||
|
||||
## 6. Verification Readiness
|
||||
|
||||
| Verification layer | Required evidence | Status | Failed items | Waivers |
|
||||
|---|---|---|---|---|
|
||||
| SWE.4 Unit Verification | Unit verification summary report | TBD | TBD | TBD |
|
||||
| SWE.5 Software Integration Verification | Integration verification summary report | TBD | TBD | TBD |
|
||||
| SWE.6 Software Verification | Software verification summary report | TBD | TBD | TBD |
|
||||
| SYS.4 System Integration Verification | System integration verification summary report | TBD | TBD | TBD |
|
||||
| Regression Verification | Regression report | TBD | TBD | TBD |
|
||||
| Manual exploratory test | Test notes | TBD | TBD | TBD |
|
||||
|
||||
## 7. Security Readiness
|
||||
|
||||
| Question | Required answer | Status | Evidence |
|
||||
|---|---|---|---|
|
||||
| Is secure storage verified for supported platforms? | Yes / waived | TBD | Security test report |
|
||||
| Are secrets excluded from plaintext logs? | Yes / waived | TBD | Redaction test result |
|
||||
| Is diagnostic export redaction verified? | Yes / waived | TBD | Diagnostics audit |
|
||||
| Is dependency/license scan completed? | Yes / waived | TBD | Dependency scan report |
|
||||
| Are high/critical dependency issues resolved or waived? | Yes / waived | TBD | Security waiver record |
|
||||
| Are user-facing errors safe and non-sensitive? | Yes / waived | TBD | Review record |
|
||||
| Are platform permissions justified? | Yes / waived | TBD | Permission review |
|
||||
|
||||
## 8. Platform Readiness
|
||||
|
||||
| Platform | Release status | Build artifact | Verification status | Known blockers | Owner |
|
||||
|---|---|---|---|---|---|
|
||||
| Windows | TBD: Go / Conditional Go / No-Go / Not in scope | TBD | TBD | TBD | TBD |
|
||||
| macOS | TBD: Go / Conditional Go / No-Go / Not in scope | TBD | TBD | TBD | TBD |
|
||||
| Linux | TBD: Go / Conditional Go / No-Go / Not in scope | TBD | TBD | TBD | TBD |
|
||||
| Android | TBD: Go / Conditional Go / No-Go / Not in scope | TBD | TBD | TBD | TBD |
|
||||
| iOS | TBD: Go / Conditional Go / No-Go / Not in scope | TBD | TBD, including Apple App Store SDK gate | TBD | TBD |
|
||||
|
||||
## 9. Legal, OSS, and Privacy Readiness
|
||||
|
||||
| Question | Required answer | Status | Evidence | Owner |
|
||||
|---|---|---|---|---|
|
||||
| Is the app clearly identified as unofficial and not affiliated with TeamSpeak? | Yes | TBD | App copy / legal notice | Legal |
|
||||
| Is the TeamSpeak trademark/non-affiliation wording reviewed? | Yes | TBD | Legal review record | Legal |
|
||||
| Is OSS license review completed? | Yes | TBD | OSS notice / license report | Legal / Engineering |
|
||||
| Are Rust, Flutter, tsclientlib, and platform dependencies included in OSS review? | Yes | TBD | OSS license report | Legal / Engineering |
|
||||
| Is privacy policy completed for the release scope? | Yes | TBD | Privacy policy URL/file | Legal |
|
||||
| Are diagnostics/logging disclosures complete? | Yes | TBD | Privacy policy / in-app notice | Legal / Product |
|
||||
| Are App Store / Play Store metadata requirements complete if applicable? | Yes / N/A | TBD | Store metadata review | Product / Legal |
|
||||
|
||||
## 10. Known Issues and Waivers
|
||||
|
||||
| Issue ID | Description | Severity | Impact | Waiver? | Waiver owner | Expiry / follow-up |
|
||||
|---|---|---|---|---|---|---|
|
||||
| TBD | TBD | TBD | TBD | TBD | TBD | TBD |
|
||||
|
||||
## 10A. Required Security, Privacy, and Legal Evidence
|
||||
|
||||
| Evidence document | Required status before External Beta / Public release |
|
||||
|---|---|
|
||||
| `CHANORA_SEC_Threat_Model_v0.9.2.2.1.md` | Reviewed; v1.0 approved before public release |
|
||||
| `CHANORA_SEC_Secure_Storage_Audit_Report_v0.9.2.2.1.md` | Completed for release-scope platforms |
|
||||
| `CHANORA_SEC_Diagnostic_Redaction_Audit_Report_v0.9.2.2.1.md` | Completed and approved |
|
||||
| `CHANORA_SEC_Dependency_And_Supply_Chain_Report_v0.9.2.2.1.md` | Completed with no unapproved critical/high risk |
|
||||
| `CHANORA_PRIV_Privacy_Policy_v0.9.2.2.1.md` | Legal/privacy reviewed; v1.0 approved before public release |
|
||||
| `CHANORA_LEGAL_Trademark_And_Attribution_Review_v0.9.2.2.1.md` | Legal reviewed; v1.0 approved before public release |
|
||||
|
||||
|
||||
## 10B. Key Product Decision Gate
|
||||
|
||||
| Decision | Required status before Go |
|
||||
|---|---|
|
||||
| Release type | Confirmed |
|
||||
| Release platform scope | Confirmed |
|
||||
| Minimum iOS version | Confirmed |
|
||||
| Apple App Store SDK gate | Confirmed and release-inspected |
|
||||
| Minimum Android version | Confirmed |
|
||||
| Android target SDK policy | Confirmed |
|
||||
| Multiple active connections in MVP | Confirmed |
|
||||
| AEC/AGC/NS/HPF default states | Confirmed |
|
||||
| Audio processing implementation path | Confirmed |
|
||||
| Legal/trademark/licensing review requirement | Confirmed |
|
||||
| Local database choice | Confirmed |
|
||||
| Flutter/Rust bridge choice | Confirmed |
|
||||
| Diagnostics upload policy | Confirmed |
|
||||
| Crash reporting policy | Confirmed |
|
||||
| Product license model | Confirmed or explicitly not required for release scope |
|
||||
|
||||
|
||||
## 11. Release Decision
|
||||
|
||||
| Decision | Meaning |
|
||||
|---|---|
|
||||
| Go | Release is approved for the stated scope and platforms. |
|
||||
| Conditional Go | Release is approved only if listed conditions are satisfied. |
|
||||
| No-Go | Release is not approved. |
|
||||
|
||||
**Decision:** TBD: Go / Conditional Go / No-Go
|
||||
|
||||
## 12. Conditional Go Conditions
|
||||
|
||||
| Condition ID | Condition | Owner | Due date | Evidence required |
|
||||
|---|---|---|---|---|
|
||||
| TBD | TBD | TBD | TBD | TBD |
|
||||
|
||||
## 13. Approval
|
||||
|
||||
| Role | Name | Decision | Date | Evidence / Signature |
|
||||
|---|---|---|---|---|
|
||||
| Product Owner | TBD | TBD | TBD | TBD |
|
||||
| Engineering Owner | TBD | TBD | TBD | TBD |
|
||||
| QA / Verification Owner | TBD | TBD | TBD | TBD |
|
||||
| Security Reviewer | TBD | TBD | TBD | TBD |
|
||||
| Legal / Compliance Reviewer | TBD | TBD | TBD | TBD |
|
||||
| Release Manager | TBD | TBD | TBD | TBD |
|
||||
|
||||
## 14. Change History
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.0 | 2026-05-14 | Initial release readiness and Go/No-Go record template. |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.1 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.1 | 2026-05-14 | Updated baseline after product decision closure: Apple App Store SDK gate uses Xcode 26+ and iOS 26 / iPadOS 26 SDK+ since 2026-04-28, platform baselines and decision traceability propagated across the document set. |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.2 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate to 2026-04-28 and checked full-package naming, references, and coverage. |
|
||||
|
||||
|
||||
## Desktop Push-to-Talk Release Readiness Addendum (Baseline Candidate 0.9.3)
|
||||
|
||||
The release readiness checklist for every desktop release artefact gains the following items per SysDes-148, SysRS-298, and DEC-023 / DEC-024 / DEC-025 / DEC-026 / DEC-027 / DEC-028.
|
||||
|
||||
| Item | Owner | Evidence required | Status |
|
||||
|---|---|---|---|
|
||||
| RR-PTT-001 Windows Global PTT verified on a Windows reference host. | Windows Platform Owner | Live measurement of `PttCapabilityLevel` + `backend_id` returned at runtime. Backend identifier shall be `raw-input` (preferred) or `low-level-hook` (fallback) for Global. | Open |
|
||||
| RR-PTT-002 macOS Global PTT verified with permission granted on a macOS reference host. | macOS Platform Owner | Live measurement + `permission_state = Granted` reported through the Event-Tap backend; UI capability badge screenshot. | Open |
|
||||
| RR-PTT-003 macOS Focused PTT fallback verified with permission denied. | macOS Platform Owner | Live measurement of `PttCapabilityLevel::L0Focused` after revoking Input Monitoring; UI capability badge screenshot showing the fallback notice. | Open |
|
||||
| RR-PTT-004 Linux Global PTT verified on GNOME-on-Wayland. | Linux Platform Owner | Live measurement returning `gnome-wayland-portal` backend identifier from a live GNOME-on-Wayland host; portal binding dialog screenshot. | **Implemented** (live `CreateSession` + `BindShortcuts` + signal subscription landed in code; awaiting live trace from a GNOME-on-Wayland reference host before the cell can be marked Done). |
|
||||
| RR-PTT-005 Linux Focused fallback verified on a non-tested compositor (any of: X11, sway, KDE) | Linux Platform Owner | Live measurement of `L0Focused` on at least one non-tested compositor; release notes do not claim Global support on the untested environment. | Open |
|
||||
| RR-PTT-006 Diagnostic export carries no key data. | Privacy Reviewer | Inspection of a user-initiated diagnostic export captured while PTT is bound to a real key; export shall contain `capability_level`, `backend_id`, `bound_input_class` and shall not contain a recognisable key code. | Open |
|
||||
| RR-PTT-007 Missed-key-up watchdog timeout demonstrated. | Audio Owner | Test trace showing `transmit_active` clearing after the configured 30 s ceiling when the watchdog forces a release. | **Done (v1.0.0-rc.4)** — covered by `chanora_audio::ptt::tests::watchdog_clears_transmit_after_timeout` (and the negative `watchdog_does_not_clear_on_normal_release`). Live platform trace still required per RR-PTT-001..005. |
|
||||
| RR-PTT-008 Capability badge matches runtime capability on every supported platform. | UX Owner | UI screenshot or platform-test trace. | Open |
|
||||
|
||||
A release decision shall be **No-Go** for any platform whose RR-PTT items are not all closed.
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.3 | 2026-05-15 | Added desktop PTT release-readiness items RR-PTT-001 through RR-PTT-008 covering Windows / macOS / Linux Global verification, permission-denied fallback verification, diagnostic-export privacy inspection, missed-key-up watchdog test, and capability-badge UI verification. |
|
||||
| 0.9.4 | 2026-05-15 | RR-PTT-007 (missed-key-up watchdog) flipped to Done — the cross-platform `chanora_audio::ptt::MissedKeyUpWatchdog` ships in v1.0.0-rc.4 with two passing unit tests. Live per-platform traces (RR-PTT-001..005, RR-PTT-008) remain required for the live verification phase but are no longer blocked on engineering. |
|
||||
| 0.9.5 | 2026-05-15 | RR-PTT-004 status flipped to Implemented (live trace from a GNOME-on-Wayland reference host pending). The Linux backend now runs the full portal `CreateSession` + `BindShortcuts` + `Activated` / `Deactivated` flow on a dedicated tokio task per backend instance. |
|
||||
@@ -1,514 +0,0 @@
|
||||
# Building Chanora v0.2.0-beta.1 on Windows via Azure VM
|
||||
|
||||
**Document type:** Release / Platform Build Instructions
|
||||
**Version:** 0.1.0
|
||||
**Status:** Draft
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
**Repo path:** `docs/release/windows-build.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document gives exact step-by-step instructions for building the
|
||||
Chanora `v0.2.0-beta.1` Internal Beta on a Windows host, using an
|
||||
Azure Virtual Machine. It exists because the development host is
|
||||
Linux; `flutter build windows` requires a Windows host with Visual
|
||||
Studio 2022 and cannot be cross-compiled.
|
||||
|
||||
After following this doc you will have:
|
||||
|
||||
- `chanora_flutter.exe` — the Windows desktop binary.
|
||||
- `chanora_bridge.dll` — the Rust cdylib loaded by the .exe via FFI.
|
||||
- A complete release bundle directory the app needs at runtime.
|
||||
|
||||
The doc assumes you have:
|
||||
|
||||
- An Azure subscription with permission to create VMs.
|
||||
- An RDP client (Windows: built-in; macOS: Microsoft Remote Desktop;
|
||||
Linux: `remmina` or `rdesktop`).
|
||||
- The Chanora source code locally (this repository).
|
||||
|
||||
---
|
||||
|
||||
## 2. Toolchain versions pinned for this build
|
||||
|
||||
| Tool | Version | Why |
|
||||
|---|---|---|
|
||||
| Windows Server | 2022 Datacenter | LTS, plenty of Azure images, ships PowerShell 5.1 + Server Core APIs |
|
||||
| Visual Studio 2022 | Build Tools (Community works too) | Required by `flutter build windows`; provides MSVC, Windows SDK, CMake, link.exe |
|
||||
| Visual Studio workload | "Desktop development with C++" | Provides MSVC v143, Windows 10/11 SDK, CMake tools, C++ ATL |
|
||||
| Flutter SDK | 3.41.9 stable | Matches the Linux/Beta build; bridge codegen is version-sensitive |
|
||||
| Dart SDK | 3.11.5 | Comes with Flutter 3.41.9 |
|
||||
| Rust toolchain | stable 1.95 (or newer) | Workspace `rust-version = "1.95"` |
|
||||
| Rust target | `x86_64-pc-windows-msvc` | Native Windows ABI; produces MSVC-compatible .dll |
|
||||
| `cargo-ndk` | N/A | Not needed for Windows; only Android needs it |
|
||||
| Opus library | bundled via `audiopus_sys` build script + cmake | On Windows there is no system libopus by default; we build it from source |
|
||||
| Git for Windows | latest | Convenient `git` + the bundled Bash for running `flutter` if needed |
|
||||
| 7-Zip (optional) | latest | Convenient for unpacking the source bundle if you uploaded it as zip |
|
||||
|
||||
---
|
||||
|
||||
## 3. Azure VM provisioning
|
||||
|
||||
### 3.1 Recommended SKU
|
||||
|
||||
| Setting | Value | Rationale |
|
||||
|---|---|---|
|
||||
| Image | `Windows Server 2022 Datacenter — x64 Gen2` | Most common LTS Windows image |
|
||||
| Size | `Standard_D4s_v5` (4 vCPU, 16 GiB) or larger | The Cargo cold build pulls hundreds of crates; 4 cores keeps the build under 30 minutes |
|
||||
| OS disk | Premium SSD 128 GiB | Default 128 GiB is enough for VS 2022 (~10 GiB), Flutter SDK (~2 GiB), Rust toolchain (~1 GiB), source + build artefacts (~15 GiB) |
|
||||
| Auth | Password (you'll RDP in) | Sufficient for a short-lived build VM |
|
||||
| Inbound port rules | Allow **RDP (3389)** only from your IP | Lock RDP to your IP via NSG; never open to 0.0.0.0/0 |
|
||||
| Networking | New VNet + public IP | Standard for an ad-hoc build host |
|
||||
| Auto-shutdown | Enable, 19:00 local time | Stops you forgetting and burning hours |
|
||||
|
||||
### 3.2 Estimated cost
|
||||
|
||||
`Standard_D4s_v5` in West US 2 is about **USD $0.20/hour** for the
|
||||
compute plus ~USD $0.01/hour for the disk. A first cold build
|
||||
(provision → install everything → compile → archive) is typically
|
||||
2–3 hours. Total: under **USD $1** per build session if you
|
||||
deallocate after.
|
||||
|
||||
> **Cost gotcha:** *Stopped (deallocated)* VMs do not bill for
|
||||
> compute; *Stopped* (in the OS shutdown sense, but not deallocated
|
||||
> in Azure) still bills compute. Always check the Azure portal shows
|
||||
> the VM as **Stopped (deallocated)**.
|
||||
|
||||
### 3.3 Provisioning checklist
|
||||
|
||||
1. Azure Portal → **Create a resource** → **Windows Server 2022 Datacenter (x64 Gen2)**.
|
||||
2. Choose region near you.
|
||||
3. Size: `Standard_D4s_v5`.
|
||||
4. Administrator account: pick a username (e.g. `chanora`) + a strong
|
||||
password.
|
||||
5. Inbound ports: RDP only, **restricted to your public IP**.
|
||||
6. Disks: keep Premium SSD 128 GiB.
|
||||
7. Networking: defaults; ensure auto-assign public IP.
|
||||
8. Management → Auto-shutdown: **On**, time = end of your work day,
|
||||
notification = email.
|
||||
9. Review + create.
|
||||
|
||||
### 3.4 First RDP login
|
||||
|
||||
1. Get the VM's public IP from the Azure portal.
|
||||
2. RDP in as `chanora` / your password.
|
||||
3. (Optional) Open Server Manager → Local Server → IE Enhanced
|
||||
Security Configuration → turn **Off** for Administrators so the
|
||||
downloads in §4 don't get blocked.
|
||||
|
||||
---
|
||||
|
||||
## 4. Install the toolchain (one-time per VM)
|
||||
|
||||
Run all of these in an **elevated PowerShell** (right-click PowerShell → Run as Administrator).
|
||||
|
||||
### 4.1 Visual Studio 2022 Build Tools + workload
|
||||
|
||||
```powershell
|
||||
# Download the VS 2022 Build Tools bootstrapper
|
||||
Invoke-WebRequest -Uri 'https://aka.ms/vs/17/release/vs_buildtools.exe' `
|
||||
-OutFile "$env:TEMP\vs_buildtools.exe"
|
||||
|
||||
# Install with the C++ desktop workload (this is what Flutter requires).
|
||||
# --quiet suppresses UI; --wait blocks until done; takes 10-15 minutes.
|
||||
& "$env:TEMP\vs_buildtools.exe" --quiet --wait --norestart `
|
||||
--add Microsoft.VisualStudio.Workload.VCTools `
|
||||
--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
|
||||
--add Microsoft.VisualStudio.Component.Windows11SDK.22621 `
|
||||
--add Microsoft.VisualStudio.Component.VC.CMake.Project `
|
||||
--add Microsoft.VisualStudio.Component.VC.ATL `
|
||||
--includeRecommended
|
||||
```
|
||||
|
||||
When this completes, **reboot the VM** (Visual Studio Build Tools
|
||||
needs it for environment variables).
|
||||
|
||||
### 4.2 Git for Windows
|
||||
|
||||
```powershell
|
||||
winget install --id Git.Git --silent --accept-source-agreements --accept-package-agreements
|
||||
```
|
||||
|
||||
### 4.3 Rust (stable, with the MSVC target)
|
||||
|
||||
```powershell
|
||||
# Download rustup-init for Windows.
|
||||
Invoke-WebRequest -Uri 'https://win.rustup.rs/x86_64' `
|
||||
-OutFile "$env:TEMP\rustup-init.exe"
|
||||
|
||||
# Install the default toolchain (stable-x86_64-pc-windows-msvc).
|
||||
& "$env:TEMP\rustup-init.exe" -y --default-toolchain stable --profile minimal
|
||||
|
||||
# Open a NEW PowerShell so PATH picks up cargo.
|
||||
# Then verify:
|
||||
cargo --version
|
||||
rustc --version
|
||||
```
|
||||
|
||||
Expected output: `cargo 1.95.0` (or newer), `rustc 1.95.0`. The
|
||||
default target on Windows is `x86_64-pc-windows-msvc` — this is what
|
||||
we want.
|
||||
|
||||
### 4.4 Flutter SDK (pinned to 3.41.9 stable)
|
||||
|
||||
```powershell
|
||||
# Download Flutter SDK
|
||||
$flutter = 'https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.41.9-stable.zip'
|
||||
Invoke-WebRequest -Uri $flutter -OutFile "$env:TEMP\flutter.zip"
|
||||
Expand-Archive "$env:TEMP\flutter.zip" -DestinationPath 'C:\'
|
||||
|
||||
# Add to PATH for the current user (persists across sessions).
|
||||
[Environment]::SetEnvironmentVariable(
|
||||
'Path',
|
||||
[Environment]::GetEnvironmentVariable('Path', 'User') + ';C:\flutter\bin',
|
||||
'User'
|
||||
)
|
||||
|
||||
# Open a NEW PowerShell so PATH applies, then:
|
||||
flutter --version
|
||||
flutter doctor
|
||||
```
|
||||
|
||||
`flutter doctor` should show green on:
|
||||
|
||||
- ✓ Flutter (Channel stable, 3.41.9, on Microsoft Windows …)
|
||||
- ✓ Windows Version (Windows … 10.0.20348 or later)
|
||||
- ✓ Visual Studio - develop Windows apps (Visual Studio Build Tools 2022 …)
|
||||
|
||||
Yellow on Android Studio / Chrome is fine — we're only building
|
||||
Windows.
|
||||
|
||||
### 4.5 `flutter_rust_bridge_codegen` and Dart deps
|
||||
|
||||
```powershell
|
||||
cargo install flutter_rust_bridge_codegen --version "=2.12.0"
|
||||
```
|
||||
|
||||
Takes ~5 minutes (compiles `flutter_rust_bridge_codegen` from source).
|
||||
|
||||
### 4.6 Opus build dependency
|
||||
|
||||
The `audiopus` Rust crate wraps the C Opus library. On Windows there
|
||||
is no system Opus, so the `audiopus_sys` build script will attempt to
|
||||
build Opus from source via CMake (which the VS workload already
|
||||
provided). No extra action is required — but verify CMake is on
|
||||
PATH:
|
||||
|
||||
```powershell
|
||||
cmake --version
|
||||
```
|
||||
|
||||
Expected: `cmake version 3.x` (any 3.x ≥ 3.18 is fine).
|
||||
|
||||
If CMake is not found, install it explicitly:
|
||||
|
||||
```powershell
|
||||
winget install --id Kitware.CMake --silent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Get the source onto the VM
|
||||
|
||||
Two options. Pick whichever is easier for you.
|
||||
|
||||
### Option A — Push the repo to a temporary git remote
|
||||
|
||||
On the Linux host where the repo lives:
|
||||
|
||||
```bash
|
||||
# E.g. create a private GitHub repo and push:
|
||||
git remote add origin https://github.com/<your-user>/chanora.git
|
||||
git push --all
|
||||
git push --tags
|
||||
```
|
||||
|
||||
Then on the Windows VM:
|
||||
|
||||
```powershell
|
||||
cd C:\
|
||||
git clone https://github.com/<your-user>/chanora.git
|
||||
cd chanora
|
||||
git checkout v0.2.0-beta.1
|
||||
```
|
||||
|
||||
### Option B — Upload the source as a zip via RDP clipboard
|
||||
|
||||
On Linux:
|
||||
|
||||
```bash
|
||||
cd /home/milkice
|
||||
git -C chanora archive --format=zip --output=/tmp/chanora-v0.2.0-beta.1.zip v0.2.0-beta.1
|
||||
```
|
||||
|
||||
Copy `/tmp/chanora-v0.2.0-beta.1.zip` into the RDP session
|
||||
(clipboard or shared drive), unzip into `C:\chanora\`.
|
||||
|
||||
Either way, you end up with the working tree at `C:\chanora\`,
|
||||
checked out at the `v0.2.0-beta.1` tag.
|
||||
|
||||
---
|
||||
|
||||
## 6. Add the Windows platform to the Flutter app
|
||||
|
||||
The product Flutter app was created with `--platforms=linux,android`,
|
||||
so the `windows/` platform folder does not yet exist. Add it once on
|
||||
the build VM:
|
||||
|
||||
```powershell
|
||||
cd C:\chanora\apps\chanora_flutter
|
||||
flutter create --platforms=windows .
|
||||
```
|
||||
|
||||
This creates `apps/chanora_flutter/windows/` containing:
|
||||
|
||||
```
|
||||
windows/
|
||||
CMakeLists.txt
|
||||
flutter/
|
||||
CMakeLists.txt
|
||||
generated_plugin_registrant.cc
|
||||
...
|
||||
runner/
|
||||
main.cpp
|
||||
Runner.rc
|
||||
chanora_flutter.exe.manifest
|
||||
...
|
||||
```
|
||||
|
||||
> **Important:** Do **not** commit this `windows/` folder back to the
|
||||
> repo from the VM unless you also do the corresponding edits the
|
||||
> source-of-truth host uses (icon, manifest, etc.). For Beta it is
|
||||
> fine to keep it VM-only.
|
||||
|
||||
---
|
||||
|
||||
## 7. Build the Rust cdylib for Windows
|
||||
|
||||
```powershell
|
||||
cd C:\chanora
|
||||
cargo build --release -p chanora_bridge
|
||||
```
|
||||
|
||||
This builds the workspace, including:
|
||||
|
||||
- The whole `tsclientlib` git dependency tree (slow first time —
|
||||
expect ~5–10 minutes for the first compile of `audiopus_sys` +
|
||||
`tsproto` etc.).
|
||||
- `chanora_bridge` as a `cdylib` + `staticlib` + `rlib`.
|
||||
|
||||
Expected output location:
|
||||
|
||||
```
|
||||
C:\chanora\target\release\chanora_bridge.dll
|
||||
```
|
||||
|
||||
(Note: no `lib` prefix on Windows MSVC.)
|
||||
|
||||
Verify:
|
||||
|
||||
```powershell
|
||||
Get-Item C:\chanora\target\release\chanora_bridge.dll | Format-List Name, Length, LastWriteTime
|
||||
```
|
||||
|
||||
The DLL is typically ~16–18 MiB.
|
||||
|
||||
---
|
||||
|
||||
## 8. Regenerate the FRB bindings (optional — only if you changed the bridge API)
|
||||
|
||||
The Linux build already produced `lib/src/rust/*.dart` and
|
||||
`crates/chanora_bridge/src/frb_generated.rs`. The bindings are
|
||||
platform-agnostic Dart + Rust source, so **they do not need
|
||||
regenerating on Windows**. Skip §8 unless you modified
|
||||
`crates/chanora_bridge/src/api.rs` after `v0.2.0-beta.1`.
|
||||
|
||||
If you do need to regenerate:
|
||||
|
||||
```powershell
|
||||
cd C:\chanora
|
||||
flutter_rust_bridge_codegen generate
|
||||
```
|
||||
|
||||
Takes ~5–10 minutes the first time on Windows.
|
||||
|
||||
---
|
||||
|
||||
## 9. Build the Flutter Windows binary
|
||||
|
||||
```powershell
|
||||
cd C:\chanora\apps\chanora_flutter
|
||||
flutter pub get
|
||||
flutter build windows --release
|
||||
```
|
||||
|
||||
`flutter build windows`:
|
||||
|
||||
1. Invokes CMake on `apps/chanora_flutter/windows/`.
|
||||
2. Builds `chanora_flutter.exe` via MSVC.
|
||||
3. Bundles the Flutter engine DLL (`flutter_windows.dll`), ICU data,
|
||||
Dart-AOT-compiled `app.so` (delivered as `data\app.so`), the
|
||||
Flutter `data\` directory, and platform-specific resources.
|
||||
|
||||
Build time: ~3–5 minutes on `Standard_D4s_v5` once dependencies are
|
||||
cached.
|
||||
|
||||
Expected output location:
|
||||
|
||||
```
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\
|
||||
```
|
||||
|
||||
Contents:
|
||||
|
||||
| File | Size (approx) | Notes |
|
||||
|---|---|---|
|
||||
| `chanora_flutter.exe` | ~10 MiB | The launcher .exe |
|
||||
| `flutter_windows.dll` | ~17 MiB | Flutter engine |
|
||||
| `data\icudtl.dat` | ~10 MiB | Unicode tables |
|
||||
| `data\app.so` | varies | AOT-compiled Dart code |
|
||||
| `data\flutter_assets\` | varies | Images, fonts, ARB-derived .json |
|
||||
|
||||
---
|
||||
|
||||
## 10. Add the Rust DLL to the bundle
|
||||
|
||||
The Flutter app loads `chanora_bridge.dll` at runtime via `dart:ffi`.
|
||||
Drop the DLL next to the .exe (the same directory):
|
||||
|
||||
```powershell
|
||||
$src = 'C:\chanora\target\release\chanora_bridge.dll'
|
||||
$dst = 'C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\'
|
||||
Copy-Item $src $dst -Force
|
||||
```
|
||||
|
||||
Verify everything is in place:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem $dst -Recurse | Select-Object FullName, Length |
|
||||
Format-Table -AutoSize
|
||||
```
|
||||
|
||||
You should see:
|
||||
|
||||
```
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_bridge.dll
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\flutter_windows.dll
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\app.so
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\icudtl.dat
|
||||
C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\data\flutter_assets\...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Smoke test on the VM
|
||||
|
||||
Double-click `chanora_flutter.exe` (or `& '...\chanora_flutter.exe'`
|
||||
in PowerShell). The Beta UI should appear:
|
||||
|
||||
- Banner: "Beta build — voice in/out wired; not production ready."
|
||||
- Form: `cn.teamspeak.app` + `ChanoraBeta` pre-populated.
|
||||
- Connect button.
|
||||
|
||||
Press **Connect** → after a few seconds you should see the channel
|
||||
tree of `cn.teamspeak.app` (Vigorous Pro). Press **Start audio** →
|
||||
PTT button appears. Hold it to transmit (a Windows mic permission
|
||||
prompt may appear).
|
||||
|
||||
> **Network gotcha:** Some Azure regions block UDP 9987 outbound by
|
||||
> default. If Connect times out, check the VM's NSG (outbound rules)
|
||||
> and the regional firewall.
|
||||
|
||||
---
|
||||
|
||||
## 12. Package the release artefact
|
||||
|
||||
```powershell
|
||||
$src = 'C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release'
|
||||
$out = 'C:\chanora-v0.2.0-beta.1-windows-x64.zip'
|
||||
Compress-Archive -Path "$src\*" -DestinationPath $out -Force
|
||||
Get-Item $out | Format-List Name, Length
|
||||
```
|
||||
|
||||
Expected size: ~50–80 MiB.
|
||||
|
||||
---
|
||||
|
||||
## 13. Download to your local host
|
||||
|
||||
From your local machine (Linux/macOS/Windows):
|
||||
|
||||
```bash
|
||||
# Use Azure CLI to copy via SAS, or just RDP the file out.
|
||||
# Simplest: in the RDP session enable clipboard file transfer
|
||||
# (mstsc /control or Remmina's "share local folder"), then drag the
|
||||
# zip out.
|
||||
```
|
||||
|
||||
Or use Azure Blob Storage if you want versioned hosting.
|
||||
|
||||
---
|
||||
|
||||
## 14. Final artefact paths (what you actually produce)
|
||||
|
||||
Inside the VM, after a successful build:
|
||||
|
||||
| Artefact | Path on the VM |
|
||||
|---|---|
|
||||
| Bridge DLL | `C:\chanora\target\release\chanora_bridge.dll` |
|
||||
| Flutter EXE | `C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe` |
|
||||
| Complete runtime bundle | `C:\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\` |
|
||||
| Release zip | `C:\chanora-v0.2.0-beta.1-windows-x64.zip` |
|
||||
|
||||
---
|
||||
|
||||
## 15. After the build — deallocate the VM
|
||||
|
||||
```powershell
|
||||
# In the Azure CLI on your local host, OR via the portal:
|
||||
az vm deallocate --resource-group <rg> --name <vm-name>
|
||||
```
|
||||
|
||||
Verify the portal says **Stopped (deallocated)**.
|
||||
|
||||
---
|
||||
|
||||
## 16. Known issues and caveats
|
||||
|
||||
| Issue | Workaround |
|
||||
|---|---|
|
||||
| `audiopus_sys` build fails with "cmake not found" | Re-run §4.6's `winget install Kitware.CMake` and open a new PowerShell. |
|
||||
| `flutter build windows` complains about Long Paths | `Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Value 1`, then reboot. |
|
||||
| Microsoft Defender quarantines `chanora_bridge.dll` | Add `C:\chanora\target\release\` to Defender exclusions before the cargo build. |
|
||||
| The build VM cannot reach `cn.teamspeak.app` on UDP 9987 | Confirm Azure regional firewall allows outbound UDP. The Linux dev host's verification doesn't translate to Azure VMs automatically. |
|
||||
| First `cargo build` takes > 30 minutes | Normal. Subsequent builds reuse `target/` and are ~1 minute. |
|
||||
| `flutter pub get` fails behind a corporate proxy | Set `HTTPS_PROXY` and `HTTP_PROXY` environment variables before running. |
|
||||
| The `windows/` folder created by `flutter create` is missing icons | Replace `windows\runner\resources\app_icon.ico` with a Chanora icon. The default Flutter icon ships otherwise. Cosmetic only for Beta. |
|
||||
|
||||
---
|
||||
|
||||
## 17. Reproducibility note
|
||||
|
||||
This build process is **not bit-reproducible** on Windows in the
|
||||
current state:
|
||||
|
||||
- The `audiopus_sys` build script picks the CMake-discovered MSVC
|
||||
toolchain, which embeds its version into the DLL.
|
||||
- Dart AOT compilation embeds a Dart kernel hash.
|
||||
- Windows resource compilation embeds a build timestamp.
|
||||
|
||||
If true reproducibility is required for a future External Beta or
|
||||
MVP Public release, that is Beta+ work; the build above is
|
||||
sufficient for an Internal Beta milestone per DEC-001.
|
||||
|
||||
---
|
||||
|
||||
## 18. Change History
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.1.0 | 2026-05-14 | Initial Windows build instructions for Chanora `v0.2.0-beta.1`. Targets Azure VM `Standard_D4s_v5` running Windows Server 2022, Visual Studio 2022 Build Tools with the C++ desktop workload, Rust 1.95 stable (`x86_64-pc-windows-msvc`), Flutter 3.41.9 stable, `flutter_rust_bridge` 2.12.0. Produces `chanora_flutter.exe` + `chanora_bridge.dll` packaged into `chanora-v0.2.0-beta.1-windows-x64.zip`. |
|
||||
Reference in New Issue
Block a user