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)
This commit is contained in:
glm-5.2 committed 2026-07-12 10:55:25 +00:00
1 parent 3954c788d4
commit 02c5b9e039
4 files changed
+184 -11

No files matched your search

@@ -140,11 +140,22 @@ delegates to `self.source`. `remote_alpn` reads `self.alpn` (unchanged).
| `from_quinn` / `from_quinn_with_alpn` (feature `quinn`) | `QuinnBidiStreamSource` (crate-private) |
| `from_iroh` (feature `iroh`) | `IrohBidiStreamSource` (crate-private) |
| `from_stream` / `from_bidi` (no feature gate) | `StreamBidiStreamSource` (crate-private, yield-once) |
| `from_source` (no feature gate) | caller-supplied `impl BidiStreamSource` — the extension point for downstream crates |
`from_source(source: impl BidiStreamSource, alpn: Vec<u8>) -> Self` is the
constructor that makes the trait the extension point. A downstream crate
implements `BidiStreamSource` (e.g. the channels crate's
`ChannelBidiStreamSource`) and constructs a `Connection` from it via
`from_source` — no core edit. The built-in impls (`QuinnBidiStreamSource`,
`IrohBidiStreamSource`, `StreamBidiStreamSource`) are crate-private;
`from_source` is the only path a downstream crate uses to wrap its own
impl. The `from_quinn` / `from_iroh` / `from_stream` / `from_bidi`
constructors are convenience wrappers for the three built-in impls.
The `Stream`-backend implementations are crate-private; downstream crates
do not implement `BidiStreamSource` by wrapping `from_stream`. They
implement the trait directly (channels: `ChannelBidiStreamSource`), or they
use a public constructor that already wraps an impl.
implement the trait directly (channels: `ChannelBidiStreamSource`) and
construct the `Connection` via `from_source`.
### `from_stream`-backed default impl is the compatibility path
@@ -233,10 +244,10 @@ the args are optional for their transport.
- `Connection` is open for extension. The channels crate implements
`ChannelBidiStreamSource` in its own crate and constructs `Connection`
from it — no core edit. A future transport, test double, or relay
connection follows the same path. This is the structural payoff: the
connection type is no longer a closed enum that every new connection
shape must edit.
from it via `from_source` — no core edit. A future transport, test
double, or relay connection follows the same path. This is the
structural payoff: the connection type is no longer a closed enum that
every new connection shape must edit.
- A channels connection is a first-class peer of QUIC: one
`ChannelConnection` that yields N streams, rather than a bag of yield-
once `Connection`s. The channels layer's API matches its actual shape.