docs(ptt): land Baseline Candidate v0.9.3 — capability-based desktop PTT

Applies the gen2 desktop-PTT review summary
(`gen2/chanora-desktop-ptt-review-summary-v0.9.2.md`) to our doc set
with the owner rulings PTT-OPEN-001 through PTT-OPEN-006 resolved as
accepted decisions DEC-023 through DEC-028:

  * DEC-023 Windows Global PTT P0 / MVP
  * DEC-024 macOS Global PTT P0 / MVP with permission UX
  * DEC-025 Linux officially-tested env: GNOME on Wayland only
  * DEC-026 Mouse side buttons supported (Win + macOS; Linux portal)
  * DEC-027 PTT diagnostics: capability + availability only, no
            raw key codes ever
  * DEC-028 Missed-key-up watchdog: P0

Requirements (SysRS / SRS) and architecture (SysDes / SAD / SDD)
gain the desktop-PTT ID set the gen2 summary describes:

  SysRS-296..302  -> SysDes-142..148
                  -> SRS-195..203
                  -> SAD-071..079
                  -> SDD-081..092

ID totals advance from 295 / 141 / 194 / 70 / 80 to 302 / 148 / 203
/ 79 / 92. The strict layered sourcing rule (`SRS -> SysDes` only,
`SAD -> SRS` only, `SDD -> SAD` only) is preserved; the
`tools/validate_docs.py` validator reports zero undefined refs and
zero direct-layer-rule violations.

New document:

  * `docs/architecture/desktop-ptt-architecture.md` — capability
    ladder (L0Focused, L1GlobalShortcut, L2GlobalHoldToTalk,
    L3GlobalWithMouseButtons, L4DeviceAware reserved), Windows /
    macOS / Linux strategies, privacy rule, audio-gate rule,
    missed-key-up watchdog, release-readiness evidence requirement,
    traceability summary.

Doc addenda (Baseline Candidate 0.9.3):

  * `privacy/privacy-policy.md` — no raw key history, capability-
    dependent Global PTT, UI reflects actual runtime capability
  * `security/threat-model.md` — THREAT-PTT-001..006
  * `security/diagnostic-redaction-audit-report.md` —
    REDACT-PTT-001..006 banned field list enforced by `PttSanitizer`
  * `release/platform-release-policy.md` — per-platform evidence
    fields, no over-claim on untested Linux compositors
  * `release/release-readiness-go-nogo-record.md` — RR-PTT-001..008
    release-readiness items
  * `verification/swe4-unit-verification-plan.md` —
    SWE4-UV-035..039
  * `verification/swe5-software-integration-verification-plan.md` —
    SWE5-IV-015
  * `verification/swe6-software-verification-plan.md` — SWE6-SV-017
  * `verification/sys4-system-integration-verification-plan.md` —
    SYS4-SIV-016
  * `governance/traceability-matrix.md` — full PTT trace rows +
    verification map
  * `governance/decision-impact-assessment.md` — DEC-023..028
    impact matrix
  * `governance/product-decision-register.md` v0.9.9 entry
    recording DEC-023..028 in the decision table and the status
    table at §7
  * `governance/document-index.md` — adds
    `desktop-ptt-architecture.md` to the controlled set
  * `architecture/proof-of-concept-plan.md` —
    PoC-PTT-001..005 platform items
  * `references/external-references.md` — Windows Raw Input,
    macOS event-tap, Linux GlobalShortcuts portal references
  * Both validation reports
    (`baseline-candidate-validation-report.md`,
    `repo-format-validation-report.md`) bumped to v0.9.3 with the
    new ID totals (302 / 148 / 203 / 79 / 92).

README §"Desktop Push-to-Talk" added between Architecture Overview
and Repository Layout: capability levels, per-platform strategy,
privacy posture, missed-key-up watchdog.

Tooling:

  * `tools/validate_docs.py` copied from the gen2 zip into the
    repo tree (was previously available only inside the zip).
    Reports zero undefined refs, zero direct-layer-rule violations,
    English-only CJK check passes. The 35 "old package-style
    filename" hits are pre-existing and identical to the gen2
    baseline (they live in `path-migration-map.md` and config-ID
    headers of governance docs and are intentional per the path
    migration policy).
  * `.gitignore` adds `/gen2/` so the externally-provided review
    package does not enter the repo.

