daemon: Unify and harden credential transport lifecycle - #220
Open
Preovaleo wants to merge 10 commits into
Open
Conversation
Preovaleo
force-pushed
the
perso/generic_transport
branch
2 times, most recently
from
August 30, 2026 14:14
6137928 to
8ab093c
Compare
This comment was marked as resolved.
This comment was marked as resolved.
Preovaleo
force-pushed
the
perso/generic_transport
branch
2 times, most recently
from
August 30, 2026 15:38
e9dfb89 to
e6c45c1
Compare
Preovaleo
marked this pull request as draft
August 30, 2026 16:28
added 2 commits
August 30, 2026 18:54
Correct grammar and wording in the architecture overview without changing the documented design.
The push-based helper was embedded in the credential service tests, and its cancellation-focused names hid that it could script any transport state. Move it to test_support, rename it around that broader role, and share typed completion and failure helpers across USB, hybrid, and NFC tests.
Preovaleo
force-pushed
the
perso/generic_transport
branch
from
August 30, 2026 17:07
e6c45c1 to
77c526b
Compare
added 8 commits
August 30, 2026 20:19
USB, hybrid, and NFC duplicated state conversion and request completion in separate stream wrappers, making their terminal behavior easy to desynchronize. Route typed transport events through one lifecycle stream and cover success and failure for every backend.
A lifecycle stream only noticed cancellation after another transport event, so idle discovery could remain pending. Await transport polling through CancellationToken::run_until_cancelled so cancellation wakes the stream immediately.
A late terminal event could consume whichever request context was active and complete a newer request. Attach the request ID and a unique marker to each lifecycle stream, then ignore terminal results whose ownership no longer matches.
Discovery let each transport read the active request independently, so a replacement between reads could mix ownership and cancellation data. Snapshot the request ID, marker, and token once and pass that typed lifecycle to every selected transport.
When the final selected transport ended without a terminal result, discovery returned EOF while the request stayed active and its caller could wait indefinitely. Complete that request with a transport-independent failure while ignoring exhaustion from stale or explicitly cancelled discovery.
A terminal event can become ready in the same poll that cancels its request. Without the post-poll cancellation check, that event could still consume the active context. Cancel the token from inside the scripted poll and verify that the terminal result is discarded without sending a response.
Describe request-scoped terminal handling, immediate cancellation wakeups, and transport exhaustion. Keep the changelog focused on the resulting fixes for stalled discovery and stale authenticator results.
Repeated DiscoveryRequested signals could spawn independent streams for the same request, consuming resources and racing request completion. Hold one request-scoped permit for the lifetime of the forwarded stream. Concurrent signals are ignored, while releasing the permit allows a later discovery attempt.
Preovaleo
force-pushed
the
perso/generic_transport
branch
from
August 30, 2026 18:25
77c526b to
9e97418
Compare
Preovaleo
marked this pull request as ready for review
August 30, 2026 19:31
Member
|
Hello! Thanks for your contribution! This looks like a good improvement. I typically only have 10 minutes blocks of time to do review, so this will take me quite a while to get through all these changes. Even though it seems you've split your commits well, limitations in GitHub's review features will also make it hard for me to get through these. Could you post these as separate PRs? You could use GitHub's new stack feature to group them together if you like. |
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.
Hello 👋,
Summary
Follow-up to #204 and #214.
Credential transports previously handled state conversion, request completion, and cancellation in separate USB, hybrid, and NFC stream wrappers. This duplicated lifecycle logic and left several edge cases around idle cancellation, stale terminal events, and transports ending without producing a result.
This PR:
Result
The first valid terminal event completes the active request and cancels the competing transports.
Explicit cancellation no longer depends on additional transport activity. Events from stale streams cannot complete a newer request, and silent transport exhaustion produces an error instead of leaving the caller pending.
Repeated
DiscoveryRequestedsignals cannot create concurrent discovery tasks for the same request. This is a concurrency bound rather than a single-discovery policy: once the active stream ends, another discovery attempt can start.Scope
This PR does not change how available authenticators are enumerated, implement dynamic source-list updates, or define a new retry policy. Those remain separate concerns tracked by #32 and #206.
Testing
The daemon now has 39 unit tests, including coverage for:
Validation performed:
cargo test -p credentialsd --bin credentialsd— 39 tests passedcargo clippy -p credentialsd --bin credentialsd -- -Dwarningscargo fmt --all --checkgit diff --check origin/main...HEADThe targeted daemon test suite also passes independently at every commit in the PR.