feat(bt-presence): Phase-2 consumer of burble's frozen BLE presence beacon#180
Merged
Merged
Conversation
…eacon burble froze its BLE nearby-presence wire format v1 on 2026-07-09 (PR #154, ADR-0015), explicitly to unblock neurophone. This lands the neurophone-side Phase-2 consumer the BT-PRESENCE plan called for: a pure-Rust, host-testable decode + contact-resolution + presence-decay core. - crates/bt-presence/vendor/: byte-exact vendored copies of burble's FROZEN nearby-presence.a2ml + ble-spa-v1.json (provenance pinned to burble 2b5914b + sha256). Vendored, not fetched, so the build is reproducible and offline. - build.rs: code-generates the wire constants from the vendored spec (single source of truth, no hand-copied protocol numbers) and FAILS THE BUILD LOUDLY if the vendored spec is not a frozen wire-version 1 (burble freeze covenant). - src/decode.rs: 24-byte frame decode, epoch = unix/900, and contact resolution by reproducing HMAC-SHA256(secret, "BRBL-PRES-v1" ‖ magic ‖ ver_type ‖ epoch) [0..18] with a constant-time compare and a ±1 epoch freshness window (mirrors burble's Burble.Presence.BleSpa.resolve_presence/3). - src/decay.rs: RSSI-reinforced exponential-decay presence score (0.0..=1.0). - tests/vectors.rs: replays burble's FROZEN conformance vectors and asserts the beacon id is byte-exact with burble's independent oracle (presence_beacon_id_is_byte_exact) — cross-implementation wire proof. - sensors: new SensorKind::Presence (arity 1) so the decoded score flows through the existing SensorPipeline into the LSM, sensor-class like light/proximity. Read-only on the wire: no microphone, no outbound advertising. Device-side scan glue (gossamer/JNI per #83) and burble's Phase-1 emitter are still pending, but the consumer is built, pinned to frozen v1, and proven wire-compatible now. Local: cargo test -p bt-presence (11 unit + 3 conformance) green; clippy --all-targets -D warnings clean; fmt clean; full workspace builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh
…plemented Yesterday's sibling-integration audit (#178) recorded burble as BLOCKED with every consumed artefact design-only. burble froze the wire format hours later (ADR-0015), so those records were stale. Corrected to reflect reality: - SIBLING-INTEGRATIONS.adoc: burble row BLOCKED -> CONSUMER IMPLEMENTED; the EXISTS-vs-PLANNED table flips (wire format, Idris2 ABI, vectors now frozen), with a description of the crates/bt-presence implementation. Only burble's Android emitter (Phase 1) remains. - BT-PRESENCE-PLAN.adoc: upstream status BLOCKED -> Phase-0 done / consumer implemented / Phase-1 emitter pending. - ECOSYSTEM.a2ml: burble status blocked-upstream -> consumer-implemented. - STATE.a2ml: add bt-presence crate; tests 160 -> 174; recent-work + blockers refreshed (burble Phase-1 is runtime-only, non-blocking for the build). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
hyperpolymath
marked this pull request as ready for review
July 10, 2026 00:17
|
8 tasks
hyperpolymath
added a commit
that referenced
this pull request
Jul 10, 2026
… build (#181) ## Summary Two follow-ups that green `main` after #180 and #175. Neither is a real defect in application logic — one is a scanner false-positive, the other a bad dependency bump. ### 1. Secret-scanner false positives (from #180) The `bt-presence` crate vendored burble's conformance vectors (`ble-spa-v1.json`), which hold burble's **published non-production HMAC test keys** as hex strings — the file header literally says *"Fixed non-production secrets."* Gitleaks / SonarCloud / hypatia all pattern-match 64-char hex as `generic-api-key`, so this turned **SonarCloud** ("E Security Rating on New Code") and the **hypatia baseline** red and posted ~28 Gitleaks comments. **No real credential was ever committed.** Fixed **without suppressing any scanner**: dropped the vendored JSON and transcribed the 3 `presence` vectors this crate actually tests against as Rust **byte-array constants** in `tests/vectors.rs` (same burble commit `2b5914b`, provenance documented). Byte arrays are unambiguously wire test-data, not credentials, so **no `.gitleaksignore`, no SonarCloud exclusion, no hypatia baseline entry** is needed — your secret detection stays fully armed for real secrets. The byte-exact conformance proof is unchanged: `presence_beacon_id_is_byte_exact` still reproduces burble's independent oracle. Also dropped the now-unused `serde_json` dev-dep and refreshed `vendor/PROVENANCE.adoc` + `STATE.a2ml` (test count 174 → 173). ### 2. Build breakage (from #175) Dependabot re-bumped `rand` 0.9 → 0.10.2 (#175), which does **not compile** against `ndarray-rand 0.16` (Distribution/Rng trait mismatch) — exactly the break the workspace comment documents and #154 reverted before. `main` currently fails to build (`esn`: `E0277`/`E0599`). Reverted the workspace pin to `rand 0.9` (lock → 0.9.4); the full workspace builds again. ## RSR Quality Checklist - [x] Tests pass — full workspace `cargo build` green; `cargo test -p bt-presence` 11 unit + 2 conformance green - [x] Formatted (`cargo fmt --check`) — clean - [x] Linter clean (`cargo clippy --all-targets -- -D warnings`) — clean - [x] No banned language patterns - [x] No `unsafe` — `#[forbid(unsafe_code)]` - [x] SPDX headers present - [x] **No secrets** — the vendored hex-string test keys are removed; zero secret-shaped hex strings remain in the crate - [x] `STATE.a2ml` updated ## Testing ``` cargo build --workspace # Finished (esn compiles again) cargo test -p bt-presence # 11 unit + 2 conformance — pass cargo clippy -p bt-presence --all-targets -- -D warnings # clean cargo fmt --check # clean grep -rE '"[a-f0-9]{32,}"' crates/bt-presence # NONE ``` ## FLAGS / owner-manual - **Dependabot will keep re-bumping `rand` to 0.10** (this is the 2nd time). Recommend a `dependabot.yml` ignore for `rand` (and/or `rand_distr`) until `ndarray-rand` ships a 0.10-compatible release — otherwise the build re-breaks on the next bump. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh --- _Generated by [Claude Code](https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh)_ Co-authored-by: Claude <noreply@anthropic.com>
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
burble froze its BLE nearby-presence wire format v1 on 2026-07-09 (PR #154, ADR-0015) — explicitly "to unblock neurophone." That resolved the exact upstream blocker recorded in #178. This PR lands the neurophone-side Phase-2 consumer the BT-PRESENCE plan called for: a pure-Rust, host-testable decode + contact-resolution + presence-decay core, proven byte-exact against burble's frozen conformance vectors.
Read-only on the wire — no microphone, no outbound advertising. End-to-end runtime still awaits burble's Phase-1 emitter (its Android client, not yet shipped), but that does not block neurophone's build: the consumer is built, tested, and pinned to the frozen v1 format, ready to receive.
Changes
New crate
crates/bt-presence/:vendor/— byte-exact vendored copies of burble's FROZENnearby-presence.a2ml+ble-spa-v1.json, provenance pinned to burble commit2b5914b+ sha256 (vendor/PROVENANCE.adoc). Vendored, not fetched → reproducible, offline-buildable.build.rs— code-generates the wire constants from the vendored spec (single source of truth, no hand-copied protocol numbers) and fails the build loudly if the vendored spec is not a frozenwire-version 1(honours burble's freeze covenant).src/decode.rs— 24-byte frame decode;epoch = unix/900; contact resolution by reproducingHMAC-SHA256(secret, "BRBL-PRES-v1" ‖ magic ‖ ver_type ‖ epoch)[0..18]with a constant-time compare and a ±1 epoch freshness window (mirrors burble'sresolve_presence/3).src/decay.rs— RSSI-reinforced exponential-decay presence score (0.0..=1.0).tests/vectors.rs— replays burble's frozen vectors;presence_beacon_id_is_byte_exactasserts the beacon id matches burble's independent HMAC oracle byte-for-byte.Wiring:
crates/sensors— newSensorKind::Presence(arity 1) so the decoded score flows through the existingSensorPipelineinto the LSM, sensor-class like light/proximity.Cargo.toml/Cargo.lock— addbt-presencemember; new depshmac,sha2(MIT/Apache-2.0),subtle(constant-time),toml(build-time spec parse).Docs corrected (yesterday's #178 recorded burble as BLOCKED; it froze hours later):
SIBLING-INTEGRATIONS.adocburble row: BLOCKED → CONSUMER IMPLEMENTED; EXISTS-vs-PLANNED table flipped.BT-PRESENCE-PLAN.adoc,ECOSYSTEM.a2ml,STATE.a2mlupdated to match (only burble Phase-1 emitter pending).RSR Quality Checklist
Required
cargo test) —bt-presence11 unit + 3 conformance green; full workspace buildscargo fmt --check) — cleancargo clippy --all-targets -- -D warnings) — clean.ktsketch in the plan is explicitly redirected to gossamer/JNI)unsafeblocks —#[forbid(unsafe_code)];deny(unwrap/expect)in non-test codeAs Applicable
.machine_readable/6a2/STATE.a2mlupdated (new crate, test count, blockers).machine_readable/6a2/ECOSYSTEM.a2mlupdated (burble status)BT-PRESENCE-PLAN.adoc,SIBLING-INTEGRATIONS.adoc)Testing
The key correctness claim — wire-compatibility — is
presence_beacon_id_is_byte_exact: this crate's Rust HMAC-SHA256 reproduces everybeacon_idin burble's frozenble-spa-v1.json(independently generated) exactly, and resolves each vector to its named contact while rejecting a stranger's secret.FLAGS / owner-manual residuals
client/android/in burble; ADR-0015 isStatus: Proposed. Nothing on the air to receive until burble ships it; this PR is deliberately the consumer side only.🤖 Generated with Claude Code
https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh
Generated by Claude Code