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:
1 parent
3954c788d4
commit
02c5b9e039
4 files changed
+184
-11
No files matched your search
@@ -34,7 +34,7 @@ Core library for ALPN-based protocol dispatch. Every handler crate depends on al
|
||||
| [031](../../decisions/031-credentialstore-repo-trait.md) | CredentialStore Repo Trait | Second repo trait in core; `InMemoryCredentialStore` default adapter |
|
||||
| [033](../../decisions/033-storage-boundary-and-repo-adapter-pattern.md) | Storage Boundary and Repo/Adapter Pattern | Core defines traits + in-memory defaults; persistence adapters are separate crates |
|
||||
| [065](../../decisions/065-connection-from-stream-generic-single-stream.md) | `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](../../decisions/070-bidistreamsource-trait.md) | BidiStreamSource Trait — Open Connection for Extension | `Connection` holds `Box<dyn BidiStreamSource>`; QUIC/iroh/stream wrap crate-private impls; downstream crates implement the trait to add connection shapes (channels, future transports) without editing core |
|
||||
| [070](../../decisions/070-bidistreamsource-trait.md) | 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
|
||||
|
||||
|
||||
@@ -94,6 +94,11 @@ impl Connection {
|
||||
remote_addr: Option<SocketAddr>,
|
||||
) -> Self;
|
||||
|
||||
/// Construct from a caller-supplied `BidiStreamSource` impl. The
|
||||
/// extension point for downstream crates — implement the trait and
|
||||
/// construct a `Connection` from it without editing core. See ADR-070.
|
||||
pub fn from_source(source: impl BidiStreamSource, alpn: Vec<u8>) -> Self;
|
||||
|
||||
pub async fn accept_bi(&self) -> Result<(SendStream, RecvStream), StreamError>;
|
||||
pub async fn open_bi(&self) -> Result<(SendStream, RecvStream), StreamError>;
|
||||
pub fn remote_alpn(&self) -> &[u8];
|
||||
@@ -186,11 +191,15 @@ indirection and are not the transport's concern.
|
||||
| `QuinnBidiStreamSource` | `Connection::from_quinn` / `from_quinn_with_alpn` (feature `quinn`) | many streams |
|
||||
| `IrohBidiStreamSource` | `Connection::from_iroh` (feature `iroh`) | many streams |
|
||||
| `StreamBidiStreamSource` | `Connection::from_stream` / `from_bidi` (no feature gate) | yield-once, then `ConnectionClosed`; `open_bi` returns `StreamClosed` |
|
||||
| *(caller-supplied)* | `Connection::from_source` (no feature gate) | per the caller's `BidiStreamSource` impl |
|
||||
|
||||
Downstream crates do not wrap `from_stream` to implement
|
||||
`BidiStreamSource` — they implement the trait directly. `from_stream` is
|
||||
the compatibility path for callers that want a `Connection` over a single
|
||||
pre-split stream (the ADR-065 use case).
|
||||
`BidiStreamSource` — they implement the trait directly and construct the
|
||||
`Connection` via `from_source`. `from_stream` is the compatibility path for
|
||||
callers that want a `Connection` over a single pre-split stream (the
|
||||
ADR-065 use case); `from_source` is the extension path for callers that
|
||||
implement `BidiStreamSource` themselves (the channels crate's
|
||||
`ChannelBidiStreamSource`, a future transport, a test double).
|
||||
|
||||
## BiStream
|
||||
|
||||
@@ -366,7 +375,7 @@ registration bundle.
|
||||
| ProtocolHandler receives Connection, not BiStream | [ADR-007](../../decisions/007-bistream-type-definition.md) | Handlers that need multiple streams (SSH, call) have direct access to the Connection |
|
||||
| BiStream is a trait | [ADR-007](../../decisions/007-bistream-type-definition.md) | WASM door preserved, test mocks possible |
|
||||
| `Connection::from_stream` — generic single-stream connections | [ADR-065](../../decisions/065-connection-from-stream-generic-single-stream.md) | `from_stream`/`from_bidi` accept any `AsyncRead + AsyncWrite`; yield-once `accept_bi` contract; unblocks TCP+TLS, SSH channels, WebTransport, wasm; QUIC variants feature-gated, `Stream` variant always available; `MockConnection`/`ConnectionKind::Mock` removed (tests use `from_stream` with `sink`/`empty`) |
|
||||
| `BidiStreamSource` — open `Connection` for extension | [ADR-070](../../decisions/070-bidistreamsource-trait.md) | `Connection` holds `Box<dyn BidiStreamSource>`; QUIC/iroh/stream wrap crate-private impls; downstream crates implement the trait to add connection shapes (channels, future transports) without editing core; public `Connection` API preserved; `close(code, reason)` kept on the trait (non-QUIC impls ignore the args — fixes the ADR-065 leftover clippy warning under `--no-default-features`) |
|
||||
| `BidiStreamSource` — open `Connection` for extension | [ADR-070](../../decisions/070-bidistreamsource-trait.md) | `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); `from_quinn`/`from_iroh`/`from_stream`/`from_bidi` preserved; `close(code, reason)` kept on the trait (non-QUIC impls ignore the args — fixes the ADR-065 leftover clippy warning under `--no-default-features`) |
|
||||
| HandlerError is non-fatal | [ADR-010](../../decisions/010-alpn-router-and-endpoint.md) | Handler errors close the connection, not the endpoint |
|
||||
| SendStream/RecvStream wrap quinn + iroh + generic streams | [ADR-010](../../decisions/010-alpn-router-and-endpoint.md), [ADR-065](../../decisions/065-connection-from-stream-generic-single-stream.md) | Internal enum dispatch for QUIC sources and the generic `Stream` variant |
|
||||
| Connection stores handler-resolved identity | OQ-11 (resolved) | `set_identity` via `OnceLock` — write-once-read-many; read by handler-side logging, not by the endpoint (C13 resolved) |
|
||||
|
||||
Reference in new issue
Block a user