docs(architecture): land Android client + cross-repo Bluetooth plan#30
Merged
Conversation
Captures the design for burble's first native Android client and the cross-repo integration with sibling repo `neurophone` as a Bluetooth presence sensor. Decisions baked in: - Two-repo layout (burble owns voice + protocol, neurophone owns presence sensor only — no mic, no voice). - minSdk 35 (Android 15, required for Channel Sounding API surface). - libwebrtc via io.getstream:stream-webrtc-android. - Zig DSP is the audio engine; WebRTC APM disabled. Intent baked structurally: BurbleAudioDspSoftFallback is named-and-shamed and removal-tracked, type-level distinction in AudioPipeline.idr, Avow attestation logs dsp mode per session, READINESS exit gate requires >=95% native-path adoption. - BLE-SPA is THE design — no legacy continuous-advertise mode ships. - MAP 1.4 + AVRCP 1.6 + LEA MCP/MCS/TMAP via MediaSession + MessagingStyle + MediaBrowserService. - Full audio offload (HAL V2) — never pull LC3 into the app. - Smoke-test device: Oppo Reno 13 only; Phase 5 Channel Sounding gracefully no-ops on hardware without BT 6.0 CS. Phase 0 is mergeable as a single follow-up PR (a2ml manifests + Idris2 types + .affine signatures + stub bridges/neurophone.ex). This commit is documentation only. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Companion ADR for the Bolt QUIC transport branch landed in 54af9a6. Captures the why behind the shape: - dual-bind UDP + QUIC on the same port (7373) rather than splitting ports, so firewalls/NAPTR records do not need updating - helper module `Burble.Bolt.Quic` rather than inlining into `Burble.Transport.QUIC` (Bolt needs a strict subset — datagrams only, no streams, no per-room state) - sender default stays UDP so cold pokes do not pay a TLS handshake; QUIC is opt-in via `:transport`/`:try_quic`/`send_quic` - broadcast targets refuse QUIC explicitly with `:quic_broadcast_unsupported` rather than silently downgrading - cert kept out of code (`scripts/gen-bolt-cert.sh`) because writing into `priv/` from a release is a footgun and operators replacing the self-signed cert with a trust-rooted one should be deliberate - 800 ms client handshake budget keeps `try_quic: true` auto-fallback responsive - ALPN `"burble-bolt-v1"` distinct from voice (`"burble-voice-v1"`) so the two QUIC listeners can share a host without collision - legacy code matched `{:quic, :datagram, ...}` but quicer ships `:dgram` — corrected in the implementation, noted here Also enumerates the deliberate out-of-scope items (NAPTR ALPN advertisement, msquic Guix/Nix packaging, mutual-auth certs) so the next reader knows what is intentionally unfinished.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lands the design for burble's first native Android client and the cross-repo Bluetooth integration with sibling repo
neurophone. Documentation only — no code changes, no Phase 0 implementation yet.Key decisions (full detail in
docs/architecture/ANDROID-CLIENT.adoc):minSdk35 (Android 15).DistanceMeasurementSession(Channel Sounding) is API 35+; apologising for Bluedroid-era devices on a from-scratch native client is incoherent. Reno 13 is canonical smoke-test device.io.getstream:stream-webrtc-androidfor libwebrtc — active fork, AAR published, tracks upstream M-130s.BurbleAudioDspSoftFallbackis named-and-shamed with removal target v1.4; type-level distinction inAudioPipeline.idr(Nativeis normal inhabitant,SoftFallbackonly reachable viaFallback : ErrorRecovery -> AudioPipeline); Avow attestation logs DSP mode per session; READINESS exit gate requires ≥95% native-path adoption over rolling 7 days.--boltknock) down to the BLE adv layer. Devices stay in passive scan (~3 mA) and broadcast nothing until an authenticated HMAC-knock is observed. Two-position toggle: Off (default) / Discoverable.MessagingStyle+MediaSession+MediaBrowserService. In-car HMI works.Phase 0 follow-up PR will add a2ml manifests + Idris2 types +
.affinesignatures + stubbridges/neurophone.ex. Mergeable in burble alone.Test plan
🤖 Generated with Claude Code