Skip to content

daemon: Share credential lifecycle across transports - #224

Open
Preovaleo wants to merge 3 commits into
linux-credentials:mainfrom
Preovaleo:perso/generic_transport-split/1
Open

daemon: Share credential lifecycle across transports#224
Preovaleo wants to merge 3 commits into
linux-credentials:mainfrom
Preovaleo:perso/generic_transport-split/1

Conversation

@Preovaleo

@Preovaleo Preovaleo commented Sep 5, 2026

Copy link
Copy Markdown

Split and stacked review

Original PR: linux-credentials/credentialsd#220.

The replacement is split into four parts. Parts 1 → 2 → 3 form native GitHub stack #4 on the fork; part 4 is independent.

Part Upstream integration PR (targets main) Focused stacked review on the fork
1 — Shared transport lifecycle #224 Preovaleo/credentialsd#2/1main
2 — Cancellation and request ownership #225 Preovaleo/credentialsd#1/2/1
3 — Silent transport exhaustion #226 Preovaleo/credentialsd#3/3/2
4 — Discovery concurrency bound #227 Independent; review directly upstream

Review and integrate parts 1 → 2 → 3 in order. Part 4 can be reviewed and merged independently.

GitHub does not support native stacks across forks. Use Files changed on the fork PRs for incremental review of each layer. The upstream PRs target main; #225 and #226 include earlier layers until their dependencies land and the branches are rebased. Integration into the main project happens through the upstream PRs; merging the fork stack only updates the fork.

Hello 👋,

Summary

Follow-up to #204 and #214. This PR extracts the shared transport lifecycle work from #220.

USB, hybrid, and NFC previously handled state conversion and request completion in separate stream wrappers. These implementations duplicated the same lifecycle logic, making changes harder to review and allowing terminal behavior to diverge between transports.

This PR:

  • extracts the existing push-based test helper into reusable typed scripted transports;
  • introduces a common transport event interface for public state conversion and terminal results;
  • replaces the separate lifecycle wrappers with one shared credential state stream;
  • preserves the public states exposed by each transport;
  • expands success and failure coverage across USB, hybrid, and NFC;
  • documents the shared lifecycle handling.

Result

Transport-specific code remains responsible for interpreting its internal events and exposing the corresponding public state and optional credential result.

The shared stream handles request completion, cancellation checks, and termination after a terminal event. This gives subsequent lifecycle fixes a common implementation point across transports.

The scripted test fixtures allow tests to emit intermediate states, complete or fail a transport, and inspect cancellation without physical authenticators.

Scope and dependencies

This is the first part of the split and is based on main.

The remaining work is handled by separate PRs:

  • part 2: prompt cancellation and ownership of terminal events;
  • part 3: failure when every selected transport ends without a result;
  • part 4: a bound on concurrent discovery at the trusted UI boundary.

Authenticator enumeration and dynamic source-list updates remain outside this change.

Diff composition

Scope Test code Daemon code Moved/reused text (included)
This PR, relative to main ≈74% ≈26% ≈17%
ebf5eb8 — Extract test fixtures ≈100% ≈0% ≈27%
775f07f — Share transport lifecycle ≈32% ≈68% ≈1%

Commit sequence and rationale

The commit order follows the dependencies between these changes:

  1. daemon: Extract scripted transport test fixtures

    Sharing lifecycle code also means being able to exercise the same outcomes across transports. The existing push-based helper already supported scripted events, but lived inside the service tests and was named around cancellation. Extracting it into typed fixtures makes success, failure, and cancellation available to USB, hybrid, and NFC tests. This preparation comes first so the following commit can introduce the common stream together with coverage of each transport.

  2. daemon: Share credential lifecycle across transports

    The repeated responsibility is the transition from a transport event to a public state and, when terminal, a request result. That is the boundary represented by TransportEvent: each transport supplies its own conversion, while credential_state_stream owns completion and stream termination. Keeping that boundary narrow preserves the transport-specific state models and gives the later lifecycle fixes one implementation point. The success and failure tests accompany the extraction because equivalent terminal behavior across the three transports is what justifies sharing this code.

  3. docs: Describe shared transport lifecycle handling

    The architecture text records this division of responsibility. It stops at the common lifecycle introduced here; the cancellation and request ownership guarantees are documented with the commits that add them in part 2.

Testing

Validation performed at the branch tip:

  • cargo test -p credentialsd --bin credentialsd — 29 tests passed
  • cargo clippy -p credentialsd --bin credentialsd -- -Dwarnings — passed
  • cargo fmt --all --check — passed
  • git diff --check — passed

Coverage includes transport success and failure, response propagation, cancellation after request completion, cancellation of competing transports, and discarding events after cancellation.

Théo Bougé added 3 commits September 5, 2026 15:52
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.
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant