Files
alknet/docs/architecture/crates/core/README.md
T
glm-5.2 02c5b9e039 docs(arch): add Connection::from_source to ADR-070 — the missing extension point
ADR-070 made Connection hold Box<dyn BidiStreamSource> so downstream
crates can add connection shapes without editing core. The trait and
three built-in impls landed, but the public constructor that lets a
downstream crate construct a Connection from its own BidiStreamSource
impl was never added — the source field is private with no from_source
constructor. The channels POC update surfaced this when it tried to
use the trait directly and found no way to build a Connection from a
ChannelBidiStreamSource.

This is a gap in the ADR-070 implementation, not a new decision. ADR-070
§Consequences says 'the channels crate implements ChannelBidiStreamSource
in its own crate and constructs Connection from it' — the constructor for
that path is what was missing.

- ADR-070: add from_source to the Constructors table + reword the
  downstream-crates paragraph to make the two paths explicit
  (from_source for custom impls; from_quinn/from_iroh/from_stream for
  built-in impls)
- core-types.md: add from_source to the impl Connection block, the
  built-in implementations table, and the design-decisions table entry
- tasks/core/connection-from-source-constructor.md: the implementation
  task (one constructor + one test, scope narrow, risk low)
2026-07-12 10:55:25 +00:00

5.6 KiB

status, last_updated
status last_updated
draft 2026-07-12

alknet-core

Core library for ALPN-based protocol dispatch. Every handler crate depends on alknet-core.

Documents

Document Status Description
core-types.md draft ProtocolHandler trait, HandlerError, Connection (Box<dyn BidiStreamSource> — ADR-070), BidiStreamSource trait, BiStream, StreamError
endpoint.md draft ALPN router, HandlerRegistry, accept loop, graceful shutdown
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 Endpoint, HandlerRegistry, accept loop
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)

Relevant Open Questions

OQ Title Status Relevance
OQ-04 Dynamic handler registration resolved (start static) HandlerRegistry is immutable at startup
OQ-05 Multi-connectivity endpoint resolved (quinn + iroh) AlknetEndpoint supports both, both feature-gated
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 deferred(scope) Blocked on a second transport's real client (not a second QUIC client); extracting a QUIC-shaped connector now would bake QUIC in as the establishment shape — the welding ADR-065 unwound on the server side

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 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.