Files
alknet/tasks/core/ssh-interface-extraction.md

62 lines
3.5 KiB
Markdown

---
id: core/ssh-interface-extraction
name: Extract SshInterface from ServerHandler — refactor SSH into Layer 2
status: completed
depends_on:
- core/interface-trait-definition
- core/config-identity-provider-into-handler
scope: broad
risk: high
impact: project
level: implementation
---
## Description
This is the most invasive change in Phase 1. Extract SSH session handling from `ServerHandler` into `SshInterface`, making it implement the `Interface` trait defined in the previous task. Per interface.md and ADR-026, SshInterface becomes one implementation of the Interface trait alongside RawFramingInterface.
**Current state**: `ServerHandler` is a `russh::server::Handler` that owns auth, channel management, and proxy logic — all tangled together.
**Target state**:
- `SshInterface` implements `Interface` and wraps the SSH handshake and session management
- Auth delegation goes through `IdentityProvider` (already wired from task 1.5)
- Channel open requests (including forwarding policy checks) are Layer 3 concerns routed through the Interface session
- Port forwarding proxy logic is per-connection state managed by the session
**Key changes**:
- `SshInterface` wraps `russh` server config and session handling
- `SshInterface::accept()` takes a `TransportStream` and `SshInterfaceConfig`, performs SSH handshake, returns a session
- The session produces call protocol events (for `alknet-control:0` channels) and handles channel routing
- Forwarding policy check is invoked from Layer 3 (call protocol handler), not embedded in the interface
- `RawFramingInterface` stub: just the type definition, no implementation (Phase 4+ for DNS and WebTransport)
- The server accept loop uses `(Transport, Interface)` pairs instead of directly spawning SSH handlers
**This is explicitly flagged as high-risk** in the integration plan. The refactoring must preserve all existing behavior. Strategy: implement `SshInterface` as a wrapper around the existing `ServerHandler` logic initially, then progressively move concerns to the right layer.
## Acceptance Criteria
- [ ] `SshInterface` struct implements `Interface` trait with `accept()` method
- [ ] `SshInterface::accept()` performs SSH handshake over `TransportStream`
- [ ] Auth is delegated through `IdentityProvider` (not embedded in SshInterface)
- [ ] Channel open requests route through the session to Layer 3 (forwarding policy, call protocol)
- [ ] `alknet-control:0` channels produce call protocol events via the session
- [ ] Port forwarding proxy logic is per-connection state, not embedded in the interface
- [ ] `RawFramingInterface` type exists but is stub-only (no implementation beyond type definition)
- [ ] Server accept loop uses `(Transport, Interface)` pairs to spawn sessions
- [ ] All existing server/auth/transport tests pass unchanged
- [ ] New tests: `SshInterface` session over TCP and TLS transports
- [ ] New tests: forwarding policy applied when channels are opened (Layer 3, not Layer 2)
## References
- docs/architecture/interface.md — SshInterface, what stays in Layer 2 vs Layer 3, OQ-IF-02
- docs/architecture/decisions/026-transport-interface-separation.md — ADR-026
- crates/alknet-core/src/server/handler.rs — current ServerHandler to be extracted
## Notes
> This is the highest-risk task in Phase 1. Consider implementing incrementally: first wrap existing ServerHandler in SshInterface, then progressively move auth to IdentityProvider, channel routing to call protocol, etc. Each step should have passing tests before proceeding.
## Summary
> To be filled on completion