docs(arch): endpoint types and entry points (ADR-086) — resolves OQ-62
Name the three-endpoint-type model (web/native/iroh) and the entry-point vs. endpoint ALPN distinction. This untangles the hub/endpoint/ALPN-config confusion that OQ-62 hinted at: - A hub composes a SUBSET of three endpoint types (web, native, iroh), each with its own identity model, auth model, and transport(s). A full hub runs all three; a minimal hub runs iroh alone (no public IP required). The first real use case is web + native. Corrects the hub README's 'must support TCP+TLS and QUIC' framing. - ALPNs split into entry points (accepted without identity — h2, http/1.1, future alknet/register) and endpoints (identity required before dispatch — alknet/channels, alknet/call, alknet/ssh). This resolves OQ-62: split ALPN lists by endpoint type (Option B), because each endpoint type serves a different client class with different negotiable ALPNs. The assembly-layer wiring pattern is now guessable. - Foundational handlers are two categories, not one: channels data-channel ALPNs (tunnel, socks5, fs, sftp — gated by channels, not in any TLS ALPN list) vs. SSH (an endpoint ALPN that wraps channels inside it, RFC 7250 keys, legacy compat, comes later). Files OQ-65 (WebSocket carrying channels — the browser story update) filed as a one-way-door question, open. ADR-048 is not superseded; OQ-65 may extend it. The web config advertises alknet/channels by default so the hub is ready if OQ-65 resolves to 'WebSocket carries channels.'
This commit is contained in:
1 parent
7610ec1f31
commit
7d9b1ebad9
9 files changed
+800
-129
No files matched your search
@@ -0,0 +1,400 @@
|
||||
# ADR-086: Endpoint Types and Entry Points
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (resolves OQ-62)
|
||||
|
||||
## Context
|
||||
|
||||
> **Terminology note.** "Endpoint" is used in three senses in the
|
||||
> alknet docs, and this ADR uses all three: (1) **`AlknetEndpoint`** —
|
||||
> the struct in `alknet-core` (ADR-010/083) that runs accept loops and
|
||||
> dispatches by ALPN; (2) **endpoint type** — one of web, native, or
|
||||
> iroh, a composition unit with its own identity/auth/transport
|
||||
> (defined in §1 below); (3) **endpoint** in the narrow ALPN sense —
|
||||
> an ALPN whose connections require identity resolution before
|
||||
> dispatch, contrasted with an **entry point** (defined in §2 below).
|
||||
> When the sense is ambiguous, this ADR uses "endpoint type" or
|
||||
> "endpoint ALPN" to disambiguate from `AlknetEndpoint` the struct.
|
||||
|
||||
### The tangle
|
||||
|
||||
The hub/endpoint/TLS configuration has an unnamed distinction at its
|
||||
core that, once named, dissolves several interlocking confusions:
|
||||
|
||||
1. **OQ-62** asked whether a hub passes the same ALPN list to both
|
||||
`TlsServerConfig`s (raw-key + X.509/ACME) or different
|
||||
transport-appropriate lists. The question could not be answered
|
||||
cleanly because the docs treated all ALPNs as the same kind of thing.
|
||||
There was no principled basis for *why* the lists would differ.
|
||||
|
||||
2. **The hub README** states a hub "**must** support TCP+TLS and QUIC
|
||||
endpoints simultaneously," framing it as a hard requirement. This is
|
||||
wrong as a general statement — a minimal hub can run on iroh alone
|
||||
(no public IP/port required), and the first real use case hosts a
|
||||
subset (web + native), not all three. The "must" framing obscures
|
||||
that a hub composes a *subset* of endpoint types, and which subset
|
||||
determines which ALPNs it advertises.
|
||||
|
||||
3. **The ALPN registry** lists `h2`/`http/1.1` alongside
|
||||
`alknet/channels` and `alknet/call` with no distinction in kind.
|
||||
But `h2`/`http/1.1` are structurally different: a connection
|
||||
negotiating `h2` is accepted without an established peer identity
|
||||
(the registration endpoint, browser API routes), while a connection
|
||||
negotiating `alknet/channels` requires identity resolution (fingerprint
|
||||
or bearer token on channel 0). Conflating these under one "ALPN" label
|
||||
is why the ALPN-list-split question had no answer.
|
||||
|
||||
4. **The foundational handlers** were listed as one undifferentiated
|
||||
backlog (ssh, tunnel, socks5, fs, sftp). In fact they fall into two
|
||||
structurally different categories: channels data-channel ALPNs (tunnel,
|
||||
socks5, fs, sftp — gated by channels, opened via `channel/open`, inherit
|
||||
ACL + bidirectionality) vs. an endpoint ALPN that wraps channels inside
|
||||
it (ssh — a legacy-client entry point that runs channels-over-SSH and
|
||||
uses RFC 7250 keys). SSH is not in the same category as the rest.
|
||||
|
||||
### The insight: endpoint types and entry points
|
||||
|
||||
A hub serves different **client classes**, each with a different
|
||||
identity model, auth model, and transport. These are **endpoint
|
||||
types** — independent, composable listeners. A hub composes a subset;
|
||||
the subset determines the ALPN lists.
|
||||
|
||||
Within each endpoint type, there are two kinds of ALPNs:
|
||||
|
||||
- **Entry points** — ALPNs whose connections are accepted without an
|
||||
established peer identity. Per-request auth may apply (registration
|
||||
token, Bearer for API routes), but the connection itself is not
|
||||
identity-gated at the TLS layer. Examples: `h2`/`http/1.1` (HTTP
|
||||
registration, browser API, stealth decoy), the future `alknet/register`
|
||||
ALPN (worker registration over QUIC/TCP without HTTP). Entry points
|
||||
exist to bootstrap a peer relationship or serve non-peer clients
|
||||
(browsers).
|
||||
|
||||
- **Endpoints** (in the narrow sense) — ALPNs whose connections require
|
||||
identity resolution before the handler runs. No identity → the
|
||||
connection is rejected (or, for channels, identity is resolved on
|
||||
channel 0 before dispatch). Examples: `alknet/channels`, `alknet/call`
|
||||
(when used as a top-level ALPN rather than channel 0), `alknet/ssh`.
|
||||
|
||||
This distinction is not cosmetic. It is what makes the ALPN-list-split
|
||||
question answerable: each endpoint type serves a client class, and the
|
||||
ALPNs that client class can negotiate are the ones that endpoint type
|
||||
advertises. A raw-key QUIC listener serving native clients advertises
|
||||
the native ALPNs (`alknet/channels`, `alknet/call`); it does not
|
||||
advertise `h2`/`http/1.1` because browsers cannot connect to a raw-key
|
||||
listener and native clients do not use HTTP ALPNs. An X.509 TCP+TLS
|
||||
listener serving browsers and registration advertises the entry-point
|
||||
ALPNs plus `alknet/channels` (for the WebSocket-channels browser path,
|
||||
per OQ-65).
|
||||
|
||||
### Why iroh is a separate endpoint type
|
||||
|
||||
Iroh is not "just another transport" alongside quinn and TCP+TLS. It is
|
||||
a distinct endpoint type because it combines three things that neither
|
||||
quinn nor TCP+TLS provide alone:
|
||||
|
||||
1. **No public IP/port required** — relay-assisted p2p. A minimal hub
|
||||
with no public presence runs iroh alone.
|
||||
2. **RFC 7250 raw keys built in** — iroh's `Endpoint` handles TLS
|
||||
internally; it does not consume a `rustls::ServerConfig` (ADR-082
|
||||
§"Iroh: shares the key, not the rustls config"). The ALPN list is
|
||||
set via `iroh::Endpoint::builder().alpns()`, not via
|
||||
`TlsServerConfig::new`.
|
||||
3. **Key-based auth (NodeId)** — same fingerprint model as the native
|
||||
quinn path, but the connectivity is p2p.
|
||||
|
||||
A hub that serves all three endpoint types (a "full hub") runs three
|
||||
independent listeners. A hub that serves only iroh (a "minimal hub")
|
||||
runs one. The composition is additive — each endpoint type is an
|
||||
independent `with_*` on `AlknetEndpoint` (ADR-083).
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. Three endpoint types
|
||||
|
||||
A hub composes a subset of three endpoint types. Each is an independent
|
||||
listener with its own identity model, auth model, and transport(s).
|
||||
|
||||
| Endpoint type | Identity | Auth model | Transport(s) | Client class |
|
||||
|---------------|----------|------------|--------------|--------------|
|
||||
| **web** | X.509 (ACME or manual) | token-based (Bearer) | TCP+TLS (HTTP, WebSocket), QUIC (WebTransport — deferred per ADR-044) | browsers, curl, registration, HTTP API consumers |
|
||||
| **native** | RFC 7250 raw key (Ed25519) | key-based (fingerprint) | QUIC (primary), TCP+TLS (fallback when UDP blocked) | alknet-native clients, workers (fingerprint auth) |
|
||||
| **iroh** | RFC 7250 raw key (NodeId) | key-based (fingerprint) | iroh (relay-assisted QUIC) | p2p peers, NAT'd nodes, minimal-hub deployments |
|
||||
|
||||
A hub may run any subset. The subsets that make sense:
|
||||
|
||||
| Hub shape | Endpoint types | Public IP required? | Example |
|
||||
|-----------|---------------|---------------------|---------|
|
||||
| **full hub** | web + native + iroh | yes (web, native) | the general case — browsers, native clients, p2p |
|
||||
| **web + native** | web + native | yes | the first real use case — public domain, native clients |
|
||||
| **native + iroh** | native + iroh | yes (native only) | a hub without browser-facing services |
|
||||
| **minimal hub** | iroh only | no | a p2p-only hub behind NAT, relay-assisted |
|
||||
|
||||
The first real use case is **web + native** (public domain with X.509
|
||||
for browsers/registration + raw-key QUIC for native clients). Iroh is a
|
||||
hard requirement for the project (the p2p, no-public-IP case) but is
|
||||
not in the first deployed subset. All three are hard requirements for
|
||||
the project as a whole — a full hub runs all three.
|
||||
|
||||
### 2. Entry points vs. endpoints (the ALPN-level distinction)
|
||||
|
||||
ALPNs fall into two categories:
|
||||
|
||||
**Entry points** — connections accepted without an established peer
|
||||
identity. The TLS handshake succeeds without client identity; auth
|
||||
happens per-request inside the handler (registration token, Bearer
|
||||
header, or the call-protocol `auth_token` on channel 0 for a channels
|
||||
connection that has not yet established identity). Entry points exist
|
||||
to bootstrap a peer relationship (worker registration) or to serve
|
||||
non-peer clients (browsers, curl).
|
||||
|
||||
| ALPN | Category | Handler | Purpose |
|
||||
|------|----------|---------|---------|
|
||||
| `h2` / `http/1.1` | entry point | `HttpAdapter` | HTTP registration, browser API routes, stealth decoy, WebSocket upgrade |
|
||||
| `alknet/register` (future) | entry point | (registration handler) | Worker registration over QUIC/TCP without HTTP — a direct ALPN for enrollment, avoiding the HTTP layer. Not yet specced; tracked as a hub concern. |
|
||||
|
||||
**Endpoints** (narrow sense) — connections that require identity
|
||||
resolution before the handler runs. The TLS handshake or the
|
||||
call-protocol first frame must produce an identity (fingerprint or
|
||||
token); no identity → rejected.
|
||||
|
||||
| ALPN | Category | Handler | Identity source |
|
||||
|------|----------|---------|-----------------|
|
||||
| `alknet/channels` | endpoint | `ChannelsAdapter` | Fingerprint (raw key / client cert) or bearer token on channel 0 (ADR-072) |
|
||||
| `alknet/call` | endpoint | `CallAdapter` | Fingerprint or bearer token (first frame) — when used as a top-level ALPN; as channel 0 inside channels, identity is resolved before dispatch |
|
||||
| `alknet/ssh` (future) | endpoint | (ssh handler) | RFC 7250 key fingerprint — SSH is a legacy-client entry point that wraps channels inside it (see §4 below) |
|
||||
|
||||
The distinction is structural, not cosmetic: it determines which
|
||||
`TlsServerConfig` advertises which ALPNs (§3 below) and which
|
||||
connections require identity at the TLS layer vs. per-request.
|
||||
|
||||
### 3. ALPN lists are split per endpoint type (resolves OQ-62)
|
||||
|
||||
**Option B — split list, transport-appropriate.** Each `TlsServerConfig`
|
||||
advertises only the ALPNs its client class can negotiate. The assembly
|
||||
layer filters `registry.alpn_strings()` by endpoint type.
|
||||
|
||||
| `TlsServerConfig` / iroh builder | Endpoint type | ALPNs advertised |
|
||||
|----------------------------------|---------------|------------------|
|
||||
| raw-key config (`for_quinn`) | native | `alknet/channels`, `alknet/call`, `alknet/ssh` (future) — the native ALPNs |
|
||||
| raw-key config (`for_tcp_tls`) | native (TCP fallback) | `alknet/channels`, `alknet/call` — native clients using TCP+TLS when UDP is blocked |
|
||||
| X.509/ACME config (`for_tcp_tls`) | web | `h2`, `http/1.1`, `alknet/channels` (for WebSocket-carrying-channels, per OQ-65), `acme-tls/1` (appended automatically by `TlsServerConfig::new`) |
|
||||
| X.509/ACME config (`for_quinn`) | web (WebTransport — deferred) | `h2`, `http/1.1`, `h3` (when WebTransport revives per ADR-044) |
|
||||
| iroh `Endpoint::builder().alpns()` | iroh | `alknet/channels`, `alknet/call` — iroh uses raw keys only; native ALPNs |
|
||||
|
||||
Rationale for split (not same-list):
|
||||
|
||||
- **No dead negotiation.** A raw-key QUIC listener does not advertise
|
||||
`h2`/`http/1.1` — browsers cannot connect to a raw-key listener
|
||||
(RFC 7250 unsupported), and native clients do not negotiate HTTP
|
||||
ALPNs. Advertising them is harmless but misleading: it implies the
|
||||
listener serves a client class it cannot.
|
||||
- **No misleading advertisement.** An X.509 TCP+TLS listener does not
|
||||
advertise `alknet/call` as a top-level ALPN unless the deployment
|
||||
explicitly serves native call-over-TCP clients. The web endpoint
|
||||
serves browsers and registration, not raw call-protocol clients. If
|
||||
a deployment wants call-over-TCP on the web endpoint, it adds
|
||||
`alknet/call` to the X.509 config's list — an explicit choice, not a
|
||||
default.
|
||||
- **The `alknet/channels` exception.** The web endpoint advertises
|
||||
`alknet/channels` so that WebSocket-carrying-channels (OQ-65) works:
|
||||
a browser opens a WebSocket (HTTP upgrade on `h2`/`http/1.1`), and
|
||||
the WebSocket stream carries the channels protocol. The channels
|
||||
ALPN is advertised on the X.509 config for this path, not for
|
||||
native-channels-over-TCP (which is the native endpoint's concern).
|
||||
- **`alknet/register` (future).** When the direct-registration ALPN
|
||||
exists, it is an entry point advertised on both the native and web
|
||||
configs (workers may register over either transport). It is not
|
||||
advertised on iroh (iroh peers establish identity via NodeId, not
|
||||
registration tokens). Revisiting the iroh exclusion requires a new
|
||||
ADR.
|
||||
|
||||
The assembly layer builds the ALPN lists. The pattern (split by
|
||||
endpoint type) is the one-way door — downstream consumers copy it.
|
||||
The specific ALPNs in each list are two-way (additive — adding
|
||||
`alknet/register` or `alknet/ssh` to a config's list is a config
|
||||
change, not a structural one).
|
||||
|
||||
### 4. Foundational handlers — two categories
|
||||
|
||||
The foundational handlers are not one undifferentiated backlog. They
|
||||
fall into two structurally different categories:
|
||||
|
||||
**Channels data-channel ALPNs** — gated by the channels substrate,
|
||||
opened via `channel/open` on channel 0, inherit ACL + bidirectionality
|
||||
from channels + call. These are NOT in any `TlsServerConfig`'s ALPN
|
||||
list — they are negotiated inside channels, not at the TLS layer.
|
||||
|
||||
| ALPN (inside channels) | Crate | Status |
|
||||
|------------------------|-------|--------|
|
||||
| `alknet/tty` | `alknet-tty` | specced (ADR-052–057), implemented |
|
||||
| `alknet/tunnel` | (in `alknet-channels` or sibling) | POC-validated, not yet specced |
|
||||
| `alknet/socks5` | (TBD) | not yet specced — SOCKS5 proxy over channels |
|
||||
| `alknet/fs` | (TBD) | not yet specced — filesystem access over channels |
|
||||
| `alknet/sftp` | (TBD) | not yet specced — SFTP over channels |
|
||||
|
||||
**SSH — an endpoint ALPN that wraps channels.** SSH is structurally
|
||||
different from the channels data-channel ALPNs. It is an endpoint ALPN
|
||||
(negotiated at the TLS layer on the native config), and it runs
|
||||
channels *inside* it (channels-over-SSH): the SSH server accepts a
|
||||
connection, and each SSH channel becomes a channels data-channel ALPN.
|
||||
SSH uses the same RFC 7250 keys as the native endpoint — it is a
|
||||
legacy-client entry point for git/sftp compatibility, not a new
|
||||
identity model. SSH is gated by channels (the channels run inside it)
|
||||
but is itself an endpoint ALPN, not a data-channel ALPN.
|
||||
|
||||
| ALPN | Crate | Category | Status |
|
||||
|------|-------|----------|--------|
|
||||
| `alknet/ssh` | `alknet-ssh` | endpoint ALPN (wraps channels) | not yet specced — russh server channels wrapper for git/sftp compat; legacy clients; comes after tunnel/sftp/etc. |
|
||||
|
||||
SSH is advertised on the **native** config's ALPN list (raw-key QUIC
|
||||
or TCP+TLS), not the web config. It is a legacy-native-client path,
|
||||
not a browser path. It comes later in the roadmap — tunnels, sftp, and
|
||||
other channels data-channel ALPNs are prioritized first because they
|
||||
serve the primary use cases; SSH serves legacy compatibility.
|
||||
|
||||
### 5. A hub composes a subset; "must support TCP+TLS and QUIC" is corrected
|
||||
|
||||
The hub README's "a hub **must** support TCP+TLS and QUIC endpoints
|
||||
simultaneously" is corrected. A hub composes a subset of endpoint
|
||||
types. The subset determines which transports and ALPN lists the hub
|
||||
uses. A minimal hub (iroh only) has no TCP+TLS and no quinn listener;
|
||||
a web+native hub has both but no iroh; a full hub has all three.
|
||||
|
||||
The "must" applied to the first real use case (web + native), not to
|
||||
all hubs. The correction is structural: the hub crate's composition API
|
||||
takes a subset of endpoint types, not a fixed pair.
|
||||
|
||||
## What this does NOT change
|
||||
|
||||
- **`AlknetEndpoint` (ADR-083)** — the endpoint struct is unchanged.
|
||||
It takes transports via `with_quinn` / `with_iroh` / `with_tcp_tls`
|
||||
and runs their accept loops. The endpoint-types model is a
|
||||
composition pattern at the assembly layer, not a new endpoint struct
|
||||
field. The assembly layer builds the `TlsServerConfig`s and the
|
||||
transports per endpoint type and hands them to the endpoint.
|
||||
- **`TlsServerConfig` (ADR-082)** — the `new(identity, alpns)` signature
|
||||
is unchanged. The caller (assembly layer) decides the ALPN list; this
|
||||
ADR specifies *how* the caller decides — by endpoint type, not by
|
||||
"same list or split" guesswork.
|
||||
- **`HandlerRegistry` (ADR-010)** — all ALPNs (entry-point and endpoint)
|
||||
are registered on the same registry. The distinction is in which
|
||||
`TlsServerConfig` advertises them, not in which registry holds them.
|
||||
A connection negotiating `h2` and a connection negotiating
|
||||
`alknet/channels` both dispatch through the same `HandlerRegistry`;
|
||||
the difference is which listener accepted them and whether identity
|
||||
was required at the TLS layer.
|
||||
- **The channels substrate (ADR-071)** — channels data-channel ALPNs
|
||||
are unchanged. They are negotiated inside channels, not at the TLS
|
||||
layer.
|
||||
- **ADR-034 (three peer roles)** — the three peer roles (public X.509
|
||||
endpoint, transport relay, hub/hosting node) are about *client-side
|
||||
outbound* identity. This ADR is about *server-side inbound* endpoint
|
||||
composition. They are orthogonal: a hub (role 3) composes endpoint
|
||||
types for inbound; a client dialing a public X.509 endpoint (role 1)
|
||||
is an outbound concern. The two decisions compose without conflict.
|
||||
- **ADR-044 (WebSocket for browsers)** — the browser bidirectional path
|
||||
uses WebSocket (unchanged). ADR-048 is **not superseded** by this
|
||||
ADR; OQ-65 is a separate question that may extend ADR-048 (WebSocket
|
||||
carrying channels, not just call). Whether WebSocket carries the call
|
||||
protocol only (ADR-048) or carries channels (OQ-65) is a separate
|
||||
question; this ADR's ALPN-list-split accounts for either outcome by
|
||||
advertising `alknet/channels` on the web config by default (the
|
||||
WebSocket-carrying-channels path needs it; the
|
||||
WebSocket-carrying-call-only path does not, but the advertisement is
|
||||
harmless if the hub also serves native channels-over-TCP on the web
|
||||
config).
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- **OQ-62 is resolved.** The ALPN-list question has a principled
|
||||
answer: split by endpoint type, because each endpoint type serves a
|
||||
different client class with different negotiable ALPNs. The assembly
|
||||
layer's wiring pattern is now guessable, not a fork in the docs.
|
||||
- **The hub's composition is explicit.** A hub composes a subset of
|
||||
endpoint types; the subset determines transports, identity models,
|
||||
auth models, and ALPN lists. "Must support TCP+TLS and QUIC" is
|
||||
corrected to "composes the subset its deployment needs." A minimal
|
||||
hub (iroh only) is a first-class shape, not a degenerate case.
|
||||
- **Entry points are named.** The structural difference between
|
||||
`h2`/`http/1.1` (accepted without identity, per-request auth) and
|
||||
`alknet/channels` (identity required) is explicit. This unblocks the
|
||||
`alknet/register` ALPN design (worker registration over QUIC/TCP
|
||||
without HTTP) — it is an entry point, not an endpoint, and its
|
||||
semantics follow from the distinction.
|
||||
- **SSH is correctly categorized.** SSH is an endpoint ALPN that wraps
|
||||
channels, not a channels data-channel ALPN. It is advertised on the
|
||||
native config, not the web config, and it uses RFC 7250 keys (same
|
||||
as the native endpoint). The foundational handler backlog is no
|
||||
longer an undifferentiated list.
|
||||
- **The first real use case is clear.** Web + native (public domain
|
||||
with X.509 + raw-key QUIC) is the first deployed subset. Iroh is a
|
||||
hard requirement for the project but not the first deployed subset.
|
||||
The roadmap is: web + native first, iroh, then foundational handlers
|
||||
(tunnel, sftp, socks5, fs), then SSH (legacy compat, last).
|
||||
|
||||
**Negative:**
|
||||
|
||||
- **The assembly layer has more logic.** Splitting ALPN lists by
|
||||
endpoint type requires the assembly layer to filter
|
||||
`registry.alpn_strings()` per `TlsServerConfig`. This is a small
|
||||
amount of code (a filter per config) but is more than "pass the same
|
||||
list to both." The pattern is documented here; downstream consumers
|
||||
copy it.
|
||||
- **`alknet/channels` appears on the web config.** This is correct
|
||||
(WebSocket-carrying-channels needs it, per OQ-65) but means the web
|
||||
config advertises an ALPN that is also on the native config. A
|
||||
deployment that does not serve WebSocket-channels and does not serve
|
||||
native-channels-over-TCP on the web endpoint can omit
|
||||
`alknet/channels` from the web config. The default (include it) is
|
||||
safer; the omission is an explicit assembly-layer choice.
|
||||
- **The `alknet/register` ALPN is not yet specced.** This ADR names it
|
||||
as a future entry point but does not design it. Worker registration
|
||||
over HTTP (the current OQ-58 path) remains the first implementation;
|
||||
`alknet/register` is a later simplification that removes the HTTP
|
||||
dependency from the registration flow.
|
||||
|
||||
## Door type
|
||||
|
||||
**One-way.** The three-endpoint-type model, the entry-point/endpoint
|
||||
distinction, and the split-by-endpoint-type ALPN list pattern are
|
||||
structural. The assembly-layer wiring pattern is what downstream
|
||||
consumers copy; reversing it (back to same-list, or back to
|
||||
undifferentiated ALPNs) would break the composition model and re-introduce
|
||||
the tangle this ADR resolves. The specific ALPNs in each list are
|
||||
two-way (additive); the pattern (split by endpoint type) is one-way.
|
||||
|
||||
## References
|
||||
|
||||
- OQ-62 (resolved by this ADR) — does a hub pass the same ALPN list to
|
||||
both `TlsServerConfig`s?
|
||||
- [ADR-082](082-alknet-tls-extraction.md) — `TlsServerConfig::new(identity, alpns)`;
|
||||
the caller decides the ALPN list; this ADR specifies how
|
||||
- [ADR-083](083-endpoint-as-accept-loop-runner.md) — `AlknetEndpoint` as
|
||||
multi-transport accept-loop runner; the endpoint-types model is a
|
||||
composition pattern on top of it
|
||||
- [ADR-085](085-workspace-scope-core-vs-consumer-repos.md) — workspace
|
||||
scope; the foundational handler categorization (§4) amends the scope
|
||||
table's handler list
|
||||
- [ADR-071](071-channels-wire-format.md) — channels data-channel ALPNs
|
||||
are negotiated inside channels, not at the TLS layer
|
||||
- [ADR-072](072-channel-0-pre-negotiated-call.md) — channel 0 identity
|
||||
resolution (why `alknet/channels` is an endpoint, not an entry point)
|
||||
- [ADR-044](044-defer-webtransport-browsers-use-websocket.md) —
|
||||
WebSocket for browsers; WebTransport deferred
|
||||
- [ADR-048](048-websocket-native-session-not-gateway.md) — WebSocket
|
||||
carries the native call-protocol session (OQ-65 may extend this to
|
||||
channels)
|
||||
- [ADR-034](034-outgoing-only-x509-and-three-peer-roles.md) — three
|
||||
peer roles (client-side outbound); orthogonal to this ADR's
|
||||
server-side inbound endpoint composition
|
||||
- [ADR-027](027-tls-identity-redesign-acme-rawkey-decoupling.md) —
|
||||
`TlsIdentity` (RawKey / X509 / Acme); the identity models per
|
||||
endpoint type
|
||||
- OQ-58 — worker registration flow (the entry point that
|
||||
`alknet/register` will eventually serve directly)
|
||||
- OQ-65 — WebSocket carrying channels (the browser path that requires
|
||||
`alknet/channels` on the web config)
|
||||
Reference in new issue
Block a user