No code changes in this commit; B (the implementation split into
`transmit_active` / `capture_active`, `PttCapabilityLevel`
reporting, `PttSanitizer` diagnostics rule, and the UI capability
badge) follows in a separate commit.
This commit is contained in:
EdisonJwa
2026-05-15 14:51:22 +08:00
parent b932dc1405
commit 02ffadfa52
26 changed files with 991 additions and 20 deletions
@@ -0,0 +1,180 @@
# 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:
1. **`LinuxGnomeWaylandBackend`** — used when `XDG_SESSION_TYPE=wayland` and the desktop environment is GNOME, **and** the `org.freedesktop.portal.GlobalShortcuts` D-Bus interface is reachable. Calls `CreateSession`, `BindShortcuts` (delegates binding capture to the portal's own dialog), and listens for `Activated` / `Deactivated` signals. Reports `L2GlobalHoldToTalk`; mouse-button support follows whatever the portal exposes for the current session.
2. **`FocusedPttBackend`** — fallback on any other Linux environment (X11, sway, KDE, untested compositor, missing portal). Reports `L0Focused`.
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. |
@@ -49,3 +49,18 @@ A PoC is not product code unless explicitly promoted.
| 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. |
+89
View File
@@ -1274,12 +1274,94 @@ Communication evidence is maintained through change history and baseline approva
- Source SRS: SRS-185 through SRS-194
- Verification method: Review, Inspection
**SAD-071**: The software architecture shall isolate desktop PTT into a `DesktopPttBackend` trait owned by the audio subsystem, with the active implementation selected at runtime by a `platform_input::select` factory. Only the factory and the audio engine know which implementation is active; the rest of the application sees only the trait surface and the published capability level.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio, Platform Input
- Source SRS: SRS-195
- Verification method: Architecture Review, Unit Test
**SAD-072**: The Windows PTT backend shall be a three-level ladder (`WindowsRawInputBackend` -> `WindowsHookBackend` -> `FocusedPttBackend`). The ladder is evaluated once at audio-engine start; the chosen rung is fixed for the lifetime of that engine and is reported as the backend identifier.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio (Windows)
- Source SRS: SRS-197
- Verification method: Platform Test (Windows), Architecture Review
**SAD-073**: The macOS PTT backend shall be a two-level ladder (`MacOSEventTapBackend` -> `FocusedPttBackend`) with explicit permission state surfaced through `PttCapabilityLevel`. The permission query shall not block the audio-engine start path; an undecided permission shall resolve to `L0` and may upgrade asynchronously when the user grants the permission.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio (macOS)
- Source SRS: SRS-198
- Verification method: Platform Test (macOS), Architecture Review
**SAD-074**: The Linux PTT backend shall be a two-level ladder (`LinuxGnomeWaylandBackend` using the freedesktop `org.freedesktop.portal.GlobalShortcuts` interface, -> `FocusedPttBackend`). Untested display servers, untested compositors, and missing D-Bus access shall all resolve to `L0`.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio (Linux)
- Source SRS: SRS-199
- Verification method: Platform Test (Linux, GNOME Wayland), Architecture Review
**SAD-075**: The audio engine shall expose `AudioTransmitGate`, a thin object that owns the `transmit_active` AtomicBool and exposes `set` and `load` operations only. The Opus encoder feed shall consult `AudioTransmitGate::load()` once per outbound frame; no other code path may flip `transmit_active`.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio
- Source SRS: SRS-201
- Verification method: Unit Test, Audio Test
**SAD-076**: The bridge shall expose PTT events through the existing `BridgeEvent` stream, adding a `BridgeEvent::PttCapability { level, backend_id }` variant. The bridge shall never carry raw key codes or scan codes across the FFI boundary; the trait surface and the event shape together enforce SRS-202 at the architectural layer.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Bridge, Audio, Diagnostics
- Source SRS: SRS-202
- Verification method: Architecture Review, Privacy Review
**SAD-077**: The diagnostics subsystem shall add a `PttSanitizer` decorator over the `RedactingLogLayer` log sink. The decorator shall scan each record's field set for the well-known names `key_code`, `scan_code`, `virtual_key`, `vk`, `keysym`, `keysym_string`, `key_sequence` and drop the record before it reaches storage.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Diagnostics
- Source SRS: SRS-202
- Verification method: Unit Test, Privacy Review
**SAD-078**: The Flutter UI shall consume `BridgeEvent::PttCapability` and render a small capability badge in the Voice Bar. When the capability resolves to `L0` on a platform that the user reasonably expected to support Global PTT (for example Windows or macOS with the relevant permission undecided), the UI shall render an explanation row pointing to the corresponding fix (run-as-administrator path, permission grant path, environment-not-supported note).
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Flutter UI
- Source SRS: SRS-196, SRS-198
- Verification method: UI Review, User Acceptance Test
**SAD-079**: The audio engine shall own the missed-key-up watchdog as a single tokio task that subscribes to `transmit_active` transitions through a `tokio::sync::watch` channel; on a configured timeout (default 30 s, owner-tunable) without a release event, the task shall clear `transmit_active` and emit a sanitised diagnostic record.
- Status: Baseline Candidate
- Type: Software Architecture Item
- Stage: P0 / MVP
- Allocated to: Audio
- Source SRS: SRS-203
- Verification method: Unit Test, Integration Test
## 27. Updated SRS-to-SAD Coverage Matrix
| SRS Range | SAD Coverage |
|---|---|
| SRS-001 through SRS-184 | Covered by inherited SAD baseline `SAD-001` through `SAD-060` |
| SRS-185 through SRS-194 | Covered by `SAD-061` through `SAD-070` |
| SRS-195 through SRS-203 | Covered by `SAD-071` through `SAD-079` |
## Baseline Candidate 0.9.1 Update
@@ -1294,3 +1376,10 @@ Communication evidence is maintained through change history and baseline approva
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate effective date and preserved layer-specific traceability. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT software-architecture items SAD-071 through SAD-079: backend isolation behind `DesktopPttBackend` trait, Windows three-rung ladder, macOS two-rung permission-aware ladder, Linux GNOME-Wayland portal ladder, `AudioTransmitGate` object, sanitised `BridgeEvent::PttCapability`, `PttSanitizer` log-sink decorator, UI capability badge with platform-specific explanation, missed-key-up watchdog task. Strict layered sourcing preserved (`SAD -> SRS` only). |
+116
View File
@@ -1005,12 +1005,121 @@ The registry supports consistency between architecture, detailed design, impleme
- Source SAD: SAD-069, SAD-070
- Verification method: Privacy Review, Security Audit
**SDD-081**: `DesktopPttBackend` shall be a Rust trait in `chanora_audio::ptt` exposing `fn capability(&self) -> PttCapabilityLevel`, `fn backend_id(&self) -> &'static str`, `fn start(&mut self, gate: Arc<AudioTransmitGate>, binding: PttBinding) -> Result<(), PttError>`, `fn stop(&mut self)`, and `fn rebind(&mut self, binding: PttBinding) -> Result<(), PttError>`. Implementations shall be Send and stop on Drop.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `DesktopPttBackend`
- Source SAD: SAD-071
- Verification method: Unit Test, Inspection
**SDD-082**: `PttCapabilityLevel` shall be a plain Rust enum (`L0Focused`, `L1GlobalShortcut`, `L2GlobalHoldToTalk`, `L3GlobalWithMouseButtons`, `L4DeviceAware`) with a public `as_str(&self) -> &'static str` mapping for diagnostics. `L4DeviceAware` is reserved and shall not be produced by any MVP implementation.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `PttCapabilityLevel`
- Source SAD: SAD-071
- Verification method: Unit Test
**SDD-083**: `WindowsRawInputBackend` shall use the `RegisterRawInputDevices` Win32 API targeting `HID_USAGE_PAGE_GENERIC` keyboard and mouse usages, run a dedicated message-only window on its own OS thread, and forward only sanitised binding-match results to the `AudioTransmitGate`. Raw `RAWINPUT` payloads shall never cross the backend boundary.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `WindowsRawInputBackend`
- Source SAD: SAD-072
- Verification method: Platform Test (Windows), Unit Test
**SDD-084**: `WindowsHookBackend` shall be used only when Raw Input registration fails. It installs `WH_KEYBOARD_LL` and `WH_MOUSE_LL` hooks on its dedicated thread; the hook callbacks compare against the active binding and call `AudioTransmitGate::set` only, never logging key data. The hook is uninstalled on Drop.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `WindowsHookBackend`
- Source SAD: SAD-072
- Verification method: Platform Test (Windows), Unit Test
**SDD-085**: `MacOSEventTapBackend` shall create a `CGEventTap` filtered to keyboard and mouse-button events, attached to the main run loop with an explicit retain. The tap callback shall consult the active binding and call `AudioTransmitGate::set` only. The backend shall expose `permission_state() -> Granted | Denied | Undetermined` via `IOHIDCheckAccess` (or the macOS-version-appropriate equivalent) and shall return `PttCapabilityLevel::L0Focused` when permission is not Granted.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `MacOSEventTapBackend`
- Source SAD: SAD-073
- Verification method: Platform Test (macOS), User Acceptance Test
**SDD-086**: `LinuxGnomeWaylandBackend` shall call `CreateSession`, `BindShortcuts`, and listen for `Activated` / `Deactivated` signals on the freedesktop `org.freedesktop.portal.GlobalShortcuts` D-Bus interface. Binding capture shall use the portal's own configuration dialog; Chanora itself does not read raw key events. Missing D-Bus or missing portal interface resolves to `PttCapabilityLevel::L0Focused`.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `LinuxGnomeWaylandBackend`
- Source SAD: SAD-074
- Verification method: Platform Test (Linux, GNOME Wayland), Unit Test
**SDD-087**: `FocusedPttBackend` shall integrate with Flutter's keyboard / pointer event stream via the existing `Listener` widget path and the bridge `set_ptt` command. Reports `PttCapabilityLevel::L0Focused` and `backend_id = "focused"`.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `FocusedPttBackend`
- Source SAD: SAD-071, SAD-072, SAD-073, SAD-074
- Verification method: Unit Test, UI Review
**SDD-088**: `PttController` shall sit in `chanora_core::ptt` and own a `Box<dyn DesktopPttBackend>`, a clone of `AudioTransmitGate`, a `watch::Sender<PttCapabilityLevel>` for live publication to the bridge, and a `tokio::sync::Mutex` over the active `PttBinding`. Public surface: `set_binding`, `current_capability`, `subscribe_capability`.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `PttController`
- Source SAD: SAD-071, SAD-076
- Verification method: Unit Test, Integration Test
**SDD-089**: `AudioTransmitGate` shall be `Arc<AudioTransmitGate>` wrapping a `tokio::sync::watch::Sender<bool>` and an internal `AtomicBool`. `set(v)` updates both atomically; `load()` reads the atomic; `subscribe()` hands out a `watch::Receiver` for the missed-key-up watchdog task.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `AudioTransmitGate`
- Source SAD: SAD-075
- Verification method: Unit Test
**SDD-090**: `PttSanitizer` shall implement `tracing_subscriber::Layer` and decorate the existing `RedactingLogLayer`. Records whose field names match the SDD-077 banned list shall be dropped before `on_event` reaches the wrapped sink. The implementation shall be allocation-free on the success path (the typical "no banned field" case).
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `PttSanitizer`
- Source SAD: SAD-077
- Verification method: Unit Test, Privacy Review
**SDD-091**: `PttCapabilityBadge` shall be a Flutter widget rendered inside the Voice Bar, subscribed to the FRB stream of `BridgeEvent::PttCapability`. The widget shall map each enum value to a short user-facing label and shall render an info icon that opens a per-platform explanation sheet when the resolved capability is `L0Focused`.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `PttCapabilityBadge`
- Source SAD: SAD-078
- Verification method: UI Review, User Acceptance Test
**SDD-092**: `MissedKeyUpWatchdog` shall be a tokio task spawned by the audio engine that holds the `watch::Receiver<bool>` from `AudioTransmitGate::subscribe()`. On each transition from `false` to `true` the task records the timestamp; on each `true -> false` transition the task clears the timestamp. If the transition timeline shows `true` for longer than the configured timeout the task calls `AudioTransmitGate::set(false)` and emits a sanitised diagnostic record.
- Status: Draft
- Type: Software Detailed Design Item
- Stage: P0 / MVP
- Software unit: `MissedKeyUpWatchdog`
- Source SAD: SAD-079
- Verification method: Unit Test, Integration Test
## 11. Updated SAD-to-SDD Coverage Matrix
| SAD Range | SDD Coverage |
|---|---|
| SAD-001 through SAD-060 | Covered by inherited SDD baseline `SDD-001` through `SDD-070` |
| SAD-061 through SAD-070 | Covered by `SDD-071` through `SDD-080` |
| SAD-071 through SAD-079 | Covered by `SDD-081` through `SDD-092` |
## Baseline Candidate 0.9.1 Update
@@ -1025,3 +1134,10 @@ The registry supports consistency between architecture, detailed design, impleme
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate effective date and preserved layer-specific traceability. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT detailed design SDD-081 through SDD-092: `DesktopPttBackend` trait, `PttCapabilityLevel` enum, Windows Raw-Input + low-level-hook + Focused implementations, macOS event-tap + Focused implementations, Linux GNOME-Wayland portal + Focused implementations, `PttController`, `AudioTransmitGate`, `PttSanitizer` layer, `PttCapabilityBadge` widget, `MissedKeyUpWatchdog` task. Strict sourcing (`SDD -> SAD` only) preserved. |
+93 -1
View File
@@ -2768,14 +2768,99 @@ This SysDes version covers all known SysRS requirements from `SysRS-001` through
- ASPICE SYS.3 alignment: Architecture constraints, communication
- Allocated SysRS: SysRS-295
**SysDes-142**: The desktop Push-to-Talk subsystem shall be allocated to a dedicated **Platform PTT Backend** layer that is selected at runtime per operating system, display server, and granted permission set, with the **Rust Core PTT State Machine** owning the authoritative `transmit_active` flag and the Flutter Voice UI owning the binding-capture UX.
- Status: Baseline Candidate
- Type: Subsystem Allocation
- Stage: P0 / MVP
- Allocated to: Platform Input, Rust Core, Flutter UI, Audio Engine
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: Architecture Review, Platform Test
- Verification owner: Software Architect
- ASPICE SYS.3 alignment: Element decomposition, interface definition
- Allocated SysRS: SysRS-296, SysRS-297
**SysDes-143**: The platform PTT backend layer shall report a typed `PttCapabilityLevel` (`L0` Focused, `L1` Global-shortcut-activation, `L2` Global-hold-to-talk, `L3` Global-with-mouse-buttons, `L4` Device-aware) to the Rust Core, and the Rust Core shall publish the same value to the Flutter UI through the bridge event stream so capability advertising matches actual runtime behaviour.
- Status: Baseline Candidate
- Type: Cross-Subsystem Interface
- Stage: P0 / MVP
- Allocated to: Platform Input, Rust Core, Flutter UI, Bridge
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: Integration Test, Architecture Review
- Verification owner: Software Architect
- ASPICE SYS.3 alignment: Interface definition, consistency
- Allocated SysRS: SysRS-298
**SysDes-144**: The audio capture pipeline shall expose two distinct atomic states: `capture_active` (the input stream is open and frames flow into the encoder feeder) and `transmit_active` (the encoder is producing outbound Opus frames and the protocol layer is forwarding them). The PTT subsystem shall drive `transmit_active` only; `capture_active` shall follow the audio engine lifecycle and the platform input-permission state independently.
- Status: Baseline Candidate
- Type: Subsystem Interface
- Stage: P0 / MVP
- Allocated to: Audio Engine, Rust Core
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: Audio Test, Integration Test
- Verification owner: Audio Owner + Software Architect
- ASPICE SYS.3 alignment: Element behaviour, interface definition
- Allocated SysRS: SysRS-296
**SysDes-145**: The Windows desktop backend shall be allocated to a Raw-Input-first implementation with a low-level-hook fallback and a Focused-PTT terminal fallback. The macOS desktop backend shall be allocated to a permission-aware Global PTT implementation with a Focused-PTT terminal fallback. The Linux desktop backend shall be allocated to a GNOME-on-Wayland portal-based implementation (the officially-tested compositor) with a Focused-PTT terminal fallback on every other Linux environment.
- Status: Baseline Candidate
- Type: Platform Allocation
- Stage: P0 / MVP
- Allocated to: Platform Input
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: Platform Test (Win/macOS/Linux), Architecture Review
- Verification owner: Software Architect + Platform Owners
- ASPICE SYS.3 alignment: Element decomposition, platform mapping
- Allocated SysRS: SysRS-299, SysRS-300, SysRS-301
**SysDes-146**: A **diagnostics sanitizer** shall sit between the platform PTT backend and the application log sink. The sanitizer shall reject any record carrying raw key codes, scan codes, virtual-key values, or key-press timing sequences before the record reaches the in-memory log sink, the platform sink (logcat / fmt / etc.), or the user-initiated diagnostic export pipeline.
- Status: Baseline Candidate
- Type: Cross-Cutting Constraint
- Stage: P0 / MVP
- Allocated to: Diagnostics, Platform Input
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: Privacy Review, Diagnostic Inspection, Unit Test
- Verification owner: Security / Privacy Reviewer
- ASPICE SYS.3 alignment: Architecture constraints, safety / security
- Allocated SysRS: SysRS-302
**SysDes-147**: The Flutter Voice UI shall surface the active PTT capability level and the active backend identifier as user-facing status (capability badge, fallback notice) so the user understands when a Global PTT binding cannot be honoured and a Focused-PTT fallback is in effect.
- Status: Baseline Candidate
- Type: User-Facing Behaviour Allocation
- Stage: P0 / MVP
- Allocated to: Flutter UI
- Downstream artifact: SRS, SAD, SDD, Verification
- Verification method: User Acceptance Test, UI Review
- Verification owner: UX Owner
- ASPICE SYS.3 alignment: Element behaviour
- Allocated SysRS: SysRS-298
**SysDes-148**: The release verification record shall carry per-platform PTT capability evidence (detected `PttCapabilityLevel`, active backend identifier, fallback exercised yes/no) before any release artefact may claim Global PTT support. Release notes shall mirror the actual capability per platform and shall not over-claim.
- Status: Baseline Candidate
- Type: Release Constraint
- Stage: P0 / MVP
- Allocated to: Release / Operations, Verification
- Downstream artifact: Release Readiness Record, Verification
- Verification method: Release Inspection, Architecture Review
- Verification owner: Release Manager
- ASPICE SYS.3 alignment: Architecture constraints
- Allocated SysRS: SysRS-298
## 17. Updated SysRS Coverage Statement
This SysDes version covers all known SysRS requirements from `SysRS-001` through `SysRS-295`.
This SysDes version covers all known SysRS requirements from `SysRS-001` through `SysRS-302`.
| SysRS Range | SysDes Coverage |
|---|---|
| SysRS-001 through SysRS-285 | Covered by inherited SysDes baseline `SysDes-001` through `SysDes-132` |
| SysRS-286 through SysRS-295 | Covered by `SysDes-133` through `SysDes-141` |
| SysRS-296 through SysRS-302 | Covered by `SysDes-142` through `SysDes-148` |
## Baseline Candidate 0.9.1 Update
@@ -2790,3 +2875,10 @@ This SysDes version covers all known SysRS requirements from `SysRS-001` through
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate effective date and separated release build SDK compliance from iOS runtime deployment target. |
## Baseline Candidate 0.9.3 Update
| Version | Date | Description |
|---|---|---|
| 0.9.3 | 2026-05-15 | Added desktop PTT subsystem allocation SysDes-142 through SysDes-148: Platform PTT Backend layer, typed `PttCapabilityLevel` cross-interface, audio-pipeline split into `capture_active` and `transmit_active`, per-OS backend allocation (Windows Raw-Input ladder, macOS permission-aware, Linux GNOME-Wayland portal), diagnostics sanitizer for raw key events, UI capability badge, release-record evidence requirement. |