docs(p0): compact MVP spec for Android Oboe focus

This commit is contained in:
Edison Jwa
2026-05-20 14:52:33 +09:00
parent 8c253f1d4d
commit 7d6d56e330
63 changed files with 8000 additions and 46507 deletions
+31
View File
@@ -0,0 +1,31 @@
# AI Agent Router — Chanora Minimal Spec
Purpose: keep AI context small. Do not load the old full bundle unless explicitly asked for audit reconstruction.
## Load Order
1. Always load this file first.
2. Load exactly one phase file: `P0_MVP_AGENT_SPEC.md`, `P1_BETA_AGENT_SPEC.md`, or `P2_PRODUCTION_AGENT_SPEC.md`.
3. Load `SOP_AGENT_OPERATIONS.md` only when changing architecture, release, security, privacy, diagnostics, build, or test gates.
4. Use `phase_index.json` for machine lookup. Do not paste full source docs into context.
## Phase Meaning
- P0 = MVP buildable product. Default implementation target.
- P1 = beta hardening and extended quality. Do not implement unless asked.
- P2 = production/public-release readiness. Do not implement until P0 and P1 gates pass.
- SOP = standing operating rules for agents, reviews, testing, release, traceability, and refusal conditions.
## Non-Negotiable Product Contract
- Product: Chanora, a cross-platform TeamSpeak 3-compatible client application.
- Stack: Flutter UI + Rust core + typed Flutter/Rust bridge + `tsclientlib` adapter.
- Platforms: Windows, macOS, Linux, Android, iOS.
- MVP server model: external TS3-compatible servers only; no Chanora-operated backend.
- MVP connection model: one active server connection per client instance.
- Privacy: no telemetry, no automatic diagnostic upload, no crash reporting unless later approved.
- Diagnostics: local, user-initiated export only.
- Storage: secrets in platform secure storage; non-secrets in bundled SQLite via `rusqlite`.
- Localization: English + Chinese Simplified at MVP; preserve server content verbatim.
- Design: Material 3 + Chanora Design System.
- License: Apache-2.0 OR MIT.
## Hard Stop Rules
Stop and ask for explicit approval before adding: telemetry, crash reporting, automatic upload, multiple active server connections, a Chanora backend, unsupported platform targets, unapproved hotkey/audio packages, or legal/trademark wording changes.
+136
View File
@@ -0,0 +1,136 @@
# P0 MVP Agent Spec — Build This First
## Objective
Create the smallest complete Chanora MVP that can connect to one TS3-compatible server, render channel/user state, support basic voice workflow, persist local non-secret settings, protect secrets, and pass platform P0 acceptance gates.
## Scope
Implement only P0/MVP. Treat P1/P2 items as backlog unless the user explicitly requests them.
## Accepted MVP Decisions
- DEC-001: Release type = Internal Alpha first, then External Beta, then MVP Public / Store Release
- DEC-002: MVP platform scope = MVP target remains Windows, macOS, Linux, Android, and iOS; first release may be staged by channel/platform
- DEC-003: Minimum iOS version = iOS 13 minimum for Flutter support baseline; test latest iOS release separately
- DEC-004: Minimum Android version = **Android API 28 (Android 9.0)** minimum, raised from the original recommendation of API 24 by explicit owner ruling on 2026-05-14. Rationale: simplifies the audio path (AAudio is unconditionally available from API 26+ and stable from API 28), narrows the TLS / privacy / scoped-storage compatibility surface, and matches typical 2026 Android baselines. The original cpal-on-Oboe Android spike was built with `minSdk = 24` and `cargo-ndk -P 26`; product code in `apps/chanora_flutter` uses `minSdk = 28` and the Android product audio backend is now direct Oboe, so Chanora no longer carries the API 24/25 OpenSL ES fallback branch.
- DEC-005: Android target SDK = Target the Google Play-required API level on the upload date; current release gate uses API 35+ unless newer Google policy applies
- DEC-006: Multiple server connections in MVP = Not in MVP; support one active server connection per client instance
- DEC-007: AEC default state = Enabled by default on platforms/audio backends where supported and stable
- DEC-008: AGC default state = Enabled by default, with user setting to disable
- DEC-009: Noise suppression default state = Enabled by default, with user setting to disable
- DEC-010: High-pass filter default state = Enabled by default
- DEC-011: Audio processing implementation path = Use platform-native audio processing first where available; use Rust/WebRTC-style processing as controlled fallback or later architecture option
- DEC-011.1: Audio crate choice = `cpal` for desktop (empirically verified on Linux/PipeWire by `poc/audio-capture-playback-spike` on 2026-05-13) and direct `oboe-rs` for Android product code. The earlier cpal-on-Oboe spike remains evidence that Rust audio reaches Oboe/AAudio on a Motorola Moto G Stylus 5G (2023) running Android 14 arm64-v8a, but product code chooses direct Oboe because P0 Android needs explicit `VoiceCommunication` input preset, `VoiceCommunication`/`Speech` output attributes, low-latency/exclusive stream requests with shared fallback, audio-session ids for hardware AEC/NS/AGC binding, and diagnostics of requested/achieved stream values. iOS crate TBD pending an iOS spike that requires macOS + Xcode hardware
- DEC-012: Official SDK / trademark / licensing review = Public/store release is blocked until legal confirms TeamSpeak non-affiliation wording, trademark usage, OSS licenses, and `tsclientlib` license posture
- DEC-013: Local database choice = Use SQLite or equivalent embedded local database for non-secret local state; secrets remain in platform secure storage
- DEC-013.1: SQLite crate = `rusqlite` with the `bundled` feature (SQLite statically linked into the binary; no system libsqlite3 dependency); verified by `poc/sqlite-storage-spike` on 2026-05-13
- DEC-013.2: Linux secure-storage backend policy = Prefer Secret Service (libsecret / gnome-keyring / kwallet / KeePassXC) on Linux; if the default collection is locked or D-Bus is unavailable, fall back to kernel keyutils with a clear user notice. Both backends are "equivalent" per SysRS-053 / SysRS-162; verified by `poc/secure-storage-spike` on 2026-05-13
- DEC-014: Bridge choice = Use a stable typed Flutter/Rust bridge with generated or schema-controlled DTOs; **`flutter_rust_bridge` 2.x pinned** (empirically verified at 2.12.0 by `poc/flutter_rust_bridge_hello` on 2026-05-13)
- DEC-015: Product language for MVP = **English + Chinese (Simplified) for MVP**, raised from the original recommendation of English-only by explicit owner ruling on 2026-05-14. Rationale: the demonstrated test-server population (verified live against `cn.teamspeak.app`) and broader TS3 audience include substantial Chinese-speaking users; shipping zh-Hans alongside en at MVP avoids a launch-window UX gap. Architecture remains i18n-ready so additional languages can be added later mechanically. Server-provided content is preserved verbatim and never translated (ADR-008 UTF-8 boundary, DEC-015 server-content rule retained).
- DEC-016: Diagnostics upload policy = No automatic upload for MVP; user-initiated local diagnostic export only
- DEC-017: Crash reporting = Disabled for MVP unless explicit opt-in provider and privacy policy are approved
- DEC-018: Public product name = Chanora
- DEC-021: Apple App Store submission SDK = Use Xcode 26 or later and the iOS 26 / iPadOS 26 SDK or later for App Store submission on or after 2026-04-28, unless Apple publishes a newer applicable requirement before upload
- DEC-020: License model = **Dual-licensed under Apache-2.0 OR MIT (recipient's choice)**, the standard Rust-ecosystem permissive license model. Accepted on 2026-05-14. Compatible with every direct dependency in the PoC tree (`tsclientlib` MIT-OR-Apache-2.0, `flutter_rust_bridge` MIT, `cpal` Apache-2.0, `rusqlite` MIT, `keyring` MIT-OR-Apache-2.0, etc.) and with the Flutter framework's BSD-3-Clause. The license texts ship as `LICENSE-APACHE` and `LICENSE-MIT` at the repository root; an aggregator `LICENSE` points to both. `NOTICE` enumerates current direct-dependency attributions. The full OSS legal review (transitive deps, license obligations, OSS notices) remains under DEC-012 and is still required before public release.
- DEC-022: Canonical implementation directory layout = Accept the README's sketch as canonical: `apps/chanora_flutter/`, `core/chanora_core/`, `crates/chanora_protocol/`, `crates/chanora_audio/`, `crates/chanora_state/`, `crates/chanora_storage/`, `crates/chanora_diagnostics/`, `crates/chanora_bridge/`. Matches SAD §7.2 module decomposition
- DEC-023: Windows desktop Global PTT priority = **P0 in MVP.** Resolves PTT-OPEN-001 from `gen2/chanora-desktop-ptt-review-summary-v0.9.2.md`. The Windows backend ladder (Raw Input → low-level keyboard hook → Focused fallback) is mandatory for the first public release; release notes shall not claim Global PTT support on Windows until live measurement confirms a Global level from a non-fallback rung.
- DEC-024: macOS desktop Global PTT priority = **P0 in MVP, with explicit permission UX flow.** Resolves PTT-OPEN-002. The macOS backend shall request the Input Monitoring / Accessibility permission, accept user denial gracefully (continue at `L0Focused` without functional regression), and upgrade to Global asynchronously when the user grants the permission.
- DEC-025: Officially-tested Linux environment for first public release = **GNOME on Wayland (only).** Resolves PTT-OPEN-003. The Linux backend shall use the freedesktop `org.freedesktop.portal.GlobalShortcuts` interface on GNOME-on-Wayland and fall back to Focused PTT on every other Linux environment (X11, sway, KDE, untested compositors). Release notes shall not claim Global PTT support outside the tested compositor.
- DEC-026: Mouse side-button support in first desktop PTT release = **Supported on Windows and macOS; Linux follows whatever the GlobalShortcuts portal exposes.** Resolves PTT-OPEN-004. The Raw Input backend (Windows) and the Event Tap backend (macOS) shall accept Mouse4 / Mouse5 bindings; the Linux portal binding accepts whatever the session exposes and the release notes shall not over-claim.
- DEC-027: PTT diagnostics privacy posture = **Capability and availability state only — no raw key codes ever leave the device.** Resolves PTT-OPEN-005. The diagnostic export shall name only `PttCapabilityLevel`, `backend_id`, `bound_input_class`, and `fallback_exercised`; the user's actual key value (scan code, virtual key, keysym) shall never be logged, persisted, or exported. `PttSanitizer` enforces this at write time.
- DEC-028: Missed-key-up watchdog requirement = **P0.** Resolves PTT-OPEN-006. The audio engine shall include a missed-key-up watchdog that clears `transmit_active` after a configured ceiling (default 30 s) when no key-up event arrives. The watchdog is a P0 release-gate item rather than an implementation-level concern because the failure mode (stuck transmission after the user has released the binding) is user-visible and reputation-relevant.
- DEC-029: Flutter global-hotkey packages rejected for PTT = **Use the native Rust `DesktopPttBackend` trait + per-OS implementations (already specified in SDD-083 / SDD-084 / SDD-085); do not adopt `hotkey_manager`, `super_hot_key`, or any equivalent pub.dev package for PTT.** Rationale: those packages wrap the OS `RegisterHotKey` / `RegisterEventHotKey` semantics — they consume the key (suppressing it from other applications), they do not deliver a key-up event, and they do not support mouse side-buttons. PTT requires the opposite primitive (observe, do not consume, deliver both up and down).
- DEC-030: Voice activity detection deferred to P1 = **`TransmitMode::VoiceActivity` ships as a reserved enum variant with no v1 implementation.** The settings UI shows it as a disabled "coming soon" option. The actual implementation choice is deferred to a future baseline. Rationale: three viable backends were compared (RMS energy threshold — trivial but quality-poor; WebRTC VAD via the `webrtc-vad` crate — frozen-but-stable C++ BSD-3 dep, ~200 KB binary, industry baseline; Silero VAD via ONNX Runtime — best quality but ~816 MB binary uplift per platform plus an ONNX-runtime dependency surface). The v1 dependency-surface budget does not have room for the trade-off review required to pick correctly. Choosing too early risks either user-visible quality regression (RMS) or a forced ONNX adoption (Silero) before there is a comparable need for ML inference elsewhere (noise suppression, AEC).
- DEC-001: Product Owner = Release type sequence
- DEC-002: Product Owner / Engineering = MVP platform strategy
- DEC-003: Product Owner / iOS Owner = Minimum iOS version
- DEC-004: Product Owner / Android Owner = Minimum Android version
- DEC-005: Android Owner / Release Manager = Android target SDK
- DEC-006: Product Owner / Software Architect = Multiple server connections in MVP
- DEC-007: Audio Owner / Product Owner = AEC default
- DEC-008: Audio Owner / Product Owner = AGC default
- DEC-009: Audio Owner / Product Owner = Noise suppression default
- DEC-010: Audio Owner = High-pass filter default
- DEC-011: Software Architect / Audio Owner = Audio processing path
- DEC-011.1: Software Architect / Audio Owner = Audio crate (desktop / mobile)
- DEC-012: Legal / Compliance = SDK/trademark/licensing review
- DEC-013: Software Architect / Storage Owner = Local database
- DEC-013.1: Software Architect / Storage Owner = SQLite crate
- DEC-013.2: Software Architect / Storage Owner / Security Reviewer = Linux secure-storage backend policy
- DEC-014: Software Architect = Bridge choice
- DEC-015: Product Owner = Product language for MVP
- DEC-016: Product Owner / Legal / Security = Diagnostics upload policy
- DEC-017: Product Owner / Legal / Security = Crash reporting
- DEC-018: Product Owner = Public product name
- DEC-020: Product Owner / Legal = License model
- DEC-021: iOS Owner / Release Manager = Apple App Store SDK gate
- DEC-022: Software Architect = Canonical implementation directory layout
- DEC-023: Product Owner / Windows Platform Owner = Windows desktop Global PTT priority
- DEC-024: Product Owner / macOS Platform Owner = macOS desktop Global PTT priority
- DEC-025: Product Owner / Linux Platform Owner = Officially-tested Linux environment
- DEC-026: Product Owner / UX Owner = Mouse side-button support
- DEC-027: Security / Privacy Reviewer = PTT diagnostics privacy posture
- DEC-028: Audio Owner / Software Architect = Missed-key-up watchdog
- DEC-029: Software Architect / Audio Owner = Flutter global-hotkey packages rejected for PTT
- DEC-030: Audio Owner / Product Owner = Voice activity detection deferred to P1
## Required P0 Capability Groups
1. App shell: routing, startup, theme, localization, adaptive layout, platform-service initialization.
2. UI/design: Material 3, Chanora design tokens, responsive desktop/tablet/mobile layouts, accessible controls, keyboard focus, safe areas/insets.
3. Protocol: TS3-compatible adapter through `tsclientlib`; no direct UI coupling to protocol internals.
4. Connection: one active server connection; visible connecting/connected/reconnecting/disconnected/error states.
5. Channel/user tree: preserve Unicode server content; do not translate server names/messages.
6. Voice basics: capture/playback path, push-to-talk where platform-supported, mute/deafen indicators, native processing defaults.
7. Audio defaults: AEC on where stable, AGC on with user toggle, noise suppression on with user toggle, high-pass filter on.
8. Storage: SQLite for non-secret state; platform secure storage for identities/tokens/password-equivalent secrets.
9. Diagnostics: local export only; redact secrets; machine fields remain language-neutral.
10. Builds: reproducible platform builds for Windows, macOS, Linux, Android, and iOS with staged release allowed.
11. Verification: unit, widget, integration, platform acceptance, and release go/no-go evidence.
## P0 Architecture Boundaries
- Flutter owns UI, navigation, Material 3 theming, accessibility, and adaptive presentation.
- Rust core owns domain state, protocol/session orchestration, storage, diagnostics, and platform-abstracted services.
- Bridge owns typed DTOs/events/errors only. Do not leak Rust internals into Flutter or Flutter objects into Rust core.
- Platform adapters own OS-specific audio, hotkey, secure storage, build, and permission behavior.
## P0 Definition of Done
- User can launch app, enter/connect to a TS3-compatible server, see server/channel/user state, and disconnect cleanly.
- App supports the selected P0 voice path without telemetry or automatic upload.
- Secrets are never stored in SQLite/plaintext.
- English and zh-Hans product strings are available; server-originated Unicode remains unchanged.
- All diagnostic exports are local/user-triggered and redacted.
- Platform P0 acceptance docs pass or contain explicit blocker records.
- Every code change cites at least one requirement or decision ID.
## P0 Requirement Index
- Count: 500
- ID groups: SAD-001..SAD-096 (71 ids); SDD-001..SDD-121 (98 ids); SRS-001..SRS-219 (178 ids); SysDes-001..SysDes-158 (153 ids)
## P0 Source Weighting
- `requirements/srs.md`: 178
- `architecture/sysdes.md`: 153
- `architecture/sdd.md`: 98
- `architecture/sad.md`: 71
## P0 Allocation Hotspots
- Unallocated: 98
- Flutter UI: 68
- Rust Core: 52
- Verification: 43
- Audio Subsystem: 42
- Software: Audio Subsystem: 39
- System Engineering: 33
- Protocol Adapter: 31
- Diagnostics: 28
- State Sync: 24
- Design System: 22
- Bridge: 21
- Storage: 21
- Software: Diagnostics: 21
- Platform: 20
- Software: Protocol Adapter: 20
- Platform Adapters: 19
- Software: Rust Core: 19
- Audio: 18
- Operations: 17
## Agent Compression Rule
Do not paste all P0 requirement statements into prompt context. Use this file as the execution contract and `phase_index.json` only when an exact ID/source lookup is required.
+58
View File
@@ -0,0 +1,58 @@
# P1 Beta Agent Spec — Harden After MVP
## Objective
Improve reliability, beta readiness, accessibility coverage, diagnostics usefulness, and platform quality after P0 works end-to-end.
## Entry Gate
Do not start P1 until P0 MVP acceptance is passing or blockers are formally recorded.
## P1 Scope
- Harden reconnection/error handling beyond MVP happy path.
- Expand integration/system tests and beta acceptance evidence.
- Improve accessibility, keyboard workflows, adaptive layout edge cases, and localization completeness.
- Improve diagnostics quality without changing the privacy model.
- Prepare external beta release notes, support workflows, and known-issue tracking.
## P1 Non-Goals
- No telemetry by default.
- No automatic diagnostic upload.
- No multiple active server connections unless a new accepted decision overrides DEC-006.
- No production/store launch gates unless explicitly promoted to P2.
## P1 Definition of Done
- P0 regressions remain passing.
- Beta blockers are triaged and traceable.
- Diagnostic exports are useful for support while still redacted and local.
- Platform-specific beta risks have owner/status records.
## P1 Requirement Index
- Count: 81
- ID groups: SAD-035..SAD-066 (18 ids); SDD-051..SDD-109 (20 ids); SRS-028..SRS-191 (38 ids); SysDes-122, SysDes-123, SysDes-124, SysDes-125, SysDes-138
## P1 Source Weighting
- `requirements/srs.md`: 38
- `architecture/sdd.md`: 20
- `architecture/sad.md`: 18
- `architecture/sysdes.md`: 5
## P1 Allocation Hotspots
- Unallocated: 20
- Diagnostics: 14
- Audio Subsystem: 13
- Flutter UI: 9
- Platform Adapters: 9
- Deployment Scripts: 7
- Software Architecture: 6
- Application Container: 6
- Storage: 5
- Protocol Adapter: 5
- Localization Service: 5
- Bridge: 4
- Flutter App Shell: 4
- Software Design: 4
- Platform Adapter: 4
- Platform Audio Adapter: 3
- State Sync: 3
- Rust Core: 3
- Verification Support: 2
- Flutter State: 2
+34
View File
@@ -0,0 +1,34 @@
# P2 Production Agent Spec — Public Release Readiness
## Objective
Prepare Chanora for public/store release only after P0 implementation and P1 beta hardening are complete.
## Entry Gate
Do not begin P2 until P0 and P1 evidence is available. Public release is blocked by legal/trademark/OSS review and store-policy readiness.
## P2 Scope
- Final release go/no-go records.
- Store metadata and platform upload compliance.
- Legal review: TeamSpeak non-affiliation wording, trademark usage, OSS license posture, `tsclientlib` license posture.
- Final privacy policy confirmation against actual app behavior.
- Production build signing, artifact policy, and staged rollout policy.
## P2 Non-Goals
- Do not add telemetry/crash reporting to satisfy production readiness unless privacy/legal/product explicitly approve it.
- Do not expand server/backend scope.
- Do not add new features that destabilize P0/P1 acceptance.
## P2 Definition of Done
- Release manager has signed go/no-go evidence.
- Legal/compliance blockers are closed.
- Platform upload SDK/target requirements are current on upload date.
- Release artifacts are reproducible, signed where required, and mapped to a version/tag.
## P2 Requirement Index
- Count: 11
- ID groups: SAD-045, SAD-046, SAD-047, SAD-048, SAD-049, SAD-050, SAD-055; SDD-063; SRS-117, SRS-154, SRS-175
## P2 Source Weighting
- `architecture/sad.md`: 7
- `requirements/srs.md`: 3
- `architecture/sdd.md`: 1
+11
View File
@@ -0,0 +1,11 @@
# Chanora AI-Agent Minimal Phased Requirements
This bundle intentionally removes the large rewritten archive and trace CSV. It is designed for AI agents with limited context.
Recommended loading:
1. `00_AGENT_ROUTER.md`
2. One phase file: P0, P1, or P2
3. `SOP_AGENT_OPERATIONS.md` only when process/release/security rules matter
4. `phase_index.json` only for exact ID lookup
Do not load the old full bundle unless performing audit reconstruction.
+46
View File
@@ -0,0 +1,46 @@
# SOP Agent Operations — Standing Rules
## Core Agent Rules
1. Default to P0. Do not implement P1/P2 unless explicitly requested.
2. Preserve traceability: commit messages, PR descriptions, tests, and review notes must cite decision/requirement IDs.
3. Make the smallest compliant change. Avoid architecture invention.
4. If requirements conflict, precedence is: Product Decision Register > SysRS > SysDes > SRS > SAD > SDD > Verification/Release/Security docs.
5. If a task requires exact historical detail, inspect `phase_index.json`; do not load the obsolete full bundle.
## Required Review Gates
- Architecture boundary review for Flutter/Rust/bridge/protocol/storage/audio changes.
- Privacy review for diagnostics, logging, crash handling, analytics, upload, identifiers, or support artifacts.
- Security review for secure storage, redaction, secrets, dependencies, and supply chain.
- Release review for platform build, signing, SDK, store, and artifact policy.
- Localization review for product strings and server-content preservation.
## Testing SOP
- Unit tests: Rust core, DTO transforms, storage, redaction, decision logic.
- Widget tests: Material 3 components, state tokens, localization, accessibility semantics, adaptive layouts.
- Integration tests: bridge events/errors, protocol adapter state, diagnostics export, storage migration.
- Platform tests: secure storage, audio capture/playback, permissions, hotkeys/PTT, packaging.
- Acceptance tests: use platform P0 acceptance docs before any release promotion.
## Build SOP
- Keep repo layout canonical: `apps/chanora_flutter/`, `core/chanora_core/`, `crates/chanora_*`.
- Pin `flutter_rust_bridge` 2.x.
- Use bundled `rusqlite` for embedded SQLite.
- Android minSdk = 28; target API must match current Google Play requirement on upload date.
- iOS minimum = 13; App Store upload SDK gate must be checked on actual upload date.
## Privacy/Security SOP
- No telemetry in MVP.
- No crash reporting unless approved.
- No automatic diagnostic upload.
- Diagnostics are local export only and must redact secrets.
- Product-owned strings may be localized; server-originated content must be preserved verbatim.
- Secrets never enter logs, diagnostics, SQLite, screenshots, or crash-like artifacts.
## Release SOP
- Release sequence: Internal Alpha -> External Beta -> MVP Public.
- Public/store release requires legal/trademark/OSS license confirmation.
- Staged platform release is allowed when documented.
- Every release must include version, commit/tag, artifact list, known issues, test evidence, and go/no-go result.
## Agent Refusal / Escalation Conditions
Stop implementation and ask for owner approval when asked to add or change: telemetry, crash reporting, diagnostic uploads, backend service, multi-server active sessions, platform scope, license, trademark/non-affiliation text, secret-storage policy, or target SDK/minimum OS baseline.
@@ -1,213 +0,0 @@
# Desktop Push-to-Talk Architecture
| Field | Value |
|---|---|
| Document type | Architecture |
| Version | 0.9.3 |
| Status | Baseline Candidate |
| Language | English |
| Product | Chanora |
| Date | 2026-05-15 |
Owner-resolved review questions from `gen2/chanora-desktop-ptt-review-summary-v0.9.2.md` are recorded as DEC-023 through DEC-028 in `docs/governance/product-decision-register.md`.
---
## 1. Purpose
Desktop Push-to-Talk (PTT) is the operation by which a user holds a bound keyboard key or mouse button to enable voice transmission and releases it to disable transmission. This document fixes the architecture so the product can describe, implement, verify, and release desktop PTT honestly — every capability claim made to the user is auditable against a live runtime measurement.
The previous architecture treated PTT as a single global behaviour. That over-promised on platforms where the operating system, the user-granted permission set, the display server, or the compositor does not permit unconditional global key capture. This document replaces that with a capability-based model.
## 2. Architectural Decisions
| ID | Decision | Source |
|---|---|---|
| DEC-023 | Windows Global PTT is **P0 / MVP**. | Owner ruling 2026-05-15 |
| DEC-024 | macOS Global PTT is **P0 / MVP** with explicit permission UX flow. | Owner ruling 2026-05-15 |
| DEC-025 | The officially-tested Linux environment for the first public release is **GNOME on Wayland** (only). | Owner ruling 2026-05-15 |
| DEC-026 | Mouse side buttons are **supported** in the first desktop PTT release on Windows and macOS; Linux support follows whatever the GlobalShortcuts portal exposes. | Owner ruling 2026-05-15 |
| DEC-027 | The diagnostic export carries **capability and availability state only** — no raw key codes, scan codes, or virtual-key values ever leave the device. | Owner ruling 2026-05-15 |
| DEC-028 | The **missed-key-up watchdog is P0**: the audio engine shall self-release `transmit_active` if the OS suppresses a key-up event. | Owner ruling 2026-05-15 |
## 3. Capability Ladder
| Level | Name | Meaning |
|---|---|---|
| `L0Focused` | Focused PTT | PTT works only while the Chanora window has input focus. Mandatory on every desktop platform per SysRS-296. |
| `L1GlobalShortcut` | Global shortcut activation | The OS recognises a global accelerator and notifies the application, but hold-to-talk semantics may be approximated rather than guaranteed. |
| `L2GlobalHoldToTalk` | Global hold-to-talk | Press and release events are delivered while the application is not focused. The common Windows / macOS / GNOME-Wayland-portal MVP target. |
| `L3GlobalWithMouseButtons` | Global hold-to-talk plus mouse buttons | Includes mouse side buttons (Mouse4 / Mouse5). |
| `L4DeviceAware` | Device-aware PTT | Backend can distinguish specific input devices. **Reserved.** No MVP implementation produces `L4DeviceAware`. |
The reported capability shall match runtime behaviour. A backend that *could* deliver `L2GlobalHoldToTalk` but lacks the user-granted permission shall report `L0Focused` until permission is granted.
## 4. Component Allocation
```
+------------------------------------+
| Flutter Voice UI |
| PTT binding-capture sheet |
| VoiceBar PttCapabilityBadge |
+---------------+--------------------+
|
| set_binding(...)
| events_stream() -> BridgeEvent::PttCapability
v
+---------------+--------------------+
| chanora_bridge |
| typed DTOs, no key data crosses |
+---------------+--------------------+
|
v
+------------------------------------+
| chanora_core |
| PttController |
| owns Box<dyn DesktopPttBackend>|
| owns Arc<AudioTransmitGate> |
| publishes PttCapabilityLevel |
| MissedKeyUpWatchdog (tokio task) |
+---------------+--------------------+
|
v
+------------------------------------+
| chanora_audio |
| DesktopPttBackend trait |
| WindowsRawInputBackend |
| WindowsHookBackend |
| MacOSEventTapBackend |
| LinuxGnomeWaylandBackend |
| FocusedPttBackend |
| AudioTransmitGate |
| capture_active / transmit_active |
+------------------------------------+
|
v
+------------------------------------+
| chanora_diagnostics |
| RedactingLogLayer |
| PttSanitizer (drops banned keys) |
+------------------------------------+
```
The audio engine reads `transmit_active` once per outbound Opus frame. No code path other than `AudioTransmitGate::set` flips the value.
## 5. Per-Platform Strategy
### 5.1 Windows
Three-level ladder evaluated once at audio-engine start:
1. **`WindowsRawInputBackend`** — preferred. Uses `RegisterRawInputDevices` with `RIDEV_INPUTSINK` to receive keyboard and mouse events even when Chanora is not focused. Runs a message-only window on its own OS thread so the WndProc is non-blocking. Reports `L2GlobalHoldToTalk` (keyboard) or `L3GlobalWithMouseButtons` (when a mouse side button is bound).
2. **`WindowsHookBackend`** — fallback. Installs `WH_KEYBOARD_LL` and `WH_MOUSE_LL` hooks on its own thread. Used when Raw Input registration fails (some constrained environments). Reports `L2GlobalHoldToTalk` / `L3GlobalWithMouseButtons`.
3. **`FocusedPttBackend`** — final fallback. Reports `L0Focused`.
The chosen rung is fixed for the lifetime of the audio engine; restart of the engine re-evaluates the ladder.
### 5.2 macOS
Two-level ladder with explicit permission gating:
1. **`MacOSEventTapBackend`** — preferred when Input Monitoring (or Accessibility, depending on macOS version) permission is `Granted`. Creates a `CGEventTap` on the main run loop, filtered to keyboard and mouse-button events. Reports `L2GlobalHoldToTalk` / `L3GlobalWithMouseButtons`.
2. **`FocusedPttBackend`** — fallback when permission is `Denied`, `Undetermined`, or revoked at runtime. Reports `L0Focused`.
The audio engine starts immediately on user request; the permission state is queried in parallel and the capability level is upgraded asynchronously through `BridgeEvent::PttCapability` if the user grants the permission. This avoids blocking voice functionality on a permission prompt.
### 5.3 Linux
Two-level ladder restricted to the officially-tested environment per DEC-025.
**Selection** at `try_select()` time:
* Reads `XDG_SESSION_TYPE` (must equal `wayland`) and `XDG_CURRENT_DESKTOP` (must contain `gnome` or `gnome-flashback`).
* Probes `org.freedesktop.portal.GlobalShortcuts` via a blocking `version` property read.
If either check fails the factory returns `None` and the caller falls back to `FocusedPttBackend` at `L0Focused`.
**Live session lifecycle (Q5b — lazy, single backend instance):**
1. `start(gate, binding)` spawns a worker `tokio::spawn` task. The worker owns its own async `zbus::Connection` and a `GlobalShortcutsProxy`.
2. The worker calls `CreateSession` with fresh `handle_token` / `session_handle_token` values (random `u32` per process). The portal returns a `Request` object path; the worker subscribes to the `Response` signal on that path and awaits the session handle from the `results` dict.
3. The worker then calls `BindShortcuts(session_handle, [("chanora-ptt", { description: "Chanora push-to-talk" })], "", {})`. The portal opens its own system-managed dialog asking the user to choose a key — Chanora does not read raw key events. The audio engine continues at `L0Focused` while the dialog is open (the descriptor watch publishes the transition once the portal returns).
4. Once `BindShortcuts` resolves:
* On `response_code == 0`: classify the `trigger_description` substring heuristically (`mouse``mouse-side-button`; otherwise `keyboard`), publish `descriptor() = L2GlobalHoldToTalk` (or `L3GlobalWithMouseButtons` for the mouse case) through the watch sender. The trigger_description string itself is never logged. **Mouse-side-button support on Linux is portal-dependent (SRS-200 / DEC-026):** the backend never offers a fixed "Mouse4 / Mouse5" capture path; the portal's own dialog decides which inputs it accepts in the current session, and Chanora honours whatever it returns. The classifier degrades to `keyboard` whenever the portal's description does not contain `mouse`.
* On `response_code == 1` (user cancelled) or `> 1` (other failure): publish `descriptor() = L0Focused` through the watch sender. The user can retry via the UI "Configure" button.
5. The worker then enters its long-lived loop, multiplexing on the command channel (`Rebind` / `Stop`) and the portal's `Activated` / `Deactivated` signals. Signal payloads scoped to a different session handle or shortcut id are ignored. Matching `Activated` calls `gate.set(true)`; matching `Deactivated` calls `gate.set(false)`.
6. `rebind(binding)` sends a command to the worker which re-runs `BindShortcuts` on the same session. The portal opens its dialog again; the user can pick a new key.
7. `stop()` (or backend Drop) signals the worker, which calls `Request::Close` on the session handle, calls `gate.set(false)`, and exits.
**UX implication on Linux:** the in-app `_PttBindingCaptureDialog` (used by Windows and macOS in MVP) is **skipped** when the active backend is `gnome-wayland-portal`. The Flutter "Configure" button calls `setPttBinding` directly with a sentinel `platform_key = "portal"` and shows a SnackBar telling the user their desktop will open its own shortcut dialog. This matches the portal's design (DEC-027 / Q3a).
**Per DEC-025 the application does not claim Global PTT support on an untested Linux environment.** The UI capability badge explicitly notes "Focused PTT — untested compositor for Global PTT" when the user runs Chanora outside GNOME-on-Wayland.
## 6. Privacy Rule
Per SysRS-302 and SRS-202:
- Raw key codes, scan codes, virtual-key values, keysyms, and key-press timing sequences shall not be logged, persisted, or included in any user-initiated diagnostic export.
- The `PttSanitizer` log-sink decorator enforces this at write time by inspecting field names and dropping records whose field names match a banned list (`key_code`, `scan_code`, `virtual_key`, `vk`, `keysym`, `keysym_string`, `key_sequence`). The check is structural — it does not rely on a content scan.
- The diagnostic export shall name only the capability level (`PttCapabilityLevel::as_str()`), the backend identifier (a fixed `&'static str` per implementation), and the bound input class (`"keyboard"`, `"mouse-side-button"`).
## 7. Audio Gate Rule
Per SRS-201:
- `capture_active: AtomicBool` is set by the audio engine on input-stream lifecycle transitions (stream opened or closed) and by the platform input-permission state. The PTT subsystem does not write `capture_active`.
- `transmit_active: AtomicBool` lives inside `AudioTransmitGate`. The Opus encoder feed reads it once per outbound frame; the gate is the only mutator path.
- A muted self-input (per `set_input_muted`) forces `transmit_active` to false regardless of the PTT subsystem's wish; this preserves the existing self-mute semantics.
## 8. Missed-Key-Up Watchdog
Per SRS-203 / DEC-028:
- The audio engine spawns one `MissedKeyUpWatchdog` task per audio session.
- It subscribes to `AudioTransmitGate`'s `watch::Receiver<bool>` and notes the timestamp of each `false -> true` transition.
- On each `true -> false` transition it clears the timestamp.
- If a `true` lifetime exceeds the configured ceiling (default 30 s, owner-tunable through a future setting), the watchdog calls `AudioTransmitGate::set(false)` and emits a sanitised diagnostic line naming only the capability level and backend identifier.
## 9. Release Readiness
Per SysDes-148 and the release-readiness record:
- Every release artefact carries a per-platform capability-evidence row listing the detected `PttCapabilityLevel`, the active backend identifier, and whether the Focused fallback was exercised during verification.
- Release notes shall mirror that evidence and shall not over-claim Global PTT support.
## 10. Traceability
```
SysRS-296..302
-> SysDes-142..148
-> SRS-195..203
-> SAD-071..079
-> SDD-081..092
```
Verification coverage:
```
SDD-081..092 -> SWE4-UV-035..039
SAD-071..079 + SDD-081..092 -> SWE5-IV-015
SRS-195..203 -> SWE6-SV-017
SysDes-142..148 -> SYS4-SIV-016
```
## 11. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Initial baseline-candidate architecture for capability-based desktop Push-to-Talk. Codifies the owner rulings for PTT-OPEN-001 through PTT-OPEN-006 as DEC-023 through DEC-028. |
| 0.9.4 | 2026-05-15 | Promoted the Linux GNOME-Wayland backend from probe-only to the live `CreateSession` + `BindShortcuts` + `Activated` / `Deactivated` session flow. Owns an async tokio task with a dedicated `zbus::Connection`; publishes descriptor transitions through a `watch::Sender` consumed by `chanora_core::ChanoraSession::start_audio`. Adds the privacy-safe `trigger_description` classifier and the cancellation / failure path (downgrade to `L0Focused` + re-emit). Updates the Flutter UI to skip the in-app capture dialog on the portal backend (Q3a) and surface a SnackBar redirecting the user to the desktop's own dialog. |
## 8. v0.9.5 lifecycle and mode-picker addendum
This addendum captures the v1 audio + PTT lifecycle refactor recorded in SysRS-303..304, SysDes-149..151, SRS-204..207, SAD-081..083, and SDD-094..097. It does not change the desktop PTT backend design captured in §1–§7; it constrains how the backends are owned and how the rest of the audio path is exposed to the UI.
1. **No "Start audio" button anywhere.** The audio engine lifecycle is bound to voice-channel membership. Input and output streams open on the user's first voice-channel join of the session and close on the last voice-channel leave. The bridge surface drops `start_audio` / `stop_audio` and exposes `voice_join(channel_id) -> Result<(), VoiceError>` and `voice_leave() -> Result<(), VoiceError>`; `AudioEngine::ensure_running()` is invoked implicitly by `voice_join` and is idempotent. The Voice Bar renders from `BridgeEvent::VoiceState { in_channel, transmit_mode, mute, release_tail_ms }` and contains no manual-start affordance. Microphone permission is requested at app first launch rather than at first channel join; the output stream opens regardless of permission state, so listen-only is a first-class flow.
2. **Transmit modes for v1 are `Ptt` and `Continuous`; `VoiceActivity` is reserved but not implemented.** `TransmitMode` is a `#[repr(u8)]` enum mirrored across the bridge; the default on fresh install is `Ptt`; the setting is persisted per identity in the identity store. The settings page renders `VoiceActivity` as a disabled "coming soon" radio row until DEC-030 is resolved and a VAD backend is allocated.
3. **200 ms PTT release tail (configurable 0500 ms).** A `ReleaseTailTimer` tokio adapter sits between the `DesktopPttBackend` `transmit` signal and `AudioTransmitGate::set()`. Key-down forwards `true` immediately; key-up starts a sleep of `release_tail_ms` (default 200, matching the TeamSpeak / Mumble default) before the gate closes; a key-down within the sleep window cancels the pending close. The tail affects only `transmit_active`; `capture_active` is unaffected. The adapter is independent of the missed-key-up watchdog (SAD-079 / SDD-092).
4. **Hard-mute overrides everything.** The Voice Bar hard-mute toggle is applied by the `TransmitModeSelector` as a final clamp on `transmit_active` and takes precedence over the active transmit mode, the PTT key state, and every other internal signal. Hard-mute is in-session only and resets on the next voice-channel join.
5. **Cross-references.** **DEC-029** locks the v1 PTT capture path to the native Rust `DesktopPttBackend` trait + per-OS implementations (SDD-083 / SDD-084 / SDD-085) and rejects Flutter global-hotkey packages such as `hotkey_manager` and `super_hot_key`, which wrap the OS `RegisterHotKey` semantics, consume the key, drop key-up events, and skip mouse side-buttons. **DEC-030** defers Voice Activity Detection to P1 pending a backend trade-off review (RMS vs WebRTC VAD vs Silero VAD); the enum surface is preserved so a P1 increment is non-breaking.
| Version | Date | Description |
|---|---|---|
| 0.9.5 | 2026-05-15 | Added the v0.9.5 lifecycle and mode-picker addendum capturing the no-manual-start audio engine bound to voice-channel membership, the v1 transmit-mode set (`Ptt` default + `Continuous`, with `VoiceActivity` reserved per DEC-030), the 200 ms (0500 ms) PTT release tail, and the hard-mute override. Cross-references DEC-029 (native PTT backend locked) and DEC-030 (VAD deferred to P1). |
@@ -1,66 +0,0 @@
# Proof-of-Concept Plan
**Document type:** Architecture / Proof-of-Concept Plan
**Version:** 0.3.0
**Status:** Draft
**Language:** English
**Product:** Chanora
**Repo path:** `docs/architecture/proof-of-concept-plan.md`
---
## 1. Purpose
This document defines technical proof-of-concept work that should be completed before heavy product implementation.
## 2. Required PoCs
| PoC | Purpose | Exit criteria | Status |
|---|---|---|---|
| Flutter/Rust bridge hello | Prove command/result/event DTO boundary | Flutter can call Rust and receive event stream data | **PASS**`poc/flutter_rust_bridge_hello/VERIFICATION.md` (Linux desktop, 3/3 tests, 2026-05-13). Closes DEC-014. |
| `tsclientlib` connect spike | Prove protocol feasibility | Rust can connect to a compatible server/test double | **PASS**`poc/tsclientlib-connect-spike/VERIFICATION.md` (live against `cn.teamspeak.app`, 2026-05-13). |
| Audio capture/playback spike | Prove platform audio behavior | Capture/playback works on at least one desktop and one mobile target | **PASS** — desktop half: `poc/audio-capture-playback-spike/VERIFICATION.md` (Linux/PipeWire, 2026-05-13). Mobile half: `poc/audio-capture-playback-android-spike/VERIFICATION.md` (Android 14 arm64-v8a on a physical Motorola Moto G Stylus 5G, 2026-05-13). Closes DEC-011.1 for desktop + Android; iOS still Deferred. |
| Secure storage spike | Prove secret storage behavior | Secret write/read/delete works through platform secure storage | **PASS (Linux only)**`poc/secure-storage-spike/VERIFICATION.md` (6/6 audit tests, 2026-05-13). Closes DEC-013.2 (Linux backend policy). |
| SQLite storage spike | Prove local non-secret persistence | Schema, migration, and repository pattern are demonstrated | **PASS**`poc/sqlite-storage-spike/VERIFICATION.md` (11/11 tests, 2026-05-13). Closes DEC-013.1. |
| Diagnostics redaction spike | Prove redaction before export | Password and identity-secret samples are redacted | **PASS**`poc/diagnostics-redaction-spike/VERIFICATION.md` (REDACT-TC-001..010, 2026-05-13). |
## 3. PoC Directory
Recommended future location:
```text
poc/
flutter-rust-bridge-hello/
tsclientlib-connect-spike/
audio-capture-playback-spike/
secure-storage-spike/
sqlite-storage-spike/
diagnostics-redaction-spike/
```
## 4. Rule
A PoC is not product code unless explicitly promoted.
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial proof-of-concept plan. |
| 0.2.0 | 2026-05-14 | Recorded PoC outcomes: 5 PASS, 1 PARTIAL PASS (mobile half of audio still open). Added Status column. Spike directories live under `poc/`; see `poc/README.md` and `docs/governance/poc-results-summary.md`. |
| 0.3.0 | 2026-05-14 | Audio PoC promoted from PARTIAL PASS to PASS after `poc/audio-capture-playback-android-spike` verified the mobile half on a physical Android device. All six PoC plan entries are now PASS. iOS is explicitly deferred per DEC-011.1 and remains an open follow-up but is no longer a PoC-plan gap. |
## Desktop Push-to-Talk PoC Items (Baseline Candidate 0.9.3)
| PoC ID | Purpose | Owner | Acceptance |
|---|---|---|---|
| PoC-PTT-001 | Confirm `WindowsRawInputBackend` registers under `RIDEV_INPUTSINK` and forwards key + mouse-button events while Chanora is not focused. | Windows Platform Owner | Live press-release sequence toggles `transmit_active` on a Windows 10/11 reference host with another window focused. |
| PoC-PTT-002 | Confirm `MacOSEventTapBackend` works under granted Input Monitoring permission and degrades to `L0Focused` under denied permission. | macOS Platform Owner | Live measurement on a macOS reference host both before and after granting Input Monitoring; permission revocation degrades capability without crashing. |
| PoC-PTT-003 | Confirm `LinuxGnomeWaylandBackend` binds a shortcut via the GlobalShortcuts portal and receives `Activated` / `Deactivated` signals on a GNOME-on-Wayland reference host. | Linux Platform Owner | Portal dialog accepts a binding; press-release sequence toggles `transmit_active` outside the Chanora window. |
| PoC-PTT-004 | Confirm `PttSanitizer` drops records with banned key field names. | Diagnostics Owner | Unit test passes; manual diagnostic export inspection on a host with PTT bound to a real key shows zero raw key data. |
| PoC-PTT-005 | Confirm `MissedKeyUpWatchdog` clears `transmit_active` after the configured timeout. | Audio Owner | Unit test passes with tokio time paused; integration test on a Windows host where the OS suppresses the key-up event clears within the timeout. |
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop-PTT PoC items PoC-PTT-001..005 covering Windows Raw Input, macOS Event Tap (permission states), Linux GlobalShortcuts portal, diagnostics sanitizer, and missed-key-up watchdog. |
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,65 +0,0 @@
# CHANORA_CFG_Baseline_Approval_Record_v0.9.2.2.1
**Document type:** Configuration / Baseline Approval Record
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/baseline-approval-record.md` ---
## 1. Baseline
| Field | Value |
|---|---|
| Baseline name | Chanora MVP Baseline Candidate |
| Baseline version | 0.9.0 |
| Package | `CHANORA_Documentation_Baseline_Candidate_v0.9.2.2.1.zip` |
| Approval target | Promote to `v1.0 Final / Approved Baseline` after review approval |
## 2. Approval Decision
| Decision | Value |
|---|---|
| Approved | Pending |
| Approved with conditions | Pending |
| Rejected | Pending |
## 3. Approvers
| Role | Name | Decision | Date | Signature / Evidence |
|---|---|---|---|---|
| Product owner | TBD | Pending | TBD | TBD |
| System architect | TBD | Pending | TBD | TBD |
| Software architect | TBD | Pending | TBD | TBD |
| Software lead | TBD | Pending | TBD | TBD |
| QA / verification owner | TBD | Pending | TBD | TBD |
| Security reviewer | TBD | Pending | TBD | TBD |
| UX owner | TBD | Pending | TBD | TBD |
| Platform owner | TBD | Pending | TBD | TBD |
## 4. Open Issues
| Issue ID | Description | Disposition |
|---|---|---|
| TBD | TBD | TBD |
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Baseline approval record template for normalized package. |
## 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. |
@@ -1,92 +0,0 @@
# Cfg Baseline Candidate Validation Report
**Document type:** Configuration / Validation Report
**Version:** 0.9.3
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/baseline-candidate-validation-report.md` ---
## 1. Package
```text
chanora-docs-repo-format-v0.9.3
```
## 2. File Count
| Type | Count |
|---|---:|
| Markdown files | 37 (added `docs/architecture/desktop-ptt-architecture.md`) |
## 3. Defined ID Counts
| ID family | Defined IDs |
|---|---:|
| SysRS | 302 |
| SysDes | 148 |
| SRS | 203 |
| SAD | 80 |
| SDD | 93 |
## 4. Undefined Reference Check
| ID family | Undefined references |
|---|---:|
| SysRS | 0 |
| SysDes | 0 |
| SRS | 0 |
| SAD | 0 |
| SDD | 0 |
## 5. Direct-Layer Rule Check
| Rule | Result |
|---|---:|
| SRS direct SysRS references | 0 |
| SAD direct SysRS references | 0 |
| SAD direct SysDes references | 0 |
| SDD direct SysRS references | 0 |
| SDD direct SysDes references | 0 |
| SDD direct SRS references | 0 |
## 6. Language Check
| Check | Result |
|---|---:|
| CJK characters in en-only doc set | 0 |
(Localised user-facing strings in `apps/chanora_flutter/lib/l10n/app_zh.arb` are out of scope of this report per DEC-015.)
## 7. Apple Gate Coverage Check
| Item | Coverage |
|---|---|
| Runtime deployment target | iOS 13+ remains separate runtime policy |
| App Store Connect upload SDK gate | Xcode 26+ and iOS 26 / iPadOS 26 SDK+ for upload on or after 2026-04-28 |
| Link chain | SysRS-287 -> SysDes-134 -> SRS-186 -> SAD-062 -> SDD-072 |
| Internal Alpha / local development distinction | Captured in Platform Release Policy |
| TestFlight / App Store upload distinction | Captured in Platform Release Policy |
## 8. Desktop Push-to-Talk Coverage Check
| Item | Coverage |
|---|---|
| Focused PTT mandatory on Win / macOS / Linux | SysRS-296 -> SysDes-142, SysDes-144 -> SRS-201 -> SAD-075 -> SDD-089 |
| Global PTT capability-dependent | SysRS-297 -> SysDes-142 -> SRS-195 -> SAD-071 -> SDD-081 |
| Capability exposed to UI + release record | SysRS-298 -> SysDes-143/147/148 -> SRS-196 -> SAD-076/078 -> SDD-082/088/091 |
| Windows ladder | SysRS-299 -> SysDes-145 -> SRS-197 -> SAD-072 -> SDD-083/084 |
| macOS permission-aware | SysRS-300 -> SysDes-145 -> SRS-198 -> SAD-073 -> SDD-085 |
| Linux GNOME-Wayland portal | SysRS-301 -> SysDes-145 -> SRS-199 -> SAD-074 -> SDD-086 |
| No raw key history in diagnostics | SysRS-302 -> SysDes-146 -> SRS-202 -> SAD-077 -> SDD-090 |
| Mouse side buttons (DEC-026) | SRS-200 -> SAD-072/073/074 -> SDD-083/085/086 |
| Missed-key-up watchdog (DEC-028) | SRS-203 -> SAD-079 -> SDD-092 |
| Owner-resolved review questions PTT-OPEN-001..006 | DEC-023..028 in `product-decision-register.md` |
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Validation report for Apple App Store Connect upload SDK gate correction, full file update, and coverage check. |
| 0.9.3 | 2026-05-15 | Validation report for desktop Push-to-Talk update: added 7 SysRS / 7 SysDes / 9 SRS / 9 SAD / 12 SDD entries, added `desktop-ptt-architecture.md`, recorded six new owner decisions DEC-023..028; ID totals advance to 302 / 148 / 203 / 79 / 92; direct-layer rule and undefined-reference counts remain zero. |
| 0.9.4 | 2026-05-15 | P0 traceability audit follow-up: added `SAD-080` and `SDD-093` to close the SRS-200 coverage gap surfaced by the audit. ID totals advance to 302 / 148 / 203 / 80 / 93; direct-layer-rule and undefined-reference counts remain zero. No code change in this revision; the existing mouse-side-button support previously implemented under the broader `SRS-195..203 -> SAD-071..079 -> SDD-081..092` umbrella is now tied to the dedicated SAD/SDD pair. |
@@ -1,103 +0,0 @@
# CHANORA_CFG_Decision_Impact_Assessment_v0.9.2.2.1
**Document type:** Configuration / Decision Impact Assessment
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/decision-impact-assessment.md` ---
## 1. Purpose
This document records how key unresolved product and architecture decisions affect requirements, architecture, detailed design, verification, release readiness, security, privacy, and legal work products.
## 2. High-Impact Decision Assessment
| Decision | Recommended decision | Impact if changed later |
|---|---|---|
| Minimum iOS version | iOS 13 | Test matrix, platform support policy, app store build configuration, platform behavior tests. |
| Minimum Android version | API 28 (per DEC-004, Accepted 2026-05-14; raised from the original API 24 recommendation) | Device support, permissions, audio routing, Google Play compatibility, platform tests. |
| Android target SDK | Google Play-required API level on upload date; current release gate uses API 35+ unless newer policy applies |
| Apple App Store SDK gate | Xcode 26+ with iOS 26 / iPadOS 26 SDK+ for App Store Connect upload on or after 2026-04-28 unless newer Apple upload policy applies | Google Play submission eligibility and platform permission behavior. |
| Multiple active connections | Exclude from MVP | If added later, affects state model, audio routing, UI layout, reconnection logic, storage, verification. |
| AEC/AGC/NS/HPF defaults | Enabled by default where supported | Affects UX, CPU, platform-specific audio settings, verification matrix. |
| Audio processing path | Platform-native first; fallback later | Affects audio architecture, Rust/native dependencies, latency, CPU, platform compatibility. |
| Trademark/legal review | Required before public/store release | Blocks public release if unresolved. |
| Local DB | SQLite or equivalent | Affects storage schema, migrations, backup/delete policy, tests. |
| Bridge | Stable typed generated/schema-controlled bridge | Affects API stability, async event flow, maintainability, code generation, tests. |
| Diagnostics upload | No automatic upload in MVP | Affects privacy policy, security review, support process. |
| Crash reporting | Disabled unless later approved | Affects privacy/legal docs, dependency and supply-chain review. |
## 3. Document Update Rules
| If decision changes | Update required |
|---|---|
| Minimum iOS/Android version changes | SysRS, SysDes, SRS, SAD, SDD, SYS.4, SWE.6, Release Readiness |
| Apple SDK submission gate changes | SysRS, SysDes, SRS, SAD, SDD, SWE.6, Release Readiness |
| Android target SDK changes | SRS, SWE.6, Release Readiness, Platform Guide |
| Multiple connections added to MVP | SysRS, SysDes, SRS, SAD, SDD, SWE.4, SWE.5, SWE.6, SYS.4 |
| Audio defaults change | SysRS, SysDes, SRS, SAD, SDD, SWE.4, SWE.5, SWE.6 |
| Audio implementation path changes | SysDes, SAD, SDD, SWE.4, SWE.5, SYS.4 |
| Legal/trademark policy changes | Release Readiness, Legal Review, Privacy Policy, External References |
| DB choice changes | SysDes, SRS, SAD, SDD, SWE.4, SWE.5 |
| Bridge choice changes | SysDes, SAD, SDD, SWE.4, SWE.5 |
| Diagnostics upload enabled | SysRS, SysDes, SRS, SAD, SDD, Threat Model, Privacy Policy, Redaction Audit, Release Readiness |
| Crash reporting enabled | SysRS, SysDes, SRS, SAD, SDD, Privacy Policy, Dependency Report, Release Readiness |
## 4. Recommended Decision Closure Sequence
1. Confirm release type and staged platform policy.
2. Confirm mobile minimum versions and Android target SDK policy.
3. Confirm one active server connection for MVP.
4. Confirm audio processing defaults.
5. Confirm audio implementation path.
6. Confirm diagnostics/crash reporting privacy policy.
7. Confirm SQLite/equivalent local database.
8. Confirm bridge choice.
9. Confirm legal/trademark/public wording review requirement.
10. Confirm license model before public release.
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial decision impact assessment for key product and architecture decisions. |
## 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+ for App Store Connect upload on or after 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 Decision Impact Addendum (Baseline Candidate 0.9.3)
The owner rulings recorded as DEC-023 through DEC-028 on 2026-05-15 affect the documents below. If any of those decisions are revisited the documents listed must be re-validated for consistency.
| Decision | Affects |
|---|---|
| DEC-023 Windows Global PTT P0 | `docs/architecture/desktop-ptt-architecture.md`, `docs/architecture/sad.md` SAD-072, `docs/architecture/sdd.md` SDD-083/084, `docs/requirements/srs.md` SRS-197, `docs/release/release-readiness-go-nogo-record.md` RR-PTT-001 |
| DEC-024 macOS Global PTT P0 + permission UX | `docs/architecture/desktop-ptt-architecture.md`, `docs/architecture/sad.md` SAD-073, `docs/architecture/sdd.md` SDD-085, `docs/requirements/srs.md` SRS-198, `docs/release/release-readiness-go-nogo-record.md` RR-PTT-002/003 |
| DEC-025 Linux GNOME-Wayland only | `docs/architecture/desktop-ptt-architecture.md`, `docs/architecture/sad.md` SAD-074, `docs/architecture/sdd.md` SDD-086, `docs/requirements/srs.md` SRS-199, `docs/release/platform-release-policy.md`, `docs/release/release-readiness-go-nogo-record.md` RR-PTT-004/005 |
| DEC-026 Mouse side buttons | `docs/architecture/desktop-ptt-architecture.md`, `docs/requirements/srs.md` SRS-200, `docs/architecture/sad.md` SAD-072/073, `docs/architecture/sdd.md` SDD-083/085 |
| DEC-027 PTT diagnostics privacy | `docs/privacy/privacy-policy.md`, `docs/security/diagnostic-redaction-audit-report.md`, `docs/security/threat-model.md`, `docs/requirements/srs.md` SRS-202, `docs/architecture/sad.md` SAD-077, `docs/architecture/sdd.md` SDD-090 |
| DEC-028 Missed-key-up watchdog P0 | `docs/architecture/desktop-ptt-architecture.md`, `docs/requirements/srs.md` SRS-203, `docs/architecture/sad.md` SAD-079, `docs/architecture/sdd.md` SDD-092, `docs/release/release-readiness-go-nogo-record.md` RR-PTT-007 |
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Recorded the desktop-PTT decision impacts for DEC-023..028. |
## Baseline Candidate 0.9.9 Update
| Version | Date | Description |
|---|---|---|
| 0.9.9 | 2026-05-17 | Updated §2 "Minimum Android version" row from API 24 to **API 28** to reconcile with DEC-004 (Accepted 2026-05-14). Document Update Rules (§3) and Decision Closure Sequence (§4) remain valid as-is. |
@@ -1,60 +0,0 @@
# Development Environment
**Document type:** Governance / Development Environment
**Version:** 0.1.0
**Status:** Draft
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/development-environment.md`
---
## 1. Purpose
This document records the intended local development environment for Chanora.
## 2. Required Toolchains
The exact versions shall be finalized when the Flutter and Rust workspaces are created.
Expected tools:
| Tool | Purpose |
|---|---|
| Flutter SDK | Cross-platform UI |
| Dart SDK | Flutter development |
| Rust toolchain | Core, protocol, audio, storage, diagnostics |
| Cargo | Rust package/build tool |
| just | Local command runner |
| Python 3 | Documentation validation scripts |
| Xcode | iOS/iPadOS/macOS development and App Store Connect upload builds |
| Android Studio / Android SDK | Android development |
| CMake / native build tools | Native dependencies if required |
## 3. Platform Notes
| Platform | Notes |
|---|---|
| iOS / iPadOS | App Store Connect upload on or after 2026-04-28 requires Xcode 26+ and iOS 26 / iPadOS 26 SDK+. |
| Android | Store upload must target the Google Play-required API level on upload date. |
| Desktop | Windows, macOS, and Linux build requirements shall be finalized during scaffold and release planning. |
## 4. Local Commands
Local commands are defined in `justfile`.
Initial commands:
```bash
just format
just lint
just test
just verify-docs
just security-scan
```
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial development environment document. |
-93
View File
@@ -1,93 +0,0 @@
# Document Index
**Document type:** Configuration / Documentation Control
**Version:** 0.9.9
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/document-index.md`
---
## 1. Purpose
This document lists the normalized latest files included in the Chanora repository documentation package.
## 2. Current Baseline Candidate Files
| File | Status |
|---|---|
| `docs/architecture/sad.md` | Baseline Candidate |
| `docs/architecture/sdd.md` | Baseline Candidate |
| `docs/architecture/sysdes.md` | Baseline Candidate |
| `docs/architecture/desktop-ptt-architecture.md` | Baseline Candidate |
| `docs/governance/baseline-approval-record.md` | Baseline Candidate |
| `docs/governance/baseline-candidate-validation-report.md` | Baseline Candidate |
| `docs/governance/decision-impact-assessment.md` | Baseline Candidate |
| `docs/governance/document-naming-convention.md` | Baseline Candidate |
| `docs/governance/document-review-report.md` | Baseline Candidate |
| `docs/governance/git-commit-message-convention.md` | Baseline Candidate |
| `docs/governance/path-migration-map.md` | Baseline Candidate |
| `docs/governance/product-decision-register.md` | Baseline Candidate |
| `docs/governance/repo-format-validation-report.md` | Baseline Candidate |
| `docs/governance/traceability-matrix.md` | Baseline Candidate |
| `docs/i18n/localization-architecture.md` | Baseline Candidate |
| `docs/legal/trademark-and-attribution-review.md` | Baseline Candidate |
| `docs/privacy/privacy-policy.md` | Baseline Candidate |
| `docs/references/aspice-swe2-swe3-integration-note.md` | Baseline Candidate |
| `docs/references/external-references.md` | Baseline Candidate |
| `docs/release/platform-release-policy.md` | Baseline Candidate |
| `docs/release/release-readiness-go-nogo-record.md` | Baseline Candidate |
| `docs/requirements/srs.md` | Baseline Candidate |
| `docs/requirements/sysrs.md` | Baseline Candidate |
| `docs/security/dependency-and-supply-chain-report.md` | Baseline Candidate |
| `docs/security/diagnostic-redaction-audit-report.md` | Baseline Candidate |
| `docs/security/secure-storage-audit-report.md` | Baseline Candidate |
| `docs/security/security-privacy-legal-guideline.md` | Baseline Candidate |
| `docs/security/threat-model.md` | Baseline Candidate |
| `docs/ui-ux/adaptive-layout-platform-guide.md` | Baseline Candidate |
| `docs/ui-ux/material3-component-catalog.md` | Baseline Candidate |
| `docs/ui-ux/material3-design-tokens.md` | Baseline Candidate |
| `docs/ui-ux/material3-guideline.md` | Baseline Candidate |
| `docs/verification/swe4-unit-verification-plan.md` | Baseline Candidate |
| `docs/verification/swe5-software-integration-verification-plan.md` | Baseline Candidate |
| `docs/verification/swe6-software-verification-plan.md` | Baseline Candidate |
| `docs/verification/sys4-system-integration-verification-plan.md` | Baseline Candidate |
| `docs/verification/verification-master-plan.md` | Baseline Candidate |
## 3. Core Engineering Hierarchy
```text
SysRS -> SysDes -> SRS -> SAD -> SDD
```
## 4. Verification Work Product Mapping
```text
SDD -> SWE.4
SAD + SDD -> SWE.5
SRS -> SWE.6
SysDes -> SYS.4
```
## 5. Repo File Naming Rules
| Rule | Decision |
|---|---|
| Product prefix in file names | Not used under `docs/` |
| Case style | lowercase kebab-case |
| Version in file name | Not used |
| Version location | Inside document metadata |
| Release package version | Used in ZIP/package name |
## 6. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Converted documentation package to repository-oriented docs folder structure and updated internal filename references. |
| 0.9.3 | 2026-05-15 | Added `docs/architecture/desktop-ptt-architecture.md` to the controlled document set. |
| 0.9.5 | 2026-05-15 | Bumped controlled-set version to 0.9.5 for the v1 audio + PTT lifecycle refactor: SysRS-303..304, SysDes-149..151, SRS-204..207, SAD-081..083, SDD-094..097, and two new governance decisions DEC-029 (Flutter global-hotkey packages rejected for PTT) and DEC-030 (Voice Activity Detection deferred to P1). No controlled files added or removed; existing files updated in place under strict layered sourcing. |
| 0.9.6 | 2026-05-16 | Added DEC-031 (missed-key-up watchdog disabled on P0; redesign deferred to P1) and new controlled document `docs/verification/windows-p0-acceptance.md` carrying the 15-row human-must acceptance plan for the v1.0.0-rc.8 Windows ship. No spec items added; DEC-028 retained as historical context, superseded by DEC-031 for the v1 ship. |
| 0.9.7 | 2026-05-16 | Added controlled document `docs/verification/linux-p0-acceptance.md` carrying the 15-row human-must acceptance plan for the v1.0.0-rc.8 Linux (GNOME on Wayland) ship. Auto-test sign-off rows filled from the Arch host `100.74.219.114` verification pass: `cargo check --workspace --release` clean, `cargo test --workspace --lib` 78 / 0 / 1, `cargo test -p chanora_audio --test linux_portal_smoke -- --ignored` 1 / 0, `cargo test -p chanora_audio --test ptt_privacy` 1 / 0. No spec items added; the existing SDD-086 GNOME-Wayland portal backend is what this document signs off. |
| 0.9.8 | 2026-05-16 | Added controlled documents `docs/verification/macos-p0-acceptance.md` (15-row checklist for Apple Silicon macOS, SDD-085 CGEventTap backend now fully live with IOHIDCheckAccess + CGEventTapCreate + per-1.5s permission watcher) and `docs/verification/ios-p0-acceptance.md` (12-row checklist for physical iPhone via the free Apple Personal Team, SDD-094..097 audio lifecycle, AVAudioSession `.playAndRecord/.voiceChat` configured Swift-side in AppDelegate). The macOS PTT backend descriptor advertises L2/L3 only when Input Monitoring is granted, otherwise L0Focused per SRS-198 honest capability advertising. iOS PTT is L0Focused by design (DEC-025 explicitly does not pursue a global PTT analogue on iOS). No new spec items. |
| 0.9.9 | 2026-05-16 | Added controlled document `docs/verification/ipad-p0-acceptance.md` carrying the 15-row checklist for iPad P0 sign-off (same TS-3.3 reach, three iPad-specific rows: wide-mode landscape layout under the existing 840 dp LayoutBuilder breakpoint, Split View / Slide Over no-crash assertion since `UIApplicationSupportsMultipleScenes` stays `false` in P0, and AirPlay 2 audio routing). The iPad build artefact is the **same** `Runner.app` produced for iPhone — `TARGETED_DEVICE_FAMILY = "1,2"` in `ios/Runner.xcodeproj/project.pbxproj` is the Universal family. DEC-025 was originally iPhone-only for the mobile target; this row formally extends P0 coverage to iPad (still within the same iOS toolchain, no new Rust or Flutter code). No spec items added. |
@@ -1,66 +0,0 @@
# Document Naming Convention
**Document type:** Configuration / Documentation Control
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/document-naming-convention.md`
---
## 1. Purpose
This document defines the official repository documentation naming convention for Chanora.
## 2. Repository Path Pattern
Markdown documents under the repository shall use this pattern:
```text
docs/<category>/<lowercase-kebab-case-title>.md
```
Examples:
```text
docs/requirements/sysrs.md
docs/architecture/sad.md
docs/verification/swe4-unit-verification-plan.md
docs/release/release-readiness-go-nogo-record.md
docs/security/threat-model.md
```
## 3. Rules
| Rule | Decision |
|---|---|
| Product prefix | Do not use `CHANORA_` inside repo file names. |
| Version in filename | Do not include document version in repo file names. |
| Filename style | Use lowercase kebab-case. |
| Directory style | Use lowercase kebab-case. |
| Version metadata | Keep version inside the Markdown document. |
| Status metadata | Keep status inside the Markdown document. |
| Release artifacts | ZIP/package names may include project name and version. |
## 4. Top-Level Documentation Categories
| Directory | Purpose |
|---|---|
| `docs/requirements/` | SysRS and SRS |
| `docs/architecture/` | SysDes, SAD, SDD |
| `docs/verification/` | SWE.4, SWE.5, SWE.6, SYS.4, verification master plan |
| `docs/release/` | Release readiness and platform release policy |
| `docs/security/` | Threat model, secure storage, redaction, dependency/supply-chain, security guidelines |
| `docs/privacy/` | Privacy policy |
| `docs/legal/` | Trademark and attribution review |
| `docs/ui-ux/` | UI/UX, Material 3, design tokens, component catalog, adaptive layout |
| `docs/i18n/` | Localization architecture |
| `docs/governance/` | Index, traceability, approval, validation, review, decisions, commit convention |
| `docs/references/` | External references and research notes |
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Replaced release-package naming convention with repository docs naming convention. |
-90
View File
@@ -1,90 +0,0 @@
# Cfg Document Review Report V0.9.2.2.1
**Document type:** Configuration / Review Report
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/document-review-report.md` ---
## 1. Executive Summary
The normalized package is suitable as a **Baseline Candidate v0.9** for human review.
The package fixes the earlier draft-package issues:
- superseded original filenames are not included in the normalized package;
- all filenames follow a consistent naming convention;
- the package contains only baseline-candidate files;
- non-English text from the earlier draft metadata has been removed;
- undefined system-design references have been removed from the verification planning package;
- a naming convention, approval record template, document index, and validation report are included.
The package is still **not Final** until human review and approval are completed.
## 2. Recommended Status
| Decision | Result |
|---|---|
| Ready for Final / Approved Baseline | No |
| Ready for Baseline Candidate review | Yes |
| Recommended current status | Baseline Candidate v0.9 |
| Next target status after approval | Final / Approved Baseline v1.0 |
## 3. Positive Review Findings
| Area | Result |
|---|---|
| File naming | Normalized |
| Package scope | Latest baseline-candidate files only |
| Core hierarchy | `SysRS -> SysDes -> SRS -> SAD -> SDD` |
| Verification mapping | `SDD -> SWE.4`, `SAD + SDD -> SWE.5`, `SRS -> SWE.6`, `SysDes -> SYS.4` |
| SRS direct-source rule | SRS does not directly link to system-requirement IDs |
| SAD direct-source rule | SAD links directly to SRS only |
| SDD direct-source rule | SDD links directly to SAD only |
| English-only baseline | Passed automated CJK check |
| Approval metadata | Approval record template included |
## 4. Remaining Review Actions Before Final
| ID | Severity | Action |
|---|---|---|
| REV-ACT-001 | Major | Human stakeholders must review and approve the baseline candidate. |
| REV-ACT-002 | Major | Review comments must be recorded and dispositioned. |
| REV-ACT-003 | Major | Open issues must be accepted, deferred, or resolved. |
| REV-ACT-004 | Major | Approval record must be completed with names, roles, dates, and decisions. |
| REV-ACT-005 | Major | After approval, promote package and documents from `v0.9.2` to `v1.0`. |
## 5. Finalization Recommendation
Do not call this package Final until the approval record is completed.
Recommended workflow:
```text
Baseline Candidate v0.9.1
-> Human review
-> Review comment disposition
-> Approval record completed
-> Promote to v1.0 Final / Approved Baseline
```
## 6. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Review report for normalized baseline candidate package. |
## 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. |
@@ -1,185 +0,0 @@
# CHANORA_CFG_Git_Commit_Message_Convention_v0.9.2.2.1
**Document type:** Configuration / Engineering Convention
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/git-commit-message-convention.md` ---
## 1. Purpose
This document defines the Git commit message convention for Chanora.
Chanora shall use a Conventional Commits style format with project-specific scopes.
## 2. Commit Format
```text
<type>(<scope>): <summary>
```
Optional body:
```text
<type>(<scope>): <summary>
<body>
Refs: <issue or requirement IDs>
```
Breaking change format:
```text
<type>(<scope>)!: <summary>
BREAKING CHANGE: <description>
```
## 3. Commit Types
| Type | Meaning |
|---|---|
| `feat` | New user-visible or system-visible capability |
| `fix` | Bug fix |
| `docs` | Documentation-only change |
| `style` | Formatting change without behavior change |
| `refactor` | Code restructuring without intended behavior change |
| `perf` | Performance improvement |
| `test` | Test addition or test update |
| `build` | Build system, dependency, packaging, CI artifact change |
| `ci` | CI/CD pipeline change |
| `chore` | Maintenance task |
| `revert` | Revert a previous commit |
| `release` | Release preparation, version bump, release metadata |
| `sec` | Security-specific change |
| `i18n` | Localization, internationalization, Unicode, locale behavior |
| `ux` | UI/UX behavior or interaction change |
## 4. Recommended Scopes
| Scope | Area |
|---|---|
| `flutter` | Flutter app in general |
| `ui` | UI components and screens |
| `theme` | Material 3, design tokens, theme extensions |
| `adaptive` | Adaptive layout and window classes |
| `voice` | Voice UI or voice control behavior |
| `audio` | Audio capture, playback, processing, DSP |
| `core` | Rust Core orchestration |
| `protocol` | `tsclientlib` integration and protocol adapter |
| `bridge` | Flutter/Rust bridge and DTOs |
| `state` | State synchronization, reducers, snapshots, events |
| `storage` | Local database or non-secret persistence |
| `secure-storage` | Keychain/Keystore/secret storage |
| `diagnostics` | Logs, redaction, diagnostic export |
| `i18n` | Localization, Unicode, locale formatting, RTL |
| `android` | Android-specific behavior |
| `ios` | iOS-specific behavior |
| `windows` | Windows-specific behavior |
| `macos` | macOS-specific behavior |
| `linux` | Linux-specific behavior |
| `build` | Build tooling |
| `ci` | CI pipeline |
| `release` | Release packaging and release metadata |
| `docs` | Documentation |
| `req` | Requirements documents |
| `sysdes` | System architectural design |
| `srs` | Software requirements |
| `sad` | Software architecture |
| `sdd` | Software detailed design |
| `ver` | Verification documents |
## 5. Examples
```text
feat(voice): add push-to-talk state handling
```
```text
fix(protocol): recover channel tree after reconnect snapshot
```
```text
docs(sad): add interface catalog and performance view
```
```text
i18n(ui): add fallback behavior for missing localization keys
```
```text
sec(diagnostics): redact server password from export bundle
```
```text
test(audio): add unit tests for audio meter level clamping
```
```text
release(android): prepare internal alpha build metadata
```
## 6. Requirement and Document References
When relevant, the commit body should reference affected IDs.
Allowed examples:
```text
Refs: SRS-156, SAD-013, SDD-017
```
```text
Refs: SWE4-UV-011
```
Do not force every commit to reference a requirement. Use references when the change affects requirements, architecture, detailed design, verification, release, security, or traceability.
## 7. Pull Request Title Rule
Pull request titles should follow the same format as commit messages when possible:
```text
feat(voice): add persistent VoiceBar controls
```
## 8. Branch Naming
Recommended branch format:
```text
<type>/<short-topic>
```
Examples:
```text
feature/voicebar-controls
fix/reconnect-state-sync
docs/baseline-candidate-v09
release/internal-alpha-001
hotfix/diagnostic-redaction
```
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial Git commit message convention for Chanora. |
## 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. |
-200
View File
@@ -1,200 +0,0 @@
# Legal review readiness — DEC-012 sign-off checklist
| Version | Date | Status |
|---|---|---|
| 0.1.0 | 2026-05-15 | Initial draft alongside v1.0.0-rc.1 |
## Purpose
DEC-012 in `product-decision-register.md` records the legal /
trademark / licensing review as the **only** outstanding gate before
the MVP public release per DEC-001 sequencing. That decision was
accepted as a *release gate* on 2026-05-14; the actual review work
has not been performed.
This document is the engineering-side handoff package for that
review. It enumerates exactly what the reviewer needs to confirm,
points to the artefacts in this repository that answer each item,
and lists the work the reviewer must perform that the engineering
side cannot.
Engineering does **not** make legal decisions. Items marked
"engineering: done" mean the underlying technical artefact is in
place; the corresponding legal confirmation is still required.
## Scope
Reviewer is expected to confirm or correct each of the following
before `v1.0.0-rc.1` is promoted to `v1.0.0` and any release
artefact is published publicly or to a store.
### 1. Trademark — "Chanora"
* **DEC-018** accepted "Chanora" as the public product name.
* Engineering: name appears in `Cargo.toml`, `pubspec.yaml`, the
About dialog, the AppBar title via the `appTitle` localisation
key, and every commit message.
* **Reviewer action**:
- Trademark registrability check in target jurisdictions (CN, US,
EU at minimum, per DEC-002 target platforms' user base).
- Confirm no conflicting registration in voice-communication
software / mobile-app categories.
- Issue go / no-go ruling. A no-go ruling triggers a rename which
invalidates `v1.0.0-rc.1` and forces a new RC.
### 2. Non-affiliation statement — TeamSpeak
* **DEC-019** accepted the working wording:
> Chanora is independent and is not affiliated with, endorsed by,
> sponsored by, or officially associated with TeamSpeak.
* Engineering: that exact sentence ships in:
- `NOTICE` (top of file).
- `README.md` `## License and trademark` section.
- The in-app About dialog (English: `aboutNonAffiliation` ARB key;
Chinese Simplified: `aboutNonAffiliation` in `app_zh.arb`,
translated by an engineer — translation should be reviewed for
legal precision).
* **Reviewer action**:
- Confirm the English wording is sufficient under target-market
consumer-protection and unfair-competition statutes.
- Confirm the Chinese-Simplified translation does not weaken the
statement.
- Confirm there is no remaining text anywhere in the product that
could imply affiliation (search hints: "TeamSpeak", "official",
"endorsed").
### 3. Trademark usage — "TeamSpeak"
The product documentation and UI strings reference "TeamSpeak" in
several places where we describe interoperability (e.g.
"TeamSpeak-compatible servers"). This is nominative use.
* **Reviewer action**:
- Confirm each occurrence of "TeamSpeak" in user-facing strings,
documentation, and store metadata is permissible nominative
use under target-jurisdiction trademark law.
- Recommend a `™` or `®` symbol convention if required.
### 4. License posture — Chanora's own code
* **DEC-020** accepted dual-license **Apache-2.0 OR MIT**.
* Engineering: the texts ship as `LICENSE-APACHE` and `LICENSE-MIT`
at the repository root; the aggregator `LICENSE` references both.
Cargo-level package manifests carry `license.workspace = true`
pointing to `Apache-2.0 OR MIT` in the workspace `Cargo.toml`.
* **Reviewer action**:
- Confirm the dual-license declaration is consistent with all
contributor agreements (none in place yet — see open items).
- Confirm `LICENSE` file contents satisfy each app store's source-
code-availability and inbound-license requirements.
### 5. Third-party license posture — direct dependencies
* `NOTICE` enumerates the direct dependency list as of v1.0.0-rc.1.
* Each direct dependency is permissively licensed
(`MIT`, `Apache-2.0`, `MIT OR Apache-2.0`, `BSD-3-Clause`).
No GPL / LGPL / AGPL surfaces in the direct set.
* **Reviewer artefacts** checked into the repository:
- `docs/security/license-inventory.md` and
`docs/security/license-inventory.html` — full transitive Rust
inventory generated by `cargo about generate` from
`about.toml`. Covers 364 crates across the workspace.
- `docs/security/flutter-license-inventory.md` — Flutter / Dart
inventory generated by `tools/dump_flutter_licenses.sh`.
Covers 94 packages including the Flutter SDK BSD-3-Clause
text.
- `deny.toml``cargo deny` configuration enforcing the
DEC-020 license posture as a CI guardrail. The `supply-chain`
job in `.github/workflows/ci.yml` runs `cargo deny check` on
every push and PR.
* **Reviewer action**:
- Confirm the `NOTICE` enumeration matches what the build tooling
actually links by spot-checking against the inventories above.
- Confirm each direct dependency's attribution obligations are
satisfied (Apache-2.0 requires a copy of the license text, the
NOTICE entry, and a list of changes in any modified copies).
- Confirm no copyleft transitive dependency creeps in via
`tsclientlib` or `cpal`. The most likely failure mode is a
crypto / DSP subdep with LGPL coverage; `cargo deny` config
should refuse those.
### 6. `tsclientlib` posture specifically
The project pins `tsclientlib` to a specific commit
(`04aa249` on `https://github.com/ReSpeak/tsclientlib`). The crate is
upstream-licensed `MIT OR Apache-2.0`. It implements the
TeamSpeak 3 protocol from publicly observed behaviour, not from
TeamSpeak proprietary sources.
* **Reviewer action**:
- Confirm linking against `tsclientlib` does not by itself create
a derivative-work obligation under TeamSpeak's own licenses or
EULAs.
- Confirm using `tsclientlib` to talk to third-party
TeamSpeak-protocol servers does not create a trademark or
contract-tort exposure.
### 7. Crypto + secure-storage compliance
* `chacha20poly1305` (Apache-2.0 OR MIT) provides envelope
encryption for the identity at rest and bookmark passwords.
* `keyring` (Apache-2.0 OR MIT) hits the platform Secret Service /
Keychain / Credential Manager for the DEK.
* No symmetric or asymmetric primitive other than the above is
introduced by Chanora's own code; `tsclientlib` carries its own
protocol-level crypto.
* **Reviewer action**:
- Confirm export-control posture for the resulting binary
(cryptography category determination, ECCN, any EAR self-
classification needed for store distribution).
- Confirm any privacy-statement updates required by jurisdictions
that treat persistent device identifiers as personal data.
### 8. Data handling — DEC-016 / DEC-017
* **DEC-016** No automatic diagnostic upload. The `export_diagnostics`
bridge function is invoked only on user action and the redacted
output is local-only (Clipboard or share-sheet).
* **DEC-017** Crash reporting disabled. Repository grep for
`sentry|crashlytics|bugsnag` returns zero hits as of v1.0.0-rc.1.
* Engineering: diagnostics redaction is enforced at write-time by
the in-bridge `RedactingLogLayer`; tests
`chanora_diagnostics::tests::*` cover the policy.
* **Reviewer action**:
- Confirm privacy policy text aligns: no telemetry, no automatic
upload, no crash reporting in MVP.
- Confirm app-store privacy-label entries are consistent.
### 9. Store-listing copy
Out of scope for engineering; reviewer drafts and validates per
DEC-002 staged platform list:
- Google Play Store (Android arm64-v8a)
- Apple App Store (iOS, MVP gate)
- Microsoft Store / direct (Windows)
- Mac App Store / direct (macOS)
- Linux (direct distribution; no store)
## Open engineering work blocking sign-off
These are concrete items that engineering must close before the
reviewer's work can complete. They do **not** require legal input
themselves — they are listed here so the reviewer's scope is clear.
| # | Item | Status |
|---|------|--------|
| 1 | `cargo about generate --workspace` output checked into `docs/security/license-inventory.{md,html}` | **Done** (v1.0.0-rc.2 candidate) — generated from `about.toml`. 364 transitive crates enumerated; CI fails on staleness. |
| 2 | Flutter `LicenseRegistry` dump checked into `docs/security/flutter-license-inventory.md` | **Done** (v1.0.0-rc.2 candidate) — generated by `tools/dump_flutter_licenses.sh`; 94 packages enumerated; CI fails on staleness. |
| 3 | `cargo deny check licenses` (with allow-list mirroring DEC-020) | **Done** (v1.0.0-rc.2 candidate) — config at `deny.toml`, CI job `supply-chain` runs `cargo deny check` on every push. |
| 4 | Live iOS and macOS build artefacts | **Open** — DEC-002 staged release allows deferring; today neither has a live build. See `staged-release-plan.md`. |
## Out-of-scope
The following are *not* part of DEC-012 and have their own owners
and decisions:
* Cryptographic primitive selection (`chacha20poly1305`, key sizes,
KDF choice) — Security Architect; closed by DEC-013.2.
* Codec choice (Opus) — Software Architect.
* TLS / connection security — falls inside `tsclientlib`.
-84
View File
@@ -1,84 +0,0 @@
# Documentation Path Migration Map
**Document type:** Configuration / Migration Map
**Version:** 0.9.3
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/path-migration-map.md`
---
## 1. Purpose
This document maps the previous package-style filenames to the new repository documentation paths.
## 2. Migration Map
| Previous package filename | New repo path |
|---|---|
| `CHANORA_SAD_ASPICE_SWE2_Software_Architecture_Description_v0.9.2.md` | `docs/architecture/sad.md` |
| `CHANORA_SDD_ASPICE_SWE3_Software_Detailed_Design_v0.9.2.md` | `docs/architecture/sdd.md` |
| `CHANORA_SYSDES_ASPICE_SYS3_System_Architectural_Design_v0.9.2.md` | `docs/architecture/sysdes.md` |
| `CHANORA_CFG_Baseline_Approval_Record_v0.9.2.md` | `docs/governance/baseline-approval-record.md` |
| `CHANORA_CFG_Baseline_Candidate_Validation_Report_v0.9.2.md` | `docs/governance/baseline-candidate-validation-report.md` |
| `CHANORA_CFG_Decision_Impact_Assessment_v0.9.2.md` | `docs/governance/decision-impact-assessment.md` |
| `CHANORA_CFG_Document_Index_v0.9.2.md` | `docs/governance/document-index.md` |
| `CHANORA_CFG_Document_Naming_Convention_v0.9.2.md` | `docs/governance/document-naming-convention.md` |
| `CHANORA_CFG_Document_Review_Report_v0.9.2.md` | `docs/governance/document-review-report.md` |
| `CHANORA_CFG_Git_Commit_Message_Convention_v0.9.2.md` | `docs/governance/git-commit-message-convention.md` |
| `CHANORA_CFG_Product_Decision_Register_v0.9.2.md` | `docs/governance/product-decision-register.md` |
| `CHANORA_CFG_Traceability_Matrix_v0.9.2.md` | `docs/governance/traceability-matrix.md` |
| `CHANORA_I18N_Localization_Architecture_v0.9.2.md` | `docs/i18n/localization-architecture.md` |
| `CHANORA_LEGAL_Trademark_And_Attribution_Review_v0.9.2.md` | `docs/legal/trademark-and-attribution-review.md` |
| `CHANORA_PRIV_Privacy_Policy_v0.9.2.md` | `docs/privacy/privacy-policy.md` |
| `CHANORA_REFS_ASPICE_SWE2_SWE3_Integration_Note_v0.9.2.md` | `docs/references/aspice-swe2-swe3-integration-note.md` |
| `CHANORA_CFG_External_References_v0.9.2.md` | `docs/references/external-references.md` |
| `CHANORA_REL_Platform_Release_Policy_v0.9.2.md` | `docs/release/platform-release-policy.md` |
| `CHANORA_REL_Release_Readiness_Go_NoGo_Record_v0.9.2.md` | `docs/release/release-readiness-go-nogo-record.md` |
| `CHANORA_SRS_ASPICE_SWE1_Software_Requirements_Specification_v0.9.2.md` | `docs/requirements/srs.md` |
| `CHANORA_SYSRS_System_Requirements_Specification_v0.9.2.md` | `docs/requirements/sysrs.md` |
| `CHANORA_SEC_Dependency_And_Supply_Chain_Report_v0.9.2.md` | `docs/security/dependency-and-supply-chain-report.md` |
| `CHANORA_SEC_Diagnostic_Redaction_Audit_Report_v0.9.2.md` | `docs/security/diagnostic-redaction-audit-report.md` |
| `CHANORA_SEC_Secure_Storage_Audit_Report_v0.9.2.md` | `docs/security/secure-storage-audit-report.md` |
| `CHANORA_SEC_Security_Privacy_Legal_Guideline_v0.9.2.md` | `docs/security/security-privacy-legal-guideline.md` |
| `CHANORA_SEC_Threat_Model_v0.9.2.md` | `docs/security/threat-model.md` |
| `CHANORA_UIUX_Adaptive_Layout_Platform_Guide_v0.9.2.md` | `docs/ui-ux/adaptive-layout-platform-guide.md` |
| `CHANORA_UIUX_Material3_Component_Catalog_v0.9.2.md` | `docs/ui-ux/material3-component-catalog.md` |
| `CHANORA_UIUX_Material3_Design_Tokens_v0.9.2.md` | `docs/ui-ux/material3-design-tokens.md` |
| `CHANORA_UIUX_Material3_Guideline_v0.9.2.md` | `docs/ui-ux/material3-guideline.md` |
| `CHANORA_VER_ASPICE_SWE4_Unit_Verification_Plan_v0.9.2.md` | `docs/verification/swe4-unit-verification-plan.md` |
| `CHANORA_VER_ASPICE_SWE5_Software_Integration_Verification_Plan_v0.9.2.md` | `docs/verification/swe5-software-integration-verification-plan.md` |
| `CHANORA_VER_ASPICE_SWE6_Software_Verification_Plan_v0.9.2.md` | `docs/verification/swe6-software-verification-plan.md` |
| `CHANORA_VER_ASPICE_SYS4_System_Integration_Verification_Plan_v0.9.2.md` | `docs/verification/sys4-system-integration-verification-plan.md` |
| `CHANORA_VER_Master_Plan_v0.9.2.md` | `docs/verification/verification-master-plan.md` |
## 3. Implementation Path Layout (DEC-022)
The canonical implementation directory layout was adopted as DEC-022
(register v0.9.5) and matches the README's sketch + SAD §7.2 module
decomposition. Implementation paths are listed here for traceability
alongside the documentation paths above.
| Logical role | Repo path | Authority |
|---|---|---|
| Flutter application | `apps/chanora_flutter/` | SAD §7.1, DEC-022 |
| Rust orchestration / top-level API | `core/chanora_core/` | SAD §7.2 |
| Protocol adapter (tsclientlib isolation) | `crates/chanora_protocol/` | SAD §7.2, SAD-067, SysDes-011/029 |
| State synchronisation | `crates/chanora_state/` | SAD §7.2 |
| Audio subsystem | `crates/chanora_audio/` | SAD §7.2, DEC-011, DEC-011.1 |
| Storage (non-secret DB + platform secure store) | `crates/chanora_storage/` | SAD §7.2, SAD-067, DEC-013, DEC-013.1, DEC-013.2 |
| Diagnostics (logs, redaction, export) | `crates/chanora_diagnostics/` | SAD §7.2, DEC-016, DEC-017 |
| Typed Flutter/Rust bridge | `crates/chanora_bridge/` | SAD §7.2, DEC-014, SDD-079, SAD-068 |
The Cargo workspace is declared at the repository root (`Cargo.toml`).
The Flutter application is **not** a Cargo workspace member; it is
owned by Flutter / Gradle / Xcode tooling and listed under the
workspace's `exclude` array along with the `poc/` spike directories.
## 4. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Initial migration map from package filenames to repo docs paths. |
| 0.9.3 | 2026-05-14 | Added §3 Implementation Path Layout recording the DEC-022 directory adoption (apps/, core/, crates/) as the workspace was first scaffolded on `product/scaffold-v0`. |
-158
View File
@@ -1,158 +0,0 @@
# 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. |
@@ -1,362 +0,0 @@
# CHANORA_CFG_Product_Decision_Register_v0.9.7.0.0
**Document type:** Configuration / Product Decision Register
**Version:** 0.9.8
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/product-decision-register.md` ---
## 1. Purpose
This document records key product, architecture, release, legal, and engineering decisions that affect Chanora scope, testing, architecture, app store eligibility, and release readiness.
A decision marked **Proposed / Owner Confirmation Required** is a recommended decision that should be confirmed by the owner before Final / Approved Baseline.
## 2. Decision Status Legend
| Status | Meaning |
|---|---|
| Proposed / Owner Confirmation Required | Recommended decision; owner must confirm before Final. |
| Accepted | Confirmed and part of baseline. |
| Deferred | Not decided for this release; must not block scope if explicitly deferred. |
| Rejected | Not selected. |
## 3. Key Blocking Decisions
| Decision ID | Decision | Recommended decision | Status | Owner | Why it matters |
|---|---|---|---|---|---|
| DEC-001 | Release type | Internal Alpha first, then External Beta, then MVP Public / Store Release | Accepted | Product Owner | Controls release gate, verification bar, legal/privacy requirements, and platform scope. |
| DEC-002 | MVP platform scope | MVP target remains Windows, macOS, Linux, Android, and iOS; first release may be staged by channel/platform | Accepted | Product Owner + Engineering Owner | Controls verification matrix, build artifacts, store readiness, and support load. |
| DEC-003 | Minimum iOS version | iOS 13 minimum for Flutter support baseline; test latest iOS release separately | Accepted | Product Owner + iOS Owner | Controls iOS compatibility, test devices, and app store eligibility. |
| DEC-004 | Minimum Android version | **Android API 28 (Android 9.0)** minimum, raised from the original recommendation of API 24 by explicit owner ruling on 2026-05-14. Rationale: simplifies the audio path (AAudio is unconditionally available from API 26+ and stable from API 28), narrows the TLS / privacy / scoped-storage compatibility surface, and matches typical 2026 Android baselines. The cpal-on-Oboe Android spike was built with `minSdk = 24` and `cargo-ndk -P 26`; product code in `apps/chanora_flutter` must move `minSdk` to 28 and may simplify the AAudio-vs-OpenSL-ES fallback logic accordingly. | Accepted | Product Owner + Android Owner | Controls Android device support, runtime permissions, and Play Store eligibility. |
| DEC-005 | Android target SDK | Target the Google Play-required API level on the upload date; current release gate uses API 35+ unless newer Google policy applies | Accepted | Android Owner + Release Manager | Required for new apps and updates submitted to Google Play after the current policy date. |
| DEC-006 | Multiple server connections in MVP | Not in MVP; support one active server connection per client instance | Accepted | Product Owner + Software Architect | Reduces state synchronization, audio routing, UI complexity, and verification scope. |
| DEC-007 | AEC default state | Enabled by default on platforms/audio backends where supported and stable | Accepted | Audio Owner + Product Owner | Affects echo quality, CPU usage, platform behavior, and user experience. |
| DEC-008 | AGC default state | Enabled by default, with user setting to disable | Accepted | Audio Owner + Product Owner | Affects perceived loudness consistency and may affect advanced user preference. |
| DEC-009 | Noise suppression default state | Enabled by default, with user setting to disable | Accepted | Audio Owner + Product Owner | Improves typical voice quality but may affect voice naturalness and CPU usage. |
| DEC-010 | High-pass filter default state | Enabled by default | Accepted | Audio Owner | Removes low-frequency rumble and usually improves speech capture. |
| DEC-011 | Audio processing implementation path | Use platform-native audio processing first where available; use Rust/WebRTC-style processing as controlled fallback or later architecture option | Accepted | Software Architect + Audio Owner | Controls architecture, latency, CPU use, platform compatibility, and testing. |
| DEC-011.1 | Audio crate choice | `cpal` for desktop (empirically verified on Linux/PipeWire by `poc/audio-capture-playback-spike` on 2026-05-13) and for Android (cpal-on-Oboe, empirically verified on a Motorola Moto G Stylus 5G (2023) running Android 14 arm64-v8a by `poc/audio-capture-playback-android-spike` on 2026-05-13); iOS crate TBD pending an iOS spike that requires macOS + Xcode hardware | Accepted (desktop + Android) / Deferred (iOS) | Software Architect + Audio Owner | Pins the desktop and Android audio dependencies; iOS remains an open risk surface. |
| DEC-012 | Official SDK / trademark / licensing review | Public/store release is blocked until legal confirms TeamSpeak non-affiliation wording, trademark usage, OSS licenses, and `tsclientlib` license posture | Accepted (as a release gate) | Legal / Compliance + Product Owner | Public release risk and store metadata risk. Owner accepted the gate on 2026-05-14; the legal review itself is still to be performed and remains a public-release blocker. |
| DEC-013 | Local database choice | Use SQLite or equivalent embedded local database for non-secret local state; secrets remain in platform secure storage | Accepted | Software Architect + Storage Owner | Controls storage schema, migrations, backup/delete policy, and portability. |
| DEC-013.1 | SQLite crate | `rusqlite` with the `bundled` feature (SQLite statically linked into the binary; no system libsqlite3 dependency); verified by `poc/sqlite-storage-spike` on 2026-05-13 | Accepted | Software Architect + Storage Owner | Pins the embedded-DB dependency; locks reproducibility. |
| DEC-013.2 | Linux secure-storage backend policy | Prefer Secret Service (libsecret / gnome-keyring / kwallet / KeePassXC) on Linux; if the default collection is locked or D-Bus is unavailable, fall back to kernel keyutils with a clear user notice. Both backends are "equivalent" per SysRS-053 / SysRS-162; verified by `poc/secure-storage-spike` on 2026-05-13 | Accepted | Software Architect + Storage Owner + Security Reviewer | Closes the SysRS-162 ambiguity surfaced by the secure-storage PoC. |
| DEC-014 | Bridge choice | Use a stable typed Flutter/Rust bridge with generated or schema-controlled DTOs; **`flutter_rust_bridge` 2.x pinned** (empirically verified at 2.12.0 by `poc/flutter_rust_bridge_hello` on 2026-05-13) | Accepted | Software Architect | Controls API stability, maintainability, async event flow, and long-term code generation. |
| DEC-015 | Product language for MVP | **English + Chinese (Simplified) for MVP**, raised from the original recommendation of English-only by explicit owner ruling on 2026-05-14. Rationale: the demonstrated test-server population (verified live against `cn.teamspeak.app`) and broader TS3 audience include substantial Chinese-speaking users; shipping zh-Hans alongside en at MVP avoids a launch-window UX gap. Architecture remains i18n-ready so additional languages can be added later mechanically. Server-provided content is preserved verbatim and never translated (ADR-008 UTF-8 boundary, DEC-015 server-content rule retained). | Accepted | Product Owner | Controls localization scope and release schedule. |
| DEC-016 | Diagnostics upload policy | No automatic upload for MVP; user-initiated local diagnostic export only | Accepted | Product Owner + Legal + Security | Controls privacy policy, support workflow, and security review scope. |
| DEC-017 | Crash reporting | Disabled for MVP unless explicit opt-in provider and privacy policy are approved | Accepted | Product Owner + Legal + Security | Avoids privacy/legal complexity before public release. |
| DEC-018 | Public product name | Chanora | Accepted | Product Owner | Branding and legal identity. Trademark / registrability check remains under DEC-012 legal review before public release. |
| DEC-019 | Public non-affiliation statement | Use legal-approved wording; drafted text accepted as working copy: "Chanora is independent and is not affiliated with, endorsed by, sponsored by, or officially associated with TeamSpeak." Subject to final legal review under DEC-012 before public release. | Accepted (drafted wording) | Legal / Compliance | Required for public release and store metadata. |
| DEC-021 | Apple App Store submission SDK | Use Xcode 26 or later and the iOS 26 / iPadOS 26 SDK or later for App Store submission on or after 2026-04-28, unless Apple publishes a newer applicable requirement before upload | Accepted | iOS Owner + Release Manager | Controls App Store Connect upload eligibility and release pipeline. |
| DEC-020 | License model | **Dual-licensed under Apache-2.0 OR MIT (recipient's choice)**, the standard Rust-ecosystem permissive license model. Accepted on 2026-05-14. Compatible with every direct dependency in the PoC tree (`tsclientlib` MIT-OR-Apache-2.0, `flutter_rust_bridge` MIT, `cpal` Apache-2.0, `rusqlite` MIT, `keyring` MIT-OR-Apache-2.0, etc.) and with the Flutter framework's BSD-3-Clause. The license texts ship as `LICENSE-APACHE` and `LICENSE-MIT` at the repository root; an aggregator `LICENSE` points to both. `NOTICE` enumerates current direct-dependency attributions. The full OSS legal review (transitive deps, license obligations, OSS notices) remains under DEC-012 and is still required before public release. | Accepted | Product Owner + Legal | Business and OSS compliance decision. No longer a public-release blocker by itself; legal review under DEC-012 is the remaining gate. |
| DEC-022 | Canonical implementation directory layout | Accept the README's sketch as canonical: `apps/chanora_flutter/`, `core/chanora_core/`, `crates/chanora_protocol/`, `crates/chanora_audio/`, `crates/chanora_state/`, `crates/chanora_storage/`, `crates/chanora_diagnostics/`, `crates/chanora_bridge/`. Matches SAD §7.2 module decomposition | Accepted | Software Architect | Unblocks product-crate scaffolding; was not formalised by any prior doc. |
| DEC-023 | Windows desktop Global PTT priority | **P0 in MVP.** Resolves PTT-OPEN-001 from `gen2/chanora-desktop-ptt-review-summary-v0.9.2.md`. The Windows backend ladder (Raw Input → low-level keyboard hook → Focused fallback) is mandatory for the first public release; release notes shall not claim Global PTT support on Windows until live measurement confirms a Global level from a non-fallback rung. | Accepted | Product Owner + Windows Platform Owner | Sets the MVP commitment level for the most common desktop platform. |
| DEC-024 | macOS desktop Global PTT priority | **P0 in MVP, with explicit permission UX flow.** Resolves PTT-OPEN-002. The macOS backend shall request the Input Monitoring / Accessibility permission, accept user denial gracefully (continue at `L0Focused` without functional regression), and upgrade to Global asynchronously when the user grants the permission. | Accepted | Product Owner + macOS Platform Owner | Forces the permission UX to ship with the rest of the macOS audio path rather than as a follow-up. |
| DEC-025 | Officially-tested Linux environment for first public release | **GNOME on Wayland (only).** Resolves PTT-OPEN-003. The Linux backend shall use the freedesktop `org.freedesktop.portal.GlobalShortcuts` interface on GNOME-on-Wayland and fall back to Focused PTT on every other Linux environment (X11, sway, KDE, untested compositors). Release notes shall not claim Global PTT support outside the tested compositor. | Accepted | Product Owner + Linux Platform Owner | Bounds the verification matrix; honest claim on Linux. |
| DEC-026 | Mouse side-button support in first desktop PTT release | **Supported on Windows and macOS; Linux follows whatever the GlobalShortcuts portal exposes.** Resolves PTT-OPEN-004. The Raw Input backend (Windows) and the Event Tap backend (macOS) shall accept Mouse4 / Mouse5 bindings; the Linux portal binding accepts whatever the session exposes and the release notes shall not over-claim. | Accepted | Product Owner + UX Owner | Common dedicated PTT input class; shipping in MVP avoids a follow-up. |
| DEC-027 | PTT diagnostics privacy posture | **Capability and availability state only — no raw key codes ever leave the device.** Resolves PTT-OPEN-005. The diagnostic export shall name only `PttCapabilityLevel`, `backend_id`, `bound_input_class`, and `fallback_exercised`; the user's actual key value (scan code, virtual key, keysym) shall never be logged, persisted, or exported. `PttSanitizer` enforces this at write time. | Accepted | Security Reviewer + Privacy Reviewer | Closes a clear privacy risk that the gen2 review flagged; aligns with DEC-016. |
| DEC-028 | Missed-key-up watchdog requirement | **P0.** Resolves PTT-OPEN-006. The audio engine shall include a missed-key-up watchdog that clears `transmit_active` after a configured ceiling (default 30 s) when no key-up event arrives. The watchdog is a P0 release-gate item rather than an implementation-level concern because the failure mode (stuck transmission after the user has released the binding) is user-visible and reputation-relevant. | Accepted | Audio Owner + Software Architect | Prevents stuck-PTT bug class regardless of platform-input quirks. |
| DEC-029 | Flutter global-hotkey packages rejected for PTT | **Use the native Rust `DesktopPttBackend` trait + per-OS implementations (already specified in SDD-083 / SDD-084 / SDD-085); do not adopt `hotkey_manager`, `super_hot_key`, or any equivalent pub.dev package for PTT.** Rationale: those packages wrap the OS `RegisterHotKey` / `RegisterEventHotKey` semantics — they consume the key (suppressing it from other applications), they do not deliver a key-up event, and they do not support mouse side-buttons. PTT requires the opposite primitive (observe, do not consume, deliver both up and down). | Accepted | Software Architect + Audio Owner | Locks the v1 PTT capture path to the native backend; removes ambiguity for future maintainers tempted to "simplify" via a Flutter package. |
| DEC-030 | Voice activity detection deferred to P1 | **`TransmitMode::VoiceActivity` ships as a reserved enum variant with no v1 implementation.** The settings UI shows it as a disabled "coming soon" option. The actual implementation choice is deferred to a future baseline. Rationale: three viable backends were compared (RMS energy threshold — trivial but quality-poor; WebRTC VAD via the `webrtc-vad` crate — frozen-but-stable C++ BSD-3 dep, ~200 KB binary, industry baseline; Silero VAD via ONNX Runtime — best quality but ~816 MB binary uplift per platform plus an ONNX-runtime dependency surface). The v1 dependency-surface budget does not have room for the trade-off review required to pick correctly. Choosing too early risks either user-visible quality regression (RMS) or a forced ONNX adoption (Silero) before there is a comparable need for ML inference elsewhere (noise suppression, AEC). | Accepted | Audio Owner + Product Owner | Locks v1 to PTT + Continuous; preserves the enum surface so a P1 increment is non-breaking. |
| DEC-031 | Missed-key-up watchdog disabled on P0; redesign deferred to P1 | **The `MissedKeyUpWatchdog` is constructed and unit-tested but is NOT spawned by `ChanoraSession::start_audio` in the P0 baseline.** Supersedes DEC-028 for the v1 ship. Rationale: the original 30 s ceiling cut real users off mid-sentence when speaking through PTT for longer than the timeout — Mumble and TeamSpeak do not ship a comparable watchdog, so the protection is stricter than industry baseline while imposing a real UX cost. The watchdog's purpose (catching OS-level key-up loss when the app loses focus / is minimised / hits App Nap) remains valid; the fixed-timeout shape is the wrong implementation. P1 will reintroduce a redesigned variant using one of: (a) raised ceiling (~5 min, owner-tunable) only, (b) active OS-level key-state polling via `GetAsyncKeyState` / `CGEventSourceKeyState` / `XQueryKeymap` so we detect the actual OS desync directly, (c) audio-activity (RMS-silence) fallback once the level meter lands, or (d) a combination. The Rust unit tests for `MissedKeyUpWatchdog::spawn_on_signal` remain in `crates/chanora_audio/src/ptt.rs` so the P1 re-enable is non-breaking. | Accepted | Audio Owner + Product Owner | Eliminates a P0-class UX regression (long PTT speech cut off at 30 s) while preserving the implementation surface for P1. |
## 4. Accepted MVP Defaults
The "Recommended" defaults below have all been confirmed by the owner;
two were modified from the original recommendation (marked **MODIFIED**).
| Area | Accepted MVP default |
|---|---|
| Release sequence | Internal Alpha → External Beta → MVP Public |
| MVP platforms | Windows, macOS, Linux, Android, iOS (staged release allowed) |
| Active connections | One active server connection |
| UI design system | Material 3 + Chanora Design System |
| Product language | **MODIFIED** — English + Chinese (Simplified) at MVP; i18n-ready architecture |
| Server content | Preserve and display Unicode; do not translate |
| Diagnostics | Local, user-initiated export only |
| Telemetry | None |
| Crash reporting | None unless later approved |
| Secret storage | Platform secure storage |
| Non-secret local storage | SQLite (`rusqlite` bundled) |
| Audio processing | Platform-native first; fallback strategy documented |
| AEC | Enabled by default where supported |
| AGC | Enabled by default (user-toggleable) |
| Noise suppression | Enabled by default (user-toggleable) |
| High-pass filter | Enabled by default |
| Android minimum | **MODIFIED** — API 28 (Android 9.0), raised from the original recommendation of API 24 |
| Android target | API 35 or newer per current Google Play policy on upload date |
| iOS minimum | iOS 13 |
| Apple App Store SDK gate | Xcode 26+ / iOS 26 SDK+ for uploads on or after 2026-04-28 |
| Audio crate | `cpal` (desktop, Android); iOS deferred |
| Bridge | Stable typed Flutter/Rust bridge; `flutter_rust_bridge` 2.x pinned |
| Implementation directory layout | `apps/chanora_flutter/`, `core/chanora_core/`, `crates/chanora_*` |
| License | **Dual-licensed under Apache-2.0 OR MIT**, recipient's choice (DEC-020) |
## 5. Decision Impact Matrix
| Decision | Affects SysRS | Affects SysDes | Affects SRS | Affects SAD | Affects SDD | Affects Verification | Affects Release |
|---|---|---|---|---|---|---|---|
| Minimum iOS / Android versions | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Android target SDK | No | No | Yes | No | No | Yes | Yes |
| Multiple active connections | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| AEC/AGC/NS/HPF defaults | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Audio implementation path | No if behavior unchanged | Yes | Possibly | Yes | Yes | Yes | Yes |
| SDK/trademark/legal review | Yes | No | No | No | No | Yes | Yes |
| SQLite/equivalent choice | Possibly | Yes | Yes | Yes | Yes | Yes | Yes |
| Bridge choice | No if API behavior unchanged | Yes | Possibly | Yes | Yes | Yes | Yes |
| Apple App Store SDK gate | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Diagnostics upload policy | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Crash reporting | Yes if included | Yes if included | Yes if included | Yes if included | Yes if included | Yes | Yes |
| Flutter hotkey packages rejected for PTT (DEC-029) | No | Yes | Yes | Yes | Yes | Yes | No |
| VAD deferred to P1 (DEC-030) | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
## 6. Decisions That Must Be Confirmed By You
All decisions in the register have been addressed by the owner. The
remaining release-gating *work* (not decisions) is the legal review
itself under DEC-012, which must complete before any public/store
release but is not an open decision:
| Priority | Item | Status |
|---|---|---|
| P0 | DEC-012 legal/trademark/licensing review — perform the actual review work (non-affiliation wording final sign-off, trademark registrability check, transitive-dependency OSS obligations, `tsclientlib` license posture confirmation). | Pending; gate Accepted. |
## 7. Open Decision Log
| Decision ID | Owner | Decision | Status | Date | Notes |
|---|---|---|---|---|---|
| DEC-001 | Product Owner | Release type sequence | Accepted | 2026-05-14 | Internal Alpha → External Beta → MVP Public. |
| DEC-002 | Product Owner / Engineering | MVP platform strategy | Accepted | 2026-05-14 | All five platforms as target; staged release allowed. |
| DEC-003 | Product Owner / iOS Owner | Minimum iOS version | Accepted | 2026-05-14 | iOS 13. |
| DEC-004 | Product Owner / Android Owner | Minimum Android version | Accepted | 2026-05-14 | **API 28** (modified from the recommendation of API 24). |
| DEC-005 | Android Owner / Release Manager | Android target SDK | Accepted | 2026-05-14 | Google Play-required API on upload date (currently API 35+). |
| DEC-006 | Product Owner / Software Architect | Multiple server connections in MVP | Accepted | 2026-05-14 | Single connection in MVP. |
| DEC-007 | Audio Owner / Product Owner | AEC default | Accepted | 2026-05-14 | Enabled by default where supported. |
| DEC-008 | Audio Owner / Product Owner | AGC default | Accepted | 2026-05-14 | Enabled by default with user toggle. |
| DEC-009 | Audio Owner / Product Owner | Noise suppression default | Accepted | 2026-05-14 | Enabled by default with user toggle. |
| DEC-010 | Audio Owner | High-pass filter default | Accepted | 2026-05-14 | Enabled by default. |
| DEC-011 | Software Architect / Audio Owner | Audio processing path | Accepted | 2026-05-14 | Platform-native first; Rust/WebRTC-style fallback. |
| DEC-011.1 | Software Architect / Audio Owner | Audio crate (desktop / mobile) | Accepted (desktop: `cpal`; Android: `cpal`-on-Oboe) / Deferred (iOS) | 2026-05-13 | Closed by `poc/audio-capture-playback-spike` (desktop) and `poc/audio-capture-playback-android-spike` (Android). iOS crate TBD pending iOS spike. |
| DEC-012 | Legal / Compliance | SDK/trademark/licensing review | Accepted as a release gate | 2026-05-14 | Required before public/store release; legal review work still to be performed. |
| DEC-013 | Software Architect / Storage Owner | Local database | Accepted | 2026-05-14 | SQLite or equivalent for non-secret state. |
| DEC-013.1 | Software Architect / Storage Owner | SQLite crate | Accepted (`rusqlite` bundled) | 2026-05-13 | Closed by `poc/sqlite-storage-spike` 11/11. |
| DEC-013.2 | Software Architect / Storage Owner / Security Reviewer | Linux secure-storage backend policy | Accepted (Secret Service preferred, keyutils fallback) | 2026-05-13 | Closed by `poc/secure-storage-spike` 6/6. Resolves SysRS-053 / SysRS-162 ambiguity. |
| DEC-014 | Software Architect | Bridge choice | Accepted (`flutter_rust_bridge` 2.x pinned) | 2026-05-13 | Closed by `poc/flutter_rust_bridge_hello` 3/3. |
| DEC-015 | Product Owner | Product language for MVP | Accepted | 2026-05-14 | **English + Chinese (Simplified)** (modified from the recommendation of English-only). |
| DEC-016 | Product Owner / Legal / Security | Diagnostics upload policy | Accepted | 2026-05-14 | User-initiated local export only; no automatic upload. |
| DEC-017 | Product Owner / Legal / Security | Crash reporting | Accepted | 2026-05-14 | Disabled for MVP. |
| DEC-018 | Product Owner | Public product name | Accepted | 2026-05-14 | Chanora. Trademark check still required under DEC-012. |
| DEC-019 | Legal / Compliance | Public non-affiliation statement | Accepted (drafted wording) | 2026-05-14 | Final legal sign-off still required under DEC-012. |
| DEC-020 | Product Owner / Legal | License model | Accepted (Apache-2.0 OR MIT dual-license) | 2026-05-14 | Compatible with every direct dependency; texts ship as LICENSE-APACHE / LICENSE-MIT. Full OSS legal review remains under DEC-012. |
| DEC-021 | iOS Owner / Release Manager | Apple App Store SDK gate | Accepted | 2026-05-14 | Xcode 26+ / iOS 26 SDK+ on or after 2026-04-28. |
| DEC-022 | Software Architect | Canonical implementation directory layout | Accepted (README sketch) | 2026-05-13 | Closes the absence flagged during PoC review. |
| DEC-023 | Product Owner / Windows Platform Owner | Windows desktop Global PTT priority | Accepted (P0 / MVP) | 2026-05-15 | Resolves PTT-OPEN-001 from the gen2 desktop-PTT review. |
| DEC-024 | Product Owner / macOS Platform Owner | macOS desktop Global PTT priority | Accepted (P0 / MVP, permission-UX required) | 2026-05-15 | Resolves PTT-OPEN-002. |
| DEC-025 | Product Owner / Linux Platform Owner | Officially-tested Linux environment | Accepted (GNOME on Wayland only) | 2026-05-15 | Resolves PTT-OPEN-003. |
| DEC-026 | Product Owner / UX Owner | Mouse side-button support | Accepted (Windows + macOS; Linux portal-dependent) | 2026-05-15 | Resolves PTT-OPEN-004. |
| DEC-027 | Security / Privacy Reviewer | PTT diagnostics privacy posture | Accepted (capability + availability only, no key codes) | 2026-05-15 | Resolves PTT-OPEN-005. |
| DEC-028 | Audio Owner / Software Architect | Missed-key-up watchdog | Accepted (P0) | 2026-05-15 | Resolves PTT-OPEN-006. |
| DEC-029 | Software Architect / Audio Owner | Flutter global-hotkey packages rejected for PTT | Accepted | 2026-05-15 | Native `DesktopPttBackend` is the v1 PTT capture path; pub.dev hotkey packages consume the key, drop key-up events, and skip mouse side-buttons. |
| DEC-030 | Audio Owner / Product Owner | Voice activity detection deferred to P1 | Accepted (deferred to P1) | 2026-05-15 | `TransmitMode::VoiceActivity` reserved on the enum surface; UI shows "coming soon"; backend choice (RMS / WebRTC / Silero) deferred for dependency-surface review. |
| DEC-031 | Audio Owner / Product Owner | Missed-key-up watchdog disabled on P0; redesign deferred to P1 | Accepted (supersedes DEC-028 for P0) | 2026-05-16 | Watchdog implementation + tests retained; not spawned by `ChanoraSession::start_audio` in v1. P1 chooses between raised ceiling / OS key-state polling / RMS-silence fallback. |
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Updated decision register with proposed decisions for mobile minimum versions, audio defaults, audio implementation path, legal review, local database, bridge choice, diagnostics policy, and MVP release scope. |
## 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+ for App Store Connect upload on or after 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-14 | Recorded owner-confirmed decisions surfaced during the initial PoC phase: DEC-014 Accepted (`flutter_rust_bridge` 2.x pinned); added DEC-011.1 Accepted for desktop (`cpal`) / Deferred for mobile; added DEC-013.1 Accepted (`rusqlite` bundled); added DEC-013.2 Accepted (Linux Secret Service preferred with keyutils fallback); added DEC-022 Accepted (canonical implementation directory layout per README sketch and SAD §7.2); DEC-020 explicitly Deferred and remains a public-release blocker. Evidence pointers: `poc/flutter_rust_bridge_hello/VERIFICATION.md`, `poc/secure-storage-spike/VERIFICATION.md`, `poc/sqlite-storage-spike/VERIFICATION.md`, `poc/audio-capture-playback-spike/VERIFICATION.md`. |
## Baseline Candidate 0.9.4 Update
| Version | Date | Description |
|---|---|---|
| 0.9.4 | 2026-05-14 | Promoted DEC-011.1 mobile half from Deferred to Accepted (Android), keeping iOS Deferred. Evidence: `poc/audio-capture-playback-android-spike/VERIFICATION.md` records empirical playback (22,050 frames at 44.1 kHz mono out of the device speaker) and capture (42,624 frames written to a valid 85,292-byte RIFF/WAVE mono 16-bit PCM file) on a physical Motorola Moto G Stylus 5G (2023) running Android 14 arm64-v8a, verifying the full Rust → cpal → Oboe → AAudio → Android audio HAL path. |
## Baseline Candidate 0.9.5 Update
| Version | Date | Description |
|---|---|---|
| 0.9.5 | 2026-05-14 | Owner confirmation pass on all previously-Proposed decisions. Accepted: DEC-001, DEC-002, DEC-003, DEC-005, DEC-006, DEC-007, DEC-008, DEC-009, DEC-010, DEC-011, DEC-012 (as a release gate), DEC-013, DEC-015, DEC-016, DEC-017, DEC-018, DEC-019 (drafted wording), DEC-021. Two decisions modified from their original recommendations: **DEC-004 Android minimum** raised from API 24 to **API 28** (simpler audio path, narrower compatibility surface); **DEC-015 product language** expanded from English-only to **English + Chinese (Simplified)** for MVP (reflects the demonstrated TS3-compatible-server audience). DEC-020 license model remains Open / Deferred — the only public-release blocker outstanding. §4 renamed from "Recommended MVP Defaults" to "Accepted MVP Defaults" with MODIFIED rows annotated. §6 collapsed to the single remaining DEC-020 item. §7 dated and statused. |
## Baseline Candidate 0.9.6 Update
| Version | Date | Description |
|---|---|---|
| 0.9.6 | 2026-05-14 | DEC-020 license model closed: **Apache-2.0 OR MIT** dual-license (standard Rust-ecosystem permissive model). The license is compatible with every direct dependency in the PoC tree (tsclientlib, flutter_rust_bridge, cpal, rusqlite, keyring, hound, etc.) and with the Flutter framework's BSD-3-Clause. License texts added as `LICENSE-APACHE` and `LICENSE-MIT` at the repository root; the existing `LICENSE` file now aggregates both with the dual-license declaration and the standard Apache-2.0 inbound-contribution clause. `NOTICE` populated with current direct-dependency attributions. README §License rewritten. §4 updated. §6 collapsed: there is no longer any open decision — DEC-012 legal review remains a pending *work* item, not a pending decision. With this change, every previously-Proposed or Open decision in the register has been resolved; the only outstanding release-gating activity is the DEC-012 legal review itself (which is sign-off work, not an architectural choice). |
## Baseline Candidate 0.9.7 Update
| Version | Date | Description |
|---|---|---|
| 0.9.7 | 2026-05-14 | DEC-001 release-sequence progress recorded: Internal Alpha (`v0.1.0-alpha.1`, commit 3bb038c) completed on 2026-05-14; **Internal Beta first build (`v0.2.0-beta.1`)** reached the same day. Beta milestone adds voice in/out: `crates/chanora_audio` promoted from scaffold to a cpal-based capture + playback engine with `audiopus` Opus encoding and tsclientlib `AudioHandler` for decode + jitter buffer + mix; `crates/chanora_protocol` extended to forward inbound voice packets and accept outbound `OutPacket`s via mpsc channels; `core/chanora_core::ChanoraSession` exposes `start_audio`, `set_ptt`, and `audio_stats`; `crates/chanora_bridge` adds matching DTOs; the Flutter UI gains a "Start audio" action and a hold-to-talk PTT button with live frame counters. Verified end-to-end against `cn.teamspeak.app`; capture runs in graceful playback-only mode on hosts with no usable microphone (e.g. the PipeWire `auto_null` source on the verification host). No decision rows change; this entry documents progress against DEC-001 only. |
| 0.9.8 | 2026-05-15 | DEC-001 release-sequence progress recorded for the polished Internal Beta and the External Beta milestones, plus the first MVP-public release candidate. **`v0.3.0-beta.1`** ("Internal Beta polish") added the supervisor + reconnect-with-watchdog path (A.6), OS-connectivity-aware backoff (A.6.1), persistent identity at rest as a plain 0600 file (A.2), the redacted in-memory log sink + user-initiated diagnostic export per DEC-016 (A.3), the `SnapshotChanged` lifecycle event for UI auto-refresh (A.4), and the `mobile_voice_preset` config-surface plumb-through (A.5). **`v0.4.0-beta.2`** ("External Beta") added the server-password input, channel join via tap, self mute (input + output), master output gain, SQLite-backed bookmark list, ChaCha20-Poly1305 encryption of the identity at rest with the DEK in a separate `identity.dek` file, Android `AudioManager.setMode(MODE_IN_COMMUNICATION)` routing engagement via JNI, and the `.github/workflows/ci.yml` pipeline. **`v1.0.0-rc.1`** ("MVP Public release candidate") closes the v0.4 DEK-on-disk weakness on every keyring-reachable platform: `chanora_storage::IdentityFileStore` now stores the DEK in the OS keyring (Linux Secret Service via D-Bus / macOS Keychain / Windows Credential Manager / iOS Keychain via the `keyring` crate) and migrates pre-existing file-fallback installs into the keyring opportunistically; bookmark server passwords are ChaCha20-Poly1305-encrypted under the same per-install DEK and the legacy plain `password TEXT` column is upgraded into a new `password_blob BLOB` column on the next `update()`; `SessionEvent::SnapshotChanged` now fires on any tree mutation (the in-channel-move blind spot from A.4 is closed); the in-app About dialog surfaces DEC-018 / DEC-019 / DEC-020. New `docs/governance/legal-review-readiness.md` carries the DEC-012 handoff package (trademark check, non-affiliation wording, third-party license posture, `cargo about` deliverables, `cargo deny` lifelines); new `docs/governance/staged-release-plan.md` enumerates the DEC-002 platform staging (Linux + Android sideload GA on DEC-012 sign-off; Windows, macOS, iOS gate on per-platform signed-build availability). No decision rows change; DEC-012 remains the sole outstanding release gate. |
| 0.9.9 | 2026-05-15 | Recorded six new accepted decisions DEC-023 through DEC-028 closing the gen2 desktop-PTT review's open questions PTT-OPEN-001 through PTT-OPEN-006: Windows Global PTT is P0/MVP (DEC-023), macOS Global PTT is P0/MVP with permission UX (DEC-024), the officially-tested Linux environment is GNOME-on-Wayland only (DEC-025), mouse side buttons are supported on Windows + macOS and Linux follows the portal (DEC-026), PTT diagnostics carry capability/availability only with no raw key codes (DEC-027), and the missed-key-up watchdog is a P0 release-gate requirement (DEC-028). No prior decision rows are mutated. |
| 0.9.10 | 2026-05-15 | Code-side promotion: the Linux GNOME-Wayland backend (DEC-025) is now a live `org.freedesktop.portal.GlobalShortcuts` session — `CreateSession` + `BindShortcuts` + `Activated` / `Deactivated` signal subscription scoped to the session handle, owned by a dedicated tokio task per backend instance. The Flutter "Configure" button on Linux portal delegates to the portal's own system dialog (Q3a) rather than the in-app `_PttBindingCaptureDialog`. Descriptor transitions broadcast via a `watch::Sender` consumed by `chanora_core::ChanoraSession::start_audio` and forwarded to `SessionEvent::PttCapability`. Cancellation / failure path downgrades to `L0Focused` and re-emits. No decision rows mutate. |
| 0.9.11 | 2026-05-15 | Added DEC-029 and DEC-030 covering the v1 audio + PTT lifecycle redesign. DEC-029 rejects Flutter global-hotkey packages (`hotkey_manager`, `super_hot_key`, equivalents) for PTT — they consume the key, do not deliver key-up, and do not support mouse side-buttons; the native Rust `DesktopPttBackend` already specified in SDD-083 / SDD-084 / SDD-085 is the v1 capture path. DEC-030 defers Voice Activity Detection to P1: `TransmitMode::VoiceActivity` ships as a reserved enum variant with no v1 implementation pending a backend trade-off review (RMS vs WebRTC VAD vs Silero VAD differ by ~816 MB and an ONNX-runtime dependency surface). No prior decision rows mutate; §5 impact matrix and §7 open-decision log gain matching rows. |
| 0.9.12 | 2026-05-16 | Added DEC-031: missed-key-up watchdog is disabled on P0 (supersedes DEC-028 for the v1 ship). The 30 s default ceiling spec'd in DEC-028 was cutting real PTT users off mid-sentence whenever a single utterance crossed the timeout; the watchdog's intent (catching OS-level key-up loss) remains valid, but the fixed-timeout implementation is the wrong shape. The `MissedKeyUpWatchdog` Rust type and its unit tests remain in `crates/chanora_audio/src/ptt.rs`; only the `ChanoraSession::start_audio` spawn is removed. P1 will choose between a raised ceiling, OS key-state polling (`GetAsyncKeyState` / `CGEventSourceKeyState` / `XQueryKeymap`), an RMS-silence fallback paired with the audio level meter, or a combination. DEC-028 stays in the register as historical context. |
## Baseline Candidate 0.9.8 Update — DEC-032
### DEC-032 — Temporary reduction of Android `abiFilters` to `arm64-v8a` only during P0 smoke-test cycle
| Field | Value |
|---|---|
| Decision ID | DEC-032 |
| Title | Temporary reduction of Android `abiFilters` to `arm64-v8a` only during P0 smoke-test cycle. |
| Status | **Resolved (canonical three-ABI set restored)** |
| Owner | Build/Toolchain |
| Restore-by | P0 release gate (must be restored before any P0 release upload). |
| Date recorded | 2026-05-18 |
| Date resolved | 2026-05-18 |
| Supersedes | None (temporary deviation from SDD-073 item 4 and SDD-118 item 3; does NOT supersede them). |
**Resolution (2026-05-18).** All four exit criteria below are met.
The propagation gap (criterion 1) is closed by a workspace
`[patch.crates-io]` stanza pinning the `cmake` crate to a fork
carrying cmake-rs PR #257
(<https://github.com/rust-lang/cmake-rs/pull/257>), which forwards the
`ANDROID_ABI` and `ANDROID_PLATFORM` environment variables (set per-
invocation by `cargo-ndk` 4.x and reinforced by the SDD-118 item 5
cleanEnv map) to the child `cmake` invocation as `-D` variables. The
fork is pinned by exact commit SHA
(`bdad5edc569d82151922c5c6c4685b1563f12aa1` on `pr2502/cmake-rs`,
branch `android-build`) for reproducibility — see the
`[patch.crates-io]` block in the workspace root `Cargo.toml`. Per-ABI
`cargo ndk --platform 28 -t <abi> build -p chanora_bridge` now passes
cleanly for all three ABIs (criterion 2). `abiFilters` in
`apps/chanora_flutter/android/app/build.gradle.kts` is restored to
`{arm64-v8a, armeabi-v7a, x86_64}` and the `TODO(x86_64/armv7
follow-up)` comment removed (criterion 3). The SDD-118 item 10
release-inspection assertion exercises every staged `.so` (including
`libc++_shared.so` per SDD-118 item 6 extended) for all three ABIs
again — no code change required, that assertion is driven by the
restored `abiFilters` set (criterion 4). Upstream tracking: re-
evaluate the `[patch.crates-io]` override once PR #257 merges and a
fresh `cmake` crates.io release lands; at that point the patch
should be removed in favour of a plain dep bump.
**Context.** SDD-073 item 4 and SDD-118 item 3 mandate the canonical
three-ABI set `{arm64-v8a, armeabi-v7a, x86_64}` for the Android AAB.
`apps/chanora_flutter/android/app/build.gradle.kts:72-79` currently has
`abiFilters` reduced to `arm64-v8a` only with a `TODO(x86_64/armv7
follow-up)` comment explaining the reduction.
**Cause.** The `audiopus_sys` + `cmake-rs` + NDK toolchain-file
interaction does not propagate `ANDROID_ABI` as a CMake variable when
invoked via the Gradle Exec task chain. `armeabi-v7a` and `x86_64`
builds fail because the inner CMake configure step does not see the
correct `-DANDROID_ABI=<abi>` argument. `arm64-v8a` (the smoke-test
emulator target) builds cleanly because it happens to be the default
that `cmake-rs` emits when no `ANDROID_ABI` is propagated.
**Scope.** Smoke-test build only. The P0 release **must** restore the
full three-ABI set before any release upload. Internal Beta / RC
builds for the smoke-test emulator path may continue using the
reduced set while the cmake-rs propagation fix is in flight.
**Exit criteria (all four must be met to close DEC-032).**
1. `audiopus_sys` / `cmake-rs` `ANDROID_ABI` propagation gap resolved
(research + builder-dispatch fix; root-cause whether upstream
`cmake-rs` patch, a builder-side env override, or a Gradle-Exec
level argument injection is the correct fix).
2. All three ABIs (`arm64-v8a`, `armeabi-v7a`, `x86_64`) compile
cleanly in CI for `chanora_bridge` cdylib.
3. The `abiFilters` declaration in
`apps/chanora_flutter/android/app/build.gradle.kts` is restored to
the canonical three-ABI set, and the `TODO(x86_64/armv7
follow-up)` comment removed.
4. The SDD-118 item 10 release-inspection assertion confirms that all
three `libchanora_bridge.so` files **and** all three
`libc++_shared.so` co-staged files (per SDD-118 item 6 extended,
absorbed into the traceability matrix v0.9.9 addendum) are present
in any release AAB.
**Impact assessment.**
- `arm64-v8a` installs work on all 64-bit modern Android devices,
including the smoke-test emulator and every device meeting the
DEC-004 API 28 minimum on 64-bit hardware.
- `armeabi-v7a` (32-bit ARM Android, ~1% of the 2026 active install
base for app-stores that still permit 32-bit) installations are
**blocked** until restoration. Affected users see Play Store
filtering and cannot install the AAB.
- `x86_64` (some Android emulators outside the smoke-test loop, rare
Chromebook deployments, some VMs) installations are **blocked**
until restoration.
- **P0 release-gate cannot pass** until the three-ABI set is
restored: release-inspection assertion (SDD-118 item 10) would
fail, and the canonical SDD-073 item 4 / SDD-118 item 3 contract
would be violated.
- No SDD edit is required: the deviation is governance-layer only
and the SDD canonical intent is unchanged.
**Cross-references.**
- SDD-073 item 4 (canonical Android ABI set).
- SDD-118 item 3 (Gradle automation enforcing the three-ABI set);
also item 6 (extended) for `libc++_shared.so` co-staging and item
10 for the release-inspection assertion that any future restoration
must satisfy.
- `apps/chanora_flutter/android/app/build.gradle.kts:72-79`
(in-source TODO comment marking the deviation site).
- Audit task `ses_1c7645e36ffeY007MaYPep4wqs` (auditor New-D — origin
of this DEC entry).
- Traceability matrix v0.9.9 §D (governance cross-reference).
- DEC-031 (separate temporary deviation, for `MissedKeyUpWatchdog`
P0 disable) — listed only as precedent for the
"Active (temporary deviation)" status pattern; no direct technical
overlap.
**§3 row (for canonical table consistency).**
| Decision ID | Decision | Recommended decision | Status | Owner | Why it matters |
|---|---|---|---|---|---|
| DEC-032 | Android `abiFilters` set during P0 smoke-test cycle | Canonical three-ABI set `{arm64-v8a, armeabi-v7a, x86_64}` (per SDD-073 item 4 / SDD-118 item 3) restored 2026-05-18 after the `audiopus_sys` + `cmake-rs` + NDK toolchain-file `ANDROID_ABI` propagation gap was closed via a workspace `[patch.crates-io]` override pinning `cmake` to a fork carrying cmake-rs PR #257 | **Resolved** | Build/Toolchain | Multi-ABI install support restored; P0 release-gate ABI blocker cleared. Re-evaluate the `[patch.crates-io]` override once cmake-rs PR #257 merges and a fresh release lands. |
**§5 row (impact matrix).**
| Decision | Affects SysRS | Affects SysDes | Affects SRS | Affects SAD | Affects SDD | Affects Verification | Affects Release |
|---|---|---|---|---|---|---|---|
| `abiFilters` temporary reduction (DEC-032) | No | No | No | No | No (canonical intent unchanged; SDD-073 item 4 / SDD-118 item 3 stand) | Yes (release-inspection assertion path) | Yes (release-gate blocker until restored) |
**§7 row (open decision log).**
| Decision ID | Owner | Decision | Status | Date | Notes |
|---|---|---|---|---|---|
| DEC-032 | Build/Toolchain | Temporary reduction of Android `abiFilters` to `arm64-v8a` only during P0 smoke-test cycle | Resolved (2026-05-18) | 2026-05-18 | Canonical three-ABI set restored 2026-05-18. Root cause (`audiopus_sys` + `cmake-rs` + NDK toolchain-file `ANDROID_ABI` propagation gap) closed by a workspace `[patch.crates-io]` override pinning the `cmake` crate to fork `pr2502/cmake-rs` @ `bdad5edc569d82151922c5c6c4685b1563f12aa1` carrying cmake-rs PR #257 (forwards `ANDROID_ABI` / `ANDROID_PLATFORM` env vars as `-D` variables to the child cmake). All four exit criteria met. Follow-up: drop the `[patch.crates-io]` override once PR #257 merges and a fresh `cmake` release lands. SDD-073 item 4 / SDD-118 item 3 unchanged. |
### Change history
| Version | Date | Description |
|---|---|---|
| 0.9.8 | 2026-05-18 | Added DEC-032: temporary reduction of Android `abiFilters` to `arm64-v8a` only during the P0 smoke-test cycle. Status: Active (temporary deviation) from SDD-073 item 4 / SDD-118 item 3, which both remain unchanged. Restore-by gate: any P0 release upload must restore the canonical three-ABI set `{arm64-v8a, armeabi-v7a, x86_64}` and satisfy the SDD-118 item 10 release-inspection assertion (including the `libc++_shared.so` co-staging per SDD-118 item 6 extended). Root cause: `audiopus_sys` + `cmake-rs` + NDK toolchain-file `ANDROID_ABI` propagation gap. Owner: Build/Toolchain. Cross-references: SDD-073 item 4, SDD-118 item 3 (+ item 6 extended, item 10), `apps/chanora_flutter/android/app/build.gradle.kts:72-79` (in-source TODO), audit task ses_1c7645e36ffeY007MaYPep4wqs, traceability matrix v0.9.9 addendum §D. No prior decision row mutates. |
| 0.9.8.1 | 2026-05-18 | DEC-032 **Resolved**: canonical three-ABI set `{arm64-v8a, armeabi-v7a, x86_64}` restored in `apps/chanora_flutter/android/app/build.gradle.kts`. Root cause closed by a workspace `[patch.crates-io]` stanza in the repo-root `Cargo.toml` pinning the `cmake` crate to fork `pr2502/cmake-rs` @ commit `bdad5edc569d82151922c5c6c4685b1563f12aa1` (branch `android-build`), which carries cmake-rs PR #257 forwarding the `ANDROID_ABI` and `ANDROID_PLATFORM` environment variables (set per invocation by `cargo-ndk` 4.x and reinforced by the SDD-118 item 5 cleanEnv map) to the child `cmake` invocation as `-D` variables. Verification (host: Linux): `cargo ndk --platform 28 -t arm64-v8a build -p chanora_bridge`, `... -t armeabi-v7a ...`, and `... -t x86_64 ...` all pass cleanly. `cargo check --workspace --all-targets` passes on the host target. SDD-073 item 4 / SDD-118 item 3 unchanged (canonical intent was always the three-ABI set). Follow-up: re-evaluate the `[patch.crates-io]` override once cmake-rs PR #257 merges and a fresh `cmake` release lands; at that point switch to a plain dep bump and remove the override. No prior decision row mutates. |
@@ -1,77 +0,0 @@
# Repo Documentation Format Validation Report
**Document type:** Configuration / Validation Report
**Version:** 0.9.3
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/repo-format-validation-report.md`
---
## 1. Package
```text
chanora-docs-repo-format-v0.9.3
```
## 2. File Count
| Type | Count |
|---|---:|
| Markdown files under docs/ | 38 (added `docs/architecture/desktop-ptt-architecture.md`) |
| README files | 1 |
## 3. Naming Check
| Check | Result |
|---|---:|
| Old `CHANORA_*_v*.md` filename references outside migration map | 0 |
| Old `CHANORA_*_v*.zip` package references outside migration map | 0 |
| CJK characters in en-only doc set | 0 |
## 4. Defined ID Counts
| ID family | Defined IDs |
|---|---:|
| SysRS | 302 |
| SysDes | 148 |
| SRS | 203 |
| SAD | 80 |
| SDD | 93 |
## 5. Undefined Reference Check
| ID family | Undefined references |
|---|---:|
| SysRS | 0 |
| SysDes | 0 |
| SRS | 0 |
| SAD | 0 |
| SDD | 0 |
## 6. Direct-Layer Rule Check
| Rule | Result |
|---|---:|
| SRS direct SysRS references | 0 |
| SAD direct SysRS references | 0 |
| SAD direct SysDes references | 0 |
| SDD direct SysRS references | 0 |
| SDD direct SysDes references | 0 |
| SDD direct SRS references | 0 |
## 7. Old Reference Details
| Type | Values |
|---|---|
| Old markdown filename references outside migration map | None |
| Old ZIP filename references outside migration map | None |
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Validated repository-format documentation package and internal filename reference updates. |
| 0.9.3 | 2026-05-15 | Re-validated repository-format after desktop PTT update: added `docs/architecture/desktop-ptt-architecture.md`; ID totals advance to 302 / 148 / 203 / 79 / 92; naming, undefined-reference, and direct-layer-rule counts remain at zero. |
| 0.9.4 | 2026-05-15 | P0 audit follow-up: ID totals advance to 302 / 148 / 203 / 80 / 93 after adding `SAD-080` (sources SRS-200) and `SDD-093` (sources SAD-080). Direct-layer-rule and undefined-reference counts remain zero. |
@@ -1,72 +0,0 @@
# Repository Bootstrap Plan
**Document type:** Governance / Repository Bootstrap Plan
**Version:** 0.1.0
**Status:** Draft
**Language:** English
**Product:** Chanora
**Repo path:** `docs/governance/repository-bootstrap-plan.md`
---
## 1. Purpose
This document defines the files and directories that should exist before product implementation begins.
## 2. Bootstrap Scope
This bootstrap package intentionally excludes CI workflow files.
The goal is to establish:
- repository metadata;
- contributor guidance;
- security policy;
- changelog;
- license placeholder;
- notice placeholder;
- editor and ignore rules;
- local command placeholders;
- documentation validation script;
- future scaffold plan.
## 3. Required Root Files
| File | Purpose |
|---|---|
| `README.md` | App/project overview |
| `CONTRIBUTING.md` | Contribution rules |
| `SECURITY.md` | Security reporting and security gates |
| `CHANGELOG.md` | Release/change history |
| `LICENSE` | License placeholder until final license decision |
| `NOTICE` | Non-affiliation and attribution placeholder |
| `.editorconfig` | Editor formatting baseline |
| `.gitignore` | Ignore rules |
| `.env.example` | Safe local environment template |
| `justfile` | Local command entrypoint |
## 4. Required Tooling Files
| File | Purpose |
|---|---|
| `tools/validate_docs.py` | Local documentation and traceability validation |
## 5. Future Work
CI workflow files should be added later after this bootstrap is committed and the repo structure is accepted.
Recommended later CI files:
```text
.github/workflows/docs.yml
.github/workflows/repo-health.yml
.github/workflows/flutter.yml
.github/workflows/rust.yml
.github/workflows/security.yml
```
## 6. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial repository bootstrap plan excluding CI. |
-111
View File
@@ -1,111 +0,0 @@
# Staged MVP release plan — DEC-002 channels
| Version | Date | Status |
|---|---|---|
| 0.1.0 | 2026-05-15 | Initial draft alongside v1.0.0-rc.1 |
## Purpose
DEC-002 in `product-decision-register.md` accepts a five-platform
MVP target (Windows, macOS, Linux, Android, iOS) and explicitly
permits a **staged release** in which not all platforms ship on the
same day. This document records the staging plan for the MVP public
release.
## Channel definitions
* **GA — Linux desktop**: x86_64 GNU/Linux. Direct distribution
via the GitHub Releases page (release tarball + AppImage when
the bundle is added). No app store.
* **GA — Android**: arm64-v8a APK. Direct distribution from the
Releases page during early MVP. Play Store submission deferred
until DEC-012 legal sign-off includes Play-specific consumer-
protection review (`docs/governance/legal-review-readiness.md`
§9). Other Android ABIs (armeabi-v7a, x86_64) are deferred to
v1.1.
* **Beta — Windows**: x86_64 MSI / portable zip. The build steps
are documented in `docs/release/windows-build.md`; a live
artefact has not yet been produced because the development
toolchain ran on Linux. Public bits land once a Windows builder
produces a signed artefact.
* **Beta — macOS**: Apple Silicon (`aarch64-apple-darwin`) + Intel
(`x86_64-apple-darwin`) universal `.app`. Same gating as Windows:
build documentation only at v1.0.0-rc.1; an Apple-side builder
must produce a notarised artefact.
* **Beta — iOS**: arm64 IPA. Same gating; in addition the
`mobile_voice_preset` AAudio engagement on Android is documented
as a routing hint, and the iOS equivalent
(`AVAudioSession.Mode.voiceChat`) is not yet wired.
## Promotion schedule
Each row triggers when the listed prerequisite is satisfied. There
is no calendar.
| Order | Channel | Prerequisite |
|---|---|---|
| 1 | Linux GA | DEC-012 legal sign-off; `v1.0.0` tag cut from `v1.0.0-rc.N` after all RC reviews close. |
| 2 | Android GA (sideload) | Same prerequisite; APK signed with the project key; Releases page updated. |
| 3 | Android Play Store | DEC-012 §9 Play-listing review complete; signing key migrated to Play App Signing if not already there. |
| 4 | Windows Beta | Live x86_64 Windows builder produces a signed MSI; smoke test on a Windows 11 host that the build host can verify. |
| 5 | macOS Beta | Live `aarch64-apple-darwin` build with code-signing certificate and notarisation; smoke test. |
| 6 | iOS Beta | TestFlight build cycle; per-device entitlement review; mic permission flow validated. |
| 7 | Windows / macOS / iOS GA | Each platform promoted from Beta after its first round of public-Beta feedback is triaged. |
## Per-platform readiness as of v1.0.0-rc.1
### Linux x86_64
* Cargo build: green (`cargo check --workspace`, `cargo test
--workspace` with `CHANORA_DISABLE_KEYRING=1`).
* Flutter build: `flutter build linux --release` documented; live
bundle exists at `apps/chanora_flutter/build/linux/x64/`.
* Audio: cpal-on-PipeWire / ALSA verified through Beta lifecycle.
* Secure storage: Secret Service via D-Bus when a session is
available; file-fallback when not.
* Status: **GA-ready** pending DEC-012.
### Android arm64-v8a
* Cargo + cargo-ndk build: green; the APK pipeline produced
`app-release.apk` for v0.4.0-beta.2.
* Audio: cpal-on-AAudio with `AudioManager.MODE_IN_COMMUNICATION`
engaged via JNI on engine start.
* Secure storage: keyring crate falls back to file on Android in
v1.0.0-rc.1 (no Android Keystore wiring yet). The identity and
bookmark passwords remain ChaCha20-Poly1305-encrypted under the
file-DEK in this configuration.
* Status: **GA-ready for sideload** pending DEC-012; Play Store
promotion is a separate gate.
### Windows / macOS / iOS
* Build docs exist (`docs/release/windows-build.md`,
`docs/release/ios-build.md`); macOS does not have a dedicated
doc yet because the build is a straightforward
`flutter build macos` once Apple-side signing is configured.
* Status: **Beta-track**. The RC tag still ships for these
platforms in source form (anyone with the appropriate toolchain
can build), but no signed binary is included.
## Rollback policy
Each platform's Releases-page artefact carries the exact `v1.0.0-rc.N`
or `v1.0.0` tag. If a critical regression surfaces in a channel:
1. Mark the affected Releases asset "deprecated — do not download" in
the GitHub UI within 24h.
2. Cut a `v1.0.x` patch from the `release-1.0` branch (created
when `v1.0.0` is tagged).
3. Re-promote per the schedule above; no platform fast-tracks the
schedule, no platform skips a channel.
## Out-of-scope for MVP
* iOS hardware AEC engagement (`AVAudioSession.Mode.voiceChat`).
* Android `setInputPreset(VOICE_COMMUNICATION)` (RISK-AUDIO-MOBILE-001).
* Android Keystore-backed DEK (the file-fallback path is exercised in
the current build).
* Multi-server connection (DEC-006: explicitly out of MVP).
* Crash reporting (DEC-017: explicitly disabled).
* Automatic diagnostic upload (DEC-016: user-initiated only).
File diff suppressed because it is too large Load Diff
-87
View File
@@ -1,87 +0,0 @@
# Chanora Internationalization and Localization Architecture
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Repo path:** `docs/i18n/localization-architecture.md` ---
## 1. Purpose
This document defines Chanora's i18n architecture. Chanora is expected to operate in multilingual environments where product UI language, server-provided names, user nicknames, channel names, chat messages, and diagnostics may contain different languages.
## 2. i18n Principles
| Principle | Rule |
|---|---|
| Product strings are localizable | UI copy, labels, settings, errors, and accessibility labels use localization resources. |
| Server content is not translated | Server names, channel names, client nicknames, and chat messages are displayed as content. |
| UTF-8 internal text | Cross-layer DTOs and storage use UTF-8-compatible strings. |
| Boundary conversion only | Non-UTF-8 conversion occurs only at explicit protocol or platform boundaries. |
| Diagnostics are stable | Machine-readable diagnostic keys remain language-neutral. |
| User-facing diagnostics may be localized | Diagnostic descriptions can be localized independently. |
| Fallback is deterministic | Missing translations fall back to English or configured baseline locale. |
## 3. Text Categories
| Category | Example | Handling |
|---|---|---|
| Product UI string | "Connect", "Settings" | Localized |
| Accessibility string | "Mute microphone" | Localized |
| Protocol/server content | Server name, channel name | Preserve and display |
| User content | Chat message, nickname | Preserve and display |
| Machine diagnostic key | `audio.device.route_changed` | Stable, not localized |
| Diagnostic description | "Audio route changed" | Localizable |
## 4. Encoding Architecture
```text
External server text
-> Protocol Adapter boundary conversion if required
-> UTF-8-compatible Rust DTO
-> Bridge DTO
-> Flutter ViewModel
-> Flutter Text rendering
Product string key
-> Localization Service
-> Locale resource lookup
-> Fallback if missing
-> Flutter rendering
```
## 5. Bidi and Mixed-Language Handling
The UI shall not assume that all text is left-to-right. Product strings and content strings should be rendered using platform text widgets capable of bidirectional text rendering where supported.
## 6. Testing
| Test | Purpose |
|---|---|
| Missing-key fallback | Ensure fallback locale works |
| Unicode server name | Ensure names survive protocol -> UI |
| Mixed-language chat | Ensure multilingual content displays |
| RTL smoke test | Ensure basic RTL strings render |
| Diagnostics Unicode export | Ensure multilingual diagnostics survive redaction |
| Machine-key stability | Ensure diagnostic keys are language-neutral |
## 7. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial i18n and localization architecture baseline. |
## 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. |
@@ -1,107 +0,0 @@
# Legal Trademark And Attribution Review V0.9.2.2.1
**Document type:** Legal / Trademark and Attribution Review
**Version:** 0.9.2
**Status:** Baseline Candidate / Legal Review Required
**Language:** English
**Product:** Chanora
**Repo path:** `docs/legal/trademark-and-attribution-review.md` ---
## 1. Purpose
This document records trademark, attribution, non-affiliation, and OSS notice review for Chanora.
This document must be reviewed by a qualified legal/compliance reviewer before public release or store submission.
## 2. Non-Affiliation Requirement
Chanora must not imply official affiliation, endorsement, sponsorship, or approval by TeamSpeak or any other third-party service provider unless such approval exists in writing.
## 3. Required Public Wording
The final wording must be approved by legal.
Draft wording:
> Chanora is an independent client application and is not affiliated with, endorsed by, sponsored by, or officially associated with TeamSpeak.
Legal reviewer shall confirm whether the wording is sufficient for:
- website;
- app store description;
- in-app About screen;
- documentation;
- release notes;
- support pages.
## 4. Trademark Usage Review
| Location | Uses third-party mark? | Wording reviewed? | Approved? | Notes |
|---|---|---|---|---|
| App name | TBD | TBD | TBD | TBD |
| App subtitle | TBD | TBD | TBD | TBD |
| App description | TBD | TBD | TBD | TBD |
| Website | TBD | TBD | TBD | TBD |
| In-app About screen | TBD | TBD | TBD | TBD |
| Documentation | TBD | TBD | TBD | TBD |
| Release notes | TBD | TBD | TBD | TBD |
| Store metadata | TBD | TBD | TBD | TBD |
## 5. Attribution Review
| Dependency / product | Attribution required? | License / basis | Attribution text | Status |
|---|---|---|---|---|
| Flutter | TBD | TBD | TBD | TBD |
| Rust dependencies | TBD | TBD | TBD | TBD |
| `tsclientlib` | TBD | TBD | TBD | TBD |
| Native audio libraries | TBD | TBD | TBD | TBD |
| Icons/fonts/assets | TBD | TBD | TBD | TBD |
## 6. OSS Notice Requirements
| Requirement | Status | Evidence |
|---|---|---|
| OSS dependency inventory complete | TBD | Dependency report |
| License compatibility reviewed | TBD | Legal review |
| Required notices included | TBD | OSS notices file |
| Source offer obligations checked if applicable | TBD | Legal review |
| App store metadata license claims reviewed | TBD | Store review |
## 7. Release Gate
| Gate | Required result |
|---|---|
| Non-affiliation wording | Approved |
| Trademark usage | Approved |
| OSS notices | Complete |
| License review | Complete |
| Store metadata | Approved if applicable |
| Website/legal pages | Approved if applicable |
## 8. Approval
| Role | Name | Decision | Date |
|---|---|---|---|
| Legal / Compliance Reviewer | TBD | Pending | TBD |
| Product Owner | TBD | Pending | TBD |
| Release Manager | TBD | Pending | TBD |
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial trademark and attribution review template; legal review required before public release. |
## 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. |
File diff suppressed because it is too large Load Diff
-122
View File
@@ -1,122 +0,0 @@
# Priv Privacy Policy V0.9.2.2.1
**Document type:** Privacy / Public Policy Draft
**Version:** 0.9.2
**Status:** Baseline Candidate / Legal Review Required
**Language:** English
**Product:** Chanora
**Repo path:** `docs/privacy/privacy-policy.md` ---
## 1. Important Notice
This is a draft privacy policy template for review. It must be reviewed by a qualified legal/privacy reviewer before public release or store submission.
## 2. Overview
Chanora is a client application for connecting to compatible voice communication servers. Chanora is designed to operate primarily on the user's device.
## 3. Data Processed by the App
Depending on how the user configures and uses the app, Chanora may process:
- server address and port;
- server password if provided by the user;
- user nickname;
- identity information needed for server connection;
- channel names and server-provided names;
- chat messages displayed in the app;
- audio input and output during voice sessions;
- local application settings;
- audio device settings;
- diagnostic information generated by the app.
## 4. Local Storage
Chanora may store local settings, bookmarks, recent server information, audio preferences, and related configuration on the user's device.
Sensitive secrets such as server passwords or identity secrets are intended to be stored using platform secure storage mechanisms where supported.
## 5. Diagnostics
Chanora may allow the user to generate diagnostic bundles for troubleshooting.
Diagnostic export is intended to be user-initiated. Diagnostic bundles should be redacted to avoid including passwords, identity secrets, and other sensitive information.
Chanora should not automatically upload diagnostic bundles unless a future version explicitly introduces an opt-in upload feature and updates this policy.
## 6. Audio and Microphone
Chanora uses microphone access to provide voice communication features. Audio is processed for voice communication and may include echo cancellation, automatic gain control, noise suppression, and high-pass filtering.
Chanora should not record or persist voice audio unless a future feature explicitly states otherwise and receives user consent where required.
## 7. Permissions
Chanora may request permissions required for voice communication, notifications, audio routing, local storage access, or platform-specific behavior.
Permission requirements vary by platform.
## 8. Data Sharing
This draft policy assumes:
- Chanora does not sell user data.
- Chanora does not automatically upload diagnostics.
- Chanora does not include automatic telemetry unless later approved and documented.
- User-initiated sharing of diagnostic bundles is controlled by the user.
These assumptions must be confirmed before public release.
## 9. Third-Party Servers
When the user connects to a compatible external server, the server may receive connection information, nickname, voice data, text messages, or other information necessary for communication. The operation of external servers is outside Chanora's control.
## 10. Third-Party Dependencies
Chanora may use third-party software dependencies. The dependency and license list should be published or made available where required by applicable licenses.
## 11. Children's Privacy
TBD by legal/privacy reviewer.
## 12. Regional Requirements
TBD by legal/privacy reviewer. Public release may require region-specific privacy disclosures.
## 13. Contact
TBD.
## 14. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial privacy policy draft template; legal review required before public release. |
## 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 Privacy Addendum (Baseline Candidate 0.9.3)
Per SysRS-302 / SRS-202 / DEC-027, the Chanora desktop PTT subsystem operates under the following privacy rule:
- Chanora shall not log, persist, or transmit raw keyboard key codes, scan codes, virtual-key values, keysyms, or key-press timing sequences.
- The user-initiated diagnostic export shall include only the detected PTT capability level (`L0Focused`, `L1GlobalShortcut`, `L2GlobalHoldToTalk`, `L3GlobalWithMouseButtons`, or the reserved `L4DeviceAware`), the active backend identifier (a fixed string per implementation, for example `"raw-input"`, `"event-tap"`, `"gnome-wayland-portal"`, `"focused"`), and the bound input class (`"keyboard"`, `"mouse-side-button"`).
- The bound key value itself is never included in any diagnostic, even when the user invokes the export explicitly.
- Whether Global PTT is available depends on the operating system, the user-granted permission set, the display server, and the available input backend. Where Global PTT cannot be honoured, Chanora falls back to Focused PTT and reports the fallback honestly through the UI capability badge.
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop Push-to-Talk privacy addendum: raw key history is not recorded or exported; Global PTT is capability-dependent and the UI reflects actual runtime capability. |
@@ -1,87 +0,0 @@
# Chanora SWE.2 / SWE.3 Reference Integration Note
**Version:** 0.9.2
**Status:** Baseline Candidate note
**Language:** English
**Repo path:** `docs/references/aspice-swe2-swe3-integration-note.md` ---
## 1. Purpose
This note records the refinements applied to Chanora SAD and SDD after reviewing additional software architecture and detailed design references.
## 2. SAD Updates
The SAD was updated to include:
- SWE.2 architecture completeness and evaluation criteria
- Interface catalog
- Performance and resource view
- Assumptions and dependencies
- Architecture glossary
- Additional SAD design items covering:
- architecture evaluation
- interface catalog
- performance/resource views
- assumptions/dependencies
- glossary
- SDD refinement requirements
- SAD/SDD communication and baseline expectations
## 3. SDD Updates
The SDD was updated to include:
- SWE.3 detailed-design completeness criteria
- Unit interface detail catalog
- Detailed design evaluation checklist
- Additional SDD detailed design items covering:
- ArchitectureViewDocs
- ADR record structure
- InterfaceDetailCatalog
- PerformanceDesignNotes
- AssumptionRegister
- ArchitectureGlossary
- SoftwareUnitDesignTemplate
- UnitConstructionGuideline
- SoftwareUnitTraceChecker
- DetailedDesignReviewRecord
- UnitVerificationHandoff
- SoftwareUnitRegistry
## 4. Traceability Rule Preserved
The updated documents preserve the strict traceability chain:
```text
SysRS -> SysDes -> SRS -> SAD -> SDD
```
Direct source rules:
| Document | Direct source |
|---|---|
| SAD | SRS only |
| SDD | SAD only |
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial research note for expanding SAD structure and updating SDD coverage. |
| 0.2.0 | 2026-05-14 | Added SWE.2 and SWE.3 reference integration summary. |
## 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. |
-128
View File
@@ -1,128 +0,0 @@
# Chanora External Reference Collection
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/references/external-references.md` ---
## 1. Material 3 and Flutter References
| Reference | Purpose |
|---|---|
| https://m3.material.io/ | Material 3 design system baseline |
| https://m3.material.io/foundations/design-tokens/overview | Material 3 design tokens |
| https://m3.material.io/styles/color/system/how-the-system-works | Material 3 color system |
| https://m3.material.io/styles/typography | Material 3 typography |
| https://m3.material.io/foundations/adaptive-design | Material 3 adaptive design |
| https://m3.material.io/components | Material 3 components |
| https://docs.flutter.dev/ui/design/material | Material Design in Flutter |
| https://docs.flutter.dev/ui/widgets/material | Flutter Material widget catalog |
| https://docs.flutter.dev/release/breaking-changes/material-3-default | Flutter Material 3 default behavior |
| https://docs.flutter.dev/release/breaking-changes/material-3-migration | Flutter Material 3 migration guidance |
| https://api.flutter.dev/flutter/material/ThemeData-class.html | Flutter ThemeData API |
| https://api.flutter.dev/flutter/material/ColorScheme-class.html | Flutter ColorScheme API |
| https://api.flutter.dev/flutter/material/ThemeExtension-class.html | Flutter ThemeExtension API |
## 2. Android and iOS Platform References
| Reference | Purpose |
|---|---|
| https://developer.android.com/develop/ui/compose/layouts/adaptive/use-window-size-classes | Android window size classes and adaptive layout reference |
| https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture | Android predictive back behavior |
| https://developer.android.com/develop/connectivity/bluetooth/bt-permissions | Android Bluetooth permissions |
| https://developer.apple.com/design/human-interface-guidelines/ | Apple Human Interface Guidelines |
| https://developer.apple.com/documentation/avfaudio/avaudiosession/category-swift.struct | AVAudioSession category reference |
## 3. ASPICE and Requirements / Design Process References
| Reference | Purpose |
|---|---|
| `Automotive-SPICE-PAM-v40.pdf` | Automotive SPICE process model |
| https://www.ul.com/sis/resources/process-swe-1 | UL SWE.1 Software Requirements Analysis guidance |
| https://www.ul.com/sis/resources/process-swe-2 | UL SWE.2 Software Architectural Design guidance |
| https://www.ul.com/sis/resources/process-swe-3 | UL SWE.3 Software Detailed Design and Unit Construction guidance |
| https://www.ul.com/sis/resources/process-swe-4 | UL SWE.4 Software Unit Verification guidance |
| https://www.ul.com/sis/resources/process-swe-5 | UL SWE.5 Software Component Verification and Integration Verification guidance |
| https://www.ul.com/sis/resources/process-swe-6 | UL SWE.6 Software Verification guidance |
| https://www.ul.com/sis/insights/system-integration-and-integration-test-sys4-automotive-spice | UL SYS.4 System Integration and Integration Test guidance |
| https://polarion.code.blog/2021/11/10/swe-2-software-architectural-design/ | Polarion SWE.2 Software Architectural Design notes |
| https://polarion.code.blog/2022/04/21/swe-3-software-detailed-design-and-unit-construction/ | Polarion SWE.3 Software Detailed Design and Unit Construction notes |
| https://polarion.code.blog/2023/01/18/swe-4-software-unit-verification/ | Polarion SWE.4 Software Unit Verification notes |
| https://polarion.code.blog/2023/06/28/swe-5-software-integration-and-integration-test/ | Polarion SWE.5 Software Integration and Integration Test notes |
| https://polarion.code.blog/2025/06/05/swe-6-software-qualification-test/ | Polarion SWE.6 Software Qualification Test notes |
| https://polarion.code.blog/2025/08/06/sys-4-system-integration-and-integration-verification-a-spice-4-0/ | Polarion SYS.4 System Integration and Integration Verification notes |
## 4. Software Architecture and Design Document References
| Reference | Purpose |
|---|---|
| https://medium.com/codex/what-goes-in-a-software-architecture-document-e97d808d5cec | Software Architecture Document content and architecture views |
| https://www.atlassian.com/work-management/knowledge-sharing/documentation/software-design-document | Software Design Document structure, including overview, architecture, data design, interface design, component design, UI design, assumptions, dependencies, and glossary |
## 5. Use in Chanora Documentation
| Reference category | Applied to |
|---|---|
| Material 3 and Flutter | UI/UX guideline, design tokens, component catalog, adaptive layout, SysDes, SRS, SAD, SDD |
| Android and iOS platform references | Platform behavior guide, SysRS, SysDes, SRS, SAD, SDD |
| ASPICE references | SysDes, SRS, SAD, SDD, SWE.4, SWE.5, SWE.6, SYS.4, traceability matrix |
| Software architecture/design document references | SAD v0.3, SDD v0.3 |
## 6. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial reference collection. |
| 0.2.0 | 2026-05-14 | Added Atlassian software design document reference, UL SWE.2, UL SWE.3, Polarion SWE.2, Polarion SWE.3, and Medium SAD article reference. |
| 0.3.0 | 2026-05-14 | Added UL and Polarion references for SWE.4, SWE.5, SWE.6, and SYS.4 verification planning. |
---
## 7. Platform Release Policy Reference Addendum
| Reference | Purpose |
|---|---|
| Apple Developer - Upcoming Requirements | Apple App Store Connect SDK submission requirement; current baseline uses Xcode 26+ and iOS 26 / iPadOS 26 SDK+ on or after 2026-04-28 unless newer Apple policy applies. |
| Flutter supported platforms | Runtime platform support baseline; current decision uses iOS 13+ and Android API 24+ unless project constraints raise them. |
| Google Play target API level requirements | Android target SDK release gate; target the Google Play-required API level on upload date. |
## 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. |
---
## 8. Apple SDK Gate Reference Correction
| Reference | Purpose |
|---|---|
| https://developer.apple.com/news/upcoming-requirements/?id=02032026a | Apple Upcoming Requirements page defining the App Store Connect upload build gate: since April 28, 2026, uploaded apps must be built with Xcode 26 or later using the applicable platform 26 SDK or later. |
## 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 Reference Addendum (Baseline Candidate 0.9.3)
| Area | Reference (informative) |
|---|---|
| Windows input APIs | Microsoft Windows Raw Input documentation (`RegisterRawInputDevices`, `WM_INPUT`); Windows low-level keyboard / mouse hook documentation (`WH_KEYBOARD_LL`, `WH_MOUSE_LL`). |
| macOS event tap | Apple Core Graphics event-tap documentation (`CGEventTapCreate`, `kCGEventTapDisabledByTimeout`); IOKit `IOHIDCheckAccess` for permission state. |
| Linux Wayland global shortcuts | freedesktop.org XDG portal documentation for the `org.freedesktop.portal.GlobalShortcuts` interface. |
| Permission-aware input on macOS | Apple privacy / TCC documentation for Input Monitoring and Accessibility entitlements. |
Reviewers should consult the current upstream version of each reference because OS surfaces change over time; the references above identify the relevant area rather than pinning a specific version.
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop-PTT external references covering Windows Raw Input + hook documentation, macOS event-tap + IOHIDCheckAccess, Linux GlobalShortcuts portal, and macOS Input Monitoring / Accessibility entitlements. |
-664
View File
@@ -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 ~510 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 (1030 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: 6090 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. |
-83
View File
@@ -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. |
-51
View File
@@ -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. |
-514
View File
@@ -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
23 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 ~510 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 ~1618 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 ~510 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: ~35 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: ~5080 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`. |
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,126 +0,0 @@
# Sec Dependency And Supply Chain Report V0.9.2.2.1
**Document type:** Security / Dependency and Supply Chain Report
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/security/dependency-and-supply-chain-report.md` ---
## 1. Purpose
This report records Chanora dependency inventory, license review, vulnerability review, SBOM status, and supply-chain release readiness.
## 2. Dependency Scope
| Ecosystem | In scope |
|---|---|
| Flutter / Dart | `pubspec.yaml`, transitive packages, Flutter SDK version |
| Rust | `Cargo.toml`, `Cargo.lock`, crates, features |
| Protocol library | `tsclientlib` and related crates/dependencies |
| Native audio | Platform audio libraries, native build dependencies, bindings |
| Build tooling | CI actions, build scripts, code generators |
| Packaging | Platform packaging tools and signing tools |
## 3. Required Outputs
| Output | Required before external release |
|---|---|
| Dependency inventory | Yes |
| License report | Yes |
| Vulnerability scan report | Yes |
| SBOM | Yes |
| Critical/high vulnerability disposition | Yes |
| Unknown license disposition | Yes |
| Build provenance record | Yes |
| Artifact hash record | Yes |
## 4. Dependency Inventory
| Component | Ecosystem | Version | License | Source | Risk | Notes |
|---|---|---|---|---|---|---|
| Flutter SDK | Flutter | TBD | TBD | TBD | TBD | TBD |
| Dart packages | Dart | TBD | TBD | TBD | TBD | TBD |
| Rust toolchain | Rust | TBD | TBD | TBD | TBD | TBD |
| Rust crates | Rust | TBD | TBD | TBD | TBD | TBD |
| `tsclientlib` | Rust/protocol | TBD | TBD | TBD | TBD | TBD |
| Native audio dependencies | Native | TBD | TBD | TBD | TBD | TBD |
| CI actions/tools | Build | TBD | TBD | TBD | TBD | TBD |
## 5. License Review
| License category | Policy |
|---|---|
| Permissive licenses | Generally acceptable after review |
| Copyleft licenses | Requires legal review before release |
| Unknown licenses | Release blocker until resolved |
| Proprietary dependencies | Requires explicit approval |
| Incompatible licenses | Release blocker unless removed or legal waiver approved |
## 6. Vulnerability Review
| Finding ID | Dependency | Severity | CVE / advisory | Status | Disposition |
|---|---|---|---|---|---|
| TBD | TBD | TBD | TBD | TBD | TBD |
## 7. SBOM
| Field | Value |
|---|---|
| SBOM format | TBD: SPDX / CycloneDX / other |
| SBOM tool | TBD |
| SBOM file | TBD |
| SBOM generation date | TBD |
| SBOM reviewer | TBD |
## 8. Build Provenance
| Field | Value |
|---|---|
| Git commit SHA | TBD |
| Git tag | TBD |
| CI pipeline ID | TBD |
| Build environment | TBD |
| Artifact hashes | TBD |
| Signing identity | TBD |
| Reproducibility status | TBD |
## 9. Release Gate
| Gate | Required result |
|---|---|
| Critical vulnerabilities | None open without approved waiver |
| High vulnerabilities | None open without approved waiver |
| Unknown licenses | None open without approved waiver |
| SBOM | Generated and archived |
| License report | Reviewed |
| Dependency report | Approved |
## 10. Approval
| Role | Name | Decision | Date |
|---|---|---|---|
| Security Reviewer | TBD | Pending | TBD |
| Legal Reviewer | TBD | Pending | TBD |
| Engineering Owner | TBD | Pending | TBD |
| Release Manager | TBD | Pending | TBD |
## 11. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial dependency and supply-chain report 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. |
@@ -1,134 +0,0 @@
# Sec Diagnostic Redaction Audit Report V0.9.3.0.0
**Document type:** Security / Diagnostic Redaction Audit Report
**Version:** 0.9.3
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/security/diagnostic-redaction-audit-report.md` ---
## 1. Purpose
This report records evidence that Chanora logs and diagnostic exports do not leak sensitive information.
## 2. Sensitive Data Redaction Policy
| Data category | Default diagnostic behavior |
|---|---|
| Server password | Must redact |
| Identity private key / identity secret | Must redact |
| Authentication tokens if later added | Must redact |
| Secure-storage keys | Must redact |
| Server address | Redact or minimize according to release policy |
| Channel names | Redact or include only with explicit user consent |
| Client nicknames | Redact or include only with explicit user consent |
| Chat messages | Exclude by default unless a future explicit opt-in policy is approved |
| Local file paths | Minimize or redact user-identifying segments |
| Device IDs | Redact or hash if collected |
| IP addresses | Redact or minimize according to release policy |
## 3. Diagnostic Surfaces
| Surface | Risk | Required control |
|---|---|---|
| Application log | Secret leakage | Redaction filter and structured logging discipline |
| Protocol log | Hostile or sensitive server content | Redaction and length limits |
| Audio diagnostics | Device privacy | Device name minimization if needed |
| Export bundle | Aggregated sensitive data | Redaction audit before release |
| Error report | Stack trace or secret context | User-safe error mapping |
| User support copy/paste | Over-sharing | Explicit review and confirmation |
## 4. Redaction Test Matrix
| Test ID | Input | Expected output | Status | Evidence |
|---|---|---|---|---|
| REDACT-TC-001 | Server password in connection data | Password replaced by `[REDACTED]` | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_001_server_password_in_connection_data` |
| REDACT-TC-002 | Identity secret in storage error | Secret absent | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_002_identity_secret_in_storage_error` (via `KnownSecretRegistry`) |
| REDACT-TC-003 | Server URL with password-like field | Secret part redacted | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_003_server_url_with_password_field` — only the password value is redacted, the host and other query params keep flowing |
| REDACT-TC-004 | Chat text in diagnostic export | Excluded by default | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_004_chat_text_excluded_by_default` — default policy sets `include_chat = false` |
| REDACT-TC-005 | Channel name with Unicode | Preserved only if permitted; otherwise redacted safely | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_005_channel_name_with_unicode_excluded_by_default` — default policy excludes; UTF-8 preservation verified in TC-010 |
| REDACT-TC-006 | Nickname with Unicode | Preserved only if permitted; otherwise redacted safely | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_006_nickname_with_unicode_preserved_in_safe_field` |
| REDACT-TC-007 | Local file path | User-identifying segments redacted or minimized | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_007_local_file_paths_user_segment_minimized` — Linux `/home/<user>/`, Windows `C:\Users\<user>\`, macOS `/Users/<user>/` all minimized |
| REDACT-TC-008 | Diagnostic bundle with mixed sensitive fields | All sensitive fields redacted | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_008_diagnostic_bundle_with_mixed_sensitive_fields` — whole-bundle JSON scan finds no plaintext |
| REDACT-TC-009 | Long hostile protocol string | Truncated or safely escaped | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_009_long_hostile_protocol_string_truncated``MAX_PROTOCOL_STRING_LEN = 256` cap with `…[truncated]` marker |
| REDACT-TC-010 | Multilingual safe diagnostic text | Unicode preserved | PoC Pass | `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_010_multilingual_safe_text_preserved` — Chinese, Japanese, Korean, and Latin-diacritic text preserved verbatim |
## 5. Export Bundle Contents
| Bundle item | Included? | Redaction rule | Status |
|---|---|---|---|
| App version | Yes | None | PoC Pass (`DiagnosticBundle.app_version` preserved verbatim) |
| Build number | Yes | None | PoC Pass (`DiagnosticBundle.build_number` preserved verbatim) |
| Platform info | Yes | Minimize device details | PoC Pass — flows through `Redactor::redact_text`, so embedded paths/usernames are minimized |
| Connection state | Yes | No secrets | PoC Pass — flows through `Redactor::redact_text` |
| Server address | Yes (redacted) | Redact/minimize | PoC Pass — passwords inside `ts3server://` URLs redacted |
| Channel tree | No by default | Redact/minimize | PoC Pass — default `include_channel_tree = false` |
| Chat history | No by default | Exclude unless explicit policy changes | PoC Pass — default `include_chat = false` |
| Logs | Yes | Redacted | PoC Pass — each log line flows through `Redactor::redact_text` |
| Audio diagnostics | Yes | No audio content | PoC Pass — only device names are exported; no PCM |
| Secure storage data | No | Never include | PoC Pass by construction — the redactor has no path that reads from `SecretStorageRepository`; the host application must never put secret material into the bundle in the first place |
## 6. Findings
| Finding ID | Severity | Description | Status | Owner |
|---|---|---|---|---|
| REDACT-FIND-001 | Informational | The PoC regex catalogue covers the documented audit matrix but is not exhaustive. Production `chanora_diagnostics` should add fuzz testing and adversarial inputs (e.g. base64 lookalikes, unicode confusables, regex evasion). | Open | Security Reviewer + `chanora_diagnostics` owner |
| REDACT-FIND-002 | Informational | The PoC redactor is a post-processor over strings. Production code should wire the redactor as a `tracing-subscriber` layer so redaction happens at write-time, not by re-walking text afterward. | Open — to be addressed when `chanora_diagnostics` is scaffolded | `chanora_diagnostics` owner |
| REDACT-FIND-003 | Informational | The `KnownSecretRegistry` defence-in-depth requires the secure-storage layer to register secrets when they materialise. The cross-spike contract is documented but not yet enforced by any product code. | Open — to be enforced by `chanora_storage` calling into `chanora_diagnostics`. | `chanora_storage` + `chanora_diagnostics` owners |
## 7. Approval
| Role | Name | Decision | Date |
|---|---|---|---|
| Security Reviewer | TBD | Pending | TBD |
| Privacy Reviewer | TBD | Pending | TBD |
| QA / Verification Owner | TBD | Pending | TBD |
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial diagnostic redaction audit report 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-14 | Recorded PoC empirical evidence: REDACT-TC-001..010 status set to PoC Pass with evidence pointers to `poc/diagnostics-redaction-spike/tests/redaction.rs`. Export bundle policy §5 populated for every row. Findings REDACT-FIND-001..003 added (regex coverage limits, tracing-layer integration gap, KnownSecretRegistry cross-spike contract). |
## Desktop Push-to-Talk Redaction Addendum (Baseline Candidate 0.9.3)
Per SysRS-302 / SRS-202 / SAD-077 / SDD-090, the redaction policy adds the following rules for desktop PTT diagnostics:
| Rule | Banned field name | Disposition |
|---|---|---|
| REDACT-PTT-001 | `key_code` | Drop record. |
| REDACT-PTT-002 | `scan_code` | Drop record. |
| REDACT-PTT-003 | `virtual_key`, `vk` | Drop record. |
| REDACT-PTT-004 | `keysym`, `keysym_string` | Drop record. |
| REDACT-PTT-005 | `key_sequence`, `key_press_history`, `key_timing` | Drop record. |
| REDACT-PTT-006 | Free-form `message` strings shall not embed key values; offending records shall be reformatted by the originating backend before emission. | Drop record. |
The `PttSanitizer` `tracing_subscriber::Layer` decorates `RedactingLogLayer` and is the enforcement point. Fields whose names match the banned list cause the entire record to be dropped — Chanora does not attempt to redact-in-place because partial-redaction false negatives are riskier than a missing line.
Permitted fields for PTT diagnostics: `capability_level`, `backend_id`, `bound_input_class`, `fallback_exercised`.
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT redaction rules REDACT-PTT-001..006: ban raw key codes, scan codes, virtual-key values, keysyms, and key timing sequences from logs and exports. |
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,97 +0,0 @@
# Sec Secure Storage Audit Report V0.9.3.0.0
**Document type:** Security / Secure Storage Audit Report
**Version:** 0.9.3
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/security/secure-storage-audit-report.md` ---
## 1. Purpose
This report records evidence that Chanora stores secrets using platform secure storage mechanisms and does not store sensitive secrets in plaintext local storage.
## 2. Secret Classification
| Secret ID | Secret | Required storage |
|---|---|---|
| SEC-STORE-001 | Identity private key / identity secret | Platform secure storage |
| SEC-STORE-002 | Server password | Platform secure storage |
| SEC-STORE-003 | Authentication tokens if later added | Platform secure storage |
| SEC-STORE-004 | Encryption keys if later added | Platform secure storage |
## 3. Platform Audit Matrix
| Platform | Secure storage mechanism | Test status | Evidence | Result |
|---|---|---|---|---|
| Windows | DPAPI / Windows Credential Manager (per DEC-013 / SysRS-158) — adapter not yet implemented | Not started | n/a | Deferred to product `chanora_storage` |
| macOS | Keychain (per SysRS-159) — adapter not yet implemented | Not started | n/a | Deferred to product `chanora_storage` |
| Linux | Secret Service (libsecret) preferred; kernel keyutils fallback per DEC-013.2 | PoC Pass | `poc/secure-storage-spike/VERIFICATION.md`; six audit tests PASS via keyutils backend; CLI run additionally observed Secret-Service-locked → keyutils fallback live | PoC PASS; product audit pending |
| Android | Android Keystore (per SysRS-161) — adapter not yet implemented | Not started | n/a | Deferred to product `chanora_storage` |
| iOS | Keychain (per SysRS-160) — adapter not yet implemented | Not started | n/a | Deferred to product `chanora_storage` |
## 4. Audit Checks
| Check ID | Check | Expected result | Status | Evidence |
|---|---|---|---|---|
| SS-AUD-001 | Identity secret is not stored in local DB. | Pass | PoC Pass (Linux) | `poc/secure-storage-spike/tests/audit.rs::ss_aud_001_identity_secret_absent_from_local_db` — raw SQLite file scanned for plaintext markers; only the lookup name appears. |
| SS-AUD-002 | Server password is not stored in local DB. | Pass | PoC Pass (Linux) | `poc/secure-storage-spike/tests/audit.rs::ss_aud_002_server_password_absent_from_local_db` — distinct plaintext marker scan. |
| SS-AUD-003 | Secret values are not written to application logs. | Pass | PoC Pass (Linux) + cross-spike | `poc/secure-storage-spike/tests/audit.rs::ss_aud_003_secret_values_not_in_logs` — captured `tracing` output contains `<redacted>` markers; never the plaintext. Cross-referenced by `poc/diagnostics-redaction-spike` REDACT-TC-002. |
| SS-AUD-004 | Secret values are not included in diagnostic export. | Pass | PoC Pass | Covered by `poc/diagnostics-redaction-spike/tests/redaction.rs::redact_tc_008_diagnostic_bundle_with_mixed_sensitive_fields` — whole-bundle JSON scan finds no plaintext. |
| SS-AUD-005 | Secure storage failure returns safe error. | Pass | PoC Pass (Linux) | `poc/secure-storage-spike/tests/audit.rs::ss_aud_005_safe_error_on_missing_entry`. Reinforced by the CLI driver run: a real locked gnome-keyring collection produced a typed `Backend` error containing no secret material, which the application then routed to the fallback adapter (DEC-013.2). |
| SS-AUD-006 | Secret deletion removes secure-storage entry. | Pass | PoC Pass (Linux) | `poc/secure-storage-spike/tests/audit.rs::ss_aud_006_delete_removes_entry` — second delete returns `NotFound`, not silent success. |
| SS-AUD-007 | Platform-specific secure storage is documented. | Pass | Partial | Linux documented in `poc/secure-storage-spike/README.md` and DEC-013.2. Windows/macOS/Android/iOS remain to be documented when adapters land in `chanora_storage`. |
| SS-AUD-008 | Migration or import path does not expose secrets. | Pass | Pending | No migration / import path exists yet; depends on product `chanora_storage` schema design (cross-references DEC-013.1 and `poc/sqlite-storage-spike`). |
## 5. Test Cases
| Test ID | Platform | Procedure | Expected result | Actual result | Status |
|---|---|---|---|---|---|
| SS-TC-001 | Windows | Save identity secret, inspect local DB/logs/export. | Secret absent from DB/logs/export. | Not run — Windows adapter not implemented in PoC | Deferred |
| SS-TC-002 | macOS | Save identity secret, inspect local DB/logs/export. | Secret absent from DB/logs/export. | Not run — macOS adapter not implemented in PoC | Deferred |
| SS-TC-003 | Linux | Save identity secret, inspect local DB/logs/export. | Secret absent from DB/logs/export. | Set / get / delete round-trip verified via keyutils backend; raw SQLite file scan confirmed plaintext absence; `tracing` log capture confirmed log absence. | **PoC Pass** |
| SS-TC-004 | Android | Save identity secret, inspect app storage/logs/export. | Secret absent from DB/logs/export. | Not run — Android adapter not implemented in PoC | Deferred |
| SS-TC-005 | iOS | Save identity secret, inspect app storage/logs/export. | Secret absent from DB/logs/export. | Not run — iOS adapter not implemented in PoC | Deferred |
## 6. Findings
| Finding ID | Severity | Description | Status | Owner |
|---|---|---|---|---|
| SS-FIND-001 | Informational | SysRS-053 / SysRS-162 ("Secret Service, libsecret, or equivalent") admitted both Secret Service and kernel keyutils as Linux backends. The PoC surfaced this ambiguity. | Resolved by DEC-013.2 on 2026-05-13 (Secret Service preferred, keyutils fallback). | Software Architect + Security Reviewer |
| SS-FIND-002 | Informational | Kernel keyutils requires a valid session keyring; cargo-test under non-interactive shells inherits an expired `_ses` and must be wrapped with `keyctl session -`. Production code on a graphical session inherits a valid session from PAM. | Documented in `poc/secure-storage-spike/README.md` and `VERIFICATION.md`. | Software Architect |
| SS-FIND-003 | Open | Windows / macOS / iOS / Android adapters not implemented; SS-TC-001/002/004/005 unverified. | Open — to be closed by per-platform adapter spikes or by the product `chanora_storage` implementation. | Platform Owners |
## 7. Approval
| Role | Name | Decision | Date |
|---|---|---|---|
| Security Reviewer | TBD | Pending | TBD |
| Platform Owner | TBD | Pending | TBD |
| QA / Verification Owner | TBD | Pending | TBD |
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial secure storage audit report 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-14 | Recorded PoC empirical evidence: SS-AUD-001/002/003/005/006 status set to PoC Pass with evidence pointers; SS-AUD-004 cross-referenced to the diagnostics-redaction PoC; SS-TC-003 Linux Actual Result populated and Status set to PoC Pass. Added findings SS-FIND-001 (closed by DEC-013.2), SS-FIND-002 (keyutils session caveat), SS-FIND-003 (non-Linux adapters still open). Non-Linux test cases SS-TC-001/002/004/005 remain Deferred. |
@@ -1,89 +0,0 @@
# Sec Security Privacy Legal Guideline V0.9.2.2.1
**Document type:** Security / Privacy / Legal Guideline
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/security/security-privacy-legal-guideline.md` ---
## 1. Purpose
This guideline defines the required security, privacy, and legal review documents that must be completed before Chanora is released outside a controlled internal engineering environment.
A public or external release shall not rely only on SysRS, SysDes, SRS, SAD, SDD, and verification documents. It also requires security, privacy, dependency, and legal evidence.
## 2. Required Pre-Release Documents
| Document | Required before | Purpose |
|---|---|---|
| `docs/security/threat-model.md` | External Beta or public release | Identify attack surfaces, assets, trust boundaries, threats, and mitigations. |
| `docs/security/secure-storage-audit-report.md` | Any release storing secrets | Prove platform secure storage behavior. |
| `docs/security/diagnostic-redaction-audit-report.md` | Any release with diagnostics export/logs | Prove diagnostics and logs do not leak sensitive information. |
| `docs/security/dependency-and-supply-chain-report.md` | Any external release | Prove dependency inventory, licenses, vulnerability status, and SBOM readiness. |
| `docs/privacy/privacy-policy.md` | Any public or store release | Explain data handling, local storage, permissions, diagnostics, and upload behavior. |
| `docs/legal/trademark-and-attribution-review.md` | Any public or store release | Confirm non-affiliation wording, OSS attribution, and trademark risk review. |
## 3. Release Gate Rule
| Release type | Required security/privacy/legal gate |
|---|---|
| Internal Alpha | Security and privacy draft checklist acceptable if not publicly distributed. |
| External Beta | Threat model, secure storage audit, diagnostic redaction audit, dependency report, privacy draft, legal review draft required. |
| MVP Public | All listed documents must be completed and approved. |
| Store Release | All listed documents must be completed, approved, and aligned with store metadata. |
## 4. Security Review Principles
| Principle | Required behavior |
|---|---|
| Secret minimization | Store only secrets needed for user-approved functionality. |
| Local-first diagnostics | Diagnostic export requires explicit user action unless a future policy says otherwise. |
| Redaction by default | Secrets and sensitive server/user data are redacted before export. |
| Boundary validation | Protocol, platform, and file boundaries validate or sanitize external input. |
| Least privilege | Platform permissions are requested only when needed and explained to users. |
| Dependency accountability | Flutter packages, Rust crates, native libraries, and protocol libraries are inventoried. |
| Release evidence | Security and privacy claims require evidence, not only design intent. |
## 5. Required Product Owner Decisions
| Decision | Owner |
|---|---|
| Whether diagnostics are local-only or upload-capable | Product Owner + Legal |
| Whether crash reporting is included | Product Owner + Legal + Security |
| Which release channels are used | Product Owner |
| Public wording for non-affiliation statement | Legal / Compliance |
| Whether any telemetry is collected | Product Owner + Legal |
| Minimum supported platforms for secure storage audit | Product Owner + Engineering |
## 6. Required Engineering Evidence
| Evidence | Owner |
|---|---|
| Secure storage test results per platform | Platform / Security |
| Diagnostic redaction test results | Security / QA |
| Dependency inventory and license output | Engineering / Legal |
| SBOM output | Engineering / Security |
| Vulnerability scan result | Security / Engineering |
| Permission list and justification | Platform / Product |
| Threat model review result | Security / Architecture |
## 7. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial security, privacy, and legal pre-release guideline. |
## 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. |
-154
View File
@@ -1,154 +0,0 @@
# Sec Threat Model V0.9.2.2.1
**Document type:** Security / Threat Model
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/security/threat-model.md` ---
## 1. Purpose
This document identifies Chanora security assets, trust boundaries, attack surfaces, threat scenarios, mitigations, and residual risks.
This document must be completed and approved before public or external release.
## 2. Security Scope
In scope:
- Identity private keys and identity material
- Server passwords
- Saved bookmarks and recent server entries
- Local database
- Secure storage
- Diagnostic logs and export bundles
- Protocol input from compatible servers
- Text messages, channel names, server names, and nicknames
- Audio device access and microphone permission
- Platform permission flows
- Dependency and supply-chain risks
- Flutter/Rust bridge boundary
- Local file export/import surfaces
Out of scope unless later added:
- Cloud account sync
- Server hosting infrastructure operated by Chanora
- Telemetry backend
- Crash reporting backend
- Payment processing
## 3. Assets
| Asset ID | Asset | Sensitivity | Required protection |
|---|---|---|---|
| SEC-ASSET-001 | Identity private key / identity secret | Critical | Store only in platform secure storage; never log. |
| SEC-ASSET-002 | Server password | Critical | Store only in platform secure storage; redact from diagnostics. |
| SEC-ASSET-003 | Server address / bookmark | Sensitive | Store locally; redact or minimize in diagnostic export. |
| SEC-ASSET-004 | Nickname / user identity display name | Personal / user-provided | Preserve Unicode; avoid unnecessary upload. |
| SEC-ASSET-005 | Channel names and server names | Potentially sensitive | Treat as user/server content; redact where configured. |
| SEC-ASSET-006 | Chat text | Sensitive user/server content | Do not upload automatically; redact from diagnostics by default unless user explicitly includes. |
| SEC-ASSET-007 | Diagnostic bundle | Sensitive aggregate | Redact secrets; user-initiated export only. |
| SEC-ASSET-008 | Local database | Sensitive | Protect via OS file permissions; avoid plaintext secrets. |
| SEC-ASSET-009 | Logs | Sensitive | Redact secrets and avoid verbose sensitive content. |
| SEC-ASSET-010 | Audio stream | Sensitive real-time data | Do not persist audio unless explicitly designed later. |
| SEC-ASSET-011 | Dependency graph | Supply-chain-sensitive | Track licenses, vulnerabilities, and source integrity. |
## 4. Trust Boundaries
| Boundary ID | Boundary | Risk |
|---|---|---|
| TB-001 | User input to Flutter UI | Malformed or hostile input. |
| TB-002 | Flutter to Rust bridge | DTO validation and error mapping required. |
| TB-003 | Rust Core to protocol adapter | Protocol events and external inputs must be normalized. |
| TB-004 | Protocol adapter to external compatible server | Untrusted network/server input. |
| TB-005 | Rust/Flutter to platform secure storage | Platform-specific failure modes. |
| TB-006 | App to local database/file system | File tampering, data leakage, permissions. |
| TB-007 | Diagnostics export to user-controlled destination | Sensitive data leakage. |
| TB-008 | Audio device boundary | Permission and device-route privacy. |
| TB-009 | Dependency supply chain | Vulnerable or malicious dependencies. |
## 5. Attack Surfaces
| Surface ID | Attack surface | Example threats |
|---|---|---|
| AS-001 | Connection form | Credential capture in logs, malformed host input. |
| AS-002 | Protocol input | Malformed packets, hostile names/messages, state desync. |
| AS-003 | Bridge DTOs | Invalid commands, unexpected event payloads. |
| AS-004 | Local database | Tampering, unauthorized read. |
| AS-005 | Secure storage | Platform fallback failure or incorrect secret classification. |
| AS-006 | Diagnostics export | Secret leakage, excessive server/user information. |
| AS-007 | Logs | Password or identity leakage. |
| AS-008 | Audio permissions | Unclear microphone use or unintended capture. |
| AS-009 | Dependency ecosystem | Vulnerable packages or license incompatibility. |
| AS-010 | Store/package distribution | Tampered artifacts or signing issues. |
## 6. Threat Scenarios and Mitigations
| Threat ID | Scenario | Impact | Mitigation | Verification |
|---|---|---|---|---|
| THR-001 | Server password is logged during connection failure. | Credential leakage. | Redaction filters; never log secret fields. | Diagnostic redaction audit. |
| THR-002 | Identity private key is stored in local DB. | Identity compromise. | Secure storage classification and audit. | Secure storage audit. |
| THR-003 | Diagnostic export includes server password or identity secret. | Credential leakage. | Export redaction and denylist/allowlist design. | Redaction audit. |
| THR-004 | Hostile server sends malformed Unicode or extremely long names. | Crash, UI corruption, log injection. | Boundary validation, length limits, safe rendering. | Protocol fuzz/sanitization tests. |
| THR-005 | Protocol event causes inconsistent UI state. | Wrong user/channel state. | State reducer validation and snapshot recovery. | SWE.5/SWE.6 tests. |
| THR-006 | Dependency has known critical vulnerability. | Compromise or exploit risk. | Dependency scan and release gate. | Supply-chain report. |
| THR-007 | OSS license is incompatible with release model. | Legal/compliance risk. | License inventory and legal review. | Dependency/license report. |
| THR-008 | Microphone permission is unclear to user. | Privacy risk. | Permission explanation and privacy policy. | Privacy/legal review. |
| THR-009 | Logs contain private channel or nickname data by default. | Privacy leakage. | Minimize logs; redact or hash sensitive content. | Diagnostics audit. |
| THR-010 | Build artifact is not traceable to commit. | Supply-chain/release integrity risk. | Release record with commit, tag, build number, hashes. | Go/No-Go record. |
## 7. Residual Risks
| Risk ID | Risk | Disposition |
|---|---|---|
| RISK-001 | External compatible servers may expose untrusted content. | Accept with boundary validation and safe rendering. |
| RISK-002 | Platform secure storage behavior differs by OS/version. | Mitigate with per-platform audit. |
| RISK-003 | Dependency vulnerabilities may appear after release. | Mitigate with recurring scan and patch policy. |
| RISK-004 | Diagnostic bundles may contain contextual sensitive data even after redaction. | Mitigate with user confirmation and privacy notice. |
## 8. Approval
| Role | Name | Decision | Date |
|---|---|---|---|
| Security Reviewer | TBD | Pending | TBD |
| Software Architect | TBD | Pending | TBD |
| Platform Owner | TBD | Pending | TBD |
| QA / Verification Owner | TBD | Pending | TBD |
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.9.0 | 2026-05-14 | Initial threat model template and baseline candidate. |
## 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 Threat Addendum (Baseline Candidate 0.9.3)
| ID | Threat | Asset | Likelihood | Impact | Mitigation |
|---|---|---|---|---|---|
| THREAT-PTT-001 | A desktop PTT backend logs raw key codes or scan codes to the in-memory log sink. | User keystroke privacy | Medium (without controls) | High | `PttSanitizer` per SAD-077 / SDD-090 drops records with banned field names before they reach any sink; backend implementations call `AudioTransmitGate::set` only and never log key data. |
| THREAT-PTT-002 | A desktop PTT backend leaks raw key codes through the user-initiated diagnostic export. | User keystroke privacy | Medium | High | Diagnostic export carries only the capability level, backend identifier, and bound input class per SRS-202 / DEC-027. |
| THREAT-PTT-003 | The application advertises Global PTT support on a platform / permission / environment where it does not actually work. | Honest release claim | Medium | Medium (UX regression, support load) | `PttCapabilityLevel` is published from the *active* backend only; the UI capability badge reflects runtime measurement (SRS-196 / SysRS-298). Release readiness record carries per-platform evidence per SysDes-148. |
| THREAT-PTT-004 | A missed key-up event leaves `transmit_active` true after the user releases the binding (for example because the OS suppressed the event while Chanora was minimised). | Voice transmission integrity, user expectation of mute | Medium | Medium | `MissedKeyUpWatchdog` per SAD-079 / SDD-092 self-clears `transmit_active` after a configured timeout (default 30 s); the watchdog timeout is a P0 requirement per DEC-028. |
| THREAT-PTT-005 | A malicious or buggy third-party application registers a global hook that intercepts Chanora's binding and forces PTT on. | Voice transmission integrity | Low | Medium (user can mitigate by switching binding) | Out of MVP scope; documented as a deferred risk. Chanora reports the active backend identifier so a support investigation can correlate. |
| THREAT-PTT-006 | macOS Input-Monitoring / Accessibility permission is revoked at runtime; the application continues to claim Global PTT. | Honest capability state | Low | Medium | `MacOSEventTapBackend` re-queries the permission state on each tap-disabled callback and downgrades to `L0Focused` via `BridgeEvent::PttCapability`. |
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT threats THREAT-PTT-001..006: raw key logging, key data in diagnostic export, capability over-claim, missed key-up, third-party hook interference, and macOS permission revocation. |
@@ -1,84 +0,0 @@
# Chanora Adaptive Layout and Platform Behavior Guide
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Repo path:** `docs/ui-ux/adaptive-layout-platform-guide.md` ---
## 1. Purpose
This guide defines adaptive layout and platform behavior for the Chanora Flutter application.
## 2. Window Classes
| Class | Width | Layout |
|---|---:|---|
| Compact | `< 600dp` | Single-column content with mobile navigation |
| Medium | `600dp - 839dp` | Navigation rail or side navigation with main content |
| Expanded | `>= 840dp` | Persistent side pane, main pane, and persistent VoiceBar |
## 3. Compact Layout
- Use one primary content area.
- Keep VoiceBar visible or directly reachable.
- Keep connection status visible.
- Use bottom navigation for primary destinations.
- Avoid multi-pane assumptions.
## 4. Medium Layout
- Use navigation rail or equivalent side navigation.
- Keep primary content and VoiceBar available.
- Use dialogs or side panels depending on width.
## 5. Expanded Layout
- Use persistent side pane for server/channel navigation.
- Use main pane for chat, details, or current feature content.
- Keep VoiceBar persistent.
- Support pointer, keyboard, hover, and context menus.
## 6. Android Platform Behavior
- Runtime permissions must be explained before request where appropriate.
- System back behavior is handled as a back intent.
- Predictive back compatibility should be considered where supported.
- Bluetooth and audio routing are handled by platform services.
- Foreground voice behavior is handled according to Android platform rules.
## 7. iOS Platform Behavior
- Microphone permission must be explained before request where platform guidelines allow.
- Safe area, home indicator, keyboard avoidance, and route changes must be respected.
- Audio session behavior must be handled through platform audio services.
- Haptics should be restrained and meaningful.
## 8. Desktop Platform Behavior
- Keyboard traversal is required for primary controls.
- Tooltips and hover states should be supported.
- Context menus should be supported for channel tree, client rows, and bookmarks.
- Window resizing must not break critical controls.
- Diagnostics export must use platform-appropriate file handling.
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial adaptive layout and platform behavior guide. |
## 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. |
-105
View File
@@ -1,105 +0,0 @@
# Chanora Component Catalog — Material 3 Baseline
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Repo path:** `docs/ui-ux/material3-component-catalog.md` ---
## 1. Purpose
This catalog defines Chanora UI components that sit above Material 3 widgets. Components shall consume design tokens and expose accessible, testable APIs.
## 2. Core Components
| Component | Stage | Responsibility |
|---|---|---|
| `ChanoraAdaptiveShell` | P0 | Layout and navigation shell for compact, medium, expanded classes |
| `ChanoraVoiceBar` | P0 | Persistent voice controls |
| `ChanoraChannelTree` | P0 | Hierarchical channel and client browser |
| `ChanoraClientTile` | P0 | Client display row |
| `ChanoraStatusBadge` | P0 | Connection, voice, latency, and diagnostic status |
| `ChanoraAudioMeter` | P0 | Input audio level indicator |
| `ChanoraConnectionBanner` | P0 | Connection, reconnect, and error feedback |
| `ChanoraSettingsSection` | P0 | Settings grouping |
| `ChanoraDiagnosticPanel` | P0 | Diagnostics status and export entry |
| `ChanoraContextMenuAnchor` | P1 | Desktop and tablet context menu behavior |
## 3. Component API Requirements
### `ChanoraVoiceBar`
Required properties:
- connected status
- current channel name
- microphone muted state
- output deafened state
- push-to-talk active state
- input level
- latency summary
- localized labels
- callbacks for mute, deaf, push-to-talk, and settings
### `ChanoraChannelTree`
Required properties:
- root channel nodes
- expanded channel IDs
- selected channel ID
- current voice channel ID
- client node list
- speaking client IDs
- join-channel callback
- context-menu callback
- keyboard traversal support
### `ChanoraStatusBadge`
Required properties:
- state
- label
- icon
- semantic label
- optional severity
- optional tooltip
### `ChanoraAudioMeter`
Required properties:
- level
- disabled state
- semantic value
- reduced-motion mode
## 4. Accessibility Rules
- Icon-only controls require semantic labels.
- Status components must not rely on color only.
- Components must support focus where interactive.
- Components must preserve touch target size where practical.
- Components must be testable through widget tests.
## 5. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial Chanora component catalog. |
## 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. |
-120
View File
@@ -1,120 +0,0 @@
# Chanora Design Tokens — Material 3 Baseline
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Repo path:** `docs/ui-ux/material3-design-tokens.md` ---
## 1. Token Strategy
Chanora uses Material 3 tokens as the foundation and adds Chanora semantic tokens for voice-client-specific states.
```text
Material 3 ColorScheme / TextTheme / Shape / Motion
-> Chanora Semantic Tokens
-> Chanora Components
-> Feature Screens
```
## 2. Token Groups
| Group | Purpose |
|---|---|
| `chanora.color.connection.*` | Connection status |
| `chanora.color.voice.*` | Voice states |
| `chanora.color.latency.*` | Latency and packet-loss status |
| `chanora.color.diagnostics.*` | Diagnostic severity |
| `chanora.spacing.*` | Layout spacing |
| `chanora.shape.*` | Corners and component shapes |
| `chanora.motion.*` | Motion duration and reduced-motion behavior |
| `chanora.density.*` | Mobile, tablet, desktop density |
| `chanora.typography.*` | Product role mapping to Material type roles |
## 3. Color Tokens
| Token | Purpose |
|---|---|
| `chanora.color.connection.connected` | Connected state |
| `chanora.color.connection.connecting` | Connection in progress |
| `chanora.color.connection.reconnecting` | Recovering connection |
| `chanora.color.connection.disconnected` | Disconnected state |
| `chanora.color.connection.error` | Connection failure |
| `chanora.color.voice.speaking` | User is speaking |
| `chanora.color.voice.muted` | Microphone muted |
| `chanora.color.voice.deafened` | Output deafened |
| `chanora.color.voice.pttActive` | Push-to-talk active |
| `chanora.color.latency.good` | Good latency |
| `chanora.color.latency.warning` | Warning latency |
| `chanora.color.latency.bad` | Bad latency |
| `chanora.color.diagnostics.info` | Informational diagnostic |
| `chanora.color.diagnostics.warning` | Warning diagnostic |
| `chanora.color.diagnostics.error` | Error diagnostic |
## 4. Typography Mapping
| Product role | Material 3 type role |
|---|---|
| App title | `headlineSmall` |
| Server name | `titleLarge` |
| Channel name | `bodyLarge` |
| Client nickname | `bodyLarge` |
| Status secondary text | `bodyMedium` |
| Diagnostic metadata | `bodySmall` |
| Button label | `labelLarge` |
| Badge label | `labelMedium` |
## 5. Spacing Tokens
| Token | Value |
|---|---:|
| `chanora.spacing.xs` | 4 |
| `chanora.spacing.sm` | 8 |
| `chanora.spacing.md` | 12 |
| `chanora.spacing.lg` | 16 |
| `chanora.spacing.xl` | 24 |
| `chanora.spacing.2xl` | 32 |
## 6. Shape Tokens
| Token | Use |
|---|---|
| `chanora.shape.sm` | Small chips, compact controls |
| `chanora.shape.md` | Cards and list containers |
| `chanora.shape.lg` | Panels and navigation surfaces |
| `chanora.shape.xl` | Dialogs and sheets |
| `chanora.shape.full` | Pills, badges, icon buttons |
## 7. Motion Tokens
| Token | Purpose |
|---|---|
| `chanora.motion.quick` | Small feedback |
| `chanora.motion.standard` | Normal UI transition |
| `chanora.motion.emphasized` | Major layout transition |
| `chanora.motion.reduced` | Reduced-motion fallback |
## 8. Flutter Implementation Requirement
Tokens should be exposed through `ThemeData`, `ColorScheme`, component themes, and `ThemeExtension`. Feature screens shall not hardcode product semantic token values.
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial design token baseline. |
## 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. |
-93
View File
@@ -1,93 +0,0 @@
# Chanora UI/UX Guideline — Material 3 Baseline
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Lifecycle support:** Supports SysDes, SRS, SAD, SDD, and Verification
**Design baseline:** Material 3 + Chanora Design System
**Repo path:** `docs/ui-ux/material3-guideline.md` ---
## 1. Purpose
This guideline defines the UI and UX baseline for the Chanora Flutter application. Chanora shall use Material 3 as the foundation, but product-specific voice, channel, connection, latency, diagnostics, platform, and accessibility semantics shall be expressed through Chanora Design System components and tokens.
## 2. Core UI Principles
| Principle | Requirement |
|---|---|
| Voice-first control | Mute, deaf, push-to-talk, current channel, and input status must be visible or directly reachable. |
| Connection awareness | Connected, connecting, reconnecting, disconnected, and error states must be visible. |
| Adaptive layout | Layout must adapt by window class rather than hardcoding behavior by platform name. |
| Accessibility baseline | Critical controls must have semantics, focus behavior, text scaling support, and non-color-only status expression. |
| Platform respect | Permission, safe area, keyboard, back, haptic, and audio-route behavior must follow platform expectations. |
| Localization-ready | Product-owned strings must be localized; server-provided content must be displayed as content. |
## 3. Primary Screens
| Screen | Stage | Purpose |
|---|---|---|
| Home | P0 | Recent servers, bookmarks, manual connect entry |
| Connect | P0 | Host, port, nickname, password, identity selection |
| Server | P0 | Channel tree, clients, connection status, current channel |
| Voice | P0 | Voice controls, input level, device summary |
| Chat | P1 | Channel text messages |
| Settings | P0 | Audio, UI, localization, platform behavior, shortcuts |
| Diagnostics | P0 | Status, redacted export, troubleshooting information |
## 4. Interaction Rules
| Area | Rule |
|---|---|
| Channel tree | Select, expand/collapse, join, context menu, keyboard traversal |
| Client tile | Show speaking, mute/deaf, volume, latency when available |
| Voice controls | Must be reachable with touch, mouse, and keyboard |
| Diagnostics | Export must require explicit user action and show redaction notice |
| Settings | Destructive or permission-changing actions require clear confirmation or explanation |
| Text entry | Chat input must respect IME and keyboard safe areas |
## 5. Motion Rules
| Scenario | Allowed behavior |
|---|---|
| Page transition | Minimal fade or shared-axis style transition |
| Speaking indicator | Subtle pulse, disabled or simplified under reduced motion |
| Reconnect banner | Clear state transition without disruptive animation |
| Layout change | Resize/reflow smoothly where possible |
| Error state | Immediate, clear, non-color-only feedback |
## 6. Accessibility Rules
| Rule | Baseline |
|---|---|
| Minimum target | Critical controls should meet a 48dp target where practical. |
| Semantics | Icon-only controls require labels. |
| Focus | Desktop and tablet keyboard use require visible focus. |
| State expression | Critical states require more than color. |
| Text scale | Critical controls remain reachable under increased text size. |
| Reduced motion | Non-essential animation is reduced or disabled. |
## 7. Internationalization UX
Product strings are localized. Server-provided server names, channel names, nicknames, and messages are not translated. Mixed-language and bidirectional text must be rendered as text content and preserved through diagnostics unless redacted.
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial UI/UX guideline for Material 3, adaptive layout, accessibility, platform behavior, and i18n. |
## 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. |
-319
View File
@@ -1,319 +0,0 @@
# Android P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
Android P0 ship of Chanora. The officially-tested environment is
**Android 9 (API 28) or later on a physical Android device, installed
via either Play Internal Track or `bundletool install-apks`** (DEC-004).
Emulator support is best-effort — microphone capture and audio routing
in the AVD do not represent real-device behaviour.
Automated tests (`cargo check`, `cargo test --workspace --lib`,
`flutter test`, `flutter build appbundle --release`) sign off the
mechanical side. This checklist signs off the user-experience side.
A failure on any row blocks promotion of the Android build from rc.8.
Source: this checklist mirrors the iOS, iPadOS, macOS, Linux, and
Windows acceptance documents. SRS references: SRS-013 (audio),
SRS-111 (foreground service P0), SRS-119 (AAB packaging),
SRS-163 (Android back navigation), SRS-187 (min API 28),
SRS-188 (Play target API), SRS-208 (in-call audio mode),
SRS-209 (RECORD_AUDIO + listen-only fallback). SAD references:
SAD-018, SAD-037, SAD-063, SAD-077, SAD-081, SAD-084, SAD-085,
SAD-086. SDD references: SDD-028, SDD-073, SDD-105, SDD-106,
SDD-107, SDD-108, SDD-109, SDD-110. Decision: DEC-004
(Android min API 28). System requirements: SysRS-288, SysRS-305,
SysRS-306.
Android does NOT have a global PTT capability comparable to Windows /
macOS / Linux desktops. Per SDD-110 the desktop PTT backend ladder
collapses to `FocusedPttBackend` on Android and the capability badge
always advertises `L0Focused`. PTT works only while Chanora itself is
the foreground app (and while the voice foreground service per
SDD-107 keeps the mic stream alive when the screen is off).
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | On a Linux/macOS host install Android SDK + NDK + cmdline-tools. Accept SDK licences. | `adb`, `bundletool`, and Gradle wrapper are runnable. |
| 0.2 | Connect a physical Android device (API 28+) via USB. Enable Developer Options → USB debugging. | `adb devices` lists the device as `device` (not `unauthorized`). |
| 0.3 | Build the bridge for Android: `rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android && cd ~/chanora && cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 -t x86 -p 28 -- build --release -p chanora_bridge`. | `target/<abi>/release/libchanora_bridge.so` exists for each ABI. (SDD-073 NDK ABI set, SDD-105 JNI load.) |
| 0.4 | Build the AAB: `cd apps/chanora_flutter && flutter build appbundle --release`. | `build/app/outputs/bundle/release/app-release.aab` exists. (SRS-119, SDD-109) |
| 0.5 | Validate the AAB with bundletool: `bundletool build-apks --bundle=app-release.aab --output=chanora.apks --connected-device`. | bundletool reports `Universal APK`/`split APKs` per ABI and no validation errors. (SDD-109) |
| 0.6 | Install on the connected device: `bundletool install-apks --apks=chanora.apks`. (Or Play Console → Internal Testing → upload + opt-in.) | App installs without signature errors. (SDD-073 release-signing CI assertion.) |
| 0.7 | Launch the app. First-launch microphone prompt appears. | Prompt rationale is localized. (SRS-209, SDD-106) |
| 0.8 | About / version label inside Chanora | Shows **`v1.0.0-rc.8`**. |
## Device matrix expectations
Per SRS-187 / SRS-188, DEC-004, AND SDD-116 (Android voice audio backend
device matrix) the human pass shall be executed on the following devices:
| Tier | Android version | Reason | Acceptance subset |
|---|---|---|---|
| Floor | Android 9 (API 28) | Minimum supported per DEC-004 / SRS-187 / SysRS-288; SDD-116 row A | TC-1..TC-11 (all), TC-14 |
| Mid-tier | Android 12 (API 31) | Covers FGS foreground-type tightening (API 31); SDD-116 row B | TC-1..TC-11 (all), TC-12 predictive-back (if API ≥ 33), TC-15 |
| Target | Android 14 (API 34) per SRS-188 | Play upload + runtime target; SDD-116 row C; FGS-type=microphone strict on API 34 | TC-1..TC-11 (all), TC-13 Play Internal install path, TC-16 |
| OEM: Pixel | Any API ≥ 28 | SDD-116 OEM coverage — Pixel | TC-17 latency rig |
| OEM: Samsung | Any API ≥ 28 | SDD-116 OEM coverage — Samsung | TC-18 latency rig |
The Pixel and Samsung OEM rows MAY overlap with the API tier rows (e.g.
the API 34 device may be a Pixel). The minimum aggregate is four
physical devices when overlap is used, five otherwise.
## TC-1: Install + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | Connect button enabled |
| 1.2 | Tap Connect | Server snapshot appears |
| 1.3 | Background + relaunch with the same nickname | Server-visible UID is the same (identity persisted in app-private files dir) |
Traces: SRS-013, SRS-209. SWE.6: SWE6-SV-018. SWE.5: SWE5-IV-016.
## TC-2: Microphone permission state machine (SRS-209, SDD-106)
| # | Step | Expected |
|---|---|---|
| 2.1 | First run: tap PTT → system prompt appears → Allow. | Mic transmits. Capability badge says `L0Focused`. |
| 2.2 | Revoke RECORD_AUDIO via Settings → Apps → Chanora → Permissions while app is running. Return to Chanora and attempt to transmit. | App degrades to listen-only stream (per SRS-209 fallback). No crash. User-visible banner explains state. |
| 2.3 | Re-grant RECORD_AUDIO. | Transmit re-enables without restart (or via clearly-labelled "Retry" button). |
| 2.4 | Fresh install: deny the prompt twice (Android treats this as "permanently denied"). Attempt PTT. | App stays in listen-only; in-app banner deep-links to system settings. |
Traces: SRS-209, SysRS-306, SAD-085, SDD-106. SWE.4: SWE4-UV-041. SWE.5: SWE5-IV-017. SWE.6: SWE6-SV-019.
## TC-3: Voice channel join + foreground service longevity (SRS-111, SDD-107)
| # | Step | Expected |
|---|---|---|
| 3.1 | Join a voice channel. | Foreground service notification appears with `foregroundServiceType="microphone"` (API 30+). Per SDD-107 the notification is non-dismissible while connected. |
| 3.2 | Lock the screen. Leave the device idle for **≥ 10 minutes**. | Voice continues to be sent/received. No `ANR`, no service kill, no `RemoteServiceException`. |
| 3.3 | Open Settings → Battery while still connected. | Chanora is not listed as "restricted". (P0: warn user if it is.) |
| 3.4 | Disconnect voice channel. | Foreground service stops, notification disappears, AudioManager mode is restored (TC-6 verifies). |
Traces: SRS-111, SAD-081, SDD-107. SWE.4: SWE4-UV-043. SWE.5: SWE5-IV-018, SWE5-IV-019. SWE.6: SWE6-SV-018.
## TC-4: PTT press / release (Focused only — Android limitation, SDD-110)
| # | Step | Expected |
|---|---|---|
| 4.1 | Open Voice settings → Push to talk | Capability badge clearly states **L0 Focused** with explanatory text noting Android does not expose global hotkeys to background apps. |
| 4.2 | Touch and hold the on-screen PTT button | Mic indicator goes active while held; releases on touch-up. |
| 4.3 | Background the app while holding PTT (swipe home). | Per SDD-110 PTT does NOT continue while backgrounded; transition is observable in the UI on return. |
Traces: SRS-195, SRS-196, SAD-086, SDD-110. SWE.4: SWE4-UV-044. SWE.6: SWE6-SV-024.
## TC-5: Release tail
| # | Step | Expected |
|---|---|---|
| 5.1 | Set release-tail to 0 ms; tap-release | Sharp on/off. |
| 5.2 | Set release-tail to 500 ms; tap-release | Mic stays on ~500 ms after release. |
## TC-6: AudioManager in-call mode round-trip (SRS-208, SDD-108)
| # | Step | Expected |
|---|---|---|
| 6.1 | Before connecting, capture `AudioManager.getMode()` via diagnostic export (or `adb shell dumpsys audio`). Note the value (typically `MODE_NORMAL`). | Baseline recorded. |
| 6.2 | Connect + join voice channel. | Per SRS-208 / SDD-108 the controller enters in-call mode (`MODE_IN_COMMUNICATION` or platform equivalent). |
| 6.3 | Disconnect. | Per SDD-108 prior-mode snapshot is restored. Re-read AudioManager mode == baseline from 6.1. |
| 6.4 | Bluetooth SCO route check (P1 awareness, P0 minimum: no crash): pair a Bluetooth headset, connect Chanora voice. | P0: no crash, no permanent route lock. P1 follow-up: SCO routes correctly. |
Traces: SRS-208, SysRS-305, SAD-084, SDD-108. SWE.4: SWE4-UV-045. SWE.5: SWE5-IV-019. SWE.6: SWE6-SV-020. SYS.4: SYS4-SIV-017.
## TC-7: Mic / speaker mute
| # | Step | Expected |
|---|---|---|
| 7.1 | Mute mic via VoiceBar | Mic icon shows muted state; PTT does not unmute. |
| 7.2 | Speaker mute | Other clients silenced locally. |
## TC-8: Reconnect
| # | Step | Expected |
|---|---|---|
| 8.1 | Toggle airplane mode for 10 s then off | Connection-lost banner, then recovers. Foreground service does not crash during the transition. |
## TC-9: Diagnostic export + privacy (DEC-027)
| # | Step | Expected |
|---|---|---|
| 9.1 | Export a diagnostic bundle (Settings → Diagnostics → Export). | Bundle is saved via the system Storage Access Framework picker. Allow-listed fields only; no raw key labels, no audio bytes, no `RECORD_AUDIO` permission token. |
Traces: SRS-117/SRS-118 family. SWE.6: SWE6-SV-006.
## TC-10: Capability badge labels (SDD-110)
| # | Step | Expected |
|---|---|---|
| 10.1 | Capability badge | Shows `L0Focused` with text explaining Android does not expose session-level global hotkeys. |
## TC-11: Android back navigation (SRS-163, SDD-028)
| # | Step | Expected |
|---|---|---|
| 11.1 | Open a modal sheet (e.g. Settings → Push-to-Talk binding sheet) and press the system back gesture / button. | Modal closes; route stack unchanged. (SDD-028 modal-first rule.) |
| 11.2 | From a leaf screen press back. | Pops one route. Does not exit the app unless on the home route. |
| 11.3 | While PTT is actively held, press back. | Back is **ignored** until PTT is released. (SDD-028 PTT-active-ignore rule.) |
| 11.4 | From the home route press back. | App backgrounds via standard activity finish (does not crash). |
Traces: SRS-163, SAD-018, SDD-028. SWE.4: SWE4-UV-040, SWE4-UV-042. SWE.5: SWE5-IV-020. SWE.6: SWE6-SV-021.
## TC-12: Predictive back (Android 13+ API 33 branch, SDD-028)
| # | Step | Expected |
|---|---|---|
| 12.1 | On API 33+ enable "Predictive back animations" in Developer Options. Trigger a back gesture from a non-home route. | Predictive back preview shows; release commits the pop. SDD-028 API 33+ branch (`OnBackInvokedCallback`) is exercised. |
| 12.2 | On API ≤ 32 the same scenario uses the legacy `OnBackPressedDispatcher` branch (SDD-028 pre-33 branch). | Same end behaviour; no predictive preview. |
Traces: SRS-163, SDD-028. SWE.4: SWE4-UV-042. SWE.6: SWE6-SV-021.
## TC-13: Play Internal Track / bundletool install path (SRS-119, SRS-188, SDD-109)
| # | Step | Expected |
|---|---|---|
| 13.1 | Upload `app-release.aab` to Play Console → Internal Testing track (or via `bundletool` for the same effect). | Play accepts the bundle: targetSdk matches SRS-188, minSdk == 28 per DEC-004, signing key is the release CI key per SDD-073. |
| 13.2 | Opt-in tester installs via Play store internal link. | App installs and runs identically to the bundletool path (TC-0.6). |
| 13.3 | Verify the AAB contains per-ABI split APKs (`armeabi-v7a`, `arm64-v8a`, `x86_64`). | bundletool report lists all expected ABIs (SDD-109 ABI splits). |
Traces: SRS-119, SRS-188, SAD-063, SDD-073, SDD-109. SWE.5: SWE5-IV-020. SWE.6: SWE6-SV-022, SWE6-SV-023. SYS.4: SYS4-SIV-018.
## TC-14: Per-device evidence collection on API 28 device (SDD-116 matrix row A)
| # | Step | Expected |
|---|---|---|
| 14.1 | On the API 28 device, complete pre-flight then `voice_join` a test channel. | Channel join succeeds; FGS active per TC-3. |
| 14.2 | Export the backend diagnostics bundle (Settings → Diagnostics → Export, or the equivalent in-app action). | Export contains `achieved_performance_mode`, `achieved_sharing_mode`, `achieved_input_preset`, `achieved_output_usage`, `achieved_output_content_type`, and per-effect `{aec, ns, agc}` engagement (`hw` / `sw` / `unavailable`). |
| 14.3 | Record all six achieved values + per-effect engagement into the SDD-116 matrix table for the API 28 row. | All fields populated; no `unknown`. |
| 14.4 | `voice_leave`. | Backend tears down cleanly per SWE5-IV-023 reverse order. |
Traces: SRS-210, SRS-211, SRS-212, SRS-213, SRS-214, SRS-215, SDD-111, SDD-112, SDD-113, SDD-116. SWE.6: SWE6-SV-026, SWE6-SV-027, SWE6-SV-028, SWE6-SV-029, SWE6-SV-030. SWE.5: SWE5-IV-021.
## TC-15: Per-device evidence collection on API 31 device (SDD-116 matrix row B)
| # | Step | Expected |
|---|---|---|
| 15.1 | On the API 31 device, complete pre-flight then `voice_join`. | Channel join succeeds. |
| 15.2 | Export diagnostics bundle. | Same fields as TC-14.2 populated. |
| 15.3 | Record values into SDD-116 matrix table for the API 31 row. | All fields populated. |
| 15.4 | Verify FGS-foreground-type tightening branch is exercised: `dumpsys activity services <pkg>` shows the voice service running. | Service entry present; type recorded. |
| 15.5 | `voice_leave`. | Clean teardown. |
Traces: SRS-210..SRS-215, SDD-111..SDD-116. SWE.6: SWE6-SV-026..030. SWE.5: SWE5-IV-021, SWE5-IV-023.
## TC-16: Per-device evidence collection on API 34 device (SDD-116 matrix row C)
| # | Step | Expected |
|---|---|---|
| 16.1 | On the API 34 device, complete pre-flight then `voice_join`. | Channel join succeeds. |
| 16.2 | Export diagnostics bundle. | Same fields as TC-14.2 populated. |
| 16.3 | Record values into SDD-116 matrix table for the API 34 row. | All fields populated. |
| 16.4 | Verify `dumpsys activity services <pkg>` shows `foregroundServiceType=microphone` for the voice service (API 34 type tightening). | `microphone` type present. |
| 16.5 | Screen-off / locked for ≥ 10 minutes during a live voice session. | Mic frames continue (per-minute frame-count probe in diagnostics is non-zero each minute). No `MissingForegroundServiceTypeException` in logcat. |
| 16.6 | `voice_leave`. | Clean teardown. |
Traces: SRS-210..SRS-215, SDD-107, SDD-111..SDD-116. SWE.6: SWE6-SV-026..030. SWE.5: SWE5-IV-021, SWE5-IV-023, SWE5-IV-026.
## TC-17: Glass-to-glass latency measurement on Pixel device (SDD-116 OEM coverage)
| # | Step | Expected |
|---|---|---|
| 17.1 | Set up the latency rig per `swe6-software-verification-plan.md` "Glass-to-glass latency measurement procedure" (DUT = Pixel device, reference listener on LAN, stereo capture on audio interface). | Rig produces clean impulse / listener channels. |
| 17.2 | Record `achieved_performance_mode` for the Pixel DUT. | Recorded (typically `LowLatency` on Pixel). |
| 17.3 | Run 20 impulses; compute median and p95 latency. | Both recorded. |
| 17.4 | Compare against SRS-210 tier per SWE6-SV-025 pass criteria. | If `LowLatency`: median ≤ 150 ms, p95 ≤ 180 ms. Otherwise: median ≤ 250 ms, p95 ≤ 300 ms. |
| 17.5 | Archive raw stereo WAVs + measurement script + per-impulse CSV. | Artifacts attached to test report. |
Traces: SRS-210, SDD-111, SDD-112, SDD-116. SWE.6: SWE6-SV-025. SWE.4: SWE4-UV-051 (tier classifier).
## TC-18: Glass-to-glass latency measurement on Samsung device (SDD-116 OEM coverage)
| # | Step | Expected |
|---|---|---|
| 18.1 | Re-run the TC-17 rig with the DUT swapped to a Samsung device. | Rig setup unchanged. |
| 18.2 | Record `achieved_performance_mode` for the Samsung DUT. | Recorded. |
| 18.3 | Run 20 impulses; compute median and p95 latency. | Both recorded. |
| 18.4 | Compare against SRS-210 tier per SWE6-SV-025 pass criteria. | Same thresholds as TC-17.4 against the Samsung-achieved tier. |
| 18.5 | Archive evidence as TC-17.5. | Artifacts attached. |
Traces: SRS-210, SDD-111, SDD-112, SDD-116. SWE.6: SWE6-SV-025. SWE.4: SWE4-UV-051.
## Auto-test sign-off
These rows do not require human interaction.
| Layer | Result |
|---|---|
| `cargo check --workspace` | clean |
| `cargo test --workspace --lib` | unchanged (Android-specific Rust code is `#[cfg(target_os = "android")]`-gated) |
| `cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 -p 28 -- build --release -p chanora_bridge` | clean per ABI |
| `flutter test` in `apps/chanora_flutter` | green; widget + e2e suites carry SRS trace headers |
| `flutter build appbundle --release` | clean — produces `app-release.aab` |
| `bundletool validate --bundle=app-release.aab` | no errors |
| Gradle `assertMinSdk28` task (per SDD-073) | passes; minSdk in merged manifest == 28 |
| R8 / ProGuard release pass (per SDD-073) | clean; mapping file archived |
| CI release-signing key custody check (per SDD-073) | signing key reference matches expected fingerprint |
## Sign-off form
```
chanora v1.0.0-rc.8 — Android P0 acceptance
Device 1 (API 28): ______________________ (model + Android version)
Device 2 (mid): ______________________ (model + Android version)
Device 3 (target): ______________________ (model + Android version)
Tester: ______________________
Date: ______________________
TC-1 Install + identity persistence [ pass / fail ] notes:
TC-2 RECORD_AUDIO state machine [ pass / fail ] notes:
TC-3 Voice channel + FGS longevity [ pass / fail ] notes:
TC-4 PTT press / release (Focused) [ pass / fail ] notes:
TC-5 Release tail [ pass / fail ] notes:
TC-6 AudioManager mode round-trip [ pass / fail ] notes:
TC-7 Mic / speaker mute [ pass / fail ] notes:
TC-8 Reconnect [ pass / fail ] notes:
TC-9 Diagnostic export + privacy [ pass / fail ] notes:
TC-10 Capability badge label [ pass / fail ] notes:
TC-11 Back navigation [ pass / fail ] notes:
TC-12 Predictive back (API 33+) [ pass / fail ] notes:
TC-13 Play Internal / bundletool install [ pass / fail ] notes:
TC-14 Per-device evidence API 28 (SDD-116 A)[ pass / fail ] notes:
TC-15 Per-device evidence API 31 (SDD-116 B)[ pass / fail ] notes:
TC-16 Per-device evidence API 34 (SDD-116 C)[ pass / fail ] notes:
TC-17 Latency rig — Pixel [ pass / fail ] notes:
TC-18 Latency rig — Samsung [ pass / fail ] notes:
Overall result: [ Android rc.8 PASS / Android rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **Bluetooth SCO routing**: P0 only requires no-crash behaviour. Full SCO route correctness is P1.
- **Background PTT**: not possible on Android per platform model; `FocusedPttBackend` only (SDD-110).
- **VAD** (`TransmitMode::VoiceActivity`) intentionally disabled in P0 (DEC-030).
- **Tablet / foldable layouts**: this checklist targets phone form factor. The wide-mode (≥ 840 dp) UI works but is not signed off here.
- **Play Console upload key custody**: depends on whoever holds the release keystore; CI signing assertion (SDD-073) covers the mechanical side only.
-183
View File
@@ -1,183 +0,0 @@
# iOS P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
iOS P0 ship of Chanora. The officially-tested environment is
**iOS 17 or later on a physical iPhone signed with the developer's
personal team** (DEC-025). Simulator support is best-effort —
microphone capture is simulated by the host's mic but global PTT
behaviour cannot be exercised in the simulator.
Automated tests (`cargo check`, `cargo test --workspace --lib`)
sign off the mechanical side. This checklist signs off the user-
experience side. A failure on any row blocks promotion of the iOS
build from rc.8.
Source: this checklist mirrors the macOS, Linux, and Windows
acceptance documents. Auto-test sign-off lives in this document's
"Auto-test sign-off" section. SDD references: SDD-094..097, SDD-098..104 (v1
audio + PTT lifecycle), DEC-025 (target environment), DEC-027
(diagnostic privacy invariant), SRS-197 (iOS audio routing
contract), SRS-198 (honest capability advertising under runtime
permission state).
iOS does NOT have a global PTT capability comparable to Windows /
macOS / Linux desktops. The desktop PTT backend ladder
(`SDD-081..088`) collapses to `FocusedPttBackend` on iOS and the
capability badge always advertises `L0Focused`. PTT works only
while Chanora itself is the foreground app. This is intentional
per DEC-025 — Apple's iOS sandbox model has no path to a
session-level event tap analogue.
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | Open `apps/chanora_flutter/ios/Runner.xcworkspace` in Xcode once. In Runner target → Signing & Capabilities → set your **personal team** (free Apple ID team is sufficient for the P0 device pass). Set a unique bundle identifier (e.g. `your.name.chanoraFlutter`) — the default `com.example.chanoraFlutter` may already be claimed in the App Store registry. | Xcode shows "Provisioning Profile: Xcode Managed Profile" with no errors. |
| 0.2 | Connect a physical iPhone via USB and trust the development Mac. On the iPhone: Settings → General → VPN & Device Management → developer-cert → Trust. | iPhone appears in Xcode's device picker. |
| 0.3 | Build the bridge for the device: `cd ~/chanora && rustup target add aarch64-apple-ios && cargo build --release --target aarch64-apple-ios -p chanora_bridge`. | `target/aarch64-apple-ios/release/libchanora_bridge.a` is produced. |
| 0.4 | Build the Flutter app: `cd apps/chanora_flutter && flutter build ios --release`. | `build/ios/iphoneos/Runner.app` exists. |
| 0.5 | Install + launch on the iPhone: in Xcode pick the device + Runner scheme → Run. | App launches on phone. |
| 0.6 | On first launch the iPhone prompts for **Microphone** access — Allow. | Prompt text matches `NSMicrophoneUsageDescription` from `ios/Runner/Info.plist`. |
| 0.7 | About / version label inside Chanora | Shows **`v1.0.0-rc.8`**. |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | Connect button enabled |
| 1.2 | Tap Connect | Server snapshot appears |
| 1.3 | Quit (background) + relaunch with the same nickname | Server-visible UID is the same (identity persisted in the app-private support directory as `identity.tskey`) |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | Tap a voice channel | Join works; voice bar shows the channel name. Mic capture starts (the iOS status bar may show a red microphone indicator). |
| 2.2 | Tap a different voice channel | Smooth move; no audio dropout. |
## TC-3: PTT press / release (Focused only — iOS limitation, SDD-103)
| # | Step | Expected |
|---|---|---|
| 3.1 | Open Voice settings (gear icon), select Push to talk | The capability badge clearly states **L0 Focused** with explanatory text noting iOS does not permit global hotkeys. |
| 3.2 | Bind a key — the only "bound" key on iOS is the on-screen PTT button in the Voice Bar | "Bound key" UI is replaced by an on-screen Push-to-Talk button. |
| 3.3 | Touch and hold the PTT button | Mic indicator turns "Mic on" while held; releases on touch-up. |
## TC-4: Release tail (SDD-096)
| # | Step | Expected |
|---|---|---|
| 4.1 | Set release-tail to 0 ms; tap-and-release the PTT button | Sharp on/off transition. |
| 4.2 | Set release-tail to 500 ms; tap-and-release | Mic stays on for ~500 ms after release. |
## TC-5: Continuous mode
| # | Step | Expected |
|---|---|---|
| 5.1 | Switch to Continuous mode | PTT button disappears; mic stays open while in the voice channel. |
## TC-6: Mic mute
| # | Step | Expected |
|---|---|---|
| 6.1 | Mute mic via the Voice Bar | Mic icon shows muted state; touching the PTT button does not unmute it. |
## TC-7: Speaker mute
| # | Step | Expected |
|---|---|---|
| 7.1 | Speaker mute | Other clients silenced locally. |
## TC-8: Background audio (UIBackgroundModes = audio, SDD-102)
| # | Step | Expected |
|---|---|---|
| 8.1 | While connected + in a voice channel + in Continuous mode, swipe Chanora to the background. | The iOS red microphone indicator stays on; voice continues to be received and sent. |
| 8.2 | Return to Chanora | Session intact; no reconnect cycle. |
| 8.3 | Lock the iPhone for 30 s, then unlock | Session still intact (provided you stayed in the channel and on cellular/wifi network). |
## TC-9: AVAudioSession routing (SDD-098, SDD-100, SDD-101)
| # | Step | Expected |
|---|---|---|
| 9.1 | With voice connected, place an iPhone phone call to yourself (or have someone call). | Chanora's audio session yields to the phone call (iOS owns the audio focus). |
| 9.2 | End the phone call | Chanora resumes audio without manual reconnect. |
| 9.3 | Connect AirPods / Bluetooth headset; talk on Chanora | Audio routes to the headset (`.allowBluetoothHFP` + `.allowBluetoothA2DP` are set in `AppDelegate.swift`). |
## TC-10: Reconnect
| # | Step | Expected |
|---|---|---|
| 10.1 | Toggle Airplane Mode on for 10 s, then off | Connection-lost banner appears, then recovers. |
## TC-11: Diagnostic export + privacy (DEC-027)
| # | Step | Expected |
|---|---|---|
| 11.1 | Export a diagnostic bundle | Allow-listed fields only; no raw key labels, no audio bytes. |
## TC-12: Capability badge labels (SDD-103)
| # | Step | Expected |
|---|---|---|
| 12.1 | Capability badge | Shows `L0Focused` with explanation that iOS does not expose global hotkeys. |
## Auto-test sign-off
These rows do not require human interaction.
| Layer | Result |
|---|---|
| `cargo check --workspace` on macOS host | clean |
| `cargo test --workspace --lib` on macOS host | unchanged (iOS-specific Rust code is `#[cfg(target_os = "ios")]`-gated and not exercised in host tests) |
| `cargo build --release --target aarch64-apple-ios -p chanora_bridge` | clean — produces `libchanora_bridge.a` |
| `flutter build ios --release` | clean — produces `Runner.app` |
| `AppDelegate.swift` registers `AVAudioSession.routeChangeNotification` and `AVAudioSession.interruptionNotification` observers (SDD-100, SDD-101) | Log lines `chanora_flutter: route change reason=…` and `chanora_flutter: audio interruption began/ended` in device console. |
## Sign-off form
```
chanora v1.0.0-rc.8 — iOS P0 acceptance
Device: ______________________ (model + iOS version)
Tester: ______________________
Date: ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release (Focused) [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Background audio [ pass / fail ] notes:
TC-9 AVAudioSession routing [ pass / fail ] notes:
TC-10 Reconnect [ pass / fail ] notes:
TC-11 Diagnostic export + privacy [ pass / fail ] notes:
TC-12 Capability badge label [ pass / fail ] notes:
Overall result: [ iOS rc.8 PASS / iOS rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **TestFlight + App Store distribution**: requires the paid $99/yr Apple Developer Program (the personal team is sufficient for sideloaded device testing but not for TestFlight). P1 follow-up.
- **Simulator audio**: cpal-via-CoreAudio inside the iOS simulator routes to the Mac's audio devices and is fine for smoke-testing the UI, but real microphone capture / AEC behaviour cannot be assessed there. Test on a physical iPhone.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally disabled in P0 (DEC-030).
- **iPad layout**: this checklist targets iPhone. The wide-mode (≥ 840 dp) UI works on iPad but is not signed off here.
-245
View File
@@ -1,245 +0,0 @@
# iPad P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
iPad P0 ship of Chanora. The build artefact is the **same**
`Runner.app` produced for iPhone (`TARGETED_DEVICE_FAMILY = "1,2"`
in `Runner.xcodeproj` — both iPhone (1) and iPad (2)). Apple's
free Personal Team provisioning profile includes iPad in the
universal family, so the same sideload that installs on an iPhone
installs on an iPad.
The officially-tested environment is **iPadOS 17 or later on a
physical iPad**, signed with the developer's personal team
(DEC-025 covers iPhone; this document extends P0 coverage to
iPad). Simulator support is best-effort — microphone capture and
AirPlay 2 routing cannot be assessed in the simulator.
Automated tests (`cargo check`, `cargo test --workspace --lib`)
sign off the mechanical side. This checklist signs off the user-
experience side. A failure on any row blocks promotion of the
iPad build from rc.8.
Source: this checklist extends `ios-p0-acceptance.md` with the
three iPad-specific rows (split-view multitasking, on-screen
keyboard occlusion, AirPlay 2 audio route) and removes the rows
that don't apply (background-audio behaviour is identical
because both share the same `UIBackgroundModes = ['audio']`
declaration in `Info.plist`). SDD references: SDD-094..097 (v1
audio + PTT lifecycle), DEC-025 (target environment), DEC-027
(diagnostic privacy invariant), SRS-197 (iOS/iPadOS audio
routing contract).
iPad does **not** have a global PTT capability — Apple's iOS /
iPadOS sandbox model has no session-level event-tap analogue.
The desktop PTT backend ladder (SDD-081..088) collapses to
`FocusedPttBackend` and the capability badge advertises
`L0Focused`. PTT works only while Chanora is the foreground app
(or the audio-background mode keeps streaming when Chanora is
backgrounded; see TC-8 / TC-13).
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | Same Xcode signing setup as iOS: in `Runner.xcworkspace`, Runner target → Signing & Capabilities → personal team selected, unique bundle id. (If you already did this for iPhone the iPad uses the same provisioning profile.) | No code-signing errors in Xcode. |
| 0.2 | Connect iPad via USB and trust the development Mac. On iPad: Settings → General → VPN & Device Management → developer-cert → Trust. | iPad appears in Xcode's device picker. |
| 0.3 | Build for iPad: in Xcode pick the iPad as the run destination + Runner scheme → Cmd+R. (Or via CLI: `flutter build ios --release` then sideload with `xcrun devicectl device install app`.) | App installs on iPad and launches. |
| 0.4 | First launch: iPad prompts for **Microphone** access — Allow. The prompt string matches `NSMicrophoneUsageDescription` from `ios/Runner/Info.plist`. | Mic permission granted. |
| 0.5 | About / version label inside Chanora | Shows **`v1.0.0-rc.8`**. |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | Connect button enabled. |
| 1.2 | Tap Connect | Server snapshot appears. |
| 1.3 | Quit (background) + relaunch with the same nickname | Server-visible UID is the same (identity persisted in `Documents/identity.tskey`). |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | Tap a voice channel | Join works; voice bar shows the channel name. Mic capture starts (iOS status bar shows the orange mic indicator on iPadOS 17+). |
| 2.2 | Tap a different voice channel | Smooth move; no audio dropout. |
## TC-3: PTT press / release (Focused only — iPadOS limitation)
| # | Step | Expected |
|---|---|---|
| 3.1 | Open Voice settings (gear icon), select Push to talk | Capability badge clearly states **L0 Focused** with explanatory text that iPadOS does not permit global hotkeys. |
| 3.2 | The "Bound key" UI is replaced by an on-screen Push-to-Talk button. | Touch and hold the button → mic indicator turns "Mic on". Release → indicator returns "Mic off" after the configured release-tail. |
## TC-4: Release tail (SDD-097)
| # | Step | Expected |
|---|---|---|
| 4.1 | Set release-tail to 0 ms; tap-and-release the PTT button | Sharp on/off transition. |
| 4.2 | Set release-tail to 500 ms; tap-and-release | Mic stays on for ~500 ms after release. |
## TC-5: Continuous mode
| # | Step | Expected |
|---|---|---|
| 5.1 | Switch to Continuous mode | PTT button disappears; mic stays open while in the voice channel. |
## TC-6: Mic mute
| # | Step | Expected |
|---|---|---|
| 6.1 | Mute mic via the Voice Bar | Mic icon shows muted state. Touching the PTT button does NOT unmute. |
## TC-7: Speaker mute
| # | Step | Expected |
|---|---|---|
| 7.1 | Speaker mute | Other clients silenced locally. |
## TC-8: Background audio (UIBackgroundModes = audio)
| # | Step | Expected |
|---|---|---|
| 8.1 | While connected + in a voice channel + in Continuous mode, swipe Chanora to the App Switcher (or press the home button if your iPad has one). | The iPadOS orange mic indicator stays on; voice continues to be received and sent. |
| 8.2 | Return to Chanora | Session intact; no reconnect cycle. |
| 8.3 | Lock the iPad for 30 s, then unlock | Session still intact (provided you stayed in the channel and on Wi-Fi/cellular). |
## TC-9: AVAudioSession routing (SRS-197)
| # | Step | Expected |
|---|---|---|
| 9.1 | Connect AirPods / Bluetooth headset; talk on Chanora | Audio routes to the headset (`.allowBluetooth` + `.allowBluetoothA2DP` are set in `AppDelegate.swift::application(_:didFinishLaunchingWithOptions:)`). |
| 9.2 | Disconnect the headset mid-call | Audio routes back to the built-in speakers (`.defaultToSpeaker`). |
| 9.3 | (If iPad has FaceTime configured) place a FaceTime call to yourself or have someone call. | Chanora's audio session yields to the FaceTime call. |
| 9.4 | End the FaceTime call | Chanora resumes audio without manual reconnect. |
## TC-10: Reconnect
| # | Step | Expected |
|---|---|---|
| 10.1 | Toggle Airplane Mode on for 10 s, then off | Connection-lost banner appears, then recovers. |
## TC-11: Diagnostic export + privacy (DEC-027)
| # | Step | Expected |
|---|---|---|
| 11.1 | Export a diagnostic bundle | Allow-listed fields only; no raw key labels, no audio bytes. |
## TC-12: Capability badge label
| # | Step | Expected |
|---|---|---|
| 12.1 | Capability badge | Shows `L0Focused` with explanation that iPadOS does not expose global hotkeys. |
## TC-13: iPad-specific — wide-mode landscape layout
The Flutter UI uses a `LayoutBuilder` 840 dp breakpoint
(`apps/chanora_flutter/lib/main.dart`). On iPhone in portrait the
body is below 840 dp, so the layout is stacked (Voice Bar on top,
channel tree below). On iPad in landscape the body is well above
840 dp, so the layout splits into a 320 dp left column (banner +
Voice Bar) and the rest filled by the channel tree.
| # | Step | Expected |
|---|---|---|
| 13.1 | Rotate iPad to landscape, connect to a server, double-click into a voice channel. | Voice Bar pinned to a 320 dp left column. Channel tree fills the rest. The "not production ready" banner sits inside the left column above the Voice Bar (per the earlier left-column-banner change). |
| 13.2 | Rotate iPad to portrait. | Layout flips back to the stacked iPhone-style arrangement. Voice Bar on top full-width, channel tree below. Banner pins full-width at the top above the connection status. |
| 13.3 | In landscape, join a channel with a very long name. | The channel-name pill in the Voice Bar truncates with an ellipsis instead of overflowing under the channel tree. Mute icons stay anchored to the right edge of the left column. |
## TC-14: iPad-specific — Split View / Slide Over
Multitasking with other iPad apps. Our scaffold currently sets
`UIApplicationSupportsMultipleScenes = false` in `Info.plist`,
so Split View is **not** supported in P0. This row exists to
document that and ensure the app doesn't crash when iPadOS tries.
| # | Step | Expected |
|---|---|---|
| 14.1 | In landscape, swipe up from the iPad home indicator → drag Chanora to the right edge to enter Split View, or pick "Slide Over" from the iPadOS multitasking menu. | iPadOS shows the Split View / Slide Over UI but Chanora remains full-screen and does not crash. The non-support is by design for P0; a P1 follow-up will switch to multi-scene. |
## TC-15: iPad-specific — AirPlay 2 audio route
| # | Step | Expected |
|---|---|---|
| 15.1 | While in a voice channel, open Control Center → AirPlay → pick an AirPlay 2 speaker (HomePod, Apple TV, AirPlay-compatible receiver). | Audio routes to the AirPlay destination. The PTT-active indicator continues to work; the mic stays routed to the iPad built-in mic (AirPlay 2 receivers don't typically have a return mic channel). |
| 15.2 | Reselect "iPad" as the audio route | Audio returns to local routing. No restart needed. |
## Auto-test sign-off
These rows do not require human interaction. The values are the
same as the iOS document — iPad uses the identical Rust + Flutter
build artefacts.
| Layer | Result |
|---|---|
| `cargo check --workspace` on macOS host | clean |
| `cargo test --workspace --lib` on macOS host | unchanged (iPad-specific Rust code does not exist; iOS-targeted code is `#[cfg(target_os = "ios")]`-gated and applies identically to iPadOS) |
| `cargo build --release --target aarch64-apple-ios -p chanora_bridge` | clean — produces `libchanora_bridge.a` |
| `flutter build ios --release` | clean — produces `Runner.app` ≈ 17 MB (same artefact as iPhone) |
| `Runner.xcodeproj` `TARGETED_DEVICE_FAMILY = "1,2"` | Universal family confirmed via `grep TARGETED_DEVICE_FAMILY ios/Runner.xcodeproj/project.pbxproj`. |
## Sign-off form
```
chanora v1.0.0-rc.8 — iPad P0 acceptance
Device: ______________________ (iPad model + iPadOS version)
Tester: ______________________
Date: ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release (Focused) [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Background audio [ pass / fail ] notes:
TC-9 AVAudioSession routing [ pass / fail ] notes:
TC-10 Reconnect [ pass / fail ] notes:
TC-11 Diagnostic export + privacy [ pass / fail ] notes:
TC-12 Capability badge label [ pass / fail ] notes:
TC-13 Wide-mode landscape layout [ pass / fail ] notes:
TC-14 Split View / Slide Over no-crash [ pass / fail ] notes:
TC-15 AirPlay 2 audio route [ pass / fail ] notes:
Overall result: [ iPad rc.8 PASS / iPad rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **Split View / Slide Over multitasking** is intentionally
unsupported in P0. `UIApplicationSupportsMultipleScenes` stays
`false` until we wire iPadOS multi-scene handling (P1).
- **Apple Pencil + external keyboard shortcuts**: not wired. A
paid Developer Program account would let us declare
`GCKeyboard` hardware-keyboard support for things like Cmd+M
to mute — P1 follow-up.
- **Stage Manager** (iPadOS 16+): app runs but the layout is not
optimised for resizable Stage Manager windows. P1.
- **TestFlight + App Store distribution**: requires the paid
$99/yr Apple Developer Program. P1 follow-up.
- **Simulator audio**: cpal-via-CoreAudio inside the iPad
simulator routes to the Mac's audio devices and is fine for
smoke-testing the UI, but real microphone capture / AEC
behaviour and AirPlay 2 routing cannot be assessed there.
Test on a physical iPad.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally
disabled in P0 (DEC-030).
-228
View File
@@ -1,228 +0,0 @@
# Linux P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
Linux P0 ship of Chanora. The officially-tested environment is
**GNOME on Wayland** (DEC-025); on every other Linux environment
(X11, sway, KDE, etc.) the desktop PTT layer cleanly downgrades to
`FocusedPttBackend` and the rest of the app continues to function.
Automated tests (`cargo check`, `cargo test --workspace --lib`,
the `#[ignore]`-gated `linux_portal_smoke.rs`, and the cross-
platform `ptt_privacy` integration test) sign off the mechanical
side. This checklist signs off the user-experience side. A failure
on any row blocks promotion of the Linux build from rc.8.
Source: this checklist mirrors `windows-p0-acceptance.md`. The
auto-test sign-off lives in this document's "Auto-test sign-off"
section. SDD references: SDD-081 (trait), SDD-086 (Linux GNOME
Wayland portal backend), SDD-094..097 (v1 audio + PTT lifecycle),
DEC-025 (target environment), DEC-027 (diagnostic privacy
invariant).
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | Log in to the GNOME on Wayland session at the physical console of `100.74.219.114` (user `edison`). Verify `echo $XDG_SESSION_TYPE` prints `wayland` and `echo $XDG_CURRENT_DESKTOP` contains `GNOME`. | Wayland GNOME session active. SSH/`tty` sessions are **not** sufficient; on those `try_select()` correctly returns `None` and the rest of this checklist is skipped from row TC-3 onward. |
| 0.2 | Confirm `xdg-desktop-portal` and `xdg-desktop-portal-gnome` are installed: `pacman -Q xdg-desktop-portal xdg-desktop-portal-gnome` | Both packages present. (On the Arch verification host these are `1.20.4-1` and `50.0-1` respectively.) |
| 0.3 | Wipe stale install: `rm -rf ~/.local/share/app.chanora/ ~/.config/app.chanora/` | First-launch from clean state. |
| 0.4 | Build: `cd ~/chanora && cargo build --release -p chanora_bridge`. Then build the Flutter Linux bundle: `cd apps/chanora_flutter && flutter build linux --release` and copy `target/release/libchanora_bridge.so` next to the runner if the build glue did not auto-bundle it. | Build succeeds, runner binary at `apps/chanora_flutter/build/linux/x64/release/bundle/chanora_flutter` exists, bridge `.so` is in `bundle/lib/` or alongside the runner. |
| 0.5 | Launch the runner from a GNOME-Wayland terminal (so the process inherits the right `DBUS_SESSION_BUS_ADDRESS` + `WAYLAND_DISPLAY`). | Window opens, no crash. |
| 0.6 | Open About / version label | Shows **`v1.0.0-rc.8`**. |
| 0.7 | Open `~/.local/share/app.chanora/chanora_flutter/logs/chanora.log` | Contains `bridge initialised`, `log file path …`, `identity store initialised`, `bookmark store initialised`. File <1 MB. The descriptor line for the PTT backend should mention `backend_id = "gnome-wayland-portal"` (or `"focused"` if not on GNOME Wayland). |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | "Connect" button enabled |
| 1.2 | Click Connect | Server snapshot appears: channel tree on left, client list visible |
| 1.3 | Note the connected server name + the channel tree | Tree is sorted (parents above children); depth indent visible up to 6 levels |
| 1.4 | Disconnect, reconnect with the same nickname | Server-visible UID is the same as previous session (identity persisted via `~/.local/share/app.chanora/identity.dek`) |
| 1.5 | Disconnect | Returns to connect form, no error |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | After connecting, observe the UI | **No "Start audio" button anywhere.** Voice Bar is visible at the bottom. |
| 2.2 | Double-click a voice channel | Client moves into that channel; voice bar shows the channel name; `voice_join` log line appears with no error |
| 2.3 | Double-click a different voice channel | Client moves; no audio glitch; `voice_join` repeats cleanly |
| 2.4 | Double-click the same channel again quickly (concurrency) | Either: no-op move, or single clean move; no duplicate audio engine spawn (engine is single-instance) |
## TC-3: PTT press / release (SDD-083, SDD-086, SDD-096) — GNOME-Wayland only
| # | Step | Expected |
|---|---|---|
| 3.1 | Open Voice settings (gear icon), select **Push to talk** | Bind-key row + Release-tail slider become visible |
| 3.2 | Click "Bind key" | GNOME's **system** portal dialog appears asking you to pick a shortcut. (Chanora itself never reads raw keys — this is the portal's own UI.) |
| 3.3 | Pick a key (e.g. Right Ctrl), accept | Dialog closes. VoiceBar's capability badge transitions from `L0` to `L2 GlobalHoldToTalk` (or `L3` for a mouse side-button). Bound-key label shows the portal's translated description. |
| 3.4 | With another window focused, hold the bound key | Mic indicator turns "Mic on"; `transmit_active` true in stats |
| 3.5 | Release the key | After the configured release-tail, indicator returns to "Mic off" |
| 3.6 | Switch focus several times while pressing the key | PTT still fires from another window — this is the portal's "global" guarantee |
## TC-4: Release tail (SDD-097)
| # | Step | Expected |
|---|---|---|
| 4.1 | Set release-tail to 0 ms in Voice settings | Slider updates immediately |
| 4.2 | Tap PTT key briefly | Mic on/off transition is sharp (no tail) |
| 4.3 | Set release-tail to 500 ms | Slider updates immediately |
| 4.4 | Tap PTT key briefly | Mic stays "on" for ~500 ms after release before flipping to off |
## TC-5: Continuous mode (SDD-094)
| # | Step | Expected |
|---|---|---|
| 5.1 | Switch transmit mode to **Continuous** | Bind-key + release-tail rows disappear; capability badge greys out. |
| 5.2 | Talk into mic | "Mic on" stays solid; no self-disable bug. |
| 5.3 | Switch back to PTT | Previously bound key still works without re-binding (binding persisted in `audio_meta.json`). |
## TC-6: Mic mute (SDD-097)
| # | Step | Expected |
|---|---|---|
| 6.1 | Press mic-mute toggle in Voice Bar | Mic icon shows muted state; selector hard-mute engaged. |
| 6.2 | Press PTT (still muted) | No "Sending audio while muted" spam in log. Mic indicator does not flip on. |
| 6.3 | Un-mute | PTT resumes working normally. |
## TC-7: Speaker mute
| # | Step | Expected |
|---|---|---|
| 7.1 | Press speaker-mute toggle | Other clients in channel are silenced locally; server still sees you in channel. |
## TC-8: Binding persistence across restart
| # | Step | Expected |
|---|---|---|
| 8.1 | With a working PTT binding, quit Chanora | `audio_meta.json` next to `identity.dek` shows the new `ptt_*` fields. |
| 8.2 | Relaunch | Binding restored without re-running the portal dialog. Hold key — mic flips on. |
## TC-9: Binding before voice-join
| # | Step | Expected |
|---|---|---|
| 9.1 | Connect to server, do **not** join a voice channel yet. Open Voice settings, bind a PTT key. | Portal dialog appears; binding succeeds. |
| 9.2 | Now double-click a voice channel | Voice engine starts with the existing binding active immediately. |
## TC-10: No-permission channel rejection (typed `ServerRejected` propagation)
| # | Step | Expected |
|---|---|---|
| 10.1 | Try to join a channel you lack permissions on | Red SnackBar with a human message derived from the TS3 error code (e.g. `permissions_client_insufficient` → "You do not have permission to join this channel."). Move does not silently fail. |
## TC-11: Reconnect
| # | Step | Expected |
|---|---|---|
| 11.1 | Yank the wifi or run `nmcli con down …` for 10 s, then reconnect | UI shows red "Connection lost" banner, then recovers. Transient `os error 111` blips are logged but **not** shown as a banner. |
## TC-12: Diagnostic export + privacy (DEC-027, SAD-077, SDD-090)
| # | Step | Expected |
|---|---|---|
| 12.1 | Open Diagnostics, export a bundle | Bundle contains tracing records with allow-listed fields only: `backend_id`, `bound_input_class`, `capability_level`, `host_id`, `timeout_secs`, `error`, `event`, `message`, `target`, `level`. **No `platform_key`, no `trigger_description`, no raw key codes.** |
| 12.2 | Grep the bundle for the human-readable PTT key label | No hit. |
## TC-13: PTT bind dialog labels
| # | Step | Expected |
|---|---|---|
| 13.1 | Open Voice settings; the Bind-key row's display reads the portal's translated description (e.g. "Ctrl+Right Shift") | The translated string never appears in `chanora.log`. |
## TC-14: Capability badge gating
| # | Step | Expected |
|---|---|---|
| 14.1 | On a non-GNOME-Wayland session (e.g. SSH-only `tty`, X11, sway), the badge displays `L0Focused` and explains it is information-only. The Bind-key UI is hidden in PTT mode if the backend is `focused`. | Verified manually by logging into the matching environment. |
## TC-15: Indicator label
| # | Step | Expected |
|---|---|---|
| 15.1 | In any mode, look at the stats line | Reads "Mic on" / "Mic off" (mode-neutral); **not** "PTT on" / "PTT off" |
## Auto-test sign-off
These rows do not require human interaction.
| Layer | Result on Arch host `100.74.219.114` |
|---|---|
| `cargo check --workspace --release` | clean (`Finished `release` profile [optimized] target(s) in 30.99s`) |
| `cargo test --workspace --lib` | **78 passed / 0 failed / 1 ignored** (sums across all 7 workspace crates: `chanora_audio` 32, `chanora_bridge` 0, `chanora_core` 13, `chanora_diagnostics` 12, `chanora_protocol` 8 + 1 ignored, `chanora_state` 1, `chanora_storage` 12) |
| `cargo test -p chanora_audio --test linux_portal_smoke -- --ignored` | **1 passed / 0 failed**; log line `GlobalShortcuts portal reachable, version = 1`. Run with `DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus` + `XDG_SESSION_TYPE=wayland` + `XDG_CURRENT_DESKTOP=GNOME` exported. |
| `cargo test -p chanora_audio --test ptt_privacy` | **1 passed / 0 failed** — DEC-027 invariant holds. |
The Linux host runs fewer tests than the Korean Win 11 host (which
reports 126 / 0 / 1) because the `#[cfg(target_os = "windows")]`-
gated PTT-backend dispatcher and full-chain tests in
`crates/chanora_audio/src/ptt_backends/windows.rs` and
`core/chanora_core/src/ptt.rs::windows_full_chain_tests` are
Windows-only by construction. The Linux equivalent — the GNOME
portal flow — is exercised by the `linux_portal_smoke` ignored
integration test and the inline unit tests in
`crates/chanora_audio/src/ptt_backends/linux.rs` (counted within
the `chanora_audio` 32 above).
## Sign-off form
```
chanora v1.0.0-rc.8 — Linux P0 acceptance
Host: Arch Linux GNOME Wayland (100.74.219.114)
Tester: ______________________
Date: ______________________
Build: apps/chanora_flutter/build/linux/x64/release/bundle/chanora_flutter @ ______________________
libchanora_bridge.so @ ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release (GNOME-Wayland) [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Binding persistence across restart [ pass / fail ] notes:
TC-9 Binding before voice-join [ pass / fail ] notes:
TC-10 No-permission channel rejection [ pass / fail ] notes:
TC-11 Reconnect [ pass / fail ] notes:
TC-12 Diagnostic export + privacy [ pass / fail ] notes:
TC-13 PTT bind dialog labels [ pass / fail ] notes:
TC-14 Capability badge gating [ pass / fail ] notes:
TC-15 Indicator label [ pass / fail ] notes:
Overall result: [ Linux rc.8 PASS / Linux rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **X11, sway, KDE, other Wayland compositors**: officially out of
scope for v1.0.0-rc.8 per DEC-025. The desktop PTT layer falls
back to `FocusedPttBackend` (L0Focused capability) on these.
Voice + identity + connect paths still work.
- **Flutter build glue**: the Linux bundle currently requires
manually copying `libchanora_bridge.so` next to the runner or
into `bundle/lib/`. Auto-bundling is a P1 carryover.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally disabled
in P0 (DEC-030) on Linux as on Windows.
- **macOS / iOS / Android** P0 acceptance is NOT covered here.
-222
View File
@@ -1,222 +0,0 @@
# macOS P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
macOS P0 ship of Chanora. The officially-tested environment is
**Apple Silicon macOS 14+** (DEC-025). Intel macOS is best-effort —
the same build runs but is not signed-off for this release.
Automated tests (`cargo check`, `cargo test --workspace --lib`,
the live `IOHIDCheckAccess` permission query path) sign off the
mechanical side. This checklist signs off the user-experience
side. A failure on any row blocks promotion of the macOS build
from rc.8.
Source: this checklist mirrors `linux-p0-acceptance.md` and
`windows-p0-acceptance.md`. The auto-test sign-off lives in this
document's "Auto-test sign-off" section. SDD references: SDD-081
(trait), SDD-085 (macOS CGEventTap backend), SDD-094..097 (v1
audio + PTT lifecycle), DEC-025 (target environment), DEC-027
(diagnostic privacy invariant), SRS-197 (iOS/macOS audio routing
contract), SRS-198 (honest capability advertising under runtime
permission state).
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | Build host: M1 / M2 / M3 Mac running macOS 14 or later. From a graphical login (NOT SSH alone) open Terminal and confirm: `sw_vers -productVersion` is `14.x` or higher; `uname -m` is `arm64`. | Apple Silicon macOS confirmed. |
| 0.2 | Wipe stale install: `rm -rf "~/Library/Application Support/app.chanora.chanoraFlutter" ~/Library/Logs/app.chanora.chanora_flutter ~/Library/Containers/com.example.chanoraFlutter`. (App-Sandbox-aware container path; macOS quietly relocates `Application Support` under `Containers/<bundle-id>/Data/` when the app is sandboxed.) | First-launch from clean state. |
| 0.3 | Build the bridge: `cd ~/chanora && cargo build --release -p chanora_bridge`. | `target/release/libchanora_bridge.dylib` ≈ 15 MB. |
| 0.4 | Build the Flutter app: `cd apps/chanora_flutter && flutter build macos --release`. | `build/macos/Build/Products/Release/chanora_flutter.app` exists, ≈ 60 MB. |
| 0.5 | Wrap + sign: `cd ~/chanora && tools/macos-postbuild.sh Release`. | Last line reads `[postbuild] OK: …chanora_flutter.app is launchable`. The `chanora_bridge.framework` is now inside `Contents/Frameworks/`. |
| 0.6 | Launch from a graphical session: `open ~/chanora/apps/chanora_flutter/build/macos/Build/Products/Release/chanora_flutter.app`. The first launch will pop a Gatekeeper warning because the app is ad-hoc signed. Click "Open Anyway" in System Settings → Privacy & Security if prompted. | Window opens; no crash. |
| 0.7 | About / version label | Shows **`v1.0.0-rc.8`**. |
| 0.8 | Open `~/Library/Logs/app.chanora.chanora_flutter/chanora.log` | Contains `bridge initialised`, `log file path …`, `identity store initialised`, `bookmark store initialised`. File < 1 MB. The PTT controller line should read `backend_id="event-tap"` and capability `L0Focused` (because Input Monitoring has not been granted yet). |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | "Connect" button enabled |
| 1.2 | Click Connect | Server snapshot appears: channel tree on left, client list visible |
| 1.3 | Note the connected server name + channel tree | Tree is sorted (parents above children); depth indent visible up to 6 levels |
| 1.4 | Disconnect, reconnect with the same nickname | Server-visible UID is the same as previous session (identity persisted via `Application Support/.../identity.tskey`) |
| 1.5 | Disconnect | Returns to connect form, no error |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | After connecting, observe the UI | **No "Start audio" button anywhere.** Voice Bar visible at the bottom. |
| 2.2 | Double-click a voice channel | First time only: macOS shows a system prompt requesting microphone access; click **Allow**. Subsequent joins do not re-prompt. Client moves into the channel; voice bar shows the channel name. |
| 2.3 | Double-click a different voice channel | Client moves; no audio glitch; the second `voice_join` is logged cleanly with no panic. |
| 2.4 | Double-click the same channel again quickly (concurrency) | Either: no-op move, or single clean move; no duplicate audio engine spawn. |
## TC-3: PTT press / release (SDD-083, SDD-085, SDD-096) — Input Monitoring granted
| # | Step | Expected |
|---|---|---|
| 3.1 | Open Voice settings (gear icon), select **Push to talk** | Bind-key row + Release-tail slider become visible. |
| 3.2 | Click "Bind key" → press a key (e.g. Right Option) | Flutter captures the key label. macOS may show a system prompt requesting **Input Monitoring** access. Open System Settings → Privacy & Security → Input Monitoring, toggle Chanora ON. |
| 3.3 | Return to Chanora; within ~1.5 s the capability badge transitions from `L0Focused` to `L2 GlobalHoldToTalk` (or `L3` for a mouse side-button). | The transition fires WITHOUT restarting Chanora — the macOS `permission re-query worker` polls every 1.5 s and re-publishes the descriptor. |
| 3.4 | With another window focused, hold the bound key | Mic indicator turns "Mic on"; `transmit_active` true in stats. |
| 3.5 | Release the key | After the configured release-tail, indicator returns to "Mic off". |
| 3.6 | Switch focus several times while pressing the key | PTT still fires from another window — confirms the CGEventTap is reading session-global events. |
## TC-4: Release tail (SDD-097)
| # | Step | Expected |
|---|---|---|
| 4.1 | Set release-tail to 0 ms in Voice settings | Slider updates immediately. |
| 4.2 | Tap PTT key briefly | Mic on/off transition is sharp (no tail). |
| 4.3 | Set release-tail to 500 ms | Slider updates immediately. |
| 4.4 | Tap PTT key briefly | Mic stays "on" for ~500 ms after release before flipping to off. |
## TC-5: Continuous mode (SDD-094)
| # | Step | Expected |
|---|---|---|
| 5.1 | Switch transmit mode to **Continuous** | Bind-key + release-tail rows disappear; capability badge greys out. |
| 5.2 | Talk into mic | "Mic on" stays solid; no self-disable bug. |
| 5.3 | Switch back to PTT | Previously bound key still works without re-binding (binding persisted in `audio_meta.json`). |
## TC-6: Mic mute (SDD-097)
| # | Step | Expected |
|---|---|---|
| 6.1 | Press mic-mute toggle in Voice Bar | Mic icon shows muted state; selector hard-mute engaged. |
| 6.2 | Press PTT (still muted) | No "Sending audio while muted" spam in log. Mic indicator does not flip on. |
| 6.3 | Un-mute | PTT resumes working normally. |
## TC-7: Speaker mute
| # | Step | Expected |
|---|---|---|
| 7.1 | Press speaker-mute toggle | Other clients in channel are silenced locally; server still sees you in channel. |
## TC-8: Binding persistence across restart
| # | Step | Expected |
|---|---|---|
| 8.1 | With a working PTT binding, quit Chanora | `audio_meta.json` next to `identity.tskey` shows the `ptt_*` fields populated. |
| 8.2 | Relaunch | Binding restored without re-running the bind flow. Hold key — mic flips on. |
## TC-9: Binding before voice-join
| # | Step | Expected |
|---|---|---|
| 9.1 | Connect to server, do **not** join a voice channel yet. Open Voice settings, bind a PTT key. | Binding succeeds. |
| 9.2 | Now double-click a voice channel | Voice engine starts with the existing binding active immediately. |
## TC-10: No-permission channel rejection (typed `ServerRejected` propagation)
| # | Step | Expected |
|---|---|---|
| 10.1 | Try to join a channel you lack permissions on | Red SnackBar with a human message derived from the TS3 error code (e.g. `permissions_client_insufficient` → "You do not have permission to join this channel."). Move does not silently fail. |
## TC-11: Reconnect
| # | Step | Expected |
|---|---|---|
| 11.1 | Toggle Wi-Fi off for 10 s, then reconnect | UI shows red "Connection lost" banner, then recovers. Transient `Operation timed out` blips are logged but **not** shown as a banner. |
## TC-12: Diagnostic export + privacy (DEC-027, SAD-077, SDD-090)
| # | Step | Expected |
|---|---|---|
| 12.1 | Open Diagnostics, export a bundle | Bundle contains tracing records with allow-listed fields only: `backend_id`, `bound_input_class`, `capability_level`, `host_id`, `timeout_secs`, `error`, `event`, `message`, `target`, `level`. **No raw key codes, no bound key labels, no mouse-button numbers, no IOHIDAccessType raw values.** |
| 12.2 | Grep the bundle for the human-readable PTT key label | No hit. |
## TC-13: PTT bind dialog labels
| # | Step | Expected |
|---|---|---|
| 13.1 | Open Voice settings; the Bind-key row displays the Flutter-supplied label (e.g. "Space", "F10"). | The translated string never appears in `chanora.log`. |
## TC-14: Capability badge gating
| # | Step | Expected |
|---|---|---|
| 14.1 | Revoke Input Monitoring in System Settings while Chanora is running. Within ~1.5 s the badge downgrades from `L2 GlobalHoldToTalk` to `L0Focused`. The Bind-key UI hides if it would be unusable; PTT then only works when Chanora is the foreground window. | The transition is logged: `macos ptt: permission state transition from=Granted to=Denied`. |
| 14.2 | Re-grant; within ~1.5 s the badge upgrades back to L2. | Same transition log line reversed. |
## TC-15: Indicator label
| # | Step | Expected |
|---|---|---|
| 15.1 | In any mode, look at the stats line | Reads "Mic on" / "Mic off" (mode-neutral); **not** "PTT on" / "PTT off". |
## Auto-test sign-off
These rows do not require human interaction.
| Layer | Result on Apple Silicon macOS (M1 host) |
|---|---|
| `cargo check --workspace` | clean |
| `cargo test --workspace --lib` | 74 baseline + 6 new macOS keymap/state tests = **80 / 0 / 1** target; currently `chanora_audio` reports 34 / 0 / 0 on macOS (Linux had 32) |
| `cargo build --release -p chanora_bridge` | clean — produces `libchanora_bridge.dylib` ≈ 15 MB |
| `flutter build macos --release` | clean — produces `chanora_flutter.app` ≈ 60 MB |
| `tools/macos-postbuild.sh Release` | exit 0; framework-wrap + install_name_tool + ad-hoc codesign succeed |
| `chanora_flutter.app` headless launch | bridge / identity / bookmark store all initialise; `~/Library/Logs/app.chanora.chanora_flutter/chanora.log` captures clean boot |
| Live `IOHIDCheckAccess(kIOHIDRequestTypeListenEvent)` | returns `Unknown` (2) on a fresh-install box — expected; transitions to Granted/Denied after the user responds to the system prompt |
The macOS host runs 6 more `chanora_audio` tests than Linux because of the macOS-only PTT keymap + descriptor builder + RunLoopHandle Send-bound tests. Linux runs 4 portal-specific tests that macOS skips. Net cross-platform delta: `+2` macOS.
## Sign-off form
```
chanora v1.0.0-rc.8 — macOS P0 acceptance
Host: Apple Silicon macOS (M1/M2/M3)
Tester: ______________________
Date: ______________________
Build: apps/chanora_flutter/build/macos/Build/Products/Release/chanora_flutter.app
@ ______________________
chanora_bridge.framework/chanora_bridge inside Contents/Frameworks/
@ ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release (Input Monitor) [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Binding persistence across restart [ pass / fail ] notes:
TC-9 Binding before voice-join [ pass / fail ] notes:
TC-10 No-permission channel rejection [ pass / fail ] notes:
TC-11 Reconnect [ pass / fail ] notes:
TC-12 Diagnostic export + privacy [ pass / fail ] notes:
TC-13 PTT bind dialog labels [ pass / fail ] notes:
TC-14 Capability badge gating [ pass / fail ] notes:
TC-15 Indicator label [ pass / fail ] notes:
Overall result: [ macOS rc.8 PASS / macOS rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **Intel macOS** (`x86_64-apple-darwin`): the same Rust build targets it cleanly but no acceptance pass; ship as best-effort.
- **macOS Gatekeeper + notarization**: ad-hoc-signed `chanora_flutter.app` requires the user to right-click → Open the first time (or approve in Privacy & Security). Developer ID + notarization for distribution is a P1 follow-up.
- **`tools/macos-postbuild.sh` is a separate manual step**: Xcode build-phase auto-integration (so a plain `flutter build macos --release` produces a launchable bundle) is a P1 carryover, same shape as the analogous Windows + Linux gaps.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally disabled in P0 (DEC-030) on macOS as on every platform.
- **iOS** P0 acceptance is NOT covered here; see `ios-p0-acceptance.md`.
@@ -1,709 +0,0 @@
# Chanora SWE.4 Software Unit Verification Plan
**Document type:** Software Unit Verification Plan
**Process alignment:** ASPICE SWE.4 Software Unit Verification
**Version:** 0.9.14
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Verification object:** Software units defined by SDD
**Direct source layer:** SDD only
**Repo path:** `docs/verification/swe4-unit-verification-plan.md` ---
## 1. Purpose
This document defines the software unit verification strategy for Chanora. It verifies that software units implement the Software Detailed Design.
This document is downstream of SDD and shall not bypass the document hierarchy.
```text
SysRS -> SysDes -> SRS -> SAD -> SDD -> SWE.4 Unit Verification
```
Direct source rule:
```text
SWE.4 unit verification items shall link directly to SDD only.
```
## 2. Verification Scope
In scope:
- Flutter unit tests
- Flutter widget-level unit verification where a widget is treated as a software unit
- Dart static analysis
- Dart code review
- Rust unit tests
- Rust static analysis
- Rust code review
- Unit-level regression verification
- Unit-level interface boundary tests
- Unit-level localization, Unicode, design-token, and diagnostics verification
Out of scope:
- Software integration verification across components; handled by SWE.5.
- Fully integrated software verification against SRS; handled by SWE.6.
- System integration verification against SysDes; handled by SYS.4.
## 3. Unit Verification Strategy
| Verification type | Applies to | Purpose |
|---|---|---|
| Static analysis | Dart, Rust | Detect structural, lint, safety, style, and maintainability issues |
| Code review | Dart, Rust, build scripts | Confirm design compliance and maintainability |
| Unit tests | Dart, Rust | Verify individual units against SDD behavior |
| Widget tests | Flutter widgets | Verify component rendering, semantics, and state behavior |
| Golden tests | Design-system components | Verify stable UI rendering where appropriate |
| Localization tests | Localization service and accessibility labels | Verify fallback, keys, and localized display strings |
| Unicode tests | Protocol/bridge/text-boundary units | Verify UTF-8 and multilingual content handling |
| Regression tests | Changed units | Confirm unchanged behavior remains valid after modifications |
## 4. Entry Criteria
| Criterion | Description |
|---|---|
| SDD baseline available | Unit design items and source SAD links are available. |
| Unit implementation available | The unit exists in source code or executable test double form. |
| Unit test environment available | Flutter and/or Rust test infrastructure is configured. |
| Verification measure defined | Test, review, or static analysis objective is defined. |
| Pass/fail criteria defined | Expected result is objective and reviewable. |
## 5. Exit Criteria
| Criterion | Description |
|---|---|
| Selected unit verification measures executed | Tests, reviews, and analyses required for the release scope are complete. |
| Results recorded | Verification results are stored in test reports or review records. |
| Nonconformances recorded | Failures are recorded for problem resolution. |
| Traceability complete | Each unit verification item traces to SDD and result evidence. |
| Regression scope complete | Changed units have selected regression measures executed. |
## 6. Unit Verification Measures
**SWE4-UV-001**: Verify `ChanoraApp` initialization order.
- Source SDD: SDD-001, SDD-045
- Verification method: Flutter unit/integration test
- Pass criteria: Theme, localization, platform services, routing, and adaptive shell initialize before feature rendering.
- Evidence: Test result
**SWE4-UV-002**: Verify `ChanoraThemeFactory` Material 3 theme creation.
- Source SDD: SDD-002, SDD-003
- Verification method: Dart unit test
- Pass criteria: Light and dark Material 3 ThemeData objects are created with valid ColorScheme and TextTheme values.
- Evidence: Test result
**SWE4-UV-003**: Verify `ChanoraSemanticColors` connection token behavior.
- Source SDD: SDD-004, SDD-006
- Verification method: Dart unit test
- Pass criteria: All connection semantic roles are present and do not require feature-screen hardcoding.
- Evidence: Test result
**SWE4-UV-004**: Verify voice semantic token behavior.
- Source SDD: SDD-005, SDD-006
- Verification method: Dart unit test
- Pass criteria: Speaking, muted, deafened, and push-to-talk active states are available through semantic tokens.
- Evidence: Test result
**SWE4-UV-005**: Verify feature widgets use theme accessors rather than hardcoded semantic values.
- Source SDD: SDD-010
- Verification method: Static inspection
- Pass criteria: Feature widgets do not construct product semantic token values directly.
- Evidence: Review record
**SWE4-UV-006**: Verify adaptive shell window classification.
- Source SDD: SDD-011, SDD-012
- Verification method: Dart unit test
- Pass criteria: Compact, medium, and expanded classes are selected deterministically.
- Evidence: Test result
**SWE4-UV-007**: Verify `CompactShell` layout behavior.
- Source SDD: SDD-013
- Verification method: Flutter widget test
- Pass criteria: Compact shell renders a single-column layout and mobile navigation entry points.
- Evidence: Test result
**SWE4-UV-008**: Verify `MediumShell` layout behavior.
- Source SDD: SDD-014
- Verification method: Flutter widget test
- Pass criteria: Medium shell renders side navigation or navigation rail behavior.
- Evidence: Test result
**SWE4-UV-009**: Verify `ExpandedShell` persistent pane behavior.
- Source SDD: SDD-015
- Verification method: Flutter widget test
- Pass criteria: Expanded shell renders persistent side pane and VoiceBar slot.
- Evidence: Test result
**SWE4-UV-010**: Verify connection status presentation uses non-color-only cues.
- Source SDD: SDD-016, SDD-022
- Verification method: Dart unit test, widget test
- Pass criteria: The presenter exposes label, icon, semantic label, and severity token.
- Evidence: Test result
**SWE4-UV-011**: Verify `ChanoraVoiceBar` exposed properties.
- Source SDD: SDD-017, SDD-018
- Verification method: Flutter widget test
- Pass criteria: Mute, deaf, push-to-talk, input meter, current channel, and latency properties render correctly.
- Evidence: Test result
**SWE4-UV-012**: Verify `ChanoraChannelTree` data and interaction behavior.
- Source SDD: SDD-019, SDD-020
- Verification method: Flutter widget test
- Pass criteria: Channel hierarchy, selected state, expansion state, join intent, and context-menu intent operate as designed.
- Evidence: Test result
**SWE4-UV-013**: Verify `ChanoraClientTile` state semantics.
- Source SDD: SDD-021
- Verification method: Widget test, accessibility test
- Pass criteria: Client status is available through text/icon/semantic cues and not color alone.
- Evidence: Test result
**SWE4-UV-014**: Verify localized semantic labels for icon-only buttons.
- Source SDD: SDD-024, SDD-031, SDD-032
- Verification method: Accessibility test, localization unit test
- Pass criteria: Icon-only controls expose localized semantic labels with fallback.
- Evidence: Test result
**SWE4-UV-015**: Verify keyboard focus traversal.
- Source SDD: SDD-025
- Verification method: Widget test
- Pass criteria: Primary interactive controls can be traversed in a logical order.
- Evidence: Test result
**SWE4-UV-016**: Verify text-scale resilience of critical controls.
- Source SDD: SDD-026
- Verification method: Accessibility widget test
- Pass criteria: Critical controls remain reachable under increased text scale.
- Evidence: Test result
**SWE4-UV-017**: Verify platform inset service unit behavior.
- Source SDD: SDD-027, SDD-030
- Verification method: Unit test with platform test doubles
- Pass criteria: Insets are normalized and exposed to the shell.
- Evidence: Test result
**SWE4-UV-018**: Verify back intent service behavior.
- Source SDD: SDD-028
- Verification method: Unit test with platform test doubles
- Pass criteria: Platform back events map to expected route-level intents.
- Evidence: Test result
**SWE4-UV-019**: Verify localization fallback.
- Source SDD: SDD-031, SDD-032, SDD-033
- Verification method: Unit test
- Pass criteria: Missing localized strings fall back deterministically.
- Evidence: Test result
**SWE4-UV-020**: Verify server-content pass-through.
- Source SDD: SDD-034
- Verification method: Unit test
- Pass criteria: Server-provided content is not translated by product localization.
- Evidence: Test result
**SWE4-UV-021**: Verify Unicode text boundary behavior.
- Source SDD: SDD-035, SDD-036, SDD-037
- Verification method: Unit test
- Pass criteria: Valid multilingual Unicode content is preserved; invalid external encodings are handled at boundaries.
- Evidence: Test result
**SWE4-UV-022**: Verify diagnostic Unicode preservation and redaction behavior.
- Source SDD: SDD-038, SDD-041, SDD-050, SDD-054
- Verification method: Unit test, security review
- Pass criteria: Secrets are redacted while multilingual content is preserved.
- Evidence: Test result, review record
**SWE4-UV-023**: Verify locale-aware formatting.
- Source SDD: SDD-040
- Verification method: Unit test
- Pass criteria: Dates, times, numbers, and timestamps format through localization utilities.
- Evidence: Test result
**SWE4-UV-024**: Verify traceability checker behavior.
- Source SDD: SDD-043, SDD-044, SDD-055, SDD-056, SDD-066, SDD-067
- Verification method: Unit test / script test
- Pass criteria: Invalid direct-layer references are detected.
- Evidence: Test result
**SWE4-UV-025**: Verify bridge DTO safety.
- Source SDD: SDD-046
- Verification method: Unit test, static inspection
- Pass criteria: Bridge DTOs do not expose internal Rust implementation types.
- Evidence: Test result, review record
**SWE4-UV-026**: Verify Rust core event mapping.
- Source SDD: SDD-047
- Verification method: Rust unit test
- Pass criteria: Core events map deterministically to view model deltas.
- Evidence: Test result
**SWE4-UV-027**: Verify voice view model separation from DSP.
- Source SDD: SDD-048
- Verification method: Code review, unit test
- Pass criteria: Voice UI receives status values and does not perform audio DSP.
- Evidence: Review record, test result
**SWE4-UV-028**: Verify storage facade isolation.
- Source SDD: SDD-049
- Verification method: Static inspection, unit test
- Pass criteria: Feature widgets do not directly call database APIs.
- Evidence: Review record, test result
**SWE4-UV-029**: Verify interface detail catalog completeness.
- Source SDD: SDD-059, SDD-060
- Verification method: Review
- Pass criteria: Unit-level interface entries include required details where applicable.
- Evidence: Review record
**SWE4-UV-030**: Verify unit construction and review records.
- Source SDD: SDD-064, SDD-065, SDD-068, SDD-069, SDD-070
- Verification method: Review
- Pass criteria: Unit construction, review, verification handoff, and registry records exist for release scope units.
- Evidence: Review record
## 7. Traceability Matrix
| SDD Range | SWE.4 Coverage |
|---|---|
| SDD-001 through SDD-010 | SWE4-UV-001 through SWE4-UV-005 |
| SDD-011 through SDD-018 | SWE4-UV-006 through SWE4-UV-011 |
| SDD-019 through SDD-026 | SWE4-UV-012 through SWE4-UV-016 |
| SDD-027 through SDD-037 | SWE4-UV-017 through SWE4-UV-021 |
| SDD-038 through SDD-050 | SWE4-UV-022 through SWE4-UV-028 |
| SDD-051 through SDD-070 | SWE4-UV-029 through SWE4-UV-030 |
## 8. Result Reporting
Unit verification results shall be summarized in a unit verification summary report including:
- verification scope
- selected verification measures
- skipped measures and rationale
- pass/fail result
- nonconformances
- regression scope
- residual risks
- release recommendation
## 9. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial SWE.4 unit verification plan derived from SDD v0.3. |
---
## 10. Platform Decision Unit Verification Addendum
**SWE4-UV-031**: Verify iOS and Android build configuration units.
- Source SDD: SDD-071, SDD-072, SDD-073
- Verification method: Static inspection, platform test
- Pass criteria: iOS minimum runtime, Apple SDK gate, Android minimum runtime, and Android target SDK configuration are inspectable and match release policy.
- Evidence: Test result, release inspection
**SWE4-UV-032**: Verify single active connection enforcement.
- Source SDD: SDD-074
- Verification method: Unit test
- Pass criteria: Attempting to create a second active MVP connection is rejected or routed through a controlled disconnect/switch policy.
- Evidence: Test result
**SWE4-UV-033**: Verify audio processing defaults and backend selection.
- Source SDD: SDD-075, SDD-076
- Verification method: Unit test, audio test
- Pass criteria: AEC, AGC, Noise Suppression, and High-Pass Filter default to enabled where supported and stable; backend selector prefers platform-native processing.
- Evidence: Test result
**SWE4-UV-034**: Verify local database, secret storage, bridge, and diagnostics privacy gate units.
- Source SDD: SDD-077, SDD-078, SDD-079, SDD-080
- Verification method: Unit test, security inspection
- Pass criteria: Non-secret storage, secret storage, typed bridge DTOs, and disabled automatic upload/crash behavior match detailed design.
- Evidence: Test result, security review
**SWE4-UV-035**: Verify `DesktopPttBackend` trait + `PttCapabilityLevel` enum + `FocusedPttBackend` units.
- Source SDD: SDD-081, SDD-082, SDD-087
- Verification method: Unit test
- Pass criteria: Trait surface compiles for every implementation; enum `as_str()` mapping is unambiguous; `FocusedPttBackend` reports `L0Focused` and forwards `set_ptt` events into `AudioTransmitGate` unchanged.
- Evidence: Test result
**SWE4-UV-036**: Verify Windows / macOS / Linux platform backend units in isolation.
- Source SDD: SDD-083, SDD-084, SDD-085, SDD-086
- Verification method: Unit test (with mocked OS surfaces), Platform Test (Windows / macOS / GNOME-Wayland reference hosts)
- Pass criteria: Each backend reports the expected `PttCapabilityLevel` for the current host configuration; the ladder falls through to `FocusedPttBackend` when its preferred OS API is unavailable.
- Evidence: Test result, platform-test trace
**SWE4-UV-037**: Verify `PttController` + `AudioTransmitGate` units.
- Source SDD: SDD-088, SDD-089
- Verification method: Unit test
- Pass criteria: `PttController::set_binding` rebinds the active backend without dropping `AudioTransmitGate`; `AudioTransmitGate::subscribe()` returns a `watch::Receiver` that delivers every transition the gate observes.
- Evidence: Test result
**SWE4-UV-038**: Verify `PttSanitizer` and `PttCapabilityBadge` units.
- Source SDD: SDD-090, SDD-091
- Verification method: Unit test, UI review
- Pass criteria: `PttSanitizer` drops records whose field names match the banned list (`key_code`, `scan_code`, `virtual_key`, `vk`, `keysym`, `keysym_string`, `key_sequence`); `PttCapabilityBadge` renders the correct label and explanation sheet for each `PttCapabilityLevel`.
- Evidence: Test result, UI screenshot
**SWE4-UV-039**: Verify `MissedKeyUpWatchdog` unit.
- Source SDD: SDD-092
- Verification method: Unit test (tokio time-paused)
- Pass criteria: After a simulated `false -> true -> (timeout elapsed)` sequence the watchdog calls `AudioTransmitGate::set(false)` exactly once and emits a sanitised diagnostic record naming only `capability_level` and `backend_id`.
- Evidence: Test result
| SDD Range | SWE.4 Coverage |
|---|---|
| SDD-071 through SDD-080 | SWE4-UV-031 through SWE4-UV-034 |
| SDD-081 through SDD-092 | SWE4-UV-035 through SWE4-UV-039 |
## 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT unit-verification items SWE4-UV-035 through SWE4-UV-039: `DesktopPttBackend` trait + `PttCapabilityLevel`, platform backends, `PttController` + `AudioTransmitGate`, `PttSanitizer` + `PttCapabilityBadge`, `MissedKeyUpWatchdog`. |
## 11. Android P0 Unit Verification Addendum
**SWE4-UV-040**: Verify Android build configuration unit (`SDD-073` expanded).
- Source SDD: SDD-073
- Verification method: Gradle task assertion + static inspection of `android/app/build.gradle.kts`
- Pass criteria: `minSdk` literal equals `28` (DEC-004); `ndk.abiFilters` set equals `{arm64-v8a, armeabi-v7a, x86_64}` (per SDD-073 item 4 and SDD-118 item 3, `x86` 32-bit is explicitly out of scope and shall not be in the set); release `signingConfig` references the CI signing key reference (not debug); R8/ProGuard `minifyEnabled = true` on release; `bundle { abi.enableSplit = true }`; assemble target produces an AAB artifact at `app/build/outputs/bundle/release/app-release.aab`.
- Evidence: Gradle log + manifest dump
**SWE4-UV-041**: Verify `AndroidPermissionRequester` state machine (`SDD-106`).
- Source SDD: SDD-106
- Source SRS: SRS-209
- Verification method: Dart/Kotlin unit test with a permission-platform test double
- Pass criteria: State transitions are exhaustive for `{granted, denied, permanently_denied, revoked_mid_session}`; transitioning out of `granted` clamps `AudioTransmitGate::set(false)`; re-entering `granted` does NOT auto-transmit (requires explicit user gesture); permanently-denied surfaces a settings-deep-link intent rather than re-prompting.
- Evidence: Test result
**SWE4-UV-042**: Verify `BackIntentService` Android branches (`SDD-028` expanded).
- Source SDD: SDD-028
- Source SRS: SRS-163
- Verification method: Dart unit test with platform-channel test double for both `OnBackInvokedCallback` (API 33+) and `OnBackPressedDispatcher` (API ≤ 32) paths.
- Pass criteria: Modal-first rule — if a modal is open, back closes the modal and does not pop the route. PTT-active-ignore — while `transmit_active == true` the back event is consumed without effect. Route-pop ordering — otherwise the topmost non-modal route pops. The API 33+ branch registers a `OnBackInvokedCallback` at `PRIORITY_DEFAULT`; the pre-33 branch registers an `OnBackPressedCallback`. Switching API level in the test double switches the active branch deterministically.
- Evidence: Test result
**SWE4-UV-043**: Verify `AndroidJniBootstrap` library load and init ordering (`SDD-105`).
- Source SDD: SDD-105
- Verification method: Instrumented unit test on Android (or Robolectric where applicable)
- Pass criteria: `System.loadLibrary("chanora_bridge")` is invoked from the `Application` subclass `onCreate` (not from an Activity); `JNI_OnLoad` runs exactly once per process and captures the `JavaVM*`; bridge init occurs before any FFI call from Dart; double-init is a no-op.
- Evidence: Test result + logcat trace
**SWE4-UV-044**: Verify `AndroidVoiceForegroundService` lifecycle unit (`SDD-107`).
- Source SDD: SDD-107
- Source SRS: SRS-111
- Verification method: Kotlin unit test + Robolectric `ServiceController`
- Pass criteria: `startForeground` is called within 5 s of `onStartCommand` (API 26+ requirement); notification channel exists with `IMPORTANCE_LOW`; `foregroundServiceType` includes `microphone` on API 30+; service stops cleanly on disconnect intent and does not leak its wakelock; restart policy is `START_NOT_STICKY` (no auto-respawn after force-stop).
- Evidence: Test result
**SWE4-UV-045**: Verify `AndroidAudioModeController` snapshot/restore + refcount (`SDD-108`).
- Source SDD: SDD-108
- Source SRS: SRS-208
- Source SysRS: SysRS-305
- Verification method: Kotlin unit test with `AudioManager` test double
- Pass criteria: First acquire snapshots prior `AudioManager.getMode()` and sets `MODE_IN_COMMUNICATION`; nested acquires increment refcount without re-snapshotting; matched release decrements; final release restores the snapshotted prior mode exactly once; when `AudioManager` is unavailable (e.g. injected null), controller logs a sanitized warning and degrades to no-op without throwing.
- Evidence: Test result
**SWE4-UV-046**: Verify `AndroidPttCapability` reports `L0Focused` and pins `FocusedPttBackend` (`SDD-110`).
- Source SDD: SDD-110
- Verification method: Rust + Dart unit test
- Pass criteria: On `target_os = "android"` the `DesktopPttBackend` factory returns `FocusedPttBackend` unconditionally (no ladder evaluation); `PttCapabilityBadge` renders the localized `L0Focused` label with the Android-specific explanation string; no Android branch attempts to bind global hotkeys.
- Evidence: Test result + UI screenshot
| SDD Range | SWE.4 Coverage |
|---|---|
| SDD-028 (expanded) | SWE4-UV-042 |
| SDD-073 (refreshed) | SWE4-UV-040 |
| SDD-105 | SWE4-UV-043 |
| SDD-106 | SWE4-UV-041 |
| SDD-107 | SWE4-UV-044 |
| SDD-108 | SWE4-UV-045 |
| SDD-110 | SWE4-UV-046 |
### Android voice audio backend unit-verification items (SDD-111..SDD-116 wave)
**SWE4-UV-047**: Verify `AndroidVoiceStreamConfig` builder records requested vs. achieved fields.
- Source SDD: SDD-112 (config struct), SDD-111 (trait surface)
- Source SRS: SRS-210, SRS-211, SRS-213, SRS-214
- Source SAD: SAD-077, SAD-081
- Verification method: Rust unit test with a fake Oboe builder return path (no device)
- Pass criteria: Given a `MobileVoiceStreamConfig` requesting `PERFORMANCE_MODE_LOW_LATENCY`, input preset `VoiceCommunication`, output usage `VoiceCommunication`, content type `Speech`, and sharing mode `Exclusive`, the resulting `AndroidVoiceStreamConfig` records the requested values verbatim AND exposes `achieved_*` accessors populated from the fake builder's grant values. Mismatch between requested and achieved is observable via the accessors with no panics. Both input and output stream configs are independently recorded.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: none directly (unit-level; matrix consumes the accessors per-device)
**SWE4-UV-048**: Verify input preset fallback ladder is observable at each step.
- Source SDD: SDD-111 (trait surface, open() error pathway), SDD-112 (preset field)
- Source SRS: SRS-211
- Source SAD: SAD-077
- Verification method: Rust unit test with a scripted Oboe builder mock that returns `ErrorIllegalArgument` for successive presets
- Pass criteria: With the mock denying `VoiceCommunication`, `open()` retries with `VoicePerformance`; with the mock denying both, `open()` retries with `Generic` (`Unprocessed`/default). Each retry is recorded in a structured field (e.g. `attempted_presets: Vec<InputPreset>`) and the final `achieved_input_preset()` returns the preset that was granted. If all presets fail, `open()` returns `BackendError::InputPresetUnavailable` (or the SDD-111 equivalent). No silent fallback.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: none directly (matrix records `achieved_input_preset` per device)
**SWE4-UV-049**: Verify sharing-mode fallback Exclusive→Shared is observable.
- Source SDD: SDD-111, SDD-112 (sharing mode field)
- Source SRS: SRS-214
- Source SAD: SAD-077
- Verification method: Rust unit test with a fake Oboe builder return path
- Pass criteria: When the fake builder accepts `SharingMode::Exclusive`, `achieved_sharing_mode()` returns `Exclusive` and no retry occurs. When the fake builder rejects `Exclusive` (returns the documented Oboe error path for exclusive denial), the unit retries with `Shared`, and `achieved_sharing_mode()` returns `Shared`. The original request (`Exclusive`) is still recorded for diagnostics.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: none directly (matrix records `achieved_sharing_mode` per device)
**SWE4-UV-050**: Verify hardware effects per-effect success/failure logic with software-AEC fallback.
- Source SDD: SDD-113 (per-effect construction + software fallback signal)
- Source SRS: SRS-212
- Source SAD: SAD-077, SAD-081
- Verification method: Rust unit test with a mocked JNI surface (`new_object`-style indirection) representing `AcousticEchoCanceler.create`, `NoiseSuppressor.create`, `AutomaticGainControl.create`
- Pass criteria: For each of AEC, NS, AGC: (a) success path — mock returns a non-null `GlobalRef`, effect is recorded as engaged, `setEnabled(true)` is invoked once; (b) failure path — mock returns null OR throws, the unit records the per-effect failure, does NOT abort the other two, and signals the engine to engage the software equivalent (per SDD-113 item 5 — for AEC failure the engine's software AEC must be flagged on). Order of effect construction does not affect outcome (no cross-effect coupling). `release()` is called on every engaged `GlobalRef` exactly once when the unit is torn down.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: per-device AEC/NS/AGC availability column
**SWE4-UV-051**: Verify performance-mode achieved recording feeds SRS-210 latency tier classification.
- Source SDD: SDD-111 (`achieved_performance_mode`), SDD-112 (mode field)
- Source SRS: SRS-210
- Source SAD: SAD-077
- Verification method: Rust unit test
- Pass criteria: When the fake builder grants `PERFORMANCE_MODE_LOW_LATENCY`, `achieved_performance_mode()` returns `LowLatency` and the SRS-210 tier classifier (the unit-level pure function that maps achieved mode → latency target) returns the 150 ms tier. When the fake builder grants `PERFORMANCE_MODE_NONE` or `POWER_SAVING`, the classifier returns the 250 ms tier. The classifier is a pure function reachable from the engine without a device.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: per-device `achieved_performance_mode` column
**SWE4-UV-052**: Verify output stream usage and content type are set correctly.
- Source SDD: SDD-112 (output config fields)
- Source SRS: SRS-213
- Source SAD: SAD-077
- Verification method: Rust unit test inspecting the builder calls captured by a mock Oboe builder
- Pass criteria: The output stream-construction path invokes `setUsage(VoiceCommunication)` and `setContentType(Speech)` exactly once on the builder before `openStream`. No other usage / content-type combination is reachable from the production path (the test asserts there is no code path that constructs the output stream with `Media` / `Music` defaults). `achieved_output_usage()` returns `VoiceCommunication` and `achieved_output_content_type()` returns `Speech` on a successful open.
- Evidence: Rust unit test result
- SDD-116 matrix row satisfied: per-device `achieved_output_usage` / `achieved_output_content_type` column
| SDD Range | SWE.4 Coverage |
|---|---|
| SDD-111 | SWE4-UV-047, SWE4-UV-048, SWE4-UV-049, SWE4-UV-051 |
| SDD-112 | SWE4-UV-047, SWE4-UV-048, SWE4-UV-049, SWE4-UV-051, SWE4-UV-052 |
| SDD-113 | SWE4-UV-050 |
| SDD-115 | (lifecycle sequencing — see SWE.5 integration items) |
| SDD-116 | (device matrix — see SWE.6 + android-p0-acceptance TC-14..TC-18) |
## Baseline Candidate 0.9.4 Update
| Version | Date | Description |
|---|---|---|
| 0.9.4 | 2026-05-18 | Added Android P0 unit-verification items SWE4-UV-040 through SWE4-UV-046 covering SDD-028 (expanded back-intent branches), SDD-073 (refreshed build config + AAB), SDD-105 (JNI bootstrap), SDD-106 (permission state machine + transmit clamp), SDD-107 (foreground service lifecycle), SDD-108 (audio mode controller refcount + restore), SDD-110 (PTT capability pin). |
| 0.9.5 | 2026-05-18 | Added Android voice audio backend unit-verification items SWE4-UV-047 through SWE4-UV-052 covering SDD-111 (trait surface), SDD-112 (config requested vs achieved), SDD-113 (per-effect hardware engagement + software fallback) and feeding SRS-210/211/213/214 unit-level classification. |
| 0.9.14 | 2026-05-18 | Wave 3 reviewer follow-up: allocated real SWE.4 IDs for two test sets that had been cited under provisional `SWE4-UV-NNN` placeholders. SWE4-UV-053..055 anchor the three `TransmitModeSelector` permission-state clamp tests in `crates/chanora_audio/src/transmit_selector.rs` (commit 635d160 was cited under the "SWE4-UV-026 family" without real anchors). SWE4-UV-056..057 anchor the two missing `DiagnosticExport::with_android_audio` rendering tests in `crates/chanora_diagnostics/src/lib.rs` (commit aea50a1 introduced the field/builder/`to_text` branch but the unit-test pair was queued for the commit-8 amend). Closes the Wave 3 traceability gap; downstream test cites in commits 4 and 8 are amended to reference these IDs. |
| 0.9.15 | 2026-05-18 | Closed SDD-120 §11 verification-engineer follow-up: allocated SWE4-UV-058 through SWE4-UV-062 anchoring the five realtime-audio bench functions landed in commit 3a7750a (`bench_capture_alloc_count` and `bench_capture_callback_wall_clock` in `crates/chanora_audio/benches/realtime_capture.rs`; `bench_opus_encode_latency` and `bench_opus_decode_latency` in `crates/chanora_audio/benches/opus_codec.rs`; `bench_resampler_throughput` in `crates/chanora_audio/benches/resampler.rs`) and feeding the SRS-216 metric families under the SRS-219 per-metric tolerance windows. Status PENDING_BASELINE: pass/fail evaluation cannot proceed until the first `bench-baseline-update.yml` `workflow_dispatch` invocation lands the SAD-089 baseline JSON; once landed, the SDD-120 §6 `bench-advisory.yml` workflow plus `examples/compare_baseline` perform automated 🔴/🟡/🟢 evaluation against the merge-base baseline snapshot. Strict-layered sourcing preserved (`SWE.4 -> SDD/SRS` only); no SDD, SRS, SAD, SysDes, or SysRS edits performed. |
## 12. Android Permission Clamp + Diagnostics Android-Audio Unit Verification Addendum (Wave 3 — v0.9.14)
**Background.** Wave 3 reviewer audit flagged two newly-landed test groups whose source comments cited verification IDs as `SWE4-UV-NNN` placeholders rather than real allocated anchors:
1. Three `TransmitModeSelector` permission-state tests at `crates/chanora_audio/src/transmit_selector.rs:343-435` (introduced by commit 635d160). The reviewer noted at `transmit_selector.rs:343` that these tests cite "SWE4-UV-026 family" without real IDs.
2. Two missing unit tests for the new `chanora_diagnostics` Android-audio surface (`android_audio: Option<String>` field, `with_android_audio` builder, `[audio.android]` `to_text` branch) introduced by commit aea50a1; queued for the commit-8 amend.
This addendum allocates the five required anchors. SWE4-UV-052 was the prior high-water mark; SWE4-UV-053..057 are the next free contiguous range.
**SWE4-UV-053**: Verify `TransmitModeSelector` clamps transmit to `false` when `permission_state == Denied` (or `PermanentlyDenied`/`Unknown`) regardless of PTT, channel, or transmit-mode state.
- Source SDD: SDD-106 §6
- Source SRS: SRS-209 (fail-safe listen-only default)
- Verification method: Rust unit test
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_denied_clamps_transmit_to_false` (lines 348-384)
- Pass criteria: With `TransmitMode::Ptt`, `in_channel = true`, `ptt_held = true` and the default `Granted` permission state the gate evaluates `true`. Publishing `PermissionGate::Denied` flips the gate to `false`. `PermanentlyDenied` and `Unknown` likewise clamp `false`. The clamp wins over `TransmitMode::Continuous`.
- Evidence: `cargo test -p chanora_audio` result
- Notes: Establishes the fail-safe semantics: cold-launch `Unknown` is listen-only per SRS-209.
**SWE4-UV-054**: Verify `TransmitModeSelector` releases the permission clamp on transition back to `Granted` and resumes normal PTT-driven evaluation.
- Source SDD: SDD-106 §6
- Source SRS: SRS-209
- Verification method: Rust unit test
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_granted_releases_clamp` (lines 389-409)
- Pass criteria: After `Denied` clamps the gate to `false`, transitioning to `PermissionGate::Granted` (with PTT held + in channel) restores the gate to `true` on the next state tick. Releasing the PTT key then drops the gate per normal PTT semantics — the clamp is no longer in effect.
- Evidence: `cargo test -p chanora_audio` result
- Notes: Pairs with SWE4-UV-053; together they cover the clamp on/off edges.
**SWE4-UV-055**: Verify `TransmitModeSelector` ignores `PermissionState` events for non-`RECORD_AUDIO` permissions (contract: bridge filters before reaching the selector).
- Source SDD: SDD-106 §5
- Verification method: Rust unit test (contract pin)
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_for_other_permission_does_not_clamp` (lines 418-435)
- Pass criteria: The selector exposes no setter for non-`RECORD_AUDIO` permissions. With `TransmitMode::Continuous` + `in_channel = true` and no call to `set_permission_state`, the selector remains in its `Granted` default and the gate evaluates `true`. Demonstrates the contract that unrelated permission events (e.g. `POST_NOTIFICATIONS`) cannot reach this code path.
- Evidence: `cargo test -p chanora_audio` result
- Notes: This is a negative/contract test; the JNI bridge is responsible for filtering by permission name before invoking `set_permission_state`.
**SWE4-UV-056**: Verify `DiagnosticExport::with_android_audio(Some(yaml))` renders the `[audio.android]` section between `[metadata]` and `[recent logs]` in `to_text()`.
- Source SDD: SDD-116 item 3 (diagnostics matrix surface), SDD-112 item 10 / SDD-113 item 7 (producing crate)
- Verification method: Rust unit test
- Test code path: `crates/chanora_diagnostics/src/lib.rs::tests::android_audio_renders_between_metadata_and_logs` (to be added by commit-8 amend)
- Pass criteria: Building a `DiagnosticExport::from_sink(...)` and chaining `.with_android_audio(Some("perf: low_latency\n".into()))` produces a `to_text()` output where the substring `[audio.android]` appears (a) after the `[metadata]` header, (b) before the `[recent logs]` header, and (c) is immediately followed by the supplied YAML fragment verbatim. The YAML fragment is not re-redacted by the diagnostics bundle (SDD-090 places sanitisation in the producing crate).
- Evidence: `cargo test -p chanora_diagnostics` result
- Notes: Section ordering is part of the SDD-116 matrix contract; downstream tooling parses by header.
**SWE4-UV-057**: Verify `DiagnosticExport` with default `android_audio = None` omits the `[audio.android]` header entirely (negative test).
- Source SDD: SDD-116 item 3 (negative case — non-Android or pre-session)
- Verification method: Rust unit test
- Test code path: `crates/chanora_diagnostics/src/lib.rs::tests::android_audio_absent_omits_section` (to be added by commit-8 amend)
- Pass criteria: A `DiagnosticExport::from_sink(...)` constructed without `.with_android_audio(...)` (i.e. `android_audio == None`) produces a `to_text()` output that does **not** contain the substring `[audio.android]`. The `[metadata]` and `[recent logs]` sections remain present in order. Calling `.with_android_audio(None)` explicitly is equivalent (idempotent omission).
- Evidence: `cargo test -p chanora_diagnostics` result
- Notes: Pairs with SWE4-UV-056; together they cover the conditional-render branch in `DiagnosticExport::to_text`.
| SDD Range | SWE.4 Coverage |
|---|---|
| SDD-106 §5 | SWE4-UV-055 |
| SDD-106 §6 | SWE4-UV-053, SWE4-UV-054 |
| SDD-116 item 3 | SWE4-UV-056, SWE4-UV-057 |
## 13. Realtime-Audio Benchmark-Harness Unit Verification Addendum (SDD-120 §11 closure — v0.9.15)
**Background.** SDD-120 (`RealtimeAudioBenchmarkHarnessAndAdvisoryCI`, v0.9.16) §11 explicitly defers the SWE.4 allocation for the five bench functions it specifies in §3, noting: "Suggested SWE.4 forward allocation: SWE4-UV-058 through SWE4-UV-062 (verification-engineer follow-up; not authored by this SDD unit)." Commit 3a7750a landed the implementation across three bench files plus two `examples/` post-processor binaries. This addendum closes the §11 follow-up by authoring the five anchors. SWE4-UV-057 was the prior high-water mark; SWE4-UV-058..062 are the next free contiguous range.
**Status conventions.** All five items are marked **PENDING_BASELINE**: pass/fail evaluation requires a committed SAD-089 baseline JSON for the active host triple (`x86_64-unknown-linux-gnu`), which is produced only by the SDD-120 §7 `bench-baseline-update.yml` `workflow_dispatch` workflow. Until that workflow has been dispatched at least once and its PR merged, the SDD-120 §6 `bench-advisory.yml` short-circuits on missing baseline (per SRS-218 clause 4 always-success) and these verification items cannot return 🟢/🟡/🔴. Automated comparison thereafter is performed by `crates/chanora_audio/examples/compare_baseline.rs` (invoked via `cargo run --example compare_baseline`) against the merge-base baseline per SRS-219.
**SWE4-UV-058**: Verify the realtime capture path performs zero heap allocations per callback after the warmup window.
- Source SDD: SDD-120 §3 (bench function `bench_capture_alloc_count` with 100-callback warmup before the dhat measurement window); SDD-120 §8 (zero-tolerance metric collapses to 🔴/🟢 only — no 🟡 band).
- Source SRS: SRS-216 metric 1 (heap allocation count per realtime callback after warmup); SRS-219 clause a (zero tolerance — "any non-zero allocation count on a PR is flagged 🔴").
- Verification method: Criterion bench with dhat global allocator. Invocation: `cargo bench --bench realtime_capture -- bench_capture_alloc_count`.
- Test code path: `crates/chanora_audio/benches/realtime_capture.rs::bench_capture_alloc_count` (line 27).
- Pass criteria: After a 100-call `CaptureState::ingest` pre-warm (per SDD-120 §3), the dhat `HeapStats.total_blocks` delta across the subsequent 1000 `CaptureState::ingest` calls **SHALL equal zero**. Any non-zero count is a 🔴 regression per SRS-219 clause a (zero tolerance).
- Acceptance evidence: dhat global-allocator `HeapStats.total_blocks` delta == 0 captured by the bench; criterion `estimates.json` projected into the SRS-217 baseline schema by `examples/emit_baseline`; advisory marker rendered by `examples/compare_baseline` against the merge-base baseline.
- Cross-trace: SAD-088 (benchmark-instrumentation seam), SDD-094 (audio-engine lifecycle as the bench-seam container).
- Status: **PENDING_BASELINE** (zero-tolerance metric — first baseline run establishes the binary 🟢/🔴 evaluation; subsequent runs gate on any non-zero allocation regardless of baseline value).
**SWE4-UV-059**: Verify the realtime capture callback wall-clock stays within the SRS-219 p95 tolerance.
- Source SDD: SDD-120 §3 (bench function `bench_capture_callback_wall_clock` with criterion default warmup; measurement reports p50/p95/p99 as a fraction of the cpal stream period).
- Source SRS: SRS-216 metric 2 (per-callback wall-clock at p50/p95/p99 as a fraction of cpal stream period); SRS-219 clause b ("per-callback wall-clock duration at p95 — tolerance is +20% relative to the baseline (p50 and p99 are advisory data only and do not drive the 🔴 marker)").
- Verification method: Criterion timing bench. Invocation: `cargo bench --bench realtime_capture -- bench_capture_callback_wall_clock`.
- Test code path: `crates/chanora_audio/benches/realtime_capture.rs::bench_capture_callback_wall_clock` (line 95).
- Pass criteria: p95 wall-clock per callback **SHALL stay within +20% of the baseline-at-merge-base** per SRS-219 clause b. p50 and p99 are reported but **advisory only** (no tolerance gate; cannot drive 🔴). Automated 🟢/🟡/🔴 evaluation by `examples/compare_baseline` per SDD-120 §8 (🔴 if `delta_pct > 20%`, 🟡 if `10% < delta_pct ≤ 20%`, 🟢 otherwise).
- Acceptance evidence: criterion p95 estimate from `target/criterion/.../estimates.json` projected through `examples/emit_baseline`; advisory marker rendered by `examples/compare_baseline`.
- Cross-trace: SAD-088, SDD-094.
- Status: **PENDING_BASELINE**.
**SWE4-UV-060**: Verify Opus encode latency on a 960-sample / 20 ms frame stays within the SRS-219 mean tolerance.
- Source SDD: SDD-120 §3 (bench function `bench_opus_encode_latency` exercising `audiopus::coder::Encoder::encode_float` **directly**, not through `tsclientlib::AudioHandler`, to isolate encode latency from higher-layer mix/jitter handling).
- Source SRS: SRS-216 metric 3 (Opus encode latency on 960-sample/20 ms frame); SRS-219 clause c ("Opus encode latency on a 960-sample / 20 ms frame — tolerance is +15% relative to the baseline on the mean").
- Verification method: Criterion timing bench. Invocation: `cargo bench --bench opus_codec -- bench_opus_encode_latency`.
- Test code path: `crates/chanora_audio/benches/opus_codec.rs::bench_opus_encode_latency` (line 21).
- Pass criteria: `encoder.encode_float()` mean latency on a 960-sample (20 ms @ 48 kHz mono) deterministic-sine frame **SHALL stay within +15% of the baseline-at-merge-base** per SRS-219 clause c. Automated 🟢/🟡/🔴 evaluation by `examples/compare_baseline` per SDD-120 §8 (🔴 if `delta_pct > 15%`, 🟡 if `7.5% < delta_pct ≤ 15%`, 🟢 otherwise).
- Acceptance evidence: criterion mean estimate from `target/criterion/.../estimates.json` projected through `examples/emit_baseline`; advisory marker rendered by `examples/compare_baseline`.
- Cross-trace: SAD-088, SDD-094.
- Status: **PENDING_BASELINE**.
**SWE4-UV-061**: Verify Opus decode latency on a 20 ms Opus frame stays within the SRS-219 mean tolerance.
- Source SDD: SDD-120 §3 (bench function `bench_opus_decode_latency` exercising `audiopus::coder::Decoder::decode_float` **directly**, not `tsclientlib::AudioHandler::fill_buffer`; SDD-120 §3 pinned this explicitly because the `AudioHandler` path conflates Opus decode with jitter-buffer dequeue and PCM mix).
- Source SRS: SRS-216 metric 4 (Opus decode latency on 960-sample/20 ms frame); SRS-219 clause c ("Opus decode latency on a 960-sample / 20 ms frame — tolerance is +15% relative to the baseline on the mean").
- Verification method: Criterion timing bench. Invocation: `cargo bench --bench opus_codec -- bench_opus_decode_latency`.
- Test code path: `crates/chanora_audio/benches/opus_codec.rs::bench_opus_decode_latency` (line 37).
- Pass criteria: `decoder.decode_float()` mean latency on a single 20 ms (960-sample @ 48 kHz mono) Opus-encoded frame **SHALL stay within +15% of the baseline-at-merge-base** per SRS-219 clause c. Automated 🟢/🟡/🔴 evaluation by `examples/compare_baseline` per SDD-120 §8 (🔴 if `delta_pct > 15%`, 🟡 if `7.5% < delta_pct ≤ 15%`, 🟢 otherwise).
- Acceptance evidence: criterion mean estimate from `target/criterion/.../estimates.json` projected through `examples/emit_baseline`; advisory marker rendered by `examples/compare_baseline`.
- Cross-trace: SAD-088, SDD-094.
- Status: **PENDING_BASELINE**.
**SWE4-UV-062**: Verify resampler throughput on the three canonical rate pairs stays within the SRS-219 samples-per-second tolerance.
- Source SDD: SDD-120 §3 (bench function `bench_resampler_throughput` structured as a criterion `BenchmarkGroup` with three sub-benches: 44.1 kHz → 48 kHz, 16 kHz → 48 kHz, and 48 kHz → 48 kHz passthrough).
- Source SRS: SRS-216 metric 5 (resampler throughput on canonical rate pairs); SRS-219 clause d ("resampler throughput on the canonical rate pairs — tolerance is 10% relative to the baseline on samples-per-second (i.e. a throughput drop greater than 10% is flagged 🔴)").
- Verification method: Criterion throughput bench. Invocation: `cargo bench --bench resampler -- bench_resampler_throughput`.
- Test code path: `crates/chanora_audio/benches/resampler.rs::bench_resampler_throughput` (line 17).
- Pass criteria: Each of the three sub-benches (44.1→48, 16→48, 48→48-passthrough) samples-per-second throughput **SHALL stay no worse than 10% of the baseline-at-merge-base** per SRS-219 clause d. A throughput drop greater than 10% on any of the three sub-benches is a 🔴 regression. Automated 🟢/🟡/🔴 evaluation by `examples/compare_baseline` per SDD-120 §8 (🔴 if `delta_pct < 10%`, 🟡 if `10% ≤ delta_pct < 5%`, 🟢 otherwise; note the sign inversion versus latency metrics — for throughput, a *decrease* is the regression direction).
- Acceptance evidence: criterion samples-per-second estimates from `target/criterion/.../estimates.json` for each of the three sub-benches projected through `examples/emit_baseline`; advisory marker rendered by `examples/compare_baseline`.
- Cross-trace: SAD-088, SDD-094.
- Status: **PENDING_BASELINE**.
### 13.1 SDD-120 Coverage Index
| SDD Range | SWE.4 Coverage | Tolerance Source |
|---|---|---|
| SDD-120 §3 (bench `bench_capture_alloc_count`) | SWE4-UV-058 | SRS-219 clause a (zero-tolerance) |
| SDD-120 §3 (bench `bench_capture_callback_wall_clock`) | SWE4-UV-059 | SRS-219 clause b (+20% p95) |
| SDD-120 §3 (bench `bench_opus_encode_latency`) | SWE4-UV-060 | SRS-219 clause c (+15% mean) |
| SDD-120 §3 (bench `bench_opus_decode_latency`) | SWE4-UV-061 | SRS-219 clause c (+15% mean) |
| SDD-120 §3 (bench `bench_resampler_throughput`) | SWE4-UV-062 | SRS-219 clause d (10% samples/sec) |
### 13.2 SWE4-UV-058..062 Status Index
| SWE.4 ID | Bench function | Bench file | Tolerance | Status |
|---|---|---|---|---|
| SWE4-UV-058 | `bench_capture_alloc_count` | `crates/chanora_audio/benches/realtime_capture.rs` | zero | PENDING_BASELINE |
| SWE4-UV-059 | `bench_capture_callback_wall_clock` | `crates/chanora_audio/benches/realtime_capture.rs` | +20% p95 | PENDING_BASELINE |
| SWE4-UV-060 | `bench_opus_encode_latency` | `crates/chanora_audio/benches/opus_codec.rs` | +15% mean | PENDING_BASELINE |
| SWE4-UV-061 | `bench_opus_decode_latency` | `crates/chanora_audio/benches/opus_codec.rs` | +15% mean | PENDING_BASELINE |
| SWE4-UV-062 | `bench_resampler_throughput` | `crates/chanora_audio/benches/resampler.rs` | 10% samples/sec | PENDING_BASELINE |
@@ -1,377 +0,0 @@
# Chanora SWE.5 Software Integration and Integration Verification Plan
**Document type:** Software Integration Verification Plan
**Process alignment:** ASPICE SWE.5 Software Component Verification and Integration Verification
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Verification object:** Integrated software elements
**Direct source layer:** SAD and SDD verification objects
**Repo path:** `docs/verification/swe5-software-integration-verification-plan.md` ---
## 1. Purpose
This document defines the software integration and integration verification strategy for Chanora. It verifies that software elements integrate correctly and interact according to the software architecture and detailed design.
```text
SysRS -> SysDes -> SRS -> SAD -> SDD
-> SWE.5 Software Integration Verification
```
SWE.5 verifies architecture interfaces, dynamic behavior, component behavior, and selected detailed-design interactions.
## 2. Integration Strategy
| Integration step | Integrated elements | Purpose |
|---|---|---|
| SWE5-INT-001 | Flutter App Shell + Design System | Confirm theme initialization and token availability |
| SWE5-INT-002 | Design System + UI Components | Confirm components consume tokens and expose semantics |
| SWE5-INT-003 | Adaptive Shell + Feature Modules | Confirm compact/medium/expanded layouts integrate with features |
| SWE5-INT-004 | Localization Service + UI Components | Confirm product strings and accessibility labels integrate |
| SWE5-INT-005 | Protocol Adapter + Rust Core | Confirm protocol events and errors integrate with core state |
| SWE5-INT-006 | Rust Core + Bridge Facade | Confirm commands, results, and event streams integrate |
| SWE5-INT-007 | Bridge Facade + Flutter State | Confirm event mapping and view model updates |
| SWE5-INT-008 | Audio Subsystem + Platform Audio | Confirm capture, processing, encode/decode, and playback interface behavior |
| SWE5-INT-009 | Diagnostics + Storage + Localization | Confirm diagnostics event keys, localized descriptions, redaction, and export integration |
| SWE5-INT-010 | Full Flutter UI + Rust Core | Confirm end-to-end software behavior before software qualification testing |
## 3. Integration Verification Measures
**SWE5-IV-001**: Verify Flutter App Shell and Design System integration.
- Source SAD: SAD-001, SAD-002, SAD-007
- Source SDD: SDD-001, SDD-002, SDD-003
- Verification method: Flutter integration test
- Pass criteria: App initializes Material 3 theme and Chanora semantic tokens before rendering feature screens.
- Evidence: Integration test result
**SWE5-IV-002**: Verify Design System and UI Component integration.
- Source SAD: SAD-002, SAD-003, SAD-014
- Source SDD: SDD-004 through SDD-010, SDD-021 through SDD-024
- Verification method: Widget integration test
- Pass criteria: Components consume design tokens and expose required accessibility semantics.
- Evidence: Integration test result
**SWE5-IV-003**: Verify adaptive shell and feature module integration.
- Source SAD: SAD-008 through SAD-011
- Source SDD: SDD-011 through SDD-015
- Verification method: Integration test
- Pass criteria: Compact, medium, and expanded layouts render correct feature regions and preserve critical voice/connection access.
- Evidence: Integration test result
**SWE5-IV-004**: Verify connection status and VoiceBar integration.
- Source SAD: SAD-012, SAD-013, SAD-016
- Source SDD: SDD-016, SDD-017, SDD-018, SDD-026
- Verification method: Integration test
- Pass criteria: Connection status and primary voice controls are visible or directly reachable across layout classes.
- Evidence: Integration test result
**SWE5-IV-005**: Verify localization and accessibility integration.
- Source SAD: SAD-014, SAD-020, SAD-026
- Source SDD: SDD-024, SDD-031, SDD-032, SDD-040
- Verification method: Integration test, accessibility test
- Pass criteria: Localized strings, semantic labels, fallback behavior, and locale-aware formatting work together.
- Evidence: Integration test result
**SWE5-IV-006**: Verify server-content text path integration.
- Source SAD: SAD-021, SAD-022, SAD-023
- Source SDD: SDD-034, SDD-035, SDD-036, SDD-037
- Verification method: Integration test
- Pass criteria: Server names, channel names, nicknames, and messages preserve Unicode and are not translated.
- Evidence: Integration test result
**SWE5-IV-007**: Verify Platform Services and App Shell integration.
- Source SAD: SAD-017, SAD-018, SAD-019
- Source SDD: SDD-027, SDD-028, SDD-029, SDD-030
- Verification method: Platform integration test
- Pass criteria: Insets, back intent, haptics, and keyboard avoidance integrate with shell behavior.
- Evidence: Platform test result
**SWE5-IV-008**: Verify Bridge Facade and Rust Core integration.
- Source SAD: SAD-040, SAD-041
- Source SDD: SDD-046, SDD-047
- Verification method: Integration test
- Pass criteria: Flutter commands and Rust events flow through stable DTOs and deterministic event mapping.
- Evidence: Integration test result
**SWE5-IV-009**: Verify Rust Core and Protocol Adapter integration.
- Source SAD: SAD-032, SAD-033, SAD-041
- Source SDD: SDD-046, SDD-047
- Verification method: Integration test with protocol test server or protocol test double
- Pass criteria: Connection, snapshot, delta events, and protocol errors integrate with core state.
- Evidence: Integration test result
**SWE5-IV-010**: Verify Audio Subsystem and Platform Audio integration.
- Source SAD: SAD-034
- Source SDD: SDD-048
- Verification method: Audio integration test
- Pass criteria: Audio status reaches UI while DSP remains isolated from UI units.
- Evidence: Audio integration test result
**SWE5-IV-011**: Verify Diagnostics integration.
- Source SAD: SAD-036, SAD-050
- Source SDD: SDD-038, SDD-041, SDD-050, SDD-054
- Verification method: Integration test, audit
- Pass criteria: Diagnostic keys, localized descriptions, redaction, Unicode preservation, and export flow operate together.
- Evidence: Integration test result, audit record
**SWE5-IV-012**: Verify storage and secure-storage integration boundaries.
- Source SAD: SAD-035
- Source SDD: SDD-049
- Verification method: Integration test, security review
- Pass criteria: Non-secret data uses storage facade and secrets use secure storage boundaries.
- Evidence: Integration test result, review record
**SWE5-IV-013**: Verify architecture-view and traceability-tooling integration.
- Source SAD: SAD-046 through SAD-060
- Source SDD: SDD-051 through SDD-070
- Verification method: Documentation/tooling integration check
- Pass criteria: Architecture views, ADRs, interface detail catalog, and traceability checker are mutually consistent.
- Evidence: Review record
## 4. Regression Strategy
Regression selection shall consider:
- changed software unit
- changed interface
- changed architecture item
- changed DTO
- changed localization resource
- changed audio pipeline behavior
- changed protocol adapter behavior
- changed diagnostics redaction behavior
- changed platform behavior
## 5. Traceability Matrix
| Architecture / Design Area | SWE.5 Coverage |
|---|---|
| SAD-001 through SAD-016 | SWE5-IV-001 through SWE5-IV-005 |
| SAD-017 through SAD-027 | SWE5-IV-005 through SWE5-IV-007, SWE5-IV-011 |
| SAD-028 through SAD-031 | SWE5-IV-013 |
| SAD-032 through SAD-041 | SWE5-IV-008 through SWE5-IV-012 |
| SAD-042 through SAD-050 | SWE5-IV-001, SWE5-IV-011, SWE5-IV-013 |
| SAD-051 through SAD-060 | SWE5-IV-013 |
| SDD-001 through SDD-030 | SWE5-IV-001 through SWE5-IV-007 |
| SDD-031 through SDD-050 | SWE5-IV-005 through SWE5-IV-012 |
| SDD-051 through SDD-070 | SWE5-IV-013 |
## 6. Result Reporting
Software integration verification results shall be summarized in an integration verification summary report including:
- integrated elements
- selected integration sequence
- selected verification measures
- regression scope
- test environment
- pass/fail result
- nonconformances
- interface issues
- residual risks
- release recommendation
## 7. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial SWE.5 software integration and integration verification plan. |
---
## 8. Platform Decision Integration Verification Addendum
**SWE5-IV-014**: Verify platform baseline, build configuration, single connection, audio defaults, storage, bridge, and diagnostics privacy integration.
- Source SAD: SAD-061 through SAD-070
- Source SDD: SDD-071 through SDD-080
- Verification method: Integration test, release inspection, security review
- Pass criteria: New product decisions integrate across build configuration, runtime behavior, audio, storage, bridge, diagnostics, and release readiness.
- Evidence: Integration verification result
| Architecture / Design Area | SWE.5 Coverage |
|---|---|
| SAD-061 through SAD-070 | SWE5-IV-014 |
| SDD-071 through SDD-080 | SWE5-IV-014 |
**SWE5-IV-015**: Verify integrated desktop PTT subsystem (audio engine, Rust core PTT controller, bridge, Flutter UI, diagnostics).
- Source SAD: SAD-071 through SAD-079
- Source SDD: SDD-081 through SDD-092
- Verification method: Software integration test on every supported desktop reference host (Windows, macOS, GNOME-on-Wayland Linux)
- Pass criteria: For each platform the live measurement of `PttCapabilityLevel` and `backend_id` matches the design expectation; pressing the bound input toggles `transmit_active` end-to-end; the missed-key-up watchdog clears `transmit_active` after the configured timeout; the user-initiated diagnostic export does not contain raw key data; the UI capability badge matches the active capability.
- Evidence: Integration test trace, diagnostic-export inspection, UI screenshot
| Architecture / Design Area | SWE.5 Coverage |
|---|---|
| SAD-061 through SAD-070 | SWE5-IV-014 |
| SDD-071 through SDD-080 | SWE5-IV-014 |
| SAD-071 through SAD-079 | SWE5-IV-015 |
| SDD-081 through SDD-092 | SWE5-IV-015 |
## 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT software-integration verification item SWE5-IV-015 covering the integrated audio engine + Rust core PTT controller + bridge + Flutter UI + diagnostics path on Windows, macOS, and GNOME-on-Wayland Linux reference hosts. |
## 9. Android P0 Software Integration Verification Addendum
**SWE5-IV-016**: Verify Android JNI bootstrap → foreground service lifecycle integration.
- Source SAD: SAD-077, SAD-081
- Source SDD: SDD-105, SDD-107
- Verification method: Instrumented integration test on a physical API 28 device
- Pass criteria: `Application.onCreate` loads `libchanora_bridge.so`, `JNI_OnLoad` captures the `JavaVM`, the bridge is initialized, and `AndroidVoiceForegroundService` can be started by the Rust core (via JNI callback) without re-loading the library or racing init. Service start completes before the first audio frame is produced.
- Evidence: Integration test result + logcat trace
**SWE5-IV-017**: Verify permission denial → foreground service not started → listen-only stream open integration.
- Source SAD: SAD-077
- Source SDD: SDD-106, SDD-107
- Source SRS: SRS-209
- Verification method: Integration test using permission-state test double + real audio stack
- Pass criteria: When `RECORD_AUDIO` is denied (or revoked mid-session) the FGS is NOT started for capture; the playback stream remains open so the user hears other participants (listen-only fallback per SRS-209); UI surfaces the degraded state; re-granting permission re-enables capture without process restart.
- Evidence: Integration test result
**SWE5-IV-018**: Verify foreground service start triggers audio mode acquisition; service stop triggers mode restore.
- Source SAD: SAD-081, SAD-085
- Source SDD: SDD-107, SDD-108
- Source SRS: SRS-208
- Source SysRS: SysRS-305
- Verification method: Integration test on a physical device with `dumpsys audio` snapshots before / during / after
- Pass criteria: Before voice channel join, `AudioManager.mode` is the device baseline. After FGS start and join, mode is `MODE_IN_COMMUNICATION`. After leave/disconnect, FGS stops and the controller restores the snapshotted prior mode. Refcount holds across rapid join/leave/join cycles.
- Evidence: Integration test result + `dumpsys audio` traces
**SWE5-IV-019**: Verify `BackIntentService` integration with the Flutter Navigator route stack.
- Source SAD: SAD-018
- Source SDD: SDD-028 (expanded)
- Source SRS: SRS-163
- Verification method: Flutter integration test on Android with a non-trivial route stack (home → channel → settings → modal)
- Pass criteria: System back closes modal first (does not pop the route); subsequent back pops one route per press; at the home route system back backgrounds the activity. PTT-active-ignore: while the test driver asserts `transmit_active`, back is consumed. API 33+ and pre-33 code paths both produce identical end states (verified on at least one device per branch).
- Evidence: Integration test result
**SWE5-IV-020**: Verify AAB build pipeline integration (`SDD-109`).
- Source SAD: SAD-063
- Source SDD: SDD-073, SDD-109
- Source SRS: SRS-119, SRS-188
- Verification method: CI build job + `bundletool` validation
- Pass criteria: `flutter build appbundle --release` produces an AAB; `bundletool validate` reports no errors; `bundletool build-apks --connected-device` produces per-ABI splits for `{arm64-v8a, armeabi-v7a, x86_64}`; signing key fingerprint matches the CI release-key reference; `targetSdkVersion` matches the SRS-188 declared target; `minSdkVersion` == 28 (DEC-004); manifest contains `FOREGROUND_SERVICE` + `FOREGROUND_SERVICE_MICROPHONE` (API 34+) + `RECORD_AUDIO` permissions and no others outside the allow-list.
- Evidence: CI artifact + bundletool report
| Architecture / Design Area | SWE.5 Coverage |
|---|---|
| SAD-018, SAD-063, SAD-077, SAD-081, SAD-084, SAD-085, SAD-086 | SWE5-IV-016 through SWE5-IV-020 |
| SDD-028 (expanded), SDD-073 (refreshed), SDD-105, SDD-106, SDD-107, SDD-108, SDD-109, SDD-110 | SWE5-IV-016 through SWE5-IV-020 |
### Android voice audio backend integration items (SDD-111..SDD-116 wave)
**SWE5-IV-021**: Verify `MobileVoiceAudioBackend` trait + audio engine integration on voice_join / voice_leave.
- Source SAD: SAD-077, SAD-081
- Source SDD: SDD-111 (trait surface), SDD-112 (config), SDD-115 (lifecycle)
- Source SRS: SRS-210, SRS-211, SRS-213, SRS-214
- Verification method: Rust integration test on a physical Android device (API 31 mid-tier minimum) driving the engine through `voice_join` / `voice_leave` against the real `AndroidVoiceUnit`
- Pass criteria: `voice_join` constructs `AndroidVoiceStreamConfig` from engine state, calls `AndroidVoiceUnit::open(...)`, opens BOTH input and output streams (verified by `session_id()` being `Some(_)` and the output-stream handle being non-null), then calls `start()`. Engine state transitions are observed in order: `Idle → Opening → Running`. `voice_leave` calls `stop()` then `close()` in that order; engine state returns to `Idle`. No stream is left open after `voice_leave` (verified by a follow-up `voice_join` succeeding with a fresh session id).
- Evidence: Integration test result + logcat with engine state transition lines
- SDD-116 matrix rows satisfied: all (open/close path exercised on every matrix device)
**SWE5-IV-022**: Verify SDD-108 audio-mode engagement precedes SDD-113 effect binding (forward) and effects release precedes mode restore (reverse).
- Source SAD: SAD-077, SAD-081, SAD-085
- Source SDD: SDD-108, SDD-113, SDD-115 (sequencing)
- Source SRS: SRS-208, SRS-212
- Verification method: Integration test instrumented with ordered event sink (timestamped events for `mode_engage`, `stream_open`, `effect_attach`, `start`, `stop`, `effect_release`, `stream_close`, `mode_restore`)
- Pass criteria: On `voice_join`, the recorded order is exactly `FGS_start → stream_open → mode_engage → effect_attach → start`. On `voice_leave`, the recorded order is exactly `stop → effect_release → mode_restore → stream_close → FGS_stop` per SDD-115 item 3 (reverse-order teardown). Any deviation fails the case. Test repeats 3 rapid join/leave cycles to surface refcount or sequencing races.
- Evidence: Integration test result + event-sink dump
- SDD-116 matrix rows satisfied: all
**SWE5-IV-023**: Verify SDD-115 full lifecycle sequencing forward and reverse.
- Source SAD: SAD-077, SAD-081
- Source SDD: SDD-107, SDD-108, SDD-111, SDD-113, SDD-115
- Source SRS: SRS-208, SRS-210, SRS-212, SRS-215
- Verification method: Instrumented integration test on physical device
- Pass criteria: Forward sequence: `FGS_start → streams_open → mode_engage → effects_bind → start_capture+playback`. Reverse sequence: `stop → effects_release → mode_restore → streams_close → FGS_stop`. Test asserts strict ordering AND that no event from one step occurs before the previous step completes (no overlap). Test re-runs across at least one API 28 device and one API 34 device to cover the FGS-type tightening branch.
- Evidence: Integration test result + ordered event log
- SDD-116 matrix rows satisfied: API 28 row, API 31 row, API 34 row
**SWE5-IV-024**: Verify audio-focus loss handling.
- Source SAD: SAD-077, SAD-081, SAD-085
- Source SDD: SDD-115 (audio focus event response)
- Source SRS: SRS-208, SRS-215
- Verification method: Integration test using a controllable secondary audio source (test app that requests focus with the three loss kinds)
- Pass criteria: `AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK` → capture and playback continue at unchanged level (Chanora does not duck itself; voice content is exempt per SDD-115). `AUDIOFOCUS_LOSS_TRANSIENT` → capture is paused (no frames produced upstream) and playback is paused; on focus regain, both resume without `voice_leave`/`voice_join`. `AUDIOFOCUS_LOSS` (permanent) → the session is left cleanly (effects released, mode restored, streams closed) and the user is surfaced an "audio focus lost" state; no auto-rejoin.
- Evidence: Integration test result + logcat
- SDD-116 matrix rows satisfied: at least API 31 + API 34 rows
**SWE5-IV-025**: Verify `ErrorDisconnected` callback marshals to tokio task and triggers reopen without blocking the callback thread.
- Source SAD: SAD-077, SAD-081
- Source SDD: SDD-111 (error/disconnect callback via bounded channel/watch), SDD-115 (recovery on disconnect)
- Source SRS: SRS-210, SRS-215
- Verification method: Integration test injecting a forced disconnect (e.g. unplug Bluetooth headset mid-session, or invoke an Oboe error-callback fault injection point)
- Pass criteria: The Oboe `onErrorBeforeClose` / `onErrorAfterClose` callback path enqueues a message onto the bounded channel and returns within the callback's documented latency budget (assert: callback returns in < 5 ms). Reopen is performed on a tokio task on the engine runtime, not on the callback thread (verified by thread-id capture in test). Reopen completes (`voice_join` round-trip on the new device route) within 2 s. The callback never holds a lock during reopen.
- Evidence: Integration test result + thread-id capture log
- SDD-116 matrix rows satisfied: all (regression surface)
**SWE5-IV-026**: Verify permission-denied `voice_join` reports listen-only and does NOT start the foreground service for capture.
- Source SAD: SAD-077
- Source SDD: SDD-106, SDD-107, SDD-111, SDD-115
- Source SRS: SRS-209, SRS-215
- Verification method: Integration test with `RECORD_AUDIO` denied via permission test double
- Pass criteria: `voice_join` opens the output (playback) stream and engine state becomes `RunningListenOnly`. `AndroidVoiceForegroundService` is NOT started with `foregroundServiceType="microphone"` for capture (the service may still run as a non-mic FGS for playback longevity per SDD-107 policy — if SDD-107 declines this, the FGS is not started at all). Backend reports `capture_state = ListenOnly`. No `AndroidVoiceUnit` input stream is opened. UI badge reflects listen-only. On runtime permission grant, the engine performs an internal upgrade to full duplex without process restart and without losing the playback stream. Cross-link: builds on SWE5-IV-017.
- Evidence: Integration test result + logcat + UI screenshot
- SDD-116 matrix rows satisfied: API 28 row, API 34 row (FGS-type tightening branch)
| Architecture / Design Area | SWE.5 Coverage |
|---|---|
| SAD-077, SAD-081 (mobile voice audio backend allocation) | SWE5-IV-021 through SWE5-IV-026 |
| SDD-111, SDD-112, SDD-113, SDD-115 | SWE5-IV-021 through SWE5-IV-026 |
| SDD-116 (device matrix coverage entry points) | SWE5-IV-021, SWE5-IV-023 |
## Baseline Candidate 0.9.4 Update
| Version | Date | Description |
|---|---|---|
| 0.9.4 | 2026-05-18 | Added Android P0 software-integration items SWE5-IV-016..SWE5-IV-020 covering JNI+FGS, permission+FGS+listen-only fallback, FGS+audio-mode round-trip, BackIntentService + Flutter route stack, and AAB build pipeline (bundletool + ABI splits). |
| 0.9.5 | 2026-05-18 | Added Android voice audio backend integration items SWE5-IV-021..SWE5-IV-026 covering MobileVoiceAudioBackend trait + engine wiring (SDD-111), SDD-108↔SDD-113 ordering and reverse-order teardown (SDD-115), full lifecycle sequencing across SDD-107/108/111/113, audio-focus loss handling, ErrorDisconnected callback marshaling, and permission-denied listen-only fallback. Cross-links: SWE5-IV-017 extended by SWE5-IV-026 (listen-only fallback). |
@@ -1,400 +0,0 @@
# Chanora SWE.6 Software Verification Plan
**Document type:** Software Verification / Software Qualification Test Plan
**Process alignment:** ASPICE SWE.6 Software Verification
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Verification object:** Fully integrated Chanora software
**Direct source layer:** SRS
**Repo path:** `docs/verification/swe6-software-verification-plan.md` ---
## 1. Purpose
This document defines the software verification strategy for Chanora. It verifies that the fully integrated software satisfies the Software Requirements Specification.
```text
SysRS -> SysDes -> SRS -> SAD -> SDD
-> SWE.6 Software Verification
```
SWE.6 verifies against SRS. It does not replace SWE.4 unit verification or SWE.5 software integration verification.
## 2. Software Verification Strategy
| Verification type | Purpose |
|---|---|
| Functional software tests | Verify integrated software behavior against SRS |
| Non-functional software tests | Verify performance, accessibility, security, diagnostics, localization, and reliability requirements |
| Platform software tests | Verify integrated software behavior on target platforms |
| Regression tests | Confirm changes did not break previously verified software requirements |
| Release-scope test selection | Select tests according to target release content |
| Summary reporting | Communicate software verification status |
## 3. Software Verification Measures
**SWE6-SV-001**: Verify server connection flow.
- Source SRS: SRS-001 through SRS-030
- Verification method: End-to-end software test
- Pass criteria: User can connect to a compatible server with configured connection data.
- Evidence: Software verification result
**SWE6-SV-002**: Verify channel tree, client list, and server state display.
- Source SRS: SRS-031 through SRS-060
- Verification method: End-to-end software test
- Pass criteria: Channel and client state is displayed and updates after server events.
- Evidence: Software verification result
**SWE6-SV-003**: Verify voice send and receive.
- Source SRS: SRS-061 through SRS-090
- Verification method: Audio software verification test
- Pass criteria: User can transmit and receive voice under supported conditions.
- Evidence: Software verification result
**SWE6-SV-004**: Verify push-to-talk, mute, deaf, and voice status.
- Source SRS: SRS-061 through SRS-090, SRS-156
- Verification method: End-to-end software test
- Pass criteria: Voice controls perform expected software behavior and display correct state.
- Evidence: Software verification result
**SWE6-SV-005**: Verify local storage and secure storage behavior.
- Source SRS: SRS-091 through SRS-110
- Verification method: Software security and persistence test
- Pass criteria: Non-secret data persists through approved storage and secrets use secure storage boundaries.
- Evidence: Software verification result
**SWE6-SV-006**: Verify diagnostics and redacted export behavior.
- Source SRS: SRS-111 through SRS-124, SRS-177, SRS-178
- Verification method: Software verification test, audit
- Pass criteria: Diagnostic export requires user action and redacts sensitive data while preserving safe Unicode content.
- Evidence: Software verification result, audit record
**SWE6-SV-007**: Verify deployment-sensitive software behavior.
- Source SRS: SRS-125 through SRS-134
- Verification method: Release build verification
- Pass criteria: Release build metadata, packaging behavior, and platform declarations are consistent with software requirements.
- Evidence: Release verification result
**SWE6-SV-008**: Verify traceability and documentation controls.
- Source SRS: SRS-135 through SRS-143, SRS-180 through SRS-183
- Verification method: Documentation verification
- Pass criteria: SRS, SAD, and SDD direct-source rules pass validation.
- Evidence: Traceability report
**SWE6-SV-009**: Verify Material 3 and Chanora Design System behavior.
- Source SRS: SRS-144 through SRS-150
- Verification method: UI software verification, review
- Pass criteria: Integrated app uses Material 3 baseline and Chanora semantic tokens without feature-screen hardcoding.
- Evidence: Software verification result
**SWE6-SV-010**: Verify adaptive layouts.
- Source SRS: SRS-151 through SRS-156
- Verification method: UI software verification
- Pass criteria: Compact, medium, and expanded layouts preserve connection status and primary voice controls.
- Evidence: Software verification result
**SWE6-SV-011**: Verify accessibility behavior.
- Source SRS: SRS-157 through SRS-161
- Verification method: Accessibility verification
- Pass criteria: Critical controls expose semantics, non-color-only state cues, focus behavior, and text-scale resilience.
- Evidence: Accessibility verification result
**SWE6-SV-012**: Verify platform behavior.
- Source SRS: SRS-162 through SRS-164
- Verification method: Platform software verification
- Pass criteria: Insets, safe areas, keyboard, Android back behavior, and iOS platform behavior operate as specified.
- Evidence: Platform verification result
**SWE6-SV-013**: Verify localization and fallback behavior.
- Source SRS: SRS-165 through SRS-169
- Verification method: Localization software verification
- Pass criteria: Product strings are externalized, English baseline exists, additional locales can be added, and fallback is deterministic.
- Evidence: Localization verification result
**SWE6-SV-014**: Verify Unicode and server-content behavior.
- Source SRS: SRS-170 through SRS-176
- Verification method: Internationalization software verification
- Pass criteria: Server content is preserved, displayed without translation, UTF-8 is used internally, and locale-aware formatting works.
- Evidence: Internationalization verification result
**SWE6-SV-015**: Verify software architecture and detailed design traceability controls.
- Source SRS: SRS-180 through SRS-184
- Verification method: Documentation/tooling verification
- Pass criteria: SAD derives from SRS and SDD derives from SAD; initialization sequence is verified.
- Evidence: Traceability validation result
## 4. Regression Strategy
Regression test selection shall consider:
- changed SRS item
- changed feature
- changed architecture component
- changed detailed design unit
- changed platform behavior
- changed localization or Unicode handling
- changed diagnostics or redaction
- changed audio behavior
- changed protocol adapter behavior
## 5. Traceability Matrix
| SRS Range | SWE.6 Coverage |
|---|---|
| SRS-001 through SRS-030 | SWE6-SV-001 |
| SRS-031 through SRS-060 | SWE6-SV-002 |
| SRS-061 through SRS-090 | SWE6-SV-003, SWE6-SV-004 |
| SRS-091 through SRS-110 | SWE6-SV-005 |
| SRS-111 through SRS-124 | SWE6-SV-006 |
| SRS-125 through SRS-134 | SWE6-SV-007 |
| SRS-135 through SRS-143 | SWE6-SV-008 |
| SRS-144 through SRS-150 | SWE6-SV-009 |
| SRS-151 through SRS-156 | SWE6-SV-010 |
| SRS-157 through SRS-161 | SWE6-SV-011 |
| SRS-162 through SRS-164 | SWE6-SV-012 |
| SRS-165 through SRS-169 | SWE6-SV-013 |
| SRS-170 through SRS-176 | SWE6-SV-014 |
| SRS-177 through SRS-184 | SWE6-SV-006, SWE6-SV-015 |
## 6. Result Reporting
Software verification results shall be summarized in a software verification summary report including:
- release scope
- selected software verification measures
- skipped measures and rationale
- platform/environment used
- pass/fail status
- nonconformances
- regression scope
- residual risks
- release recommendation
## 7. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial SWE.6 software verification plan derived from SRS v0.5. |
---
## 8. Platform Decision Software Verification Addendum
**SWE6-SV-016**: Verify platform baseline, release SDK gates, single connection MVP scope, audio defaults, storage/bridge policy, and diagnostics/crash reporting policy.
- Source SRS: SRS-185 through SRS-194
- Verification method: Software verification, release inspection, security/privacy review
- Pass criteria: Integrated software and release configuration satisfy the accepted product decisions.
- Evidence: Software verification result, release inspection record
| SRS Range | SWE.6 Coverage |
|---|---|
| SRS-185 through SRS-194 | SWE6-SV-016 |
**SWE6-SV-017**: Verify integrated software behaviour for desktop Push-to-Talk against SRS-195 through SRS-203.
- Source SRS: SRS-195, SRS-196, SRS-197, SRS-198, SRS-199, SRS-200, SRS-201, SRS-202, SRS-203
- Verification method: Software verification test (end-to-end) on Windows, macOS, GNOME-on-Wayland reference hosts
- Pass criteria: PTT trait abstraction is platform-agnostic from the caller's perspective; reported capability level equals live runtime behaviour; Windows ladder degrades correctly when Raw Input is denied; macOS Global ↔ Focused toggles with permission state changes; Linux honours portal availability; mouse-side-button binding works where the backend exposes it; `capture_active` and `transmit_active` are independently observable; diagnostic export contains zero raw key data; missed-key-up watchdog clears `transmit_active` after the configured timeout.
- Evidence: SWE.6 test report
| SRS Range | SWE.6 Coverage |
|---|---|
| SRS-185 through SRS-194 | SWE6-SV-016 |
| SRS-195 through SRS-203 | SWE6-SV-017 |
## 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT software-verification item SWE6-SV-017 covering end-to-end SRS-195..203 verification across Windows, macOS, and GNOME-on-Wayland Linux reference hosts. |
## 9. Android P0 Software Verification Addendum
**SWE6-SV-018**: Verify Android voice foreground service satisfies SRS-111.
- Source SRS: SRS-111
- Verification method: Device-level software-qualification test on API 28 floor device + mid-tier + current target (per `docs/verification/android-p0-acceptance.md` TC-3)
- Pass criteria: While connected to a voice channel the foreground service runs with `foregroundServiceType="microphone"` (API 30+) and a non-dismissible notification; mic capture and playback continue with the screen off for ≥ 10 minutes without being killed; service stops cleanly on disconnect.
- Evidence: Device test log + screen-recording
- Cross-link (added in 0.9.5): SRS-215 device-matrix expansion is covered by SWE6-SV-030. SWE6-SV-018 remains the single-device baseline; SWE6-SV-030 collects per-SDD-116-row evidence.
**SWE6-SV-019**: Verify RECORD_AUDIO request timing and listen-only fallback satisfy SRS-209.
- Source SRS: SRS-209
- Source SysRS: SysRS-306
- Verification method: Device-level test (android-p0-acceptance.md TC-2)
- Pass criteria: The mic permission is requested at the user gesture that first needs it (not at app launch); denial drops capture but keeps playback open (listen-only); permanently-denied state opens the system settings deep-link instead of re-prompting; re-grant re-enables capture without process restart.
- Evidence: Device test log
**SWE6-SV-020**: Verify Android in-call audio mode round-trip satisfies SRS-208.
- Source SRS: SRS-208
- Source SysRS: SysRS-305
- Verification method: Device-level test with `dumpsys audio` (android-p0-acceptance.md TC-6)
- Pass criteria: Pre-join mode is recorded; during voice session mode is `MODE_IN_COMMUNICATION`; on leave/disconnect prior mode is restored exactly. No permanent mode lock across multiple sessions. No crash if a Bluetooth headset is connected/disconnected mid-session (P0 minimum).
- Evidence: Device test log + dumpsys traces
**SWE6-SV-021**: Verify Android back navigation satisfies SRS-163.
- Source SRS: SRS-163
- Verification method: Device-level test (android-p0-acceptance.md TC-11 + TC-12) on API 28, an API ≤ 32 device, and an API 33+ device.
- Pass criteria: Modal-first close; one-pop-per-press; home-route back backgrounds; PTT-active ignores back. Predictive-back animation present on API 33+ and absent on pre-33 with identical end behaviour.
- Evidence: Device test log + screen-recording
**SWE6-SV-022**: Verify Android minimum API satisfies SRS-187 and DEC-004.
- Source SRS: SRS-187
- Source SysRS: SysRS-288
- Verification method: Manifest inspection + install attempt on API 28 device
- Pass criteria: Merged manifest declares `minSdkVersion = 28`. Install on API 28 succeeds. Install attempt on API 27 simulator/device is rejected with a clean error.
- Evidence: Manifest dump + install logs
**SWE6-SV-023**: Verify Android Play target API and AAB packaging satisfy SRS-119 and SRS-188.
- Source SRS: SRS-119, SRS-188
- Verification method: AAB inspection + Play Console upload to Internal Testing (android-p0-acceptance.md TC-13)
- Pass criteria: `targetSdkVersion` matches the currently-required Play target per SRS-188; release artifact is an AAB (not a bare APK) per SRS-119; Play Console accepts the bundle; signing key is the CI release key.
- Evidence: AAB dump + Play Console acceptance screenshot
**SWE6-SV-024**: Verify Android PTT capability badge reports `L0Focused` per SAD-086 / SDD-110.
- Source SRS: SRS-208 (mode boundary), SRS-209
- Verification method: Device-level UI test (android-p0-acceptance.md TC-4 + TC-10)
- Pass criteria: Capability badge shows `L0Focused` with Android-specific explanatory copy. No global hotkey is bound. Backgrounding the app stops PTT transitions from being delivered.
- Evidence: UI screenshot + log
| SRS Range | SWE.6 Coverage |
|---|---|
| SRS-111 | SWE6-SV-018 |
| SRS-119 | SWE6-SV-023 |
| SRS-163 | SWE6-SV-021 |
| SRS-187 | SWE6-SV-022 |
| SRS-188 | SWE6-SV-023 |
| SRS-208 | SWE6-SV-020, SWE6-SV-024 |
| SRS-209 | SWE6-SV-019, SWE6-SV-024 |
### Android voice audio backend qualification items (SRS-210..SRS-215, SDD-111..SDD-116 wave)
**SWE6-SV-025**: Verify SRS-210 mouth-to-ear latency target per device-class on the SDD-116 device matrix.
- Source SRS: SRS-210
- Source SDD: SDD-111, SDD-112, SDD-116
- Verification method: Glass-to-glass acoustic measurement on each SDD-116 matrix device (API 28, API 31, API 34; at least one Pixel + one Samsung). See "Glass-to-glass latency measurement procedure" below.
- Pass criteria: On devices where `achieved_performance_mode() == LowLatency` the measured mouth-to-ear latency is **≤ 150 ms** (median of 20 samples, 95th percentile ≤ 180 ms). On devices where the achieved mode is `None`/`PowerSaving` the measured latency is **≤ 250 ms** (median of 20 samples, 95th percentile ≤ 300 ms). Tier classification is derived from the SWE4-UV-051 unit-level mapping evaluated against the per-device `achieved_performance_mode` from SWE6-SV-026.
- Evidence: Per-device measurement log (CSV: device, API, achieved_mode, sample_index, latency_ms) + reference audio recording for spot-check + acceptance form rows TC-17, TC-18
- SDD-116 matrix rows satisfied: all (one row per device)
**SWE6-SV-026**: Verify SRS-211 input preset achieved value recorded per device.
- Source SRS: SRS-211
- Source SDD: SDD-112 (`achieved_input_preset()`), SDD-116
- Verification method: Device-level test reading the backend's diagnostics export after `voice_join`
- Pass criteria: For each SDD-116 matrix device the diagnostics record one of `{VoiceCommunication, VoicePerformance, Generic}` and that value is consistent with the fallback ladder verified by SWE4-UV-048. `VoiceCommunication` is preferred and any deviation must be accompanied by a recorded fallback rationale (e.g. preset rejected by OEM stack). No device reports an unrecorded/unknown preset.
- Evidence: Per-device diagnostics export
- SDD-116 matrix rows satisfied: all
**SWE6-SV-027**: Verify SRS-212 hardware AEC engagement (and NS/AGC where supported) per device.
- Source SRS: SRS-212
- Source SDD: SDD-113, SDD-116
- Verification method: Device-level test inspecting backend diagnostics + audible regression check (echo audibility) under speakerphone-routed playback
- Pass criteria: For each matrix device the diagnostics record per-effect engagement: `{aec: hw|sw|unavailable, ns: hw|sw|unavailable, agc: hw|sw|unavailable}`. Where `AcousticEchoCanceler.isAvailable()` returns true the recorded value MUST be `hw`. Where it returns false the recorded value MUST be `sw` (software fallback per SDD-113 item 5) — never silent. Audible echo evaluation (test sequence: 10 s of speakerphone playback with mic open at conversational distance) yields no operator-perceptible echo on at least one Pixel device and at least one Samsung device.
- Evidence: Per-device diagnostics export + audible-check operator note
- SDD-116 matrix rows satisfied: all (AEC/NS/AGC availability column)
**SWE6-SV-028**: Verify SRS-213 output usage and content type achieved per device.
- Source SRS: SRS-213
- Source SDD: SDD-112 (`achieved_output_usage`, `achieved_output_content_type`), SDD-116
- Verification method: Device-level test reading backend diagnostics; cross-checked with `dumpsys media.audio_flinger` where queryable
- Pass criteria: For each matrix device the diagnostics record `achieved_output_usage == VoiceCommunication` AND `achieved_output_content_type == Speech`. Where `dumpsys` exposes the stream attributes, the dump corroborates. Mismatch fails the case. Also verifies the in-call routing side-effect: volume slider during the session adjusts the call-volume stream, not media volume (operator check on at least one device).
- Evidence: Per-device diagnostics export + dumpsys excerpt + operator volume-routing note
- SDD-116 matrix rows satisfied: all
**SWE6-SV-029**: Verify SRS-214 sharing mode achieved per device.
- Source SRS: SRS-214
- Source SDD: SDD-112 (`achieved_sharing_mode`), SDD-116
- Verification method: Device-level test reading backend diagnostics on each matrix device
- Pass criteria: For each matrix device the diagnostics record `achieved_sharing_mode ∈ {Exclusive, Shared}`. The requested value is always `Exclusive`; deviation to `Shared` is acceptable and must be recorded with no operational regression (assert: no callback errors in the first 60 s of the session when the achieved mode is `Shared`). The aggregate device-matrix table in the test report cross-tabulates `requested vs achieved` per device.
- Evidence: Per-device diagnostics export
- SDD-116 matrix rows satisfied: all
**SWE6-SV-030**: Verify SRS-215 background mic capture under foreground-service-type=microphone per device.
- Source SRS: SRS-215
- Source SDD: SDD-107, SDD-114 (manifest declarations), SDD-115 (FGS-first sequencing), SDD-116
- Verification method: Device-level test (extends SWE6-SV-018 / android-p0-acceptance.md TC-3) executed on each SDD-116 matrix device
- Pass criteria: With the screen off (device locked or screen timed out) for ≥ 10 minutes the input stream remains open AND frames continue to be produced by the AAudio input (verified by a periodic per-minute frame-count probe in the diagnostics) on every matrix device. On API 34 devices the FGS-type is `microphone` (verified by `dumpsys activity services` excerpt). No `ForegroundServiceDidNotStartInTimeException` or `MissingForegroundServiceTypeException` in logcat. Cross-link annotation: this item extends SWE6-SV-018 with per-matrix-row evidence; SWE6-SV-018 remains the single-device baseline and SWE6-SV-030 is the device-matrix expansion.
- Evidence: Per-device test log + dumpsys excerpt + frame-count probe export
- SDD-116 matrix rows satisfied: all
| SRS Range | SWE.6 Coverage |
|---|---|
| SRS-210 | SWE6-SV-025 |
| SRS-211 | SWE6-SV-026 |
| SRS-212 | SWE6-SV-027 |
| SRS-213 | SWE6-SV-028 |
| SRS-214 | SWE6-SV-029 |
| SRS-215 | SWE6-SV-018 (single-device baseline), SWE6-SV-030 (device-matrix expansion) |
#### Glass-to-glass latency measurement procedure (SWE6-SV-025)
Mouth-to-ear (glass-to-glass) latency for SRS-210 shall be measured end-to-end across the Android device under test acting as the speaker AND a second Android device (or reference Linux host) acting as the listener, both joined to a controlled test TeamSpeak 3 server on the same LAN (no internet hop; LAN RTT must be measured and recorded separately, and subtracted as a baseline only if > 5 ms).
Measurement setup:
1. Connect the DUT and the reference listener device to the test server. The DUT is the talker; the reference is the listener.
2. Drive a short acoustic impulse (a 1 kHz tone burst, 20 ms duration, or a click track) into the DUT microphone from a controlled acoustic source (small loudspeaker at fixed distance, OR a wired line-in adapter where the DUT supports one).
3. Capture the listener device's loudspeaker output with a reference microphone connected to a stereo audio interface; the same audio interface ALSO captures the source impulse on the second channel via a hardwired tap from the impulse generator. Both channels are recorded into a single stereo WAV at ≥ 48 kHz, 16-bit minimum.
4. Latency is the time delta between the impulse-onset sample on channel A (source tap) and the impulse-onset sample on channel B (listener loudspeaker capture), expressed in milliseconds. Onset detection: first sample exceeding 10× the RMS noise floor of the preceding 100 ms.
5. Required precision: ≤ 1 ms (achievable at 48 kHz with single-sample onset detection). The measurement tool is unspecified; any DAW, `sox`, or custom script that meets the precision requirement is acceptable. The script and raw WAV files are part of the evidence and shall be archived.
6. Per-device run: 20 impulses spaced ≥ 2 s apart. Record median and 95th percentile.
7. Baseline subtraction: LAN one-way latency to the test server is measured (e.g. via ICMP / TS3 control-channel ping) and recorded but NOT subtracted from the SRS-210 result, because SRS-210's "mouth-to-ear" definition includes the network hop on a representative network. The LAN result is the ceiling case; WAN regression is out of scope for SRS-210 on this matrix.
8. Operator notes record: DUT model, Android API, `achieved_performance_mode`, `achieved_sharing_mode`, `achieved_input_preset`, headset/loudspeaker routing, ambient noise estimate, ambient temperature only if extreme.
This procedure is reproducible without proprietary fixtures. A loopback-cable-only variant (DUT line-out → DUT line-in on a single device with a wired headset adapter) is acceptable as a screening test but is NOT sufficient for SRS-210 sign-off because it does not exercise the network path.
## Baseline Candidate 0.9.4 Update
| Version | Date | Description |
|---|---|---|
| 0.9.4 | 2026-05-18 | Added Android P0 software-qualification items SWE6-SV-018..SWE6-SV-024 mapped to SRS-111, SRS-119, SRS-163, SRS-187, SRS-188, SRS-208, SRS-209; cross-linked to `docs/verification/android-p0-acceptance.md` test cases. |
| 0.9.5 | 2026-05-18 | Added Android voice audio backend software-qualification items SWE6-SV-025..SWE6-SV-030 covering SRS-210 (latency tier per SDD-116 matrix, with glass-to-glass measurement procedure), SRS-211 (input preset achieved), SRS-212 (hardware AEC engagement + software fallback evidence), SRS-213 (output usage/content type achieved), SRS-214 (sharing mode achieved), SRS-215 (FGS-hosted background capture per matrix row). Annotated SWE6-SV-018 with cross-link to SWE6-SV-030 (device-matrix expansion). |
@@ -1,303 +0,0 @@
# Chanora SYS.4 System Integration and Integration Verification Plan
**Document type:** System Integration and Integration Verification Plan
**Process alignment:** ASPICE SYS.4 System Integration and Integration Verification
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Verification object:** Integrated application system elements
**Direct source layer:** SysDes
**Repo path:** `docs/verification/sys4-system-integration-verification-plan.md` ---
## 1. Purpose
This document defines the system integration and integration verification strategy for the Chanora application system. It verifies that the system elements defined by SysDes are integrated and interact according to the system architecture.
```text
SysRS -> SysDes -> SYS.4 System Integration Verification
```
SYS.4 verifies system architecture integration. It does not replace SWE.4, SWE.5, or SWE.6.
## 2. System Integration Scope
System elements include:
- User/operator interaction
- Client device hardware
- Operating system services
- Network environment
- External compatible voice server
- Chanora application container
- Flutter UI
- Rust Core
- Protocol adapter
- Audio subsystem
- Platform adapters
- Storage
- Secure storage
- Diagnostics
- Deployment environment
- Localization and UI/UX architecture elements
## 3. System Integration Strategy
| Integration step | System elements | Purpose |
|---|---|---|
| SYS4-INT-001 | Chanora app + OS permissions | Verify microphone, notification, secure storage, lifecycle, and permission integration |
| SYS4-INT-002 | Chanora app + audio hardware | Verify input/output device integration and route changes |
| SYS4-INT-003 | Chanora app + network environment | Verify connection behavior, reconnect, and failure presentation |
| SYS4-INT-004 | Chanora app + external compatible server | Verify channels, clients, voice, and text behavior with real or representative server |
| SYS4-INT-005 | Flutter UI + platform services | Verify safe areas, system bars, keyboard, and platform navigation behavior |
| SYS4-INT-006 | Rust Core + external protocol server | Verify protocol integration at system level |
| SYS4-INT-007 | Diagnostics + user export target | Verify diagnostic export workflow at system level |
| SYS4-INT-008 | Deployment artifact + target OS | Verify packaged application launches and uses required services |
| SYS4-INT-009 | Localization + server multilingual content | Verify multilingual product UI and server-provided content handling |
| SYS4-INT-010 | Full application system | Verify integrated behavior across supported platform classes |
## 4. System Integration Verification Measures
**SYS4-SIV-001**: Verify OS permission integration.
- Source SysDes: SysDes-048 through SysDes-058, SysDes-118
- Verification method: Platform system integration test
- Pass criteria: Required permissions, lifecycle behavior, safe areas, keyboard behavior, and platform navigation behavior integrate with the application.
- Evidence: System integration test result
**SYS4-SIV-002**: Verify audio hardware integration.
- Source SysDes: SysDes-059 through SysDes-074
- Verification method: Audio system integration test
- Pass criteria: Audio capture, playback, route change handling, and processing feature availability work with supported devices.
- Evidence: System integration test result
**SYS4-SIV-003**: Verify network environment integration.
- Source SysDes: SysDes-075 through SysDes-087
- Verification method: Network system integration test
- Pass criteria: Connection, recoverable network loss, reconnect, and user-safe errors work under defined network conditions.
- Evidence: System integration test result
**SYS4-SIV-004**: Verify external compatible server integration.
- Source SysDes: SysDes-088 through SysDes-101
- Verification method: Server system integration test
- Pass criteria: Server connection, channel list, client list, voice, text, and disconnect behavior integrate correctly.
- Evidence: System integration test result
**SYS4-SIV-005**: Verify application functional system integration.
- Source SysDes: SysDes-102 through SysDes-120
- Verification method: System integration test
- Pass criteria: User-visible workflows operate across UI, Rust Core, protocol, state, audio, storage, and diagnostics elements.
- Evidence: System integration test result
**SYS4-SIV-006**: Verify protocol system integration.
- Source SysDes: SysDes-121 through SysDes-128
- Verification method: System integration test with compatible server
- Pass criteria: Protocol adapter integrates with Rust Core and external compatible server without exposing protocol internals to UI.
- Evidence: System integration test result
**SYS4-SIV-007**: Verify state synchronization system integration.
- Source SysDes: SysDes-129 through SysDes-132
- Verification method: System integration test
- Pass criteria: Snapshot, delta, reconnect, event ordering, and UI update behavior operate together.
- Evidence: System integration test result
**SYS4-SIV-008**: Verify storage and security system integration.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: Security and system integration test
- Pass criteria: Bookmarks, settings, secure storage, redaction, and privacy constraints integrate correctly.
- Evidence: System integration test result, audit record
**SYS4-SIV-009**: Verify diagnostics and operations system integration.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: System integration test
- Pass criteria: Logs, redaction, diagnostics, export, and support workflow operate as an integrated capability.
- Evidence: System integration test result
**SYS4-SIV-010**: Verify non-functional system behavior.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: Performance and reliability system integration test
- Pass criteria: Responsiveness, audio latency, memory growth controls, reconnect, and malformed-event behavior meet defined expectations.
- Evidence: System integration test result
**SYS4-SIV-011**: Verify deployment and release environment integration.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: Deployment system integration test
- Pass criteria: Target platform packages install, launch, and access required OS services as expected.
- Evidence: Deployment integration result
**SYS4-SIV-012**: Verify interface integration.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: Interface system integration test
- Pass criteria: User, bridge, protocol, audio, storage, secure storage, network, and diagnostic interfaces integrate correctly.
- Evidence: Interface integration result
**SYS4-SIV-013**: Verify constraints and assumptions integration impact.
- Source SysDes: SysDes-001 through SysDes-132
- Verification method: Review, inspection, system integration test
- Pass criteria: Constraints and assumptions are respected or deviations are documented.
- Evidence: Review record, system integration test result
**SYS4-SIV-014**: Verify UI/UX, Material 3, platform, and i18n system integration.
- Source SysDes: SysDes-111 through SysDes-132
- Verification method: System integration test
- Pass criteria: Material 3 design system, adaptive shell, accessibility, platform behavior, localization, Unicode, diagnostics localization, and traceability controls integrate correctly.
- Evidence: System integration test result
## 5. Regression Strategy
Regression selection shall consider:
- changed system element
- changed software release
- changed platform adapter
- changed audio hardware support
- changed compatible server behavior
- changed network behavior
- changed deployment package
- changed localization or Unicode handling
- changed diagnostics export behavior
- changed system architecture item
## 6. Traceability Matrix
| SysDes Range | SYS.4 Coverage |
|---|---|
| SysDes-001 through SysDes-034 | SYS4-SIV-005, SYS4-SIV-006, SYS4-SIV-007 |
| SysDes-035 through SysDes-058 | SYS4-SIV-001 |
| SysDes-059 through SysDes-074 | SYS4-SIV-002 |
| SysDes-075 through SysDes-087 | SYS4-SIV-003 |
| SysDes-088 through SysDes-101 | SYS4-SIV-004 |
| SysDes-102 through SysDes-110 | SYS4-SIV-005 |
| SysDes-111 through SysDes-132 | SYS4-SIV-014 |
| SysDes-121 through SysDes-128 | SYS4-SIV-006 |
| SysDes-129 through SysDes-132 | SYS4-SIV-007 |
| SysDes-above-current-baseline and above | Not applicable; no such IDs exist in current SysDes baseline. |
## 7. Result Reporting
System integration verification results shall be summarized in a system integration verification summary report including:
- release scope
- integrated system elements
- integration sequence
- selected verification measures
- regression scope
- platform/environment used
- pass/fail status
- nonconformances
- interface issues
- dynamic behavior issues
- residual risks
- release recommendation
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial SYS.4 system integration and integration verification plan derived from SysDes v0.6. |
---
## 9. Platform Decision System Integration Verification Addendum
**SYS4-SIV-015**: Verify platform baseline, Apple SDK gate, Android target gate, MVP single connection, audio defaults, storage, bridge, and diagnostics privacy system integration.
- Source SysDes: SysDes-133 through SysDes-141
- Verification method: System integration test, release inspection, security/privacy review
- Pass criteria: System-level integration reflects accepted product decisions and release gates.
- Evidence: System integration result, release readiness evidence
| SysDes Range | SYS.4 Coverage |
|---|---|
| SysDes-133 through SysDes-141 | SYS4-SIV-015 |
**SYS4-SIV-016**: Verify integrated system-level desktop Push-to-Talk behaviour against SysDes-142 through SysDes-148.
- Source SysDes: SysDes-142, SysDes-143, SysDes-144, SysDes-145, SysDes-146, SysDes-147, SysDes-148
- Verification method: System integration verification on Windows, macOS, GNOME-on-Wayland reference hosts
- Pass criteria: Platform PTT Backend layer is the only surface generating PTT state transitions; `PttCapabilityLevel` and `backend_id` propagate from backend through Rust Core through bridge to Flutter UI without modification; `transmit_active` and `capture_active` are observably independent at the system boundary; diagnostics sanitizer rejects raw key payloads; UI capability badge matches the active capability; release readiness record carries the live-measurement evidence per RR-PTT-001..008.
- Evidence: SYS.4 verification report
| SysDes Range | SYS.4 Coverage |
|---|---|
| SysDes-133 through SysDes-141 | SYS4-SIV-015 |
| SysDes-142 through SysDes-148 | SYS4-SIV-016 |
## 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. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT system-integration verification item SYS4-SIV-016 covering SysDes-142..148 across Windows, macOS, and GNOME-on-Wayland Linux reference hosts. |
## 10. Android P0 System Integration Verification Addendum
SYS4-SIV-015 (Platform Decision gate) is strengthened to require the
Android-specific evidence below. Two new SYS.4 entries are added.
**SYS4-SIV-015 (strengthened — Android target gate)**: In addition to
the original platform-baseline checks, the Android target gate now
requires:
- A boot + connect + voice-channel run on a physical Android 9 (API 28) device per DEC-004 / SysRS-288.
- AAB upload acceptance on the Play Console Internal Testing track (or `bundletool` equivalent) per SRS-119 / SRS-188.
- Foreground service surviving lock-screen for ≥ 10 minutes per SRS-111.
- AudioManager mode snapshot/restore verified via `dumpsys audio` per SRS-208 / SysRS-305.
- Evidence: System integration result + Play Console acceptance record + dumpsys traces.
**SYS4-SIV-017**: Verify Android in-call audio mode round-trip with Bluetooth SCO route awareness.
- Source SysDes: SysDes-133 through SysDes-148 (Android-specific subset), SysRS-305
- Source SRS: SRS-208
- Verification method: System integration test on a physical Android device with at least one Bluetooth headset
- Pass criteria: Pre-session `AudioManager.mode` is captured; voice session sets `MODE_IN_COMMUNICATION`; disconnect restores the prior mode. Bluetooth headset connect/disconnect during a session does not crash the app and does not lock the audio route permanently (P0 minimum). Full SCO-route correctness is logged as a P1 follow-up.
- Evidence: Device test log + dumpsys + Bluetooth-event log
**SYS4-SIV-018**: Verify Android AAB install via Play Internal Track or bundletool.
- Source SysDes: SysDes-133 through SysDes-148 (Android-specific subset)
- Source SRS: SRS-119, SRS-187, SRS-188
- Verification method: Release-pipeline integration test
- Pass criteria: The exact AAB produced by the release CI job is accepted by Play Console Internal Testing (or by `bundletool install-apks --connected-device`). The installed app boots on an API 28 device and a current-target-API device. Signing key fingerprint matches the CI release-key fingerprint. ABI splits exist for `{arm64-v8a, armeabi-v7a, x86_64}`.
- Evidence: Play Console acceptance screenshot + bundletool report + adb install log
| SysDes Range | SYS.4 Coverage |
|---|---|
| SysDes-133 through SysDes-148 (Android subset) | SYS4-SIV-015 (strengthened), SYS4-SIV-017, SYS4-SIV-018 |
## Baseline Candidate 0.9.4 Update
| Version | Date | Description |
|---|---|---|
| 0.9.4 | 2026-05-18 | Strengthened SYS4-SIV-015 Android target gate (API 28 boot, FGS lock-screen longevity, AudioManager round-trip, Play AAB acceptance) and added SYS4-SIV-017 (in-call mode + Bluetooth SCO awareness) and SYS4-SIV-018 (AAB install via Play Internal Track / bundletool). |
@@ -1,83 +0,0 @@
# Chanora Verification Master Plan
**Document type:** Verification Master Plan
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Product:** Chanora
**Repo path:** `docs/verification/verification-master-plan.md` ---
## 1. Purpose
This document defines how Chanora verification documents relate to the engineering hierarchy.
Core engineering hierarchy:
```text
SysRS -> SysDes -> SRS -> SAD -> SDD
```
Verification work products are downstream evidence-producing artifacts and do not replace the hierarchy.
## 2. Verification Layers
| Process | Verification target | Direct verification source | Purpose |
|---|---|---|---|
| SWE.4 | Software units | SDD | Verify software units against detailed design |
| SWE.5 | Integrated software elements | SAD and SDD | Verify software architecture integration, interfaces, dynamic behavior, and component interaction |
| SWE.6 | Fully integrated software | SRS | Verify integrated software satisfies software requirements |
| SYS.4 | Integrated application system elements | SysDes | Verify system elements integrate according to system architecture |
## 3. Verification Flow
```text
SDD -> SWE.4 Unit Verification
SAD + SDD -> SWE.5 Software Integration Verification
SRS -> SWE.6 Software Verification
SysDes -> SYS.4 System Integration Verification
```
## 4. Regression Rule
A change in any design or requirement artifact shall trigger impact analysis for the corresponding verification layer:
| Changed artifact | Verification impact |
|---|---|
| SDD | SWE.4 and SWE.5 impact analysis |
| SAD | SDD, SWE.5, and possibly SWE.4 impact analysis |
| SRS | SAD, SDD, SWE.6, and related lower-level verification impact analysis |
| SysDes | SRS/SAD/SDD impact analysis and SYS.4 impact analysis |
| SysRS | SysDes/SRS/SAD/SDD impact analysis and system/software verification impact analysis |
## 5. Required Verification Reports
| Report | Source |
|---|---|
| Unit Verification Summary Report | SWE.4 |
| Software Integration Verification Summary Report | SWE.5 |
| Software Verification Summary Report | SWE.6 |
| System Integration Verification Summary Report | SYS.4 |
| Regression Verification Report | Any affected verification layer |
| Problem Resolution Report | Failed verification requiring defect handling |
## 6. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial verification master plan covering SWE.4, SWE.5, SWE.6, and SYS.4. |
## 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. |
-246
View File
@@ -1,246 +0,0 @@
# Windows P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
Windows P0 ship of Chanora. Automated tests (cargo + flutter
analyze + windows-smoke.cmd) sign off the mechanical side; this
checklist signs off the user-experience side. A failure on any
row blocks the rc.8 tag.
Source: this checklist supersedes the inline plan in the
conversation that produced the v1.0.0-rc.8 baseline. The auto-test
sign-off lives in this document's "Auto-test sign-off" section.
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | RDP into `100.84.219.45` as `admin` / `jkorisno1` | Desktop visible |
| 0.2 | Wipe stale install: delete `%LOCALAPPDATA%\app.chanora\` and `%APPDATA%\app.chanora\` if they exist | First-launch from clean state |
| 0.3 | Launch `C:\Users\admin\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe` | Window opens, no crash |
| 0.4 | Open About / version label | Shows **`v1.0.0-rc.8`** (not rc.1) |
| 0.5 | Open `C:\Users\admin\AppData\Local\app.chanora\chanora_flutter\logs\chanora.log` | Contains `bridge initialised`, `log file path …`, `identity store initialised`, `bookmark store initialised`. File size <1 MB. |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter `cn.teamspeak.app` (or your own test server), nickname, blank password | "Connect" button enabled |
| 1.2 | Click Connect | Server snapshot appears: channel tree on left, client list visible |
| 1.3 | Note the connected server name + the channel tree | Tree is sorted (parents above children); no duplicate roots |
| 1.4 | Disconnect, reconnect with the same nickname | Server-visible UID is the same as previous session (identity persisted) |
| 1.5 | Disconnect | Returns to connect form, no error |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | After connecting, observe the UI | **No "Start audio" button anywhere** |
| 2.2 | Click a non-default voice channel in the tree | Voice Bar widget appears at top |
| 2.3 | Voice Bar shows: channel-name pill on left, speaker-mute + mic-mute on right, mode badge ("PTT"), capability badge — expected `L2GlobalHoldToTalk (raw-input)` or `L3GlobalWithMouseButtons (raw-input)` after a successful Raw Input register | All five visible; capability NOT `L0Focused` on this Win 11 host |
| 2.4 | Tap a different voice channel | Voice Bar's channel-name pill updates to the new channel; other clients see us move |
| 2.5 | There is **no** "Leave voice" button | TS3 model: you are always in *some* channel |
## TC-3: PTT mode press / release (SDD-088, SDD-096, SAD-083)
| # | Step | Expected |
|---|---|---|
| 3.1 | In a voice channel, click the gear "Voice settings" | Dialog opens with three mode radio rows (PTT selected, Voice activity disabled "Coming soon"), bind-key button, release-tail slider at 200 ms |
| 3.2 | Click "Bind PTT key", press Space, observe Captured value, click Save | "Captured: **Space**" (not blank); after Save the Voice Bar's PTT line reads **"PTT: Space"** + release tail value |
| 3.3 | Press and hold Space, watch the stats line | Within ~100 ms: **"Mic on"** appears; level meter goes active |
| 3.4 | Release Space | After ~200 ms: **"Mic off"** appears; level meter returns to idle |
| 3.5 | Repeat 3.33.4 ten times rapidly | Each press toggles Mic on/off; no stuck-on state |
| 3.6 | Hold Space for 60 seconds continuously while saying something | **Mic stays on the entire time** (watchdog is disabled per DEC-031; no mid-sentence cut-off) |
| 3.7 | Alt-tab to another application, press Space (no mouse focus on chanora) | Mic on toggles even though chanora is not focused (verifies L2/L3 global path); other clients hear you |
## TC-4: Release tail (SDD-096, SRS-206)
| # | Step | Expected |
|---|---|---|
| 4.1 | Open Voice settings, slide release tail to 0 ms, save | Slider shows "0 ms" |
| 4.2 | Hold Space briefly then release | "Mic off" appears within ~100 ms of release |
| 4.3 | Set release tail to 500 ms, save | Slider shows "500 ms" |
| 4.4 | Hold Space briefly then release | "Mic on" persists for ~500 ms after release, then "Mic off" |
| 4.5 | Set release tail back to 200 ms | Slider shows "200 ms" |
## TC-5: Continuous mode (SAD-083, SRS-205, regression: DEC-031)
| # | Step | Expected |
|---|---|---|
| 5.1 | Open Voice settings → select "Continuous" radio → Save | Mode badge reads "Continuous"; **no "PTT: …" line**; **no release-tail line**; **no capability badge** (all PTT-only surfaces hidden) |
| 5.2 | Observe the stats line | "Mic on" immediately and **stays on** indefinitely |
| 5.3 | Wait 60 seconds continuously | **Mic stays on** the whole time (the old bug — watchdog disabling Continuous after 30 s — must not reproduce) |
| 5.4 | Switch back to PTT mode | Mode badge reads "PTT: Space"; PTT-only lines reappear; Mic off (no key held) |
## TC-6: Mic mute toggle (SRS-207, regression: log spam)
| # | Step | Expected |
|---|---|---|
| 6.1 | In Continuous mode, click the mic-mute icon | Icon toggles to crossed-out; Mic shows off immediately |
| 6.2 | Have a second client check our status | Other client sees a microphone-off icon next to your nickname |
| 6.3 | Wait 30 seconds while muted, then check log file size | `chanora.log` stays <500 KB (no "Sending audio while muted" flood) |
| 6.4 | Click mic-mute again to unmute | Icon clears; Mic returns to on |
| 6.5 | In PTT mode with key held, click mic-mute | Mic immediately goes off mid-press; key release is ignored as long as muted |
| 6.6 | Unmute, key still held | Mic returns to on |
## TC-7: Speaker mute (server-broadcast)
| # | Step | Expected |
|---|---|---|
| 7.1 | Have a second client talk to you | You hear them |
| 7.2 | Click speaker-mute (headset icon) | Icon toggles; their voice is silent |
| 7.3 | Other client checks our status | They see a headset-off icon next to our nickname |
| 7.4 | Click speaker-mute again | Voice returns |
## TC-8: Binding persistence across restart (SDD-095)
| # | Step | Expected |
|---|---|---|
| 8.1 | Bind PTT to F10 → Save | Voice Bar shows "PTT: F10" |
| 8.2 | Close the app entirely | Window dismissed |
| 8.3 | Relaunch | Connect form appears |
| 8.4 | Connect + join a voice channel | Voice Bar shows **"PTT: F10"** (binding survived restart) |
| 8.5 | Press F10 | Mic on |
## TC-9: Binding before voice-join (SDD-094 follow-up)
| # | Step | Expected |
|---|---|---|
| 9.1 | Wipe storage again (steps 0.2) | Clean state |
| 9.2 | Launch, connect, but do not join a voice channel yet | Channel tree visible |
| 9.3 | Open Voice settings, bind a key, Save | No `audio not started` error |
| 9.4 | Join a voice channel | Voice Bar reflects the binding |
## TC-10: No-permission channel rejection (issue 3 from rc.7 review)
| # | Step | Expected |
|---|---|---|
| 10.1 | Identify a channel where your account lacks join permission | Server tree shows it as locked or similar |
| 10.2 | Tap it | After ~1.5 s, **red error banner** appears: "channel move rejected by server (no permission, wrong password, or channel full)" |
| 10.3 | Voice Bar's channel-name pill does **not** update | We did NOT join the channel locally |
| 10.4 | Other clients confirm we are NOT in the requested channel | Server-side reality matches the error banner |
## TC-11: Reconnect (real disconnect, not transient blip)
| # | Step | Expected |
|---|---|---|
| 11.1 | Connect, join a voice channel | Voice Bar visible |
| 11.2 | Force a hard disconnect (server-side kick, firewall block, or `nm-cli con down` on Linux RDP host) | UI shows red "Connection lost" banner with a spinning indicator and reconnect attempt counter |
| 11.3 | Restore network | Reconnect succeeds; voice channel rejoined automatically; banner disappears |
## TC-12: Diagnostic export + privacy (DEC-027)
| # | Step | Expected |
|---|---|---|
| 12.1 | Trigger a settings change (e.g. toggle mode) | Activity in log |
| 12.2 | Trigger the diagnostic export (if a button exists) or copy `%LOCALAPPDATA%\app.chanora\chanora_flutter\logs\chanora.log` | Multi-line text |
| 12.3 | Read it — privacy invariant | Contains `capability_level`, `backend_id`, `bound_input_class` (`keyboard` / `mouse-side-button`); **does NOT** contain any `vk`, `scan_code`, `keysym`, the actual key label, or any timing sequence of presses |
| 12.4 | File size at end of session | <5 MB (rotation: previous session is at `chanora.log.1`; the one before at `chanora.log.2`) |
## TC-13: PTT bind dialog labels (regression)
| # | Step | Expected |
|---|---|---|
| 13.1 | Open binding dialog | Initial state: "Captured: " is blank or shows a placeholder |
| 13.2 | Press Space | "Captured: **Space**" (not blank — the rc.7 regression) |
| 13.3 | Press Enter | "Captured: Enter" |
| 13.4 | Press Tab | "Captured: Tab" |
| 13.5 | Press A | "Captured: A" |
| 13.6 | Press F12 | "Captured: F12" |
| 13.7 | Press Shift alone | Captured field unchanged (modifier-only press ignored) |
| 13.8 | Press a mouse side button (Mouse4 / Back) | "Captured: mouse-side-button:8" |
## TC-14: Capability badge gating
| # | Step | Expected |
|---|---|---|
| 14.1 | In PTT mode | Capability badge visible (`L2GlobalHoldToTalk (raw-input)` or similar) |
| 14.2 | Switch to Continuous mode | **Capability badge disappears** (no info-icon, no level label) |
| 14.3 | Switch to "Voice activity (coming soon)" | Cannot select (disabled); confirms the radio row is non-interactive |
## TC-15: Indicator label (regression)
| # | Step | Expected |
|---|---|---|
| 15.1 | In any mode, look at the stats line | Reads "Mic on" / "Mic off" (mode-neutral); **not** "PTT on" / "PTT off" |
## Auto-test sign-off
These rows do not require human interaction. The values are filled
in from CI / local invocation.
| Layer | Result on Linux | Result on Korean Win 11 |
|---|---|---|
| `cargo check --workspace` | clean | clean |
| `cargo test --workspace --lib` | 80 / 0 / 3 | 126 / 0 / 1 |
| `flutter analyze` | clean (6 pre-existing Radio.groupValue infos) | n/a |
| `python3 tools/validate_docs.py` | strict layered sourcing OK; pre-existing 35-filename warning | n/a |
| `tools/windows-smoke.cmd` | n/a | exit 0 |
The Windows host runs 44 more tests than Linux because of the
`#[cfg(target_os = "windows")]`-gated PTT-backend, dispatcher, and
full-chain tests in `crates/chanora_audio/src/ptt_backends/windows.rs`
and `core/chanora_core/src/ptt.rs::windows_full_chain_tests`.
## Sign-off form
```
chanora v1.0.0-rc.8 — Windows P0 acceptance
Host: Korean Win 11 (HP LAPTOP-37KAQO05, ko-KR locale)
Tester: ______________________
Date: ______________________
Build: chanora_flutter.exe @ ______________________
chanora_bridge.dll @ ______________________
data\app.so @ ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Binding persistence across restart [ pass / fail ] notes:
TC-9 Binding before voice-join [ pass / fail ] notes:
TC-10 No-permission channel rejection [ pass / fail ] notes:
TC-11 Reconnect [ pass / fail ] notes:
TC-12 Diagnostic export + privacy [ pass / fail ] notes:
TC-13 PTT bind dialog labels [ pass / fail ] notes:
TC-14 Capability badge gating [ pass / fail ] notes:
TC-15 Indicator label [ pass / fail ] notes:
Overall result: [ rc.8 PASS / rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **macOS / iOS / Linux** P0 acceptance is NOT covered here; this
document is Windows-only. Tagging rc.8 ships Linux from a separate
pass and remains Windows-gated for macOS / iOS / Android.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally disabled
per DEC-030 (deferred to P1). UI shows it as a "Coming soon" radio
row.
- **Missed-key-up watchdog** is disabled on P0 per DEC-031 (long PTT
speech would have been cut off at 30 s). P1 reintroduces a
redesigned variant.
- **Audio level meter** is binary (`pttActive` only). Real RMS meter
is a P1 follow-up.