Files
alknet/docs/architecture/crates/core/README.md
T
glm-5.2 bf6ce957c0 docs(arch): tighten tls/endpoint/client specs — remove connect/connect_quic, move CallCredentials to core, shed alknet-call TLS deps
Review of the three new crates (alknet-tls, alknet-endpoint, alknet-client)
+ revised core found compile-blocking inconsistencies, stale claims, and
dep-graph contradictions. All resolved:

Critical:
- C1: CallClient::connect / ChannelClient::connect_quic REMOVED (not
  delegated) — keeping them as thin wrappers over AlknetClient::dial_quic
  would make protocol crates depend on alknet-client, contradicting the
  dep graph. Callers compose dial + take-over (2 lines).
- C2: alknet-client feature gates now pull alknet-core/quinn +
  alknet-core/iroh (for Connection::from_quinn_with_alpn / from_iroh).
- C3: rustls-native-certs + webpki-roots added to alknet-tls deps
  (always-present, not feature-gated — CA-verify path is transport-agnostic).

Warning:
- W1: CallCredentials/RemoteIdentity moved to alknet-core (from
  alknet-call) — the dial must not depend on the call protocol; not a
  two-way-door, it determines the dep graph.
- W2: webpki-roots fallback implemented in spec (ADR-088 §5 added) —
  the code claimed a fallback that never existed; now the store is never
  empty, NoRootAnchors unreachable, containerized deployments work.
- W3: EndpointError removed entirely (BindFailed + HandlerNotFound both
  vestigial after ADR-083); shutdown() is now infallible.
- W4: FingerprintPinVerifier moved to alknet-tls (from alknet-call) —
  alknet-call sheds quinn/rustls/rustls-pemfile/rustls-native-certs
  entirely; CallClient becomes a pure protocol crate.

Plus: ClientError removed (only produced by removed connect); S1
(CallCredentials → ClientVerifierContext mapping + auth_token stripped
at TLS boundary documented); amendment notes on ADR-017, ADR-069,
ADR-080, ADR-082, ADR-087, ADR-090; overview crate graph + README index
updated.

29 files, consistency-reviewed.
2026-07-16 11:33:18 +00:00

6.9 KiB

status, last_updated
status last_updated
draft 2026-07-15

alknet-core

Shared types, auth, config, and identity for ALPN-based protocol dispatch. Every handler crate depends on alknet-core for ProtocolHandler, Connection, AuthContext, IdentityProvider, and config types. The endpoint (AlknetEndpoint, HandlerRegistry) has been extracted to alknet-endpoint (ADR-083 Amendment 2026-07-15; EndpointError is removed — both variants were vestigial); core no longer carries the accept-loop runner or its transport deps (quinn, iroh, rcgen, rustls-acme). Connection::from_quinn / from_iroh stay in core's types.rs as shared constructors (gated on core's quinn / iroh features). CallCredentials and RemoteIdentity move to alknet-core (from alknet-call, per ADR-089 §5) — both the call and channels clients need them, and the dial (alknet-client) must not depend on the call protocol for the credential type.

Documents

Document Status Description
core-types.md draft ProtocolHandler trait, HandlerError, Connection (Box<dyn BidiStreamSource> — ADR-070), BidiStreamSource trait, BiStream, StreamError
endpoint.md deprecated Endpoint spec — moved to alknet-endpoint (ADR-083 Am. 2026-07-15); this file is a stub
auth.md draft AuthContext (incl. anonymous constructor), Identity, IdentityProvider, AuthToken, resolution flow, PeerEntry, CredentialStore
config.md draft StaticConfig, DynamicConfig, ArcSwap, ConfigReloadHandle, AuthPolicy.peers

Applicable ADRs

