5.9 KiB
5.9 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| implementation/composed-accept | Composed — the bind-first accept (the listener on a listen resource) | pending |
|
moderate | medium | component | implementation |
Description
The composed feature's accept provider (ADR-008's composed
variants; ADR-007 variant 2): the BIND accept whose listener lives on
an alktunnels 0.2.0 bind-first listen resource
(register_tunnel_bindfirst_openable + BindFirstInjections) —
per-listener ACL for free, hub-relayable. Vanilla-fidelity with no
stand-ins since the graduation (ADR-007): reply#1 advertises the
real OS-chosen bound (the open-op reply's bound field, alkcall
0.8.0 reply projection); reply#2 carries the real peer (the forwarded
op's peer param).
Deliverables:
src/composed/additions (featurecomposed) — the composed accept, named per producer.md §Wiring:bindfirst_accept(...)→BindAcceptFactory: the POC #5composed_bind_acceptshape updated to the graduation — the POC's pinned workaround (reply#1 first, the tunnel open rides the accept future; the factory carries an expectedbind_addr) is retired (ADR-007 §Consequences). The landed shape: the factory opens the bind-first listen channel (TunnelListener::open— the reply projection surfacesbound), reply#1 advertises the realbound, and the accept future correlates the forwarded sessions (thelistentoken → the adopted forwarded sessions the assembly correlates; the forwarded op'speerparam is reply#2's peer).- The correlation shape is the design center (the POC's
upstream-ask ledger retired by the graduation): the factory
returns
BindAcceptwhose accept future waits for the ONE forwarded session matching the listener's token. The correlation registry is assembly-side bookkeeping (the alktunnelsTunnelListenerdocs: "forwarded sessions arrive as ordinary adopted sessions on the manager; the listener does not own the receipt queue"). The provider owns: theregister_tunnel_forwarded_openableserving side (the opener half — the SOCKS5 producer's connection must serve the forwarded op), the token→waiter map, and the per-forwarded pump. Design the wait shape against the landed alkcall 0.8.0 adopt surface (manager.adopt_channel) and record it in Notes. - The Sync-bound wrinkle (shared with composed-egress): the
accepted halves must be
Box<dyn AsyncRead + Send + Sync + Unpin>(BindTargetHandle's payloads); alktunnels'Taken HalvesyieldsSend + Unpinonly. The owner-wrapper rides inside the handle payloads (egress.rs's documented posture) — the wrapper owns the adopted channel session so dropping the handle drops everything (the teardown-at-birth discipline, compiler-enforced). This is the load-bearing wrapper: design it once (with composed-egress's needs), pin it with a test. - Peer-address fidelity: the forwarded op's
peerparam is reply#2's real peer (the graduation's win); the wrapper-aware sentinel (0.0.0.0:0) is the in-band default's shape, not this variant's. - The establishment bound covers only the open-op round trip
(ADR-007): the accept wait lives in the teardown-governed pump
phase — the quiet wait's
select!drop of the accept future IS the client-gone teardown; the listener (inside the future) closes with it. The forwarded-op correlation must survive a client-gone drop without leaking the listener (the accept future owns it end-to-end — the seam contract). - Module doc: names the ADRs (007/008), the graduation's vanilla-fidelity win, the correlation shape, the owner-wrapper.
- Tests (
tests/composed-accept.rs): the full composed BIND story over channels — a bind-first tunnel producer (register_tunnel_bindfirst_openable+ injections), the SOCKS5 producer withcomposed::bindfirst_accept(...), a consumer BIND session: reply#1 carries the realbound, an app server dials the far listener, reply#2 carries the real peer, the pass-through data plane round-trips; the client-gone teardown releases the listener (drop-witness); two concurrent BIND sessions get distinct tokens; a forwarded-open failure is per-accept isolated.
Acceptance Criteria
cargo testpasses;cargo test --all-featurespassescargo check --features composed --target wasm32-unknown- unknownclean (hard gate)cargo clippy --all-targets --all-features -- -D warningsclean;cargo fmt --checkclean- The graduation's shape lands (reply#1 = the real
bound; reply#2 = the forwarded op's realpeer) — no expected-addr stand-in — pinned by test - The owner-wrapper rides inside the handle payloads (Sync halves; teardown structural) — pinned by test
- The client-gone teardown releases the listener (the accept future owns it end-to-end) — pinned by drop-witness test
- The forwarded-op serving side + correlation land; per-accept isolation — pinned by tests
References
- docs/architecture/decisions/007-bind-in-base.md (variant 2 + the graduation), 008-provider-defaults.md, 004 (the accept seam's contracts), 006 (the command gate)
- docs/architecture/producer.md §Wiring
(
composed::bindfirst_accept), §The Three Seams - POC reference:
/workspace/alksocks-bind-poc/src/accept.rs(composed_bind_accept— the superseded-in-shape workaround, the owner-wrapper's first witness) - Landed surfaces:
src/egress.rs(BindAccept/BindTargetHandle— the contracts), alktunnels 0.2.0 (register_tunnel_bindfirst_ openable,BindFirstInjections,TunnelListener,register_tunnel_forwarded_openable,ForwardedHandler)
Notes
To be filled by implementation agent
Summary
To be filled on completion