The watchdog spawned by ChanoraSession::start_audio cleared ptt_held after 30 s of continuous PTT key-down. That was correct for the 'OS lost the key-up event' failure mode the original SAD-079 / DEC-028 was designed to catch, but it was the wrong shape for real human speech: anyone holding the bound key for a long answer got cut off mid-sentence. For P0: - Comment out the spawn site in ChanoraSession::start_audio with the rationale + the P1 redesign options under consideration (raised ceiling / OS key-state polling / RMS-silence fallback). - Leave the MissedKeyUpWatchdog Rust type, its spawn / spawn_on_signal entry points, and all unit tests in chanora_audio::ptt unchanged so P1 can re-enable with the chosen detection strategy without re-implementing anything. Spec: new DEC-031 in product-decision-register.md supersedes DEC-028 for the v1 ship. DEC-028 stays in the register as historical context. The §7 open-decisions log + §8 change history get matching 0.9.12 rows. Note: Mumble and TeamSpeak ship without a comparable watchdog — the 30 s ceiling was stricter than industry baseline. The underlying protection (OS-level key-up loss) is still worth solving, just not with a fixed timeout. cargo test --workspace --lib: 80 passed / 0 failed / 1 ignored (unchanged; the watchdog unit tests still run because the type itself is unchanged). docs validator: clean (pre-existing 35-filename warning only).
36 KiB
CHANORA_CFG_Product_Decision_Register_v0.9.7.0.0
Document type: Configuration / Product Decision Register
Version: 0.9.7
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 ~8–16 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 OutPackets 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 ~8–16 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. |