First speccing pass for alknet-http (HTTP interface crate: h2/http1.1/h3 server + from_openapi/to_openapi/from_mcp/to_mcp adapters). Specs (crates/http/): - README.md, overview.md — crate index, two-roles-in-one-crate framing, adapter location map, feature gates (h3, mcp), no-env-vars invariant - http-server.md — HttpAdapter for h2/http1.1, axum over QUIC stream, Bearer auth, SSE projection for subscriptions, /healthz, stealth decoy - http-adapters.md — from_openapi (reqwest) and to_openapi (projection), error fidelity (HTTP_<status> per ADR-023), type definitions - http-mcp.md — from_mcp/to_mcp (feature-gated), streamable-HTTP-only - webtransport.md — h3/WebTransport handler, browser streaming path, HTTP/3 request vs WebTransport session distinguished at framing layer ADRs: - ADR-036 HTTP-to-Call Operation Mapping (Proposed) — direct path mapping; to_openapi is projection, not router (the load-bearing one-way door from Phase 0 DH-3) - ADR-037 MCP Stdio Transport Exclusion (Proposed) — streamable HTTP only; stdio is not built (RCE-vector security position) - ADR-038 HTTP/3 and WebTransport as First-Class HTTP Transports (Proposed) — corrects the Phase 0 DH-2 deferral framing; h3 is in scope, not deferred, per ADR-009 §'What this framework is NOT' - ADR-039 HTTP Server and Client Host Colocated in alknet-http (Proposed) — one crate for server + client host (shared HTTP deps, shared operation-spec->HTTP mapping) - ADR-003 Amendment 1 — clarifies alknet-call is a protocol-foundation crate (the alknet-http -> alknet-call dependency edge) Open questions (OQ-38, OQ-39, OQ-40 added under 'Theme: alknet-http'): - OQ-38 WebTransport relay-as-proxy scope (genuine scope question, not a deferral — the decision is made when the use case becomes concrete) - OQ-39 to_openapi published-spec versioning (one-way after first publication) - OQ-40 reqwest client config and connection pooling (two-way-door) Architecture README and overview updated with doc table, ADR table (036-039), current-state note, and crate graph (alknet-http -> alknet-call edge). Reviewed by architecture-reviewer subagent: 3 critical, 4 warning, 5 suggestion issues found and fixed (missing ADR-039, WebTransport stream routing conflation, undefined types, stale OQ-37 deferral language, README OQ table completeness, Bearer-only attribution, cross-references, ADR-038 ALPN quote, feature-gate placeholder, MCP temporal language).
18 KiB
status, last_updated
| status | last_updated |
|---|---|
| draft | 2026-06-28 |
Alknet Architecture
Current State
Pre-implementation of the storage/repo pattern. The project has completed a pivot from a three-layer model to an ALPN-as-service model. The greenfield workspace contains alknet-vault (stable — implementation complete and verified, local-only by construction per ADR-025, HD-derivation key model per ADR-026) and research/reference material. Foundational ADRs (001–035) are in place, with the call crate implemented and reviewed.
The storage and auth strategy research (docs/research/alknet-storage-strategy/findings.md) surfaced the repo/adapter pattern as the answer to cross-node state (peer identity, credentials). This has now landed as four ADRs:
- ADR-030 (PeerEntry and Identity.id decoupling):
authorized_fingerprints: HashSet<String>→peers: Vec<PeerEntry>;Identity.idbecomes the stablepeer_id(not the fingerprint); key rotation changes the fingerprint, not the identity. Supersedes ADR-029's v1 UUID source (the one-way door —PeerIdis logical, not crypto — is preserved; the source changes from UUID toIdentity.idfromPeerEntry). Resolves OQ-33 and the storage-boundary half of OQ-34. - ADR-031 (CredentialStore repo trait): the second repo trait in core (alongside
IdentityProvider), withInMemoryCredentialStoredefault adapter. Establishes the credential-persistence abstraction. - ADR-032 (Forwarded-for identity):
forwarded_forfield oncall.requestedandOperationContext; metadata only —AccessControl::checknever reads it; thefrom_callhandler populates it. Wire-format one-way door, included with the ADR-029 migration window. - ADR-033 (Storage boundary and repo/adapter pattern): core defines repo traits + in-memory defaults; persistence adapters are separate crates; the assembly layer wires the adapter. Resolves OQ-34's storage-boundary question. Concrete adapter shapes now committed by ADR-035 (was OQ-36).
The alknet-call crate is implemented and reviewed — both the server-side core and the client/adapter surface (207 lib + 2 integration tests passing). The alknet-core and alknet-call crate specs are in draft; the alknet-vault crate specs are stable.
alknet-http specs drafted. The alknet-http crate (HTTP interface — h2/http/1.1/h3 server + from_openapi/to_openapi/from_mcp/to_mcp adapters) now has architecture specs: crates/http/ (overview, http-server, http-adapters, http-mcp, webtransport) and four new ADRs — ADR-036 (HTTP-to-call mapping), ADR-037 (MCP stdio exclusion), ADR-038 (HTTP/3 + WebTransport as first-class, correcting the Phase 0 deferral framing), ADR-039 (HTTP server + client host colocated in one crate). ADR-003 Amendment 1 clarifies that alknet-call is a protocol-foundation crate (the alknet-http → alknet-call dependency edge). The specs are in draft; implementation has not started. Three open questions carried: OQ-38 (WebTransport relay-as-proxy scope), OQ-39 (to_openapi published-spec versioning), OQ-40 (reqwest client config).
Next step: The storage/repo-pattern ADRs (030–033) are accepted and amend the core and call specs. The next implementation phase is the ADR-029 migration (peer-keyed overlays, PeerRef routing, retire remote_safe/trusted_peer) with the ADR-030 PeerEntry change and the ADR-032 forwarded_for field folded in — the OperationContext, from_call handler, and AuthPolicy are all under edit, making this the cheapest window. After that: alknet-http implementation (specs drafted, ADRs 036–038 proposed), which consumes the CredentialStore trait and the OperationAdapter contract. The alknet-ssh crate (the other post-core crate, specced in parallel) proceeds independently — it depends on alknet-core, not alknet-call.
Architecture Documents
| Document | Status | Description |
|---|---|---|
| overview.md | draft | Workspace-level overview, crate graph, shared types, design principles |
| open-questions.md | draft | Centralized OQ tracker with door-type classifications |
| crates/core/README.md | draft | alknet-core crate index |
| crates/core/core-types.md | draft | ProtocolHandler, HandlerError, Connection, BiStream, StreamError |
| crates/core/endpoint.md | draft | ALPN router, HandlerRegistry, accept loop, shutdown |
| crates/core/auth.md | draft | AuthContext, Identity, IdentityProvider, AuthToken, resolution flow |
| crates/core/config.md | draft | StaticConfig, DynamicConfig, ArcSwap, ConfigReloadHandle |
| crates/call/README.md | draft | alknet-call crate index |
| crates/call/call-protocol.md | draft | CallAdapter, EventEnvelope framing, stream model, PendingRequestMap, bidirectional calls, streaming subscribe example |
| crates/call/operation-registry.md | draft | OperationSpec, Handler, OperationRegistry, AccessControl, capability injection, service discovery, irpc integration |
| crates/call/client-and-adapters.md | draft | CallClient (outbound connection opener), from_call / from_jsonschema, OperationAdapter trait, adapter location map, no-env-vars invariant, exchange-of-operations pattern |
| crates/http/README.md | draft | alknet-http crate index |
| crates/http/overview.md | draft | Crate purpose, two roles (server + client host), dependencies, adapter location map |
| crates/http/http-server.md | draft | HttpAdapter for h2/http1.1, axum over QUIC, Bearer auth, stealth, /healthz |
| crates/http/http-adapters.md | draft | from_openapi (reqwest) and to_openapi (projection); no-env-vars injection point |
| crates/http/http-mcp.md | draft | from_mcp / to_mcp (feature-gated), streamable-HTTP-only, stdio exclusion |
| crates/http/webtransport.md | draft | h3/WebTransport handler — the browser streaming path |
| crates/vault/README.md | stable | alknet-vault crate index |
| crates/vault/mnemonic-derivation.md | stable | BIP39, SLIP-0010, BIP-0032, derivation paths, key types |
| crates/vault/encryption.md | stable | AES-256-GCM, EncryptedData, key versioning, salt (Phase B reserved) |
| crates/vault/service.md | stable | VaultServiceHandle lifecycle, direct dispatch, cache, error model |
| crates/vault/protocol.md | stable | DerivedKey redaction, KeyType, serialization behavior |
ADR Table
| ADR | Title | Status |
|---|---|---|
| 001 | ALPN-Based Protocol Dispatch | Accepted |
| 002 | ProtocolHandler Trait | Accepted |
| 003 | Crate Decomposition | Accepted |
| 004 | Auth as Shared Core (IdentityProvider) | Accepted |
| 005 | irpc as Call Protocol Foundation | Accepted |
| 006 | ALPN String Convention and Connection Model | Accepted |
| 007 | BiStream Type Definition | Accepted |
| 008 | Vault Integration Point | Accepted |
| 009 | One-Way Door Decision Framework | Accepted |
| 010 | ALPN Router and Endpoint | Accepted |
| 011 | AuthContext Structure and Resolution Flow | Accepted |
| 012 | Call Protocol Stream Model | Accepted |
| 013 | Rust as Canonical Implementation Language | Accepted |
| 014 | Secret Material Flow and Capability Injection | Accepted |
| 015 | Privilege Model and Authority Context | Accepted |
| 016 | Abort Cascade for Nested Calls | Accepted |
| 017 | Call Protocol Client and Adapter Contract | Accepted |
| 018 | Vault as Standalone Crate | Accepted |
| 019 | Vault Assembly-Layer-Only Access | Accepted |
| 020 | HD Derivation for Encryption Keys | Accepted |
| 021 | Key Rotation via Version-Indexed Paths | Accepted |
| 022 | Handler Registration, Provenance, and Composition Authority | Accepted |
| 023 | Operation Error Schemas | Accepted |
| 024 | Operation Registry Layering | Accepted |
| 025 | Vault Local-Only Dispatch | Accepted |
| 026 | Vault Key Model — HD Derivation | Accepted |
| 027 | TLS Identity Redesign — ACME + RawKey Decoupling | Accepted |
| 028 | Peer-Scoped Registry Filtering for CallClient Inbound Dispatch | |
| 029 | Peer-Graph Routing Model for alknet-call Composition | Accepted (Assumption 1's PeerId source superseded by ADR-030) |
| 030 | PeerEntry and Identity.id Decoupling | Accepted (supersedes ADR-029 Assumption 1's UUID source) |
| 031 | CredentialStore Repo Trait | Accepted |
| 032 | Forwarded-For Identity (Metadata, Not Authority) | Accepted |
| 033 | Storage Boundary and Repo/Adapter Pattern | Accepted |
| 034 | Outgoing-Only X.509 and the Three Peer Roles | Accepted |
| 035 | Concrete Persistence Adapter Shapes — Read/Write Split, honker+SQLite | Accepted |
| 036 | HTTP-to-Call Operation Mapping | Proposed |
| 037 | MCP Stdio Transport Exclusion | Proposed |
| 038 | HTTP/3 and WebTransport as First-Class HTTP Transports | Proposed |
| 039 | HTTP Server and Client Host Colocated in alknet-http | Proposed |
Open Questions
See open-questions.md for the full tracker.
Resolved one-way doors:
- OQ-01: BiStream type — trait with Connection parameter (ADR-007)
- OQ-02: AuthContext timing — hybrid model (ADR-004)
- OQ-03: ALPN naming —
alknet/prefix, no version (ADR-006) - OQ-05: Multi-connectivity endpoint — quinn + iroh, both feature-gated (ADR-010)
- OQ-06: ALPN per connection, not per stream (ADR-006)
- OQ-08: Vault integration — CLI-embedded, assembly-layer only (ADR-008, ADR-014)
- OQ-16: Safe vault operations for call protocol exposure — none for now (ADR-014)
- OQ-18: Privilege model —
internal= authority switch, External/Internal visibility, handler identity + scoped env (ADR-015) - OQ-17: Abort cascade —
call.abortedcascades to descendants; defaultabort-dependents,continue-runningopt-in (ADR-016) - OQ-15: Call protocol client and adapter contract —
CallClientopens connections;from_callimports remote ops; connection direction independent of call direction (ADR-017)
Resolved two-way doors:
- OQ-04: Dynamic handler registration — static at startup (ADR-010); scoped to the
HandlerRegistry(ALPN-level) by ADR-024, which governsOperationRegistrymutability separately - OQ-07: Call protocol scope — bidirectional streams, EventEnvelope, ID-based correlation (ADR-012)
- OQ-11: Handler-level auth resolution observability — handlers store resolved identity on Connection (Option B); two identity scopes: connection-level (observability) and per-request (ACL)
- OQ-12: TLS identity provisioning — two use cases: RFC 7250 raw keys (default, P2P) and X.509 certs (domain-hosted, browsers). ACME designed in ADR-027; RawKey decoupled from iroh feature.
- OQ-13: Operation path format —
/{service}/{op}is the correct design for alknet-call, not a simplification - OQ-14: Batch operation semantics — multiple correlated
call.requestedevents is the correct protocol design, not a simplification - OQ-19: Session-scoped registries — agent-written operations via
OperationEnvtrait layering; protocol doesn't need changes;OperationEnvmust remain a trait. Generalized by ADR-024 to cover connection-scoped overlays as well. - OQ-20: Encryption key derivation — HD derivation from BIP39 seed, not PBKDF2; salt field unused in v2 (wire-format compat) (ADR-020)
- OQ-21: Remote vault access — resolved (ADR-025): vault is local-only by construction; remote access requires a separate vault-server crate with its own ADR
- OQ-22: Key rotation — version-indexed derivation paths;
rotatemethod re-encrypts (ADR-021) - OQ-23: Handler identity registration path — registration bundle with provenance, composition authority, scoped env, capabilities (ADR-022)
- OQ-24: Operation error schemas — declared domain errors with typed
detailspayload; adapter fidelity forfrom_openapi/to_openapi(ADR-023)
Resolved by the storage/repo-pattern ADRs (ADR-030–033):
- OQ-33:
PeerId stability— resolved by ADR-030 (logical id; source isIdentity.id=PeerEntry.peer_id, stable across key rotation; UUID workaround removed) - OQ-34:
Persistent peer registry— resolved by ADR-030 + ADR-031 + ADR-033 (storage boundary: core defines repo traits + in-memory defaults; persistence adapters are separate crates) - OQ-35:
API key asymmetry— dissolved (the framing was wrong;PeerEntrysupports multiple credential paths)
Resolved by the call-completion / ADR-029 work:
- OQ-27:
— resolved (auto-re-import on connection establishment;from_callre-import triggerrefresh()is a feature addition) - OQ-28:
— resolved (same-peer collision = error; cross-peer dissolved by ADR-029)from_callnamespace collision - OQ-29:
CallClient TLS client-auth— resolved (wire quinn client-auth; key-type-aware server cert verification; fingerprint normalization toed25519:across quinn/iroh) - OQ-30:
— resolved (insertion-order first-match; richer routing is a feature extension)PeerRef::Anyrouting policy - OQ-31:
— resolved (opt-inservices/list-peersre-export semanticsservices/list-peers;services/listis "own ops only")
Open (feature extensions, not blocking):
- OQ-32: Multi-hop federation — the one-hop model is the architectural commitment; multi-hop is a feature extension that doesn't break downstream
- OQ-36:
Concrete persistence adapter shapes— resolved by ADR-035 (read-sync / write-async / honker-NOTIFY cache invalidation;alknet-store-sqlitecrate;IdentityStorewrite trait;CredentialStore::put/deleteasync) - OQ-37:
X.509 outgoing-only case— resolved by ADR-034 (three remote roles named: public X.509 endpoint, transport relay, hub;PeerEntryasymmetry is correct; client-side verifier selection byPeerEntrypresence) - OQ-38: WebTransport relay-as-proxy scope — does the proxy live in
alknet-httpor a separate relay crate? (scope question, not deferral; ADR-038 brought h3 into scope) - OQ-39:
to_openapipublished-spec versioning — versioning strategy for generated OpenAPI specs (one-way after first publication) - OQ-40: reqwest client config and connection pooling — two-way-door config shape for the outbound HTTP client
Deferred (not active):
- OQ-09: WASM target boundaries — design constraint, not deliverable
- OQ-10: Git adapter scope — start with smart protocol, add ERC721 later
Document Lifecycle
| Status | Meaning | Transitions |
|---|---|---|
draft |
Under active development. May change significantly. | → reviewed when open questions are resolved |
reviewed |
Architecture is final. Implementation may begin. Changes require review. | → stable when implementation is complete and verified |
stable |
Locked. Changes require review and may warrant an ADR. | → deprecated when superseded |
deprecated |
Superseded. Kept for reference. | Removed when no longer referenced |
References
- Pivot proposal:
docs/research/pivot/alpn-service-architecture.md - Cleanup plan:
docs/research/pivot/cleanup-plan.md - SDD process:
docs/sdd_process.md - Reference implementation:
/workspace/@alkdev/alknet-main/