Add validate_nickname() to ProtocolClient::connect() and bridge connect(). Trim whitespace, reject empty, truncate to 30 chars. Re-export validate_nickname from protocol and core.
chanora_core
Top-level Rust API and orchestration layer for the Chanora client. Composes subsystem crates behind a stable, typed API consumed by chanora_bridge. Owns no protocol, audio, or storage logic directly.
Architecture
Per SAD §7.2, chanora_core is the integration point:
ChanoraSession— the primary public type. Owns at most one active server connection (DEC-006). Provides connect, disconnect, snapshot, audio lifecycle, PTT, bookmarks, and diagnostics methods.- Supervisor — a per-connection tokio task that monitors connection health via a loss notifier and a watchdog probe, and auto-reconnects with exponential backoff (1 s → 60 s capped). Re-attaches the audio engine if it was running prior to the loss.
SessionEvent— broadcast enum emitted on connect/lost/reconnecting/disconnected/audio-started/audio-stopped/voice-state/chat/route changes. Subscribers consume viasubscribe_events().- File transfer — avatar/icon download routed through a cacache-backed blob cache with LRU eviction.
- Channel join state machine — reducer-based state tracking for voice channel joins, with optimistic commands, snapshot reconciliation, and error projection.
- PTT controller — platform input backend management, binding persistence, and release-tail timer wiring (SDD-088/094/096).
Public API Summary
Core types
| Type | Role |
|---|---|
ChanoraSession |
Top-level session handle; cloneable, thread-safe |
CoreError |
Unified error enum covering all subsystem errors |
SessionEvent |
Broadcast lifecycle event enum |
ConnectConfig |
Typed connection parameters |
NetworkState |
OS connectivity state enum |
Key methods on ChanoraSession
new()— construct an empty session (no I/O)init_storage(dir)— wire identity + bookmark storesinit_cache(dir)— wire the blob cache for avatars/iconsconnect(cfg)→ServerSnapshot— dial a server (single-connection invariant)disconnect()— clean teardown including supervisoris_connected()— check connection statesnapshot()→ServerSnapshot— refresh server stateclient_profile(client_id)— rich profile for one clientvoice_join(channel_id, password)/voice_leave()— audio lifecyclestart_audio(cfg)— initialize audio subsystemset_input_device(id)/set_output_device(id)— device selectionset_output_gain(gain)/set_client_volume(client_id, volume)— volume controlset_transmit_mode(mode)/get_transmit_mode()— transmit modeset_hard_mute(muted)— hard-mute clampset_release_tail_ms(ms)/get_release_tail_ms()— release-tail configset_ptt(active)/set_ptt_binding(binding)/ptt_descriptor()— PTT controlsend_text_message(message, target)— chatmove_to_channel(id, password)/set_self_muted(input, output)— channel + mutesubscribe_events()— broadcast receiver forSessionEventdrain_protocol_events()/protocol_events_snapshot()— protocol event accessexport_diagnostics()— redacted diagnostic bundle (includes network stats)audio_stats()— audio subsystem telemetrynetwork_diagnostics_summary()— network statisticsprefetch_server(host)— warm server-address resolutionset_audio_processing_config(cfg)/get_audio_processing_config()— audio DSP configset_audio_debug_wav_dump(enabled)— WAV dump toggleset_vad_model_path(path)— Silero model pathtransmit_selector()/release_tail_timer()— subsystem accessors
Re-exports
Re-exports selected types from chanora_protocol, chanora_audio, chanora_storage, and chanora_diagnostics so the bridge only depends on chanora_core.
Platform notes
- iOS/macOS-specific methods (
ios_handle_route_change,ios_handle_interruption_began, etc.) are gated behindcfg(target_os = "ios" | "macos")inside method bodies. - Android-specific reconnect paths are similarly gated.
- The crate itself compiles on all targets; platform-specific code is runtime- or cfg-gated.
Invariants
- Single active connection at runtime (DEC-006)
tsclientlibtypes never cross out ofchanora_protocol(SAD-067)- Secret material never lands in non-secret storage (DEC-013.2)
- Audio engine construction failure preserves the previous engine state