Add http feature flag with axum, hyper, hyper-util, tower, and http-body-util
dependencies. Create http module with auth middleware (extracts Bearer token,
calls IdentityProvider::resolve_from_token, attaches Identity to extensions)
and router scaffold (default 404 fallback, no operational routes yet). Replace
send_fake_nginx_404 with axum router handoff when http feature is enabled;
fake 404 behavior preserved when http is disabled. Wire HttpInterface with
build_router() method and pass IdentityProvider through Server to handle_connection.
Define the outbound authentication abstraction in alknet_core::credentials:
- CredentialProvider trait with get_credentials and refresh_credentials
- CredentialSet enum with ApiKey, Basic, Bearer, S3AccessKey, OidcToken, Custom variants
- ConfigCredentialProvider reads credentials from DynamicConfig.credentials
- SecretStoreCredentialProvider stub returns None for all lookups (Phase 3)
- Wire CredentialProvider into OperationEnv via credentials() method
- Add credentials HashMap field to DynamicConfig
Per ADR-035: split Interface trait into StreamInterface (stream-based, SSH/RawFraming)
and MessageInterface (request/response, HTTP/DNS). Remove TransportKind::Dns (DNS is
a MessageInterface). Change WebTransport { host } to { server_name: Option<String> }.
Restructure ListenerConfig from flat struct to enum with Stream/Http/Dns variants.
- 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.
Add Layer 2 interface abstraction per ADR-026:
- Interface trait with accept() and associated Session type
- InterfaceConfig enum with Ssh and RawFraming variants
- SshInterfaceConfig with auth, forwarding, host_key fields
- RawFramingConfig (minimal, no SSH-specific config)
- InterfaceSession trait with recv()/send() producing InterfaceEvent frames
- InterfaceEvent wraps EventEnvelope with optional Identity
- Resolves OQ-IF-01: every session produces EventEnvelope frames
via InterfaceSession, making Layer 3 interface-agnostic
- Valid (Transport, Interface) pair enumeration with
TransportKindBase and is_valid_pair validation function
- Module re-exported from lib.rs
Add local dispatch for OperationEnv with invoke() method, EventEnvelope
wire format struct, 4-byte BE length-prefixed frame encoding/decoding,
PendingRequestMap for call/subscribe correlation, call protocol event type
constants, and default /services/list and /services/schema operations.
Add ForwardingPolicy, ForwardingAction, ForwardingRule, and TargetPattern
types in config/forwarding.rs. Implement policy evaluation with first-match
wins semantics, principal and transport matching, CIDR and glob patterns.
Modify ServerHandler to check ForwardingPolicy before proxying in
channel_open_direct_tcpip. Reserved alknet-* destinations bypass policy.
Preserve existing behavior with default allow_all() policy.
Add AuthProtocol enum (VerifyPubkey, VerifyToken, ReloadKeys, CheckAccess),
AuthResult enum (Ok(Identity), Denied(String)), and AuthServiceImpl
wrapping ConfigIdentityProvider via ArcSwap<DynamicConfig>. All gated
behind the irpc feature flag per ADR-028.
- Add ListenerConfig struct with transport_kind, listen_addr, per-transport config
- Add Dns and WebTransport variants to TransportKind (tags only, no behavior)
- Add .listeners() builder method to ServeOptions for multi-listener config
- Keep .transport_mode() backwards compatible (creates single-element listeners vec)
- Update Server::run() to use listeners from Server struct (first listener)
- Add Server::listeners() accessor for multi-transport listener configs
- Update StaticConfig to support listeners field, converted from ServeOptions
- All listeners share Arc<ArcSwap<DynamicConfig>>, ConnectionRateLimiter, and IdentityProvider
- Graceful shutdown terminates accept loop via existing shutdown signal
- TOML [[listeners]] array-of-tables syntax supported via ListenerConfig in StaticConfig
- Add comprehensive tests for ListenerConfig, multi-listener ServeOptions, Server creation
Add Identity struct with id/scopes/resources fields and IdentityProvider
trait with resolve_from_fingerprint/resolve_from_token methods. Implement
ConfigIdentityProvider reading from ArcSwap<DynamicConfig.auth> for
fingerprint-based key lookups. Delegate ServerHandler::auth_publickey()
through IdentityProvider instead of direct AuthPolicy access. Store
authenticated Identity in the handler for use by ForwardingPolicy.
ConfigServiceImpl wraps ArcSwap<DynamicConfig> providing forwarding_policy(),
rate_limits(), and reload() methods for direct use (always available).
ConfigProtocol enum (GetForwardingPolicy, GetRateLimits, ReloadForwarding,
ReloadRateLimits) is gated behind the irpc feature flag per ADR-030.
Split alknet-core configuration into StaticConfig (immutable after startup)
and DynamicConfig (hot-reloadable at runtime via ArcSwap).
- Add StaticConfig struct in config/static_config.rs with all fields per ADR-030
- Add DynamicConfig struct with AuthPolicy, ForwardingPolicy, RateLimitConfig
- Add ForwardingPolicy with allow_all()/deny_all() defaults (ADR-031)
- Add ConfigReloadHandle with reload() method for runtime config updates
- Replace Arc<ServerAuthConfig> with Arc<ArcSwap<DynamicConfig>> in ServerHandler
- Add config_reload_handle() to Server for obtaining reload handles
- Add AuthPolicy with authenticate_publickey/authenticate_certificate methods
- All existing tests pass with the new config structure
- Default DynamicConfig produces identical behavior to current code