ADR Title Relevance
001 ALPN-Based Protocol Dispatch Core architectural model
002 ProtocolHandler Trait The trait every handler implements
003 Crate Decomposition alknet-core's position in the crate graph
004 Auth as Shared Core IdentityProvider in core
006 ALPN String Convention ALPN format, one-ALPN-per-connection
007 BiStream Type Definition Connection, BiStream trait, SendStream, RecvStream
009 One-Way Door Framework Decision classification
010 ALPN Router and Endpoint HandlerRegistry, accept loop — endpoint extracted to alknet-endpoint per ADR-083 Am. 2026-07-15
011 AuthContext Structure AuthContext fields and resolution flow
015 Privilege Model and Authority Context Per-request identity on OperationContext; admin scope for config reload
030 PeerEntry and Identity.id Decoupling authorized_fingerprints → peers: Vec<PeerEntry>; Identity.id = peer_id (stable)
031 CredentialStore Repo Trait Second repo trait in core; InMemoryCredentialStore default adapter
033 Storage Boundary and Repo/Adapter Pattern Core defines traits + in-memory defaults; persistence adapters are separate crates
065 Connection::from_stream — Generic Single-Stream Connections from_stream/from_bidi accept any AsyncRead + AsyncWrite; yield-once accept_bi contract; unblocks TCP+TLS, SSH channels, WebTransport, wasm
070 BidiStreamSource Trait — Open Connection for Extension Connection holds Box<dyn BidiStreamSource>; QUIC/iroh/stream wrap crate-private impls; from_source is the public constructor for downstream crates that implement the trait (channels, future transports)
083 Endpoint as accept-loop runner + crate extraction The endpoint is extracted from core into alknet-endpoint; core loses quinn/iroh/rcgen/rustls-acme deps; Connection::from_quinn/from_iroh stay in core as shared constructors

Relevant Open Questions

OQ Title Status Relevance
OQ-04 Dynamic handler registration resolved (start static) HandlerRegistry is immutable at startup (now in alknet-endpoint)
OQ-05 Multi-connectivity endpoint resolved (quinn + iroh) AlknetEndpoint supports both, both feature-gated (now in alknet-endpoint)
OQ-11 Handler-level auth resolution observability resolved Handlers store resolved identity on Connection; two identity scopes (connection-level for observability, per-request for ACL)
OQ-33 PeerId — logical id vs crypto identity resolved by ADR-030 PeerId = Identity.id = PeerEntry.peer_id (stable across key rotation)
OQ-34 Persistent peer registry (storage boundary) resolved by ADR-030+031+033 Core defines repo traits + in-memory defaults; persistence adapters are separate crates
OQ-35 API key asymmetry dissolved PeerEntry supports multiple credential paths; ApiKeyEntry is for tokens that ARE the identity
OQ-36 Concrete persistence adapter shapes resolved by ADR-035 Read-sync / write-async split (IdentityStore); SQLite adapter caches in memory, honker NOTIFY for no-restart cache invalidation; alknet-store-sqlite crate
OQ-37 X.509 outgoing-only case resolved by ADR-034 Three remote roles (public X.509 endpoint, transport relay, hub); PeerEntry asymmetry correct; client-side verifier by PeerEntry presence (CA vs fingerprint pin)
OQ-55 AlknetClient / Client Establishment Extraction resolved by ADR-089 The native dial seam is extracted as alknet-client — the client-side analogue of AlknetEndpoint (now in alknet-endpoint). Three dial methods (QUIC + TCP+TLS via TlsClientConfig, iroh via key).

Key Design Principles

  1. One trait, one dispatch point: ProtocolHandler is the only abstraction handlers implement. No StreamInterface/MessageInterface split.
  2. ALPN does the routing: The endpoint (in alknet-endpoint) dispatches by ALPN string. No byte-peeking, no ListenerConfig enum.
  3. Handlers own their wire format: Each handler manages its own protocol parsing. alknet-core provides the Connection, not the framing.
  4. Auth is hybrid: The endpoint provides what it can (TLS-level auth). Handlers complete what they need. AuthContext may be partial.
  5. WASM door preserved: BiStream is a trait, Connection is an opaque type. Core types don't assume tokio or quinn in public APIs.