# Chanora Software Detailed Design

**Lifecycle:** SWE.3 Software Detailed Design and Unit Construction Handoff  
**Document status:** DV meeting baseline candidate  
**Date:** 2026-05-29  
**Direct upstream source:** `docs/architecture/sad.md`  
**Related software requirements:** `docs/srs.md`

## 1. Purpose

This Software Detailed Design defines the module-level design details needed for SWE.4 unit verification and SWE.5 integration verification. It is based on the current repository layout and the SWE.2 architecture baseline.

## 2. Module Catalogue

| SDD module | Source location | Primary responsibility | Upstream SAD component |
|---|---|---|---|
| SDD-MOD-001 Flutter app bootstrap | `apps/chanora_flutter/lib/services/app_bootstrap.dart`, `main.dart` | Initialize Rust bridge, localization, app services, theme/design baseline | Flutter app shell |
| SDD-MOD-002 Connect UI | `apps/chanora_flutter/lib/widgets/connect_widgets.dart` | Host/bookmark inputs, connect actions, pre-request UX | Flutter widget layer |
| SDD-MOD-003 Snapshot and channel UI | `snapshot_view.dart`, `snapshot_state_mapper.dart`, `channel_spacer.dart` | Present channel tree, clients, and mapped state | Flutter widget/service layer |
| SDD-MOD-004 Chat UI | `chat_views.dart`, `bbcode_text.dart` | Channel text rendering and BBCode-safe display | Flutter widget layer |
| SDD-MOD-005 Voice UI | `voice_bar.dart`, `voice_compact.dart`, `voice_settings*.dart`, `voice_level_meter.dart`, `ptt_capability_badge.dart` | Voice controls, processing settings, metering, PTT capability | Flutter widget layer |
| SDD-MOD-006 Platform services | `android_permissions_service.dart`, `ios_permissions_service.dart`, `audio_lifecycle_service.dart`, `back_intent_*`, `link_trust_service.dart` | Permission, lifecycle, navigation, route/link trust behavior | Flutter service layer |
| SDD-MOD-007 Bridge API | `crates/chanora_bridge/src/api.rs`, generated Dart/Rust bridge files | Typed command/event boundary | Bridge layer |
| SDD-MOD-008 Rust core supervisor | `core/chanora_core/src/lib.rs`, `ptt.rs` | Connection orchestration, reconnect, PTT state, storage coordination | Rust core |
| SDD-MOD-009 Protocol adapter | `crates/chanora_protocol/src/` | `tsclientlib` isolation, DTO/error mapping | Protocol adapter |
| SDD-MOD-010 State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` | Snapshot/delta model, reducer, channel join support | State sync |
| SDD-MOD-011 Audio subsystem | `crates/chanora_audio/src/` | Audio capture/playback, DSP, Opus, PTT, mode stack, platform units | Audio subsystem |
| SDD-MOD-012 Storage | `crates/chanora_storage/src/lib.rs` | Bookmarks, identity storage, encrypted local records, keyring abstraction | Storage |
| SDD-MOD-013 Diagnostics | `crates/chanora_diagnostics/src/lib.rs` | Redaction, log sink, known-secret registry, export bundle | Diagnostics |
| SDD-MOD-014 Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` | SRV/TSDNS/DNS fallback and generation-safe resolution warming | Server resolver / prefetch |
| SDD-MOD-015 Build and release hooks | `.github/workflows/`, `tools/`, platform project files | CI, unsigned iOS build, benchmark advisory, platform smoke procedures | Release / platform architecture |

## 3. Bridge Boundary Design

The bridge boundary is the only supported Flutter-to-Rust command path. Dart code uses generated APIs under `apps/chanora_flutter/lib/src/rust/`; Rust exposes bridge functions through `crates/chanora_bridge/src/api.rs`.

Design rules:

| Rule | Detail |
|---|---|
| DTO stability | DTO fields must be explicit and serializable through Flutter Rust Bridge generation |
| Error safety | Rust errors exposed to Flutter must be user-safe or mapped before display |
| Secret handling | Secrets may cross only as command inputs or protected DTO fields and must be registered for diagnostic redaction where relevant |
| Capability reporting | Platform and PTT capability fields must reflect actual active backend state |
| Regeneration control | Generated bridge files are implementation artifacts and must be regenerated when bridge API signatures change |

## 4. Connection and State Design

| Detail | Design |
|---|---|
| Connection lifecycle | Rust core owns connect/disconnect/reconnect decisions and suppresses reconnect after user disconnect |
| Backoff | Reconnect uses exponential backoff as described in implementation status, capped at 60 seconds |
| Server resolution | Resolver performs SRV/TSDNS/DNS fallback; prefetch cache may warm but must not be required for connect success |
| Snapshot mapping | Rust state and bridge DTOs are mapped into Flutter view models by `snapshot_state_mapper.dart` |
| Channel join | Channel join logic and errors are represented through Rust state/protocol handling and Flutter error mapper service |
| Reducers | `chanora_state` owns snapshot/delta reducer design with unit coverage for snapshot, delta, reconnect, duplicate normalization, disconnected/lost suppression, unknown-client voice activity, deterministic ordering, and channel-delete/client cleanup. Current runtime UI refresh still flows through `chanora_core` snapshot/probe paths; full live-event folding through `chanora_state::reduce` is an integration follow-up. |

## 5. Audio Detailed Design

| Audio element | Design detail |
|---|---|
| Capture/playback | Platform-specific units handle Android, iOS, desktop/fallback paths behind Rust audio abstractions |
| Codec | Opus encode/decode lives in `opus_voice.rs` and associated audio modules |
| DSP chain | High-pass filter, noise suppression, echo cancellation, and AGC are represented by audio processing modules/backends |
| Transmit control | `TransmitMode` supports `Ptt`, `Continuous`, and reserved `VoiceActivity`; `VoiceActivity` has no active MVP implementation |
| VoiceActivity gate (capture-side) | `voice_activity::VoiceActivityStateMachine` is the 10 ms-cadence gate for `TransmitMode::VoiceActivity`; open-after 40 ms (debounce), hangover 500 ms (anti-chatter), min-tx 200 ms (anti-flicker), weak-hold 30-100 frames (anti-stale-VAD); live `configure()` re-clamps existing timers on settings change without resetting state; 9 unit tests cover the main paths |
| PTT | Desktop/mobile backends expose capability level and active backend; missed-key-up watchdog prevents stuck transmit |
| Release tail | Tail handling prevents abrupt cutoffs after PTT release where configured |
| Render peak limiter | `voice_render::limit_peak_inplace` is a single-pass, allocation-free per-frame peak scaler applied in both the macOS and iOS render callbacks before the i16 downmix; default threshold 0.99 prevents hard clipping on multi-client mixes that sum past 0 dBFS while remaining transparent for normal voice levels (allocation-free, lock-free, safe on the realtime audio thread) |
| macOS render cadence (producer + ring) | `ios_voice_unit.rs:851-961` runs a 20 ms tokio producer task that calls `AudioHandler::fill_buffer(1920)` and `force_push`es each sample into a `crossbeam ArrayQueue<f32>` (SPSC-effective, MPMC-but-wait-free-per-end); ring capacity 12000 samples ≈ 6.25× pull quantum; 100 ms prebuffer (`PREBUFFER_SAMPLES = 9600` stereo f32) before the VPIO render callback starts draining, matching Mumble's playout margin and WebRTC's kStartDelayMs order of magnitude |
| iOS render cadence (direct-fill) | `ios_voice_unit.rs:968-1034` does `AudioHandler::fill_buffer` directly in the VPIO render callback (VPIO on iOS requests 480-frame ≈ 10 ms slices that align with tsclientlib's 20 ms Opus frame); scratch buffer preallocated to 4096×2 f32 at setup time so the realtime callback never `resize()`s; `try_lock` (not `lock`) on the AudioHandler mutex so contention never stalls the realtime IO thread; on `WouldBlock` the callback emits silence and increments `callback_xrun` |
| VPIO ducking config (macOS 14+) | `ios_voice_unit.rs` writes an 8-byte `AuVoiceIoOtherAudioDuckingConfiguration` struct (`m_enable_advanced_ducking = 0` disables dynamic voice-activity-driven ducking; `m_ducking_level = kAUVoiceIOOtherAudioDuckingLevelMin = 10`) to selector `kAUVoiceIOProperty_OtherAudioDuckingConfiguration` (= 2108) on the VoiceProcessingIO AudioUnit at startup, minimising the ducking of other apps' audio during a voice session; on macOS 13 the property is silently ignored (VPIO returns the default ducking behaviour) and the code logs a debug message and continues |
| Benchmarks | Realtime capture, Opus, and resampler benchmarks provide advisory baseline evidence |

## 6. Storage and Secret Design

| Storage item | Design detail |
|---|---|
| Bookmarks | Stored locally through the storage crate and surfaced in Flutter connect UI |
| Identity references | Stored through `IdentityFileStore` and platform secure storage where available |
| Passwords/secrets | Encrypted at rest using the current storage design; Android Keystore-backed DEK is deferred and must be disclosed |
| CI keyring behavior | CI disables real keyring access with `CHANORA_DISABLE_KEYRING=1` to avoid headless blocking |
| Fallback behavior | Platform fallback modes must be represented as limitations in release/security evidence |

## 7. Diagnostics Detailed Design

| Diagnostic element | Design detail |
|---|---|
| Log sink | Runtime logs can be captured by diagnostic sinks for export |
| Known-secret registry | Runtime secrets are registered for redaction where applicable |
| Redactor | Redacts configured sensitive patterns before export |
| Export bundle | Diagnostic export is JSON-based and user-initiated |
| Upload policy | MVP has no automatic diagnostic, telemetry, or crash upload |

## 8. Flutter UI Detailed Design

| UI area | Design detail |
|---|---|
| Design tokens | `chanora_tokens.dart` centralizes product styling over Material 3 |
| Platform capability display | `platform_capabilities.dart` and PTT capability widgets expose platform-specific support honestly |
| Localization | Generated localization files provide English and Simplified Chinese resources |
| Responsive behavior | Current widgets support compact/mobile-oriented layouts; expanded side-pane hardening remains P1/P2 as recorded |
| Accessibility | Critical status should use text/icons/semantics and not color alone; verification remains through UI tests/audit |
| UI settings persistence | `UiPreferencesService` persists host, nickname, permission explanation state, and theme mode through `shared_preferences`; invalid stored theme values fall back to system theme |

## 9. Build and Release Detailed Design

| Build/release item | Design detail |
|---|---|
| Rust CI | `.github/workflows/ci.yml` runs cargo check/test and advisory clippy |
| Flutter CI | `.github/workflows/ci.yml` runs Flutter pub get, analyze, and tests |
| Supply chain | CI runs cargo-deny and license inventory checks |
| iOS unsigned build | CI runs `flutter build ios --release --no-codesign` |
| Audio benchmarks | `bench-advisory.yml` runs audio benchmarks and posts advisory evidence |
| Platform packages | Public binary packaging/signing/notarization remains release-gated |

## 10. Verification Hook Design

| Module | SWE.4 unit hooks | SWE.5/SWE.6 integration hooks |
|---|---|---|
| Flutter services/widgets | Dart unit/widget tests under `apps/chanora_flutter/test/` | Widget/system demos and candidate device smoke |
| Bridge | API compile/generation checks | Flutter-to-Rust command/event smoke |
| Rust core | Cargo tests | Compatible-server lifecycle demo |
| Protocol | DTO/error mapping tests | Protocol compatibility matrix and server demo |
| State sync | Reducer tests | Snapshot/delta/reconnect integration evidence |
| Audio | DSP/codec/PTT tests and benchmarks | Platform audio loopback/device demo |
| Storage | Repository/encryption/keyring-disabled tests | Platform secure-storage audit |
| Diagnostics | Redaction/export tests | User-initiated export inspection |
| Release hooks | CI workflow validation | Release readiness record and artifact evidence |

## 11. Traceability to SAD

| SAD component | SDD modules |
|---|---|
| Flutter app shell | SDD-MOD-001 |
| Flutter service layer | SDD-MOD-006, SDD-MOD-014 |
| Flutter widget layer | SDD-MOD-002 through SDD-MOD-005 |
| Bridge layer | SDD-MOD-007 |
| Rust core | SDD-MOD-008 |
| Protocol adapter | SDD-MOD-009 |
| State sync | SDD-MOD-010 |
| Audio subsystem | SDD-MOD-011 |
| Storage | SDD-MOD-012 |
| Diagnostics | SDD-MOD-013 |
| Server resolver/prefetch | SDD-MOD-014 |
| Release/platform architecture | SDD-MOD-015 |

## 12. Open Detailed-Design Risks

| Risk | Impact | Control |
|---|---|---|
| Detailed item IDs from historical SDD references are not reconstructed | Existing references such as `SDD-109` are not itemized in this baseline | Treat this as a DV baseline SDD and add strict item numbering later if required |
| Some module designs are summarized rather than API-by-API | May be insufficient for final process audit | Use this as DV baseline; deepen high-risk modules before final release gate |
| Android Keystore-backed DEK is not implemented | Limits storage/security design claims | Controlled by waiver and release-readiness records |
| Full event replay tooling and live reducer integration evidence are absent | Limits state verification design beyond reducer unit behavior | Controlled as P1 gap and runtime-integration follow-up |

## 13. DV Conclusion

This SWE.3 baseline is sufficient to remove the missing-SDD traceability gap for DV review and to feed SWE.4/SWE.5 verification plans. It does not close release evidence gaps or replace source-level tests.
