Files
alkssh/tasks/implementation/w2-auth-bridge.md
T
glm-5.3-flash 18ef55c60d docs(tasks): decompose wave 2 — the server stack
Six implementation tasks + the gate under tasks/implementation/,
chained sequentially (the auth hooks, dispatch, and channel cap all
edit the same per-connection Handler impl):

- w2-server-mount: SshAdapter::handle mount + russh Config
  construction from the serve-config (honest advertisement, host-key
  decrypt-at-construction, the Limits knob mapping) + the Handler
  skeleton at fail-closed defaults
- w2-auth-bridge: the ADR-004 dispositions (ed25519-only explicit
  decline, fingerprint-only resolution, explicit declines for every
  non-publickey method)
- w2-loopback-harness: the in-process client/server contract-test
  vehicle over the wave-1 doubles
- w2-dispatch-decline-core: parse-only dispatch + the fail-closed
  decline core, contract-tested per feature build
- w2-spawn-return: the structural constraint pinned by test + the
  exit-reporting mechanics via the cloned Session::handle()
- w2-bounded-resources: the in-crate concurrent-channel cap at the
  handler surface
- review-wave-2: the gate

The plan carries the wave-2 decomposition record with four
interpretations flagged for the gate (skeleton-level git probe,
declining routing stubs, the adapter error surface, the harness
transport choice). taskgraph validate: 19 tasks, clean.
2026-10-28 07:38:04 +00:00

3.4 KiB
Raw Blame History

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
w2-auth-bridge Wave 2 — the auth bridge (dispositional handler surface) pending
w2-server-mount
w1-fingerprint
w1-test-doubles
moderate low component implementation

Description

Fill the Handler skeleton's auth hooks with the ADR-004 dispositions — the fingerprint → identity bridge, fail-closed on every path:

  • auth_publickey (fires post-verification; the key arrives as VerifiedPublicKey.public_key with the signature .algorithm exposed): non-ed25519 algorithm → explicit reject (ADR-002 decision 4 — the explicit-over-inherited pattern, so the posture survives a pin bump); ed25519 → fingerprint via the crate's single fingerprint path (src/fingerprint.rs, the ADR-004 contract invariant) → IdentityProvider::resolve_from_fingerprint → Some(identity) → Auth::Accept with the resolved identity stored in the per-connection handler state (it rides the session for the wave-3 seam propagation — auth_succeeded is the ride-along hook); None → reject fail-closed. The resolved-identity-None path never creates a weakly authorized session.
  • auth_publickey_offered — accept-and-delegate (the russh default shape at this pin; keep it explicit so the counting stays honest — the hook does not consume an attempt, POC-1 verified).
  • Explicit declines — auth_none, auth_password, auth_keyboard_interactive, auth_openssh_certificate each get an explicit Auth::reject() implementation (family contract, not inherited defaults — a pin bump could silently change them).
  • The username carries no semantics (OQ-03) — resolution is fingerprint-only; the user string is never an identity input.

Auth declines are dispositions (Auth::Reject), not errors — the error model stays key-source-only. Tests run against the wave-1 doubles (MemIdentityProvider + the ed25519 fixture keys) at the handler level; the loopback harness proves the bridge end to end over the wire in w2-loopback-harness.

Acceptance Criteria

  • auth_publickey: non-ed25519 → explicit reject; ed25519 → fingerprint → resolve_from_fingerprint → accept-with-identity / reject fail-closed; the resolved identity lands in per-connection handler state
  • auth_publickey_offered accepts-and-delegates explicitly
  • auth_none / auth_password / auth_keyboard_interactive / auth_openssh_certificate each explicitly reject
  • The username is never an identity input (fingerprint-only resolution; OQ-03)
  • Handler-level tests: known-fingerprint accept (fixture key + MemIdentityProvider), unknown-fingerprint reject, non-ed25519 explicit reject, every non-publickey method rejects
  • cargo test, cargo clippy --all-targets -- -D warnings, cargo fmt --check pass

References

  • docs/architecture/decisions/004-auth-dispositions.md (the dispositions, decisions 1–5)
  • docs/architecture/auth.md §Server direction (the bridge steps; the 0.65.0 VerifiedPublicKey shape)
  • docs/architecture/decisions/002-russh-pin.md (decision 4 — ed25519-only, the explicit-decline rationale)
  • docs/plans/implementation.md §Wave 2 (the auth-bridge bullet)
  • russh 0.65.0 in-source: Auth, VerifiedPublicKey, PublicKeyOffer, the auth hook signatures

Notes

To be filled by implementation agent

Summary

To be filled on completion