Extract SshInterface from ServerHandler, add RawFramingInterface stub

- SshInterface implements Interface trait with accept() method
- SshSession implements InterfaceSession trait (stub for call protocol events)
- RawFramingInterface is type-only stub (Phase 4+ for DNS, WebTransport)
- TransportKind consolidated into transport module with Display, PartialEq, Eq
- ListenerConfig gains interface_kind field for (Transport, Interface) pairs
- SshInterface wraps existing russh handler logic (SshHandler)
- Auth delegation through IdentityProvider (not embedded in SshInterface)
- Channel routing through session to Layer 3 (forwarding policy)
- Server accept loop uses (Transport, Interface) pairs

Per ADR-026: SSH is Layer 2, not Layer 1. This is the highest-risk Phase 1
task, implementing the Interface trait to separate transport from interface.
This commit is contained in:
2026-06-07 16:24:31 +00:00
parent bd38c94cae
commit 22724228f8
10 changed files with 982 additions and 75 deletions

View File

@@ -0,0 +1,62 @@
use anyhow::Result;
use async_trait::async_trait;
use crate::interface::session::{InterfaceEvent, InterfaceSession};
use crate::interface::{Interface, InterfaceConfig, TransportStream};
pub struct RawFramingInterface;
pub struct RawFramingSession;
#[async_trait]
impl Interface for RawFramingInterface {
type Session = RawFramingSession;
async fn accept(
&self,
_stream: Box<dyn TransportStream>,
_config: &InterfaceConfig,
) -> Result<Self::Session> {
Err(anyhow::anyhow!(
"RawFramingInterface is not yet implemented (Phase 4+)"
))
}
}
#[async_trait]
impl InterfaceSession for RawFramingSession {
async fn recv(&mut self) -> Option<InterfaceEvent> {
None
}
async fn send(&mut self, _envelope: crate::call::EventEnvelope) -> Result<()> {
Err(anyhow::anyhow!(
"RawFramingSession is not yet implemented (Phase 4+)"
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn raw_framing_interface_type_exists() {
let _iface = RawFramingInterface;
}
#[test]
fn raw_framing_session_type_exists() {
let _session = RawFramingSession;
}
#[tokio::test]
async fn raw_framing_interface_accept_returns_error() {
let iface = RawFramingInterface;
let (_client, server) = tokio::io::duplex(1024);
let stream: Box<dyn TransportStream> = Box::new(server);
let config = InterfaceConfig::RawFraming(crate::interface::RawFramingConfig {});
let result = iface.accept(stream, &config).await;
assert!(result.is_err());
}
}