docs(arch): endpoint as pure accept-loop runner + acme-tls/1 guard relocation (ADR-083, OQ-60/61)
ADR-083: AlknetEndpoint becomes a pure accept-loop runner with a public dispatch method. Transport construction moves out of the endpoint — the assembly layer reads StaticConfig, builds transports from TlsServerConfig(s), and hands pre-built quinn/iroh endpoints to the endpoint via with_quinn/with_iroh. TCP+TLS dispatch is first-class (same dispatch path as quinn/iroh); ADR-010 Amendment 1's duplicated-dispatch workaround is retired. StaticConfig stays in core as the assembly-layer config; the endpoint takes only drain_timeout. The acme-tls/1 guard moves from dispatch_quinn to the shared dispatch method — ACME TLS-ALPN-01 challenges arrive over TCP (CAs validate via TCP to port 443, not QUIC), so the guard's quinn-specific location was a latent bug once TCP+TLS exists. The guard is transport-agnostic; the rationale (no handler, silent close) is unchanged. ADR-027 §5 amended. OQ-60: where build_iroh_endpoint lives (assembly layer / alknet-tls helper / transport module). build_quinn_server_config_from_rustls is decided — it moves to alknet-tls as for_quinn() per ADR-082; only build_iroh_endpoint is genuinely undecided. OQ-61: multi-owner shutdown coordination. Boundary committed (endpoint owns dispatched handlers; assembly layer owns spawned accept loops); mechanism open. ADR-082 amended: drops the Arc<TlsServerConfig> endpoint signature (superseded by ADR-083); keeps its scope as the alknet-tls crate's TlsServerConfig + accessors. Review: zero critical issues, five warnings fixed (build_iroh_endpoint destination contradiction, undeclared shutdown_sender, missing ADR-027 amendment marker, underspecified dispatch no-match behavior, stale door-type timing clause).
This commit is contained in:
1 parent
9823c6e4ab
commit
81bde6f28f
8 files changed
+564
-50
No files matched your search
@@ -0,0 +1,50 @@
|
||||
# OQ-60: Where Does Transport Construction Live?
|
||||
|
||||
- **Origin**: `docs/architecture/decisions/083-endpoint-as-accept-loop-runner.md`
|
||||
(the endpoint refactor commits to the boundary — construction is not
|
||||
in the endpoint — but not the location of `build_iroh_endpoint`).
|
||||
- **Status**: open
|
||||
- **Door type**: one-way (where `build_iroh_endpoint` lives determines
|
||||
who depends on `iroh` for transport construction; moving it later
|
||||
churns the dep graph and every binary's assembly code)
|
||||
- **Priority**: high (the hub is the first multi-transport consumer;
|
||||
its assembly code sets the pattern)
|
||||
- **Blocked on**: nothing structural. The three options are clear; the
|
||||
decision is a trade-off, not a missing capability.
|
||||
- **Scope**: This OQ covers **`build_iroh_endpoint`** — the function
|
||||
that reads `StaticConfig` and builds an `iroh::Endpoint`.
|
||||
`build_quinn_server_config_from_rustls` is **decided** (it moves to
|
||||
`alknet-tls` as `TlsServerConfig::for_quinn()` per ADR-082 — it's a
|
||||
thin wrapper over a `rustls::ServerConfig`, which `alknet-tls` owns).
|
||||
Only `build_iroh_endpoint` is genuinely undecided: it reads
|
||||
`StaticConfig` (not a rustls config), builds an `iroh::Endpoint` from
|
||||
an `Ed25519SecretKey` + relay URL, and doesn't fit the `alknet-tls`
|
||||
cert-provider boundary.
|
||||
- **Resolution**: Not yet decided. The options:
|
||||
|
||||
**Option A: In the assembly layer (the binary).** Each binary reads
|
||||
`StaticConfig` and hand-assembles quinn/iroh/TCP+TLS. Pro: maximal
|
||||
flexibility, core stays lean. Con: every binary duplicates the
|
||||
"build an iroh endpoint from an `Ed25519SecretKey` + relay URL"
|
||||
boilerplate; a 10-step procedure is copy-pasted per binary.
|
||||
|
||||
**Option B: In `alknet-tls` as convenience helpers.** `alknet-tls`
|
||||
gains a `build_iroh_endpoint` helper. Pro: one place. Con: `alknet-tls`
|
||||
then depends on `iroh`, bloats a crate whose stated job is "TLS setup,
|
||||
not transport endpoint construction" (ADR-082 scopes `alknet-tls` to
|
||||
cert config and its accessors — `build_iroh_endpoint` doesn't touch
|
||||
certs, it touches iroh's relay/secret-key APIs).
|
||||
|
||||
**Option C: A new crate or module — `alknet-transport` / an
|
||||
`alknet-core::transport` module — that owns transport construction.**
|
||||
Pro: clean separation (TLS = certs, transport = endpoints, endpoint =
|
||||
dispatch). Con: another layer in the dep graph.
|
||||
|
||||
The ADR-082 boundary ("`alknet-tls` is the cert provider, not the
|
||||
transport constructor") is a strong argument against Option B. Option C
|
||||
is the cleanest separation but adds a layer. Option A is simplest but
|
||||
risks per-binary duplication that drifts.
|
||||
- **Cross-references**: ADR-083 (endpoint refactor), ADR-082
|
||||
(`alknet-tls` — the cert provider boundary; `for_quinn()` is in scope,
|
||||
`build_iroh_endpoint` is not), ADR-010 (original endpoint design,
|
||||
where construction was welded to the endpoint)
|
||||
@@ -0,0 +1,42 @@
|
||||
# OQ-61: Multi-Owner Shutdown Coordination
|
||||
|
||||
- **Origin**: `docs/architecture/decisions/083-endpoint-as-accept-loop-runner.md`
|
||||
(the endpoint owns dispatched handlers; the assembly layer owns
|
||||
spawned accept loops — coordination between them on shutdown is
|
||||
unspecified).
|
||||
- **Status**: open
|
||||
- **Door type**: two-way (the coordination mechanism is an
|
||||
implementation detail; the ownership boundary — endpoint owns
|
||||
dispatched handlers, assembly layer owns spawned accept loops — is
|
||||
the one-way part, committed in ADR-083)
|
||||
- **Priority**: medium (matters for clean hub shutdown; doesn't block
|
||||
the endpoint-shape decision or the TLS extraction)
|
||||
- **Blocked on**: nothing structural. The question is which
|
||||
coordination primitive (shared `shutdown_sender`, separate channel,
|
||||
drain semantics) — a design choice, not a missing capability.
|
||||
- **Resolution**: Not yet decided. The boundary is clear:
|
||||
|
||||
- The endpoint owns shutdown of **dispatched handlers** (it spawned
|
||||
them via `tokio::spawn` in `dispatch`).
|
||||
- The assembly layer owns shutdown of the **accept loops it spawned**
|
||||
(the TCP+TLS listeners).
|
||||
|
||||
The open question is the **coordination mechanism**:
|
||||
|
||||
- Does the assembly layer use the endpoint's `shutdown_sender()` to
|
||||
signal the TCP+TLS loops, or a separate channel?
|
||||
- Does `endpoint.shutdown()` drain in-flight dispatched handlers
|
||||
(including those from TCP+TLS loops), or only the quinn/iroh ones
|
||||
it spawned via `run()`?
|
||||
- What happens to in-flight `dispatch` calls after the endpoint is
|
||||
shut down — are they rejected, or do they complete?
|
||||
|
||||
A likely shape: the assembly layer uses the endpoint's
|
||||
`shutdown_sender()` for all its accept loops (one signal, all loops
|
||||
stop accepting); the endpoint's `shutdown()` drains all dispatched
|
||||
handlers regardless of which transport spawned them (the endpoint
|
||||
owns them all once `dispatch` is called). But this needs to be
|
||||
written down and verified against the drain semantics.
|
||||
- **Cross-references**: ADR-083 (endpoint refactor — ownership
|
||||
boundary), ADR-010 (original shutdown design — single-owner, the
|
||||
simpler case being generalized)
|
||||
Reference in new issue
Block a user