Reaches the Internal Beta milestone of DEC-001's release sequence the
same day as Alpha. Adds voice capture and playback through the full
Flutter UI → FRB → Rust core → tsclientlib → server path.
Promotions from PoC:
poc/audio-capture-playback-spike → crates/chanora_audio/
New product code:
crates/chanora_audio/src/engine.rs — cpal capture and playback,
audiopus Opus VoIP encoder (48 kHz mono 20 ms frames), tsclientlib
AudioHandler for decode + jitter buffer + mix on playback,
push-to-talk gate, graceful playback-only fallback when capture
is unavailable.
crates/chanora_protocol/src/adapter.rs — extended with
voice_out_tx (clonable mpsc::Sender<OutPacket>) and
take_voice_in() (one-shot mpsc::Receiver<InboundVoice>); main
loop now interleaves outbound voice drain, event pumping, and
control-request handling.
crates/chanora_protocol/src/lib.rs — re-exports the few
tsproto_packets types (OutAudio, OutPacket, InAudioBuf,
AudioData, CodecType, Direction) that chanora_audio
legitimately needs. Documented as the single deliberate
cross-crate type re-export per SAD-067, justified by the
performance cost of a parallel type hierarchy on the 20 ms
voice frame.
core/chanora_core/src/lib.rs — ChanoraSession::start_audio,
set_ptt, audio_stats; disconnect now stops the engine first.
crates/chanora_bridge/src/api.rs — startAudio, setPtt,
audioStats commands and BridgeAudioStats DTO.
apps/chanora_flutter/lib/main.dart — "Start audio" button +
hold-to-talk PTT button with pressed/released visual state +
live stats line (TX/RX/PTT). Stats polled every 500 ms.
ARB:
Both en and zh-Hans gain startAudioAction, pttHoldToTalk,
pttTransmitting, audioStatsLine. Banner updated to
"Beta build — voice in/out wired; not production ready."
FRB config:
flutter_rust_bridge.yaml gains local: true so codegen resolves
the workspace member's library stem to "chanora_bridge" instead
of falling back to "UNKNOWN".
Empirical verification (2026-05-14, against cn.teamspeak.app):
cargo check + cargo test --workspace: all green.
flutter analyze: 0 issues.
flutter test: 4/4 passing including:
- test/alpha_e2e_test.dart (regression: Alpha still works)
- test/beta_e2e_test.dart (Beta: connect → startAudio →
PTT cycle → disconnect against cn.teamspeak.app).
Live smoke (cargo test alpha_smoke -- --ignored): 49 channels,
37 clients retrieved.
Capture stream open against the host PipeWire auto_null source
refused (snd_pcm_hw_params); engine correctly logged the warning
and continued in playback-only mode. TX=0 frames, RX=0 frames
reflects the headless null-source environment; on a real mic
host the encoder produces ~50 frames/second while PTT is held.
Honest Beta scope (NOT in this release):
- AEC / AGC / NS / HPF DSP (DEC-007..010): AudioEffects exists
as a struct but the filters are no-ops. Beta+ work.
- Production-quality resampler: current code is linear
interpolation. Beta+ work.
- Identity persistence via chanora_storage: still ephemeral.
- Push-to-Dart event stream: UI polls instead.
- chanora_diagnostics tracing-layer wiring: still scaffold.
- Mobile (Android) cdylib + UI: PoC-proven, not yet in product.
- Reconnect / network-loss recovery for the voice path.
Docs updates:
- docs/governance/product-decision-register.md bumped to v0.9.7
(Beta-milestone change-history entry; no row changes).
- docs/governance/poc-results-summary.md bumped to v0.6.0
(RISK-PoC-005 updated with Beta progress).
159 lines
13 KiB
Markdown
159 lines
13 KiB
Markdown
# PoC Results Summary
|
|
|
|
**Document type:** Governance / PoC Results Summary
|
|
**Version:** 0.6.0
|
|
**Status:** Draft
|
|
**Language:** English
|
|
**Product:** Chanora
|
|
**Repo path:** `docs/governance/poc-results-summary.md`
|
|
|
|
---
|
|
|
|
## 1. Purpose
|
|
|
|
This document is the single top-level entry point summarising the
|
|
outcome of the technical proof-of-concept (PoC) phase defined by
|
|
[`docs/architecture/proof-of-concept-plan.md`](../architecture/proof-of-concept-plan.md).
|
|
|
|
It exists so that reviewers (security, audit, baseline-approval) can
|
|
read one page and follow pointers to evidence, rather than having to
|
|
crawl seven `VERIFICATION.md` files under `poc/`.
|
|
|
|
This summary records facts as of **2026-05-13**.
|
|
|
|
## 2. Status table
|
|
|
|
| Spike | PoC plan exit criterion | Status | Evidence |
|
|
|---|---|---|---|
|
|
| `flutter_rust_bridge_hello` | Flutter can call Rust and receive event stream data | **PASS** | `poc/flutter_rust_bridge_hello/VERIFICATION.md` |
|
|
| `tsclientlib-connect-spike` | Rust can connect to a compatible server/test double | **PASS** | `poc/tsclientlib-connect-spike/VERIFICATION.md` |
|
|
| `secure-storage-spike` | Secret write/read/delete works through platform secure storage | **PASS (Linux only)** | `poc/secure-storage-spike/VERIFICATION.md` |
|
|
| `sqlite-storage-spike` | Schema, migration, and repository pattern are demonstrated | **PASS** | `poc/sqlite-storage-spike/VERIFICATION.md` |
|
|
| `diagnostics-redaction-spike` | Password and identity-secret samples are redacted (REDACT-TC-001..010 covered) | **PASS** | `poc/diagnostics-redaction-spike/VERIFICATION.md` |
|
|
| `audio-capture-playback-spike` (desktop half) + `audio-capture-playback-android-spike` (mobile half) | Capture/playback works on at least one desktop **and** one mobile target | **PASS** — desktop on Linux + PipeWire; mobile on a physical Motorola Moto G Stylus 5G running Android 14 arm64-v8a. iOS remains explicitly deferred per DEC-011.1. | `poc/audio-capture-playback-spike/VERIFICATION.md`, `poc/audio-capture-playback-android-spike/VERIFICATION.md` |
|
|
|
|
Aggregate test count across the PoCs: **44 tests + 1 live-server CLI
|
|
run + 1 desktop-audio CLI round-trip + 1 Android playback + 1 Android
|
|
capture (real-device, with WAV file inspection)**, all passing in the
|
|
recorded runs. **All six PoC plan entries now PASS.**
|
|
|
|
## 3. Toolchain exercised
|
|
|
|
| Tool | Version |
|
|
|---|---|
|
|
| Rust toolchain | stable 1.95.0 (59807616e 2026-04-14) |
|
|
| Rust Android targets | aarch64-linux-android, armv7-linux-androideabi, x86_64-linux-android, i686-linux-android |
|
|
| Flutter SDK | 3.41.9 stable (Dart 3.11.5) |
|
|
| `flutter_rust_bridge` (Rust + Dart) and codegen | 2.12.0 |
|
|
| `tsclientlib` | git `04aa2491` (no published crates.io release) |
|
|
| `cpal` | 0.16 |
|
|
| `rusqlite` | 0.32 (bundled) |
|
|
| `keyring` | 3.6.3 (sync-secret-service + linux-native) |
|
|
| `linux-keyutils` | 0.2.5 |
|
|
| `regex` / `serde` / `serde_json` | 1 |
|
|
| Android SDK | platform 34, build-tools 34.0.0 |
|
|
| Android NDK | r26.3.11579264 |
|
|
| `cargo-ndk` | 4.1.2 |
|
|
| AGP / Gradle / Kotlin | 8.5.2 / 8.7 / 1.9.24 |
|
|
| `jni`, `ndk-context`, `android_logger` | 0.21, 0.1.1, 0.14 |
|
|
| Host OS for verification | Linux (Arch, kernel 7.0.5-arch1-1, x86_64) |
|
|
| Host audio server | PipeWire 1.6.4 (via pcm_pipewire ALSA plugin) |
|
|
| Host Secret Service backend | gnome-keyring (default collection observed locked; kernel keyutils backend used for hermetic tests) |
|
|
| Android test device | Motorola Moto G Stylus 5G (2023), Android 14 (SDK 34), arm64-v8a |
|
|
|
|
## 4. Owner-confirmed decisions
|
|
|
|
Recorded in [`docs/governance/product-decision-register.md`](product-decision-register.md) at version **0.9.5**:
|
|
|
|
### From the PoC phase (decisions surfaced by the spikes)
|
|
|
|
| Decision | Status | Closed by |
|
|
|---|---|---|
|
|
| **DEC-014** typed bridge | Accepted (`flutter_rust_bridge` 2.x pinned) | `flutter_rust_bridge_hello` |
|
|
| **DEC-013.1** SQLite crate | Accepted (`rusqlite` bundled) | `sqlite-storage-spike` |
|
|
| **DEC-013.2** Linux secure-storage backend policy | Accepted (Secret Service preferred, keyutils fallback) | `secure-storage-spike` |
|
|
| **DEC-011.1** audio crate | Accepted (desktop: `cpal`; Android: `cpal`-on-Oboe) / Deferred (iOS) | `audio-capture-playback-spike` (desktop) + `audio-capture-playback-android-spike` (mobile) |
|
|
| **DEC-022** canonical implementation directory layout | Accepted (README sketch — `apps/chanora_flutter/`, `core/chanora_core/`, `crates/chanora_*`) | Owner ruling on 2026-05-13 |
|
|
| **DEC-020** license | Accepted (Apache-2.0 OR MIT dual-license) | Owner ruling on 2026-05-14; license texts added as `LICENSE-APACHE` and `LICENSE-MIT`. |
|
|
|
|
### From the 2026-05-14 owner-confirmation pass (all 17 previously-Proposed)
|
|
|
|
| Decision | Status | Notes |
|
|
|---|---|---|
|
|
| DEC-001 Release type sequence | Accepted | Alpha → Beta → Public. |
|
|
| DEC-002 MVP platform scope | Accepted | All five platforms; staged release allowed. |
|
|
| DEC-003 Minimum iOS | Accepted | iOS 13. |
|
|
| **DEC-004 Minimum Android** | **Accepted — MODIFIED** | **API 28** (raised from the recommendation of API 24). Affects the Android spike's `minSdk = 24`; product `apps/chanora_flutter` must move it to 28. |
|
|
| DEC-005 Android target SDK | Accepted | Google Play-required API on upload date. |
|
|
| DEC-006 Connections in MVP | Accepted | Single connection. |
|
|
| DEC-007 AEC | Accepted | Enabled by default where supported. |
|
|
| DEC-008 AGC | Accepted | Enabled by default + toggle. |
|
|
| DEC-009 Noise suppression | Accepted | Enabled by default + toggle. |
|
|
| DEC-010 High-pass filter | Accepted | Enabled by default. |
|
|
| DEC-011 Audio path | Accepted | Platform-native first. |
|
|
| DEC-012 Legal review gate | Accepted (as a release gate) | The legal review work itself is still to be performed. |
|
|
| DEC-013 Local DB | Accepted | SQLite or equivalent. |
|
|
| **DEC-015 Product language for MVP** | **Accepted — MODIFIED** | **English + Chinese (Simplified)** at MVP (expanded from the recommendation of English-only). Affects translation pipeline and design-system text length budgets. |
|
|
| DEC-016 Diagnostics upload | Accepted | User-initiated local export only. |
|
|
| DEC-017 Crash reporting | Accepted | Disabled for MVP. |
|
|
| DEC-018 Product name | Accepted | Chanora. |
|
|
| DEC-019 Non-affiliation statement | Accepted (drafted wording) | Final legal sign-off still required under DEC-012. |
|
|
| DEC-021 Apple App Store SDK gate | Accepted | Xcode 26+ / iOS 26 SDK+ on or after 2026-04-28. |
|
|
|
|
### Still open
|
|
|
|
(none — DEC-020 closed on 2026-05-14; see register v0.9.6.)
|
|
|
|
DEC-012 legal/trademark/licensing review remains a release-gating
|
|
*work* item but is not an open decision.
|
|
|
|
## 5. Audit-report coverage
|
|
|
|
| Audit ID | Verified by | Audit-report row updated? |
|
|
|---|---|---|
|
|
| SS-AUD-001 (identity secret absent from local DB) | `secure-storage-spike` | Yes — `docs/security/secure-storage-audit-report.md` §4 v0.9.3 |
|
|
| SS-AUD-002 (server password absent from local DB) | `secure-storage-spike` | Yes |
|
|
| SS-AUD-003 (no secrets in logs) | `secure-storage-spike` + cross-ref `diagnostics-redaction-spike` | Yes |
|
|
| SS-AUD-004 (no secrets in diagnostic export) | `diagnostics-redaction-spike` REDACT-TC-008 | Yes |
|
|
| SS-AUD-005 (safe error on backend failure) | `secure-storage-spike` (test + live CLI fallback) | Yes |
|
|
| SS-AUD-006 (delete removes entry) | `secure-storage-spike` | Yes |
|
|
| SS-AUD-007 (per-platform documentation) | Linux only — partial | Yes (status: Partial) |
|
|
| SS-AUD-008 (migration path safety) | Pending (depends on product `chanora_storage`) | Yes (status: Pending) |
|
|
| SS-TC-001 (Windows) | Not run | Status: Deferred |
|
|
| SS-TC-002 (macOS) | Not run | Status: Deferred |
|
|
| SS-TC-003 (Linux) | `secure-storage-spike` | **PoC Pass** |
|
|
| SS-TC-004 (Android) | Not run | Status: Deferred |
|
|
| SS-TC-005 (iOS) | Not run | Status: Deferred |
|
|
| REDACT-TC-001..010 | `diagnostics-redaction-spike` (12/12) | Yes — `docs/security/diagnostic-redaction-audit-report.md` §4 v0.9.3 |
|
|
| Export bundle policy §5 (all rows) | `diagnostics-redaction-spike` | Yes — §5 v0.9.3 |
|
|
|
|
## 6. Open risks and gaps
|
|
|
|
| ID | Risk | Owner | Recommended close path |
|
|
|---|---|---|---|
|
|
| RISK-PoC-001 | iOS audio (AVAudioEngine via cpal or a per-platform iOS adapter) is not verified. The desktop and Android halves of the PoC plan's audio criterion are met; iOS is explicitly deferred per DEC-011.1. | Audio Owner + iOS Owner | iOS spike on macOS + Xcode hardware; or accept the risk and discover it during product integration (not recommended). |
|
|
| RISK-PoC-002 | Windows / macOS / iOS / Android secure-storage adapters not implemented. SS-TC-001/002/004/005 unverified. | Platform Owners | Per-platform adapter spike or first-implementation-in-`chanora_storage` with the audit checks re-run on each target. |
|
|
| RISK-PoC-003 | ~~License (DEC-020) deferred. Blocks public/store release.~~ **CLOSED 2026-05-14.** DEC-020 Accepted as Apache-2.0 OR MIT dual-license; texts present in repository root. Release-gating legal review under DEC-012 remains pending as a separate *work* item, but no longer a license-choice blocker. | Product Owner + Legal | Closed. |
|
|
| RISK-PoC-004 | ~~DEC-001..012, 015..019, 021 still in Proposed status.~~ **CLOSED 2026-05-14.** All 17 decisions were owner-reviewed; statuses recorded in the register at v0.9.5. | Product Owner | Closed. |
|
|
| RISK-PoC-005 | Production code does not exist yet. README's "Implementation status: Not production-ready" remains accurate. | Software Architect | **Further progress 2026-05-14.** Internal Alpha (`v0.1.0-alpha.1`, 3bb038c) wired the connect/snapshot/disconnect cycle. **Internal Beta (`v0.2.0-beta.1`) reached the same day** with voice in/out: `chanora_audio` promoted from scaffold; PTT, Opus encode, decode + jitter buffer + mix all wired through to Flutter. README's status line remains accurate (not production-ready) but is now genuinely close to dogfoodable. |
|
|
| RISK-PoC-006 | **DEC-004 Android minimum was raised to API 28 from the spike's `minSdk = 24`.** The Android spike still builds and runs; product code in `apps/chanora_flutter` must move `minSdk` to 28 and may simplify its AAudio fallback logic accordingly. | Android Owner | Set `minSdk = 28` when the Android target is added to `apps/chanora_flutter`. |
|
|
| RISK-PoC-007 | **DEC-015 expanded the MVP language scope from English-only to English + Chinese (Simplified).** Adds zh-Hans translation, font, and design-system text-length-budget work to MVP. | Product Owner + i18n Owner | Land en + zh-Hans message catalogues in `chanora_flutter/lib/i18n/` at scaffolding time; verify Material 3 design tokens accommodate CJK text metrics. |
|
|
|
|
## 7. Non-promotion reminder
|
|
|
|
Per `proof-of-concept-plan.md` §4: **a PoC is not product code unless
|
|
explicitly promoted.** Nothing under `poc/` should be imported by
|
|
the future `apps/chanora_flutter` or `crates/chanora_*` trees
|
|
without an explicit promotion record per spike.
|
|
|
|
## 8. Change History
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.1.0 | 2026-05-14 | Initial PoC results summary. Records the outcome of the first PoC batch (5 PASS, 1 PARTIAL), the toolchain versions exercised, the owner-confirmed decisions, audit-report coverage, and the open risks. |
|
|
| 0.2.0 | 2026-05-14 | Audio PoC promoted from PARTIAL to PASS after the Android spike verified the mobile half on a physical Motorola Moto G Stylus 5G running Android 14 arm64-v8a. All six PoC plan entries now PASS. RISK-PoC-001 narrowed from "mobile audio" to "iOS audio only". Android toolchain (NDK r26.3, cargo-ndk, AGP/Gradle/Kotlin, jni/ndk-context/android_logger) added to the toolchain table. |
|
|
| 0.3.0 | 2026-05-14 | Recorded the owner-confirmation pass on the 17 remaining Proposed decisions (register at v0.9.5). RISK-PoC-004 closed. Added RISK-PoC-006 (Android `minSdk` 24 → 28) and RISK-PoC-007 (MVP language expanded to English + Chinese Simplified) for the two decisions that diverged from the original recommendations. DEC-020 license remains the sole open release-gating decision. |
|
|
| 0.4.0 | 2026-05-14 | DEC-020 license closed as Apache-2.0 OR MIT dual-license (register v0.9.6). RISK-PoC-003 closed. No remaining open decisions; the only release-gating activity outstanding is the DEC-012 legal review *work*, which is sign-off rather than an architectural choice. |
|
|
| 0.5.0 | 2026-05-14 | Internal Alpha build reached. `poc/tsclientlib-connect-spike` promoted into `crates/chanora_protocol`; `core/chanora_core::ChanoraSession` wires the typed protocol API; `crates/chanora_bridge` exposes the FRB 2.12.0 boundary; `apps/chanora_flutter` runs the connect → snapshot → disconnect cycle end-to-end against `cn.teamspeak.app`. Verified by `apps/chanora_flutter/test/alpha_e2e_test.dart` + `core/chanora_core/tests/alpha_smoke.rs`. Tag: `v0.1.0-alpha.1` (commit 3bb038c). RISK-PoC-005 partially closed. |
|
|
| 0.6.0 | 2026-05-14 | **Internal Beta build reached** (same day as Alpha). `poc/audio-capture-playback-spike` promoted into `crates/chanora_audio`: cpal capture/playback + `audiopus` Opus encode + `tsclientlib::audio::AudioHandler` decode/jitter/mix. `chanora_protocol` extended with voice-out mpsc and voice-in mpsc; `chanora_core` adds `start_audio` / `set_ptt` / `audio_stats`. `chanora_bridge` adds matching DTOs (`BridgeAudioStats`). Flutter UI gains "Start audio" + hold-to-talk PTT + live frame counters. Verified end-to-end on `cn.teamspeak.app` by `apps/chanora_flutter/test/beta_e2e_test.dart`. Tag: `v0.2.0-beta.1`. Capture runs gracefully in playback-only mode on hosts with no usable microphone. |
|