Conversation
…ed send gate Adds TOGGLE_LABRADOR_DATA_GENERATION(124), TOGGLE_LABRADOR_RAW_SAVE(125) and TOGGLE_LABRADOR_FILTERED(139) to CommandNumber, the ECG probe opt-in key (noopWhoop5Ecg, same string as macOS), and a send gate consulted by the single send() chokepoint that admits an ECG opcode only when it is in the positive allow-list, the strap is a connected positively-attested MG, and the opt-in is on. Nothing in this change can make the gate return true in practice: there is no ECG caller on Android yet and no Settings row sets the opt-in. The enum widening and the gate that bounds it land together; the probe that needs it lands next. Tests: the deferred guard everyDispatchableOpcodeIsAConstructibleCommandNumber is restored (it needed exactly these entries); the catalogue test that asserted the three were NOT constructible is flipped and explains why; the neighbouring assertion that 142/143/144 stay unconstructible is untouched and still green.
|
Reviewed at What I verified independently
The gate admits four opcodes, not three
The inline comment in
That last one reads as "123 does not change", when what is untouched is the enum entry. The send surface for 123 does change, and it is the one opcode of the four the allow-list itself flags as PERSISTENT wrist config rather than a session toggle. Different risk class from the other three: a toggle stops when the session does, a persistent config write does not. Could you say four in the body, and give 123 a sentence saying it is persistent and newly admitted? The reviewer heuristic the body offers ("check nothing sends by looking for a caller") stays true either way, but someone auditing the wire surface later should not have to derive the fourth opcode from the allow-list. A test lost its doc commentThe KDoc that used to sit above On the change itselfThe reasoning is right and the sequencing is the part I want to call out as good practice: landing the enum widening and the gate that bounds it together, so the probe arrives against a gate already in
|
…ersistent; restore the KDoc on noForbiddenOpcodeIsReachableThroughTheProbeCases Review of ryanbr#1969: the gate admits four opcodes, not three, and 123 is the one the allow-list flags as persistent wrist config rather than a session toggle. The test comment said it was untouched; the enum entry is, the send surface is not. The second test lost its doc comment when the deferral note above it was repurposed for the restored guard.
|
Thanks — and for the decode-side check; the body now states that half too, credited to the review. Both notes taken in
|
|
Re-reviewed at Because this one widens what the command sender can express to a strap, I checked the containment argument link by link rather than reading it:
So the "with this merged and nothing else, no code path sends any of the four" claim is accurate, and I was able to check it the way the body says a reviewer can: by looking for a caller and finding none. One placement change I would likeThe SELECT_WRIST(123) explanation landed in Could you move or copy those three lines into A question for the next PR, not a change hereThe gate keys off Today that is harmless, since nothing sends at all, and I can see the argument for one source of truth: a second, narrower "sendable" set could drift from what What I would like is that the probe PR treats 123's admission as an open question to argue, rather than as settled by this one. If that PR ships without a control for it, the gate should narrow to the three session toggles at that point. Worth a line in Move the SELECT_WRIST note to the gate and I am happy to merge this. |
Split 4 of the MG ECG research series; split 3 is merged (#1941 →
7ec7e778). This is the review-sensitive one.What this PR does
Adds
TOGGLE_LABRADOR_DATA_GENERATION(124),TOGGLE_LABRADOR_RAW_SAVE(125)andTOGGLE_LABRADOR_FILTERED(139)toCommandNumber, adds the ECG probe opt-in key(
PuffinExperiment.ecgProbe,noopWhoop5Ecg— the same key string macOS already uses), and wires a sendgate into the single
send()chokepoint:The gate admits four opcodes, not three.
PROBE_OPCODESis{123, 124, 125, 139}andecgSendAdmittedkeys off that set, so
SELECT_WRIST(123)— already constructible onmain, but absent from the 5/MG send guard andtherefore skipped today — becomes sendable to an attested MG whenever the probe opt-in is on. It is the one opcode of
the four the allow-list flags as persistent wrist config rather than a session toggle: a toggle stops when the
session does, a wrist-config write does not. That is a different risk class, and it is why the probe PR offers no
control for it (its right/left mapping is unverified on hardware and one value the measured firmware refuses).
This answers the comment it removes.
Enums.ktexcluded these three on purpose: "Android has no ECGapp layer and sends none of them, so growing the SENDER enum to buy a label would widen what the command
sender can express for nothing." The label half is still right — #893's read-only
CommandNamestablenames every opcode without making any constructible, and nothing here is added for a label. What changed
is the premise: the gated MG ECG research probe (#891/#1100) is an Android ECG app layer, and it does send
them, exactly as Apple's
WhoopCommandalready does for the same probe.Adding them does not widen the reachable surface, which is the property that matters. Every send
passes the one
send()chokepoint; there the opcode must be in the positive allow-listEcgResearchAllowList.PROBE_OPCODES(a closed set of four — #1941), the probe opt-in must be on, and thestrap must be a connected, positively-attested MG. The firmware-load family three codes above 139
(142/143/144) is not expressible through it — asserted by
senderEnumStaysCuratedAfterTheLabelFix, whichis untouched and still green.
The enum is also a lookup table, and that side does not leak either (checked in review):
CommandNumber.fromRawhas one caller in the tree,
advanceDeviceConfigProbe, independently gated onDeviceConfigReadProbe.isReadOnlyOpcode,so 124/125/139 becoming non-null there changes nothing.
With this PR merged and nothing else, no code path sends any of the four. There is no ECG caller on
Android yet and no Settings row sets the opt-in. The enum widening and the gate that bounds it land
together, so the probe that needs them (next PR) lands against a gate already in
main, and tightens it(arming state, stop-override) rather than introducing it. A reviewer can check "nothing sends" by looking
for a caller: there is none.
Type of change
How it was tested
Android unit tests, full suite on
3ec6f49f(the code head), basemain@0e6845cd: 5,554 tests, 0 failures,0 errors, 662 classes — main's 5,553 plus the restored guard. Counted from the JUnit XML with the results
directory cleared first, oracle synced in its own invocation.
986b9153on top is comment-only (the review's twonotes);
CommandCatalogueTest+EcgResearchAllowListTestanddoc_comment_lintre-run on it.The tests that change, deliberately:
EcgResearchAllowListTest.everyDispatchableOpcodeIsAConstructibleCommandNumber— restored. It assertsevery allow-listed opcode is a constructible
CommandNumber, so an allow-listed opcode the sender cannotform is caught. It was held out of ecg: the pure research modules — allow-list, stats and log #1941 because it would have failed there for the correct reason
(
CommandNumber must carry opcode 139); this PR is what makes it true.CommandCatalogueTest.theMgEcgTogglesAreNamedButNotSendable→…AndNowConstructibleBehindTheSendGate.The
assertNullon 124/125/139 flips to asserting their raw values, with the reasoning in its KDoc.Its neighbour
senderEnumStaysCuratedAfterTheLabelFix(25/36/37/38/45/99/142/143/144 stayunconstructible) is untouched — the evidence that moving the enum's top from 123 to 139 dragged nothing
in.
Gates:
Tools/doc_comment_lint.pyclean ·Tools/i18n_audit.py --ci upstream/mainclean (no strings —there is deliberately no Settings row in this PR).
Not run on hardware — by construction nothing here can send. Swift: n/a, no Swift touched;
swift testunchanged.What this does NOT claim
isMGby construction, and the probe PR carries the hardware run.
Checklist
./gradlew testFullDebugUnitTest, full suite)StrandDesigntokens — n/a, no UIare the schema numbers, already in
CommandNamesdocs/CONTRIBUTING.mdRelated issues
#891, #1100 · builds on #1941 (the allow-list, merged as
7ec7e778), #1765, #1727 · #893 (the label table thisdeliberately does not duplicate). Does not close anything.