Repository navigation
fix(agent): enrollment screen refuses when already enrolled; retry loop re-checks identity - #119
Merged
Merged
Conversation
…op re-checks identity The enrollment screen kept trying after the device was already enrolled, and force-quit was the only way out. Two defects composed into it: 1. `EnrollActivity` never asked whether the device is already enrolled. It built a `FileIdentityStore` and never called `hasIdentity()` - so on the scanned path, where the presenting activity is torn down and the operator opens the app later, the enrollment form was offered to a device with nothing to enroll, and the spent code went back on the wire. 2. Neither retry loop re-checked identity. A certificate arriving by any route while the screen was open did not end the loop. `EnrollmentFlow.isEnrolled()` is the new decision point (the Activity stays thin: it turns taps into calls). `present()` and `collect()` both return `Enrolled` when the store already holds an identity - checked before the keystore and before the network, so a stray poll landing after enrollment cannot overwrite "Enrolled" with "this enrollment is no longer available". `EnrollActivity` shows "already enrolled" with the form disabled instead of offering it; the back button still leaves. Terminal refusals were already terminal in the flow (`code-used` -> Stopped); the missing piece was the enrolled device ever reaching the screen, and the loops never noticing it got enrolled underneath them. Closes #105.
WalkthroughThis PR resolves muster#105, where an already-enrolled device was being shown the enrollment form and could re-present a spent pairing code. The enrollment flow now checks for an existing identity at three points—when the screen opens, before each present, and before each collect poll—returning Enrolled immediately instead of touching the network or keystore. The EnrollActivity disables (rather than hides) the form and informs the operator, so the screen still reads as the enrollment screen and the back button remains functional. Tests cover both the upfront refusal and the mid-poll exit. Review effort: moderate (~15 min) Changed files (3)
Shape of the changegraph TD
subgraph "agent"
N0["EnrollActivity.kt"]
N1["EnrollmentFlow.kt"]
N2["EnrollmentFlowTest.kt"]
end
Last walked at |
4 of 5 tasks
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.
Refs #105. Part of #121.
Why
The enrollment screen kept trying after the device was already enrolled, and force-quitting was the only way out. Measured on the second Pixel: it held a valid identity at 22:55:15 and the screen was still presenting at 22:57:52, logging
code-usedrefusals. To the operator that looks like enrollment failed, for an enrollment that had succeeded two minutes earlier. Two defects compose:EnrollActivitynever asked whether the device was enrolled, and the retry loop never re-checked.Summary
Back still leaves the screen; nothing traps the operator.
Evidence
anAlreadyEnrolledDeviceIsToldSoInsteadOfPresentingandaCertificateArrivingByAnotherRouteEndsThePollfail.After: the agent JVM harness gives 335 tests passed (
MUSTER_JDKpointing at an arm64 JDK 17).Merge Danger
Door: two-way. Reverting restores the old retry behavior.
Blast Radius: the enrollment screen. A device that already holds an identity can no longer present a code from this screen; re-enrolling it means clearing the app's data. That is what #105 asked for, and re-presenting reuses the same key, so it could only re-join as the same device.
Acceptance criteria
Size: S
Out of scope
Resuming a poll across an activity restart, which is filed separately.
https://claude.ai/code/session_01UkWktkaYXZwdwzUvZQrN9q