Files
BikeControl/crates/probe/Cargo.toml
T
dtourolleandClaude Opus 5 4e400cdd3b Ask the pod whether answering its key offer keeps the paddles alive
`probe unlock` — the experiment §2.3.3 ends on, not an implementation.

The pod offers a compressed P-256 point and gives up on us when we do not
answer; the paddle bits freeze while the D-pad keeps reporting. What a
working client writes back is the half no capture has, and the public
descriptions are all of the older Play hardware — different message
types, an uncompressed key, a different channel.

But the offer looks like the handshake we already know, moved into a
protobuf envelope: its field 2 is `0x02030000`, and `RESPONSE_START` —
the pod's confirmed cleartext reply marker — is `[0x02, 0x03]`. That
makes the client side a short list rather than a search, and the device
is a perfect oracle: either a paddle edge arrives after the cliff or one
does not, every run, in two minutes.

So the command sends one candidate per run — `ours` (00 09, what we
already write), `play` (01 02, the 2023 client marker), `echo` (02 03,
in case field 2 names the suite rather than the speaker) — and reports
HELD, FAILED or INCONCLUSIVE. Omitting `--candidate` answers nothing and
measures the cliff this pod actually has, which is the control every
result needs.

The verdict deliberately refuses to call a failure from silence: it needs
the D-pad still reporting while the paddles do not, because a pod nobody
touched proves nothing and a dropped link is void rather than negative.

Field 3 of the offer — 40 or 60 bytes, unexplained — is omitted from the
reply. If it is load-bearing no candidate will hold, and that is a
finding too.

p256 is a dependency of the probe alone. The app takes no crypto
dependency on a guess.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 19:19:29 +02:00

27 lines
898 B
TOML

[package]
name = "bikecontrol-probe"
version.workspace = true
edition.workspace = true
license.workspace = true
[[bin]]
name = "probe"
path = "src/main.rs"
[dependencies]
bikecontrol-core = { workspace = true }
bikecontrol-ble = { workspace = true }
btleplug = { workspace = true }
tokio = { workspace = true, features = ["full"] }
futures = { workspace = true }
uuid = { workspace = true }
anyhow = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
# Protocol discovery only (§9): the pod offers a compressed P-256 point and we
# need a real one to answer with. Pure Rust, and deliberately confined to the
# probe until an unlock candidate is proven — the app takes no crypto
# dependency on a guess.
p256 = { version = "0.13", default-features = false, features = ["ecdh", "arithmetic"] }
rand_core = { version = "0.6", features = ["getrandom"] }