docs(architecture): resolve one-way doors, clean up Phase 0 specs

Resolve blocking one-way door decisions:
- ADR-007: BiStream is a trait, handlers receive Connection not BiStream
- ADR-008: Secret service is CLI-embedded, exposed via call protocol
- ADR-009: One-way door decision framework (classify by reversal cost)

Update existing documents:
- overview.md: add design principles, revise ProtocolHandler signature,
  update shared types, add WASM as design constraint
- open-questions.md: add door-type classifications, resolve OQ-01/OQ-08,
  move OQ-09/OQ-10 to deferred section, mark two-way doors as impl-deferred
- README.md: reflect resolved questions, remove crate spec stubs from index
- ADR-002: cross-reference ADR-007 for signature revision

Clean up premature artifacts:
- Remove 11 empty crate spec stubs (16-28 lines each, no unique content)
- Specs will be created when each crate enters Phase 1
This commit is contained in:
2026-06-16 10:43:31 +00:00
parent f77b515968
commit b47a6fe70b
18 changed files with 357 additions and 348 deletions

View File

@@ -1,165 +1,116 @@
---
status: draft
last_updated: 2026-06-15
last_updated: 2026-06-16
---
# Open Questions
Questions are organized by theme. Each question has a stable OQ-ID for cross-referencing from spec documents.
Door type classifications follow ADR-009:
- **One-way door**: Reversal requires rewriting significant code or permanently closes a capability. Requires ADR before implementation.
- **Two-way door**: Reversal is cheap or additive. Can be decided during implementation.
## Theme: Core Types
### OQ-01: BiStream Type Definition
- **Origin**: [overview.md](overview.md), future [crates/alknet-core/spec.md](crates/alknet-core/spec.md)
- **Status**: open
- **Origin**: [overview.md](overview.md)
- **Status**: resolved
- **Door type**: One-way
- **Priority**: high
- **Resolution**: (pending)
- **Cross-references**: ADR-002
What exactly does BiStream expose? The pivot proposal defines it as a joined `(SendStream, RecvStream)` implementing `AsyncRead + AsyncWrite`. Should it be:
- A concrete type wrapping quinn's `SendStream` + `RecvStream`?
- A trait `BiStream: AsyncRead + AsyncWrite + Send + Unpin` with a QuinnBiStream implementation?
- A type alias or newtype?
The choice affects WASM compatibility (quinn doesn't compile to WASM) and testing (mock BiStream needs to be constructible without a QUIC connection). If BiStream is a trait, WASM targets can implement it over WebTransport streams.
- **Resolution**: BiStream is a trait (`AsyncRead + AsyncWrite + Send + Unpin`). Handlers receive a `Connection` (not a single BiStream). This preserves the WASM door — browser clients can implement BiStream over WebTransport streams. See ADR-007.
- **Cross-references**: ADR-002, ADR-007, ADR-009
### OQ-02: AuthContext Resolution Timing
- **Origin**: [overview.md](overview.md), future [crates/alknet-core/spec.md](crates/alknet-core/spec.md)
- **Origin**: [overview.md](overview.md)
- **Status**: resolved
- **Door type**: One-way
- **Priority**: high
- **Resolution**: Hybrid model (Option C) — endpoint resolves what it can (e.g., TLS client certificate), handler resolves what it must (e.g., AuthToken in first frame). AuthContext may be partial when `handle()` is called. See ADR-002 and ADR-004.
- **Resolution**: Hybrid model (Option C) — endpoint resolves what it can (e.g., TLS client certificate), handler resolves what it must (e.g., AuthToken in first frame). AuthContext may be partial when `handle()` is called. See ADR-004.
- **Cross-references**: ADR-002, ADR-004
~~Should AuthContext be fully resolved before `handle()` is called, or should the handler participate in credential extraction?~~
Resolved: The hybrid approach. The endpoint resolves TLS-level credentials (client certificate fingerprints). Handlers that use protocol-level credentials (AuthToken, Bearer headers) extract them inside `handle()` and call `IdentityProvider` to resolve. The `AuthContext` passed to `handle()` may contain only transport-level information.
## Theme: ALPN and Routing
### OQ-03: ALPN String Naming Convention
- **Origin**: [overview.md](overview.md)
- **Status**: resolved
- **Door type**: One-way
- **Priority**: medium
- **Resolution**: Custom ALPNs use `alknet/<name>` prefix (no version), standard ALPNs use IANA strings, no version negotiation initially. See ADR-006.
- **Resolution**: Custom ALPNs use `alknet/<name>` prefix (no version), standard ALPNs use IANA strings. No version negotiation initially. See ADR-006.
- **Cross-references**: ADR-001, ADR-006
~~The pivot proposal uses `alknet/ssh`, `alknet/call`, `alknet/git`, etc. Questions:~~
Resolved: See ADR-006 for the full convention. Custom ALPNs use `alknet/` prefix without version numbers. Standard ALPNs (`h2`, `http/1.1`, `h3`) use their IANA strings and route to HttpAdapter. If a protocol needs a breaking change, a new ALPN string is registered.
### OQ-04: Dynamic Handler Registration at Runtime vs Static at Startup
- **Origin**: [overview.md](overview.md)
- **Status**: open
- **Priority**: medium
- **Resolution**: (pending)
- **Door type**: Two-way
- **Priority**: low
- **Resolution**: (deferred to implementation) Start with static registration at startup. The `ArcSwap<DynamicConfig>` pattern from the previous implementation can be applied later if needed. ALPN advertisement requires endpoint restart anyway (TLS ALPN is negotiated during handshake), so dynamic registration has limited value in v1.
- **Cross-references**: ADR-001
Can handlers be registered and deregistered while the endpoint is running, or only at startup?
The previous implementation used `ArcSwap<DynamicConfig>` for hot-reloading routing rules. The same pattern could apply to handler registration. However:
- Adding a handler at runtime requires updating the TLS ALPN advertisement (may require endpoint restart)
- Removing a handler at runtime affects in-flight connections
- The CLI assembles handlers at startup — is dynamic registration even needed?
## Theme: Transport and Endpoint
### OQ-05: Multi-Transport Endpoint
- **Origin**: [overview.md](overview.md)
- **Status**: open
- **Priority**: medium
- **Resolution**: (pending)
- **Door type**: Two-way
- **Priority**: low
- **Resolution**: (deferred to implementation) Start with quinn (QUIC over UDP). The endpoint can be made transport-agnostic later by abstracting the connection accept loop behind a trait. iroh connectivity produces QUIC connections that can feed into the same ALPN router.
- **Cross-references**: ADR-001
The previous implementation supported TCP, TLS, and iroh (QUIC P2P) transports. In the new model, does the endpoint:
- Accept connections on a single QUIC listener (quinn) and the ALPN handles the rest?
- Also support raw TCP listeners (for clients that don't speak QUIC)?
- Support iroh as an additional transport that produces QUIC connections?
iroh's Router pattern accepts a quinn::Endpoint and dispatches by ALPN. The alknet endpoint likely wraps a quinn::Endpoint with TLS configuration that advertises all registered ALPNs. Iroh connectivity could be an additional transport that produces the same BiStream type.
### OQ-06: Server-Side ALPN vs Client-Side ALPN
- **Origin**: ADR-001
- **Status**: resolved
- **Door type**: One-way
- **Priority**: low
- **Resolution**: One ALPN per connection. Clients open one QUIC connection per ALPN. See ADR-006.
- **Resolution**: One ALPN per connection. Clients open one QUIC connection per ALPN. QUIC connections are cheap (multiplexed over the same UDP flow). See ADR-006.
- **Cross-references**: ADR-001, ADR-006
~~The ADR focuses on server-side dispatch (client connects, server selects ALPN). What about the client side? When a client opens a stream to a specific ALPN on an existing connection, does it: - Open a new QUIC connection with the target ALPN? - Open a bidirectional stream on an existing connection with ALPN metadata?~~
Resolved: ALPN is negotiated per-connection, not per-stream. A client that wants multiple ALPNs opens one QUIC connection per ALPN. QUIC connections are cheap (multiplexed over the same UDP flow). See ADR-006.
## Theme: Call Protocol
### OQ-07: Call Protocol Scope Within a Connection
- **Origin**: ADR-005
- **Status**: open
- **Door type**: Two-way
- **Priority**: medium
- **Resolution**: (pending)
- **Resolution**: (deferred to implementation) Start with one stream per operation/request in the call protocol. Multiplexing within a stream can be added later if needed without breaking existing clients. Resolve when speccing alknet-call.
- **Cross-references**: ADR-005
If a client opens a connection with ALPN `alknet/call`, can it make multiple operations over that connection? Is each operation a separate QUIC stream, or can operations be multiplexed within a single stream?
irpc supports both request/response and streaming. The mapping to QUIC streams needs definition:
- One stream per request/response pair?
- One stream per streaming subscription?
- Or a single long-lived stream with multiplexed operations?
## Theme: Security
### OQ-08: Secret Service Integration Point
- **Origin**: [overview.md](overview.md)
- **Status**: open
- **Status**: resolved
- **Door type**: One-way
- **Priority**: medium
- **Resolution**: (pending)
- **Cross-references**: ADR-004
- **Resolution**: CLI-embedded with call protocol exposure. The CLI binary instantiates `SecretServiceHandle` locally and registers secret operations in the call protocol's operation registry. alknet-secret has no ALPN and no alknet-core dependency. Key derivation is local-only; only public key material crosses the network via `alknet/call`. See ADR-008.
- **Cross-references**: ADR-003, ADR-005, ADR-008
alknet-secret is standalone (no alknet-core dependency). How does the rest of the system access it?
- As an irpc service that other services call? (current implementation)
- As an ALPN handler on `alknet/secret` that only internal services use?
- As a library that alknet-core calls directly (breaking the independence)?
- As a library that the CLI embeds, exposing it via the call protocol?
## Deferred Questions
The answer affects whether alknet-secret needs to know about BiStream and ProtocolHandler, or if it remains purely an irpc service that the CLI bootstraps and other services call over local irpc.
## Theme: WASM and Browser
These questions are acknowledged but not active. They will be promoted to open when their crate becomes a Phase 1 implementation target.
### OQ-09: WASM Target Boundaries
- **Origin**: [overview.md](overview.md)
- **Status**: open
- **Priority**: medium
- **Resolution**: (pending)
- **Cross-references**: OQ-01
Which crates need to compile to WASM?
- alknet-call client (for browser/NAPI usage) — yes
- alknet-sftp protocol core — yes (browser SFTP clients)
- alknet-git pkt-line parser — potentially
- alknet-core (BiStream, AuthContext) — only the types, not the endpoint/router
This affects the BiStream type definition (OQ-01) and dependency choices. If alknet-call's client needs to work in WASM, it can't depend on tokio or quinn directly — it needs abstracted I/O.
## Theme: Git and Distributed
- **Status**: deferred
- **Door type**: One-way (when applicable)
- **Priority**: low
- **Resolution**: Not an active question — WASM compatibility is a design constraint (see ADR-009, overview.md design principles), not a deliverable. Specific WASM targeting decisions will be made when individual crates are implemented. The BiStream trait decision (ADR-007) has already preserved the most important WASM door.
- **Cross-references**: ADR-007, ADR-009
### OQ-10: Git Adapter Scope — Smart Protocol Only or Full Server?
- **Origin**: [overview.md](overview.md)
- **Status**: open
- **Status**: deferred
- **Door type**: Two-way
- **Priority**: low
- **Resolution**: (pending)
- **Cross-references**: ADR-001
The pivot proposal mentions Git over QUIC streams (no HTTP layer). Does the GitAdapter implement:
- Just the git smart protocol (ls-refs, fetch, receive-pack) over QUIC streams?
- A full git server with ref management, pack generation, etc.?
- The ERC721 integration for on-chain repository management?
This is deferred per the cleanup plan but worth noting as an open question.
- **Resolution**: Deferred per the cleanup plan. Start with git smart protocol over QUIC streams. ERC721 integration and full server capabilities are additive. Resolve when speccing alknet-git.
- **Cross-references**: ADR-001