feat(voice): harden Android audio and channel joins
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
**Document type:** SAD / Software Architecture Description
|
||||
**Process alignment:** ASPICE SWE.2 Software Architectural Design
|
||||
**Version:** 0.9.8
|
||||
**Version:** 0.9.11
|
||||
**Status:** Baseline Candidate
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
@@ -1478,15 +1478,77 @@ A single SRS item may be intentionally allocated to more than one SAD item when
|
||||
|
||||
Pinned at SAD layer to remove a downstream ambiguity that would otherwise surface as an open question in the SAD-090 SDD unit: the 🟡 "within tolerance but trending" marker (SRS-218 clause 3, third element of the marker set) shall be defined as follows: a metric is rendered 🟡 if and only if (a) the metric is within the SRS-219 per-metric tolerance window relative to the merge-base baseline (i.e. it is not 🔴), AND (b) the absolute delta between the PR's current measurement and the **previous run of the SAD-090 workflow on the default branch** (i.e. the most recent default-branch CI bench result, not the baseline JSON itself) is greater than 50% of the SRS-219 tolerance window for that metric. Metrics whose SRS-219 tolerance is exactly zero (the heap-allocation-count metric, SRS-219 clause a) cannot be 🟡 because the 50% trigger is undefined when the window has zero width; for those metrics only 🟢 (zero allocations) and 🔴 (any non-zero allocation count) apply. Rationale for pinning at SAD rather than deferring to SDD: the question "is yellow relative to baseline or relative to previous-run-on-default" is an architectural choice about what state the workflow consumes (baseline JSON only, vs baseline JSON + a previous-runs cache), not an implementation detail; pinning it here fixes the workflow's required inputs at the architecture layer so SDD has a fully determined input set. Operationally, the "previous-run-on-default" datum may be sourced from the SAD-091 baseline (treating the committed baseline as the latest default-branch run, which is the simpler and recommended SDD realization) or from a separate run-history artifact; SDD selects which.
|
||||
|
||||
## 27. Updated SRS-to-SAD Coverage Matrix
|
||||
## 27. Channel Join Pending-State Architecture
|
||||
|
||||
**SAD-092**: The software architecture shall assign authoritative current-channel membership ownership to Rust Core and the State Synchronization Engine. The authoritative current channel is the last channel membership state confirmed by Rust Core from the protocol path or from a reconciled server snapshot. Flutter state, Flutter feature screens, and bridge DTO consumers shall treat that value as read-only render state and shall not create, overwrite, or finalize authoritative membership locally.
|
||||
|
||||
- Status: Baseline Candidate
|
||||
- Type: Software Architecture Item
|
||||
- Stage: P0 / MVP
|
||||
- Allocated to: Rust Core, State Sync
|
||||
- Source SRS: SRS-023, SRS-054, SRS-056, SRS-057, SRS-058
|
||||
- Related SysDes: SysDes-069
|
||||
- Verification method: Architecture Review, Integration Test, System Test
|
||||
|
||||
**SAD-093**: The software architecture shall model a channel-join request as user intent crossing the bridge, not as an immediate local membership mutation. Flutter may expose the requested target channel as a non-authoritative pending target for visual feedback while continuing to render the authoritative current channel from SAD-092 until Rust Core/protocol confirmation changes that authoritative state. The bridge shall provide command and event contracts that distinguish join intent, pending target visibility, confirmed membership, and user-safe failure reporting; the bridge and Flutter layers shall not directly mutate authoritative channel membership.
|
||||
|
||||
- Status: Baseline Candidate
|
||||
- Type: Software Architecture Item
|
||||
- Stage: P0 / MVP
|
||||
- Allocated to: Flutter UI, Flutter State, Bridge Facade, Rust Core
|
||||
- Source SRS: SRS-023, SRS-049, SRS-054
|
||||
- Related SysDes: SysDes-069
|
||||
- Verification method: UI Test, Integration Test, System Test
|
||||
|
||||
**SAD-094**: The software architecture shall preserve the previous authoritative current channel on channel-join failure or timeout and shall clear the non-authoritative pending target through Rust Core / State Sync events. Join denial, network/protocol error, timeout, and cancellation-like outcomes shall be surfaced as user-safe errors without reclassifying the pending target as the current channel. Diagnostics shall record the join lifecycle at sanitized event level, including request, confirmation, failure, timeout, stale outcome, and reconciliation decisions, without leaking secrets or raw protocol payloads.
|
||||
|
||||
- Status: Baseline Candidate
|
||||
- Type: Software Architecture Item
|
||||
- Stage: P0 / MVP
|
||||
- Allocated to: Rust Core, State Sync, Protocol Adapter, Bridge Facade, Diagnostics, Flutter State
|
||||
- Source SRS: SRS-023, SRS-048, SRS-049, SRS-054, SRS-056, SRS-057, SRS-058
|
||||
- Related SysDes: SysDes-069
|
||||
- Verification method: Integration Test, System Test, Diagnostics Review
|
||||
|
||||
**SAD-095**: The downstream SDD shall define deterministic State Sync handling for channel-join edge cases while preserving the SAD-092 authoritative ownership boundary. Required SDD coverage includes duplicate join requests, a different target requested while a join is pending, leave/switch races, stale acknowledgements or failures for superseded requests, reconnect and fresh-snapshot reconciliation, and per-connection ordering boundaries. The architecture requires a single deterministic reducer/state-machine ownership point for those cases in Rust Core / State Sync; Flutter may render only the resulting authoritative and pending-view states.
|
||||
|
||||
- Status: Baseline Candidate
|
||||
- Type: Software Architecture Item
|
||||
- Stage: P0 / MVP
|
||||
- Allocated to: State Sync, Rust Core, Protocol Adapter, Bridge Facade, Flutter State, Verification Support
|
||||
- Source SRS: SRS-023, SRS-049, SRS-054, SRS-056, SRS-057, SRS-058
|
||||
- Related SysDes: SysDes-069
|
||||
- Verification method: Architecture Review, SDD Inspection, Unit Test, Integration Test, System Test
|
||||
|
||||
**SAD-096**: The software architecture shall expose an explicit Protocol Adapter command seam for leaving the current voice channel / moving the current client out of channel membership; downstream design may name the seam `leave_channel`, `move_out_of_channel`, or an equivalent verb, but it shall not require Rust Core, Bridge, Flutter, or the State Sync reducer to invent a synthetic channel id or rely on implicit `move_to_channel` behavior to realize `voice_leave()`. Rust Core shall invoke this Protocol Adapter seam only as a side effect of the State Sync reducer returning a leave action, and the Protocol Adapter shall report command lifecycle separately from authoritative membership. Authoritative current-channel membership remains owned by Rust Core / State Sync under SAD-092: a successful leave/move-out command acknowledgement is command acceptance/completion evidence only, while the membership value changes to `None` or to a server-provided replacement channel only after a live protocol self-move/client-leave delta or a reconciled snapshot confirms that state. Protocol errors, denials, timeouts, and stale outcomes shall be returned to Rust Core as user-safe error categories and sanitized diagnostics; raw protocol payloads, passwords, server addresses, and unredacted external strings shall not cross into logs or Flutter DTOs.
|
||||
|
||||
- Status: Baseline Candidate
|
||||
- Type: Software Architecture Item
|
||||
- Stage: P0 / MVP
|
||||
- Allocated to: Rust Core, State Sync, Protocol Adapter, Bridge Facade, Diagnostics, Verification Support
|
||||
- Source SRS: SRS-021, SRS-023, SRS-038, SRS-054, SRS-056, SRS-057, SRS-058, SRS-204
|
||||
- Related SysDes: SysDes-069
|
||||
- Verification method: Architecture Review, Integration Test, System Test, Diagnostics Review
|
||||
|
||||
### SWE.5 verification implications
|
||||
|
||||
SWE.5 verification shall include evidence that channel-join pending-state behavior remains server-authoritative end to end: Flutter sends intent only, authoritative current-channel state changes only after Rust Core/protocol confirmation or snapshot reconciliation, failure/timeout keeps the prior current channel, and edge-case sequences named in SAD-095 are deterministic. Tests shall cover both UI-visible pending feedback and Rust Core / State Sync reducer behavior through bridge-level integration seams. SWE.5 shall also verify the SAD-096 leave/move-out seam end to end: `voice_leave()` / `leave_channel()` intent reduces to a single Protocol Adapter leave/move-out command side effect, no synthetic target channel id is generated by upper layers, command success alone does not clear authoritative membership, and live-delta/snapshot confirmation is required before the projection reports `current_channel = None` or a server-provided replacement.
|
||||
|
||||
## 28. 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-021 (client join/leave/move events reflected in channel display) | Covered specifically for current-channel leave/move-out confirmation by `SAD-096` |
|
||||
| SRS-023 (channel join confirmation before authoritative UI state) | Covered specifically by `SAD-092` through `SAD-096` |
|
||||
| SRS-038 (Rust Core bridge command suite) | Covered specifically for voice/channel leave command routing by `SAD-096` |
|
||||
| SRS-049 (Protocol Adapter channel join success/failure reporting) | Covered specifically by `SAD-093` through `SAD-095` |
|
||||
| SRS-054 (State Sync connection state model) | Covered specifically for current-channel membership by `SAD-092` through `SAD-096` |
|
||||
| SRS-056, SRS-057, SRS-058 (deterministic deltas, ordering, reducers) | Covered specifically for pending-join and leave/move-out edge cases by `SAD-092`, `SAD-094`, `SAD-095`, and `SAD-096` |
|
||||
| SRS-185 through SRS-194 | Covered by `SAD-061` through `SAD-070` |
|
||||
| SRS-195 through SRS-199, SRS-201 through SRS-203 | Covered by `SAD-071` through `SAD-079` |
|
||||
| SRS-200 | Covered by `SAD-080` |
|
||||
| SRS-204 through SRS-207 | Covered by `SAD-081` through `SAD-083` |
|
||||
| SRS-204 through SRS-207 | Covered by `SAD-081` through `SAD-083`; the protocol leave/move-out realization required by `voice_leave()` is covered by `SAD-096` |
|
||||
| SRS-208 | Covered by `SAD-084` |
|
||||
| SRS-209 | Covered by `SAD-085` |
|
||||
| SRS-111 (Android foreground voice service) | Covered by `SAD-086` (Android-specific allocation; SAD-036 retains the cross-cutting diagnostics allocation for the SRS-111–124 range per §24.1 dual-allocation pattern) |
|
||||
@@ -1539,6 +1601,20 @@ Pinned at SAD layer to remove a downstream ambiguity that would otherwise surfac
|
||||
| 0.9.6 | 2026-05-17 | Propagated reconciled P0 Android SRS updates into SAD. SAD-063 text extended in place (ID preserved) to record the API 28 minimum runtime baseline per DEC-004 (Accepted 2026-05-14, superseding the earlier API 24 recommendation), while keeping the existing SRS-187 / SRS-188 trace. Added SAD-084 (Android in-call audio mode controller in the platform audio adapter, bound to the voice-session lifecycle, sourced from SRS-208). Added SAD-085 (Android `RECORD_AUDIO` runtime permission flow on the existing Android permission adapter, naming listen-only — `capture_active = false` with output stream open per SAD-081 — as a first-class operating mode at the architecture layer, sourced from SRS-209). Added SAD-086 (`AndroidVoiceForegroundService` allocation for SRS-111, bound to `voice_join` / `voice_leave` lifecycle rather than UI lifecycle, coordinating with SAD-084 and SAD-085). SAD-018 (Android back intent, SRS-163) and the existing Android AAB allocation in §9 / SAD-037 (SRS-119) were re-read and left unchanged because they remain coherent with the reconciled SRS. Strict layered sourcing preserved (`SAD -> SRS` only). |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.10 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.10 | 2026-05-18 | Added dedicated channel-join pending-state architecture items SAD-092 through SAD-095. The new items assign authoritative current-channel membership to Rust Core / State Sync, constrain Flutter to user intent plus non-authoritative pending-target rendering, preserve the prior authoritative channel on failure or timeout, require sanitized diagnostics for join lifecycle outcomes, and push deterministic duplicate/different-target/leave-race/stale-ack/reconnect-reconciliation handling into SDD under the Rust Core / State Sync ownership boundary. Added specific §28 coverage rows for SRS-023, SRS-049, SRS-054, and SRS-056 through SRS-058, with SysDes-069 recorded as a related upstream design anchor while retaining SRS as the direct SAD source. |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.11 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.11 | 2026-05-19 | Added SAD-096 to close the protocol leave/move-out architecture seam blocking SDD-121 implementation. The Protocol Adapter must expose an explicit leave/move-out command seam for `voice_leave()` / `leave_channel()` side effects; upper layers must not synthesize channel ids or rely on implicit `move_to_channel` behavior. Command acknowledgement remains separate from authoritative membership: Rust Core / State Sync clear or replace `current_channel` only from authoritative live deltas or reconciled snapshots. SWE.5 implications and §28 SRS coverage rows were updated for SRS-021, SRS-023, SRS-038, SRS-054, SRS-056 through SRS-058, and SRS-204. Strict layered sourcing preserved (`SAD -> SRS` only). |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.7 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|
||||
Reference in New Issue
Block a user