- open-questions.md: OQ-39 → ADR-052, OQ-40 → ADR-053 (resolutions replace
the deferred-until-needed posture)
- channel-operations.md: the put contract (initiator allocates + streams,
reserved input key, one response, acks-in-result sentence), the control
routing (ADR-052), the enumerator aggregation (ADR-053), the
connection-owner paragraph's pub-era correction, the ADR table rows
- ADR-051 §6: PubTypedOpen → the put translation; ADR-047's 2026-09-06
amendment records its era honestly (the dynamic half is now ADR-053)
- review 010: all four findings resolved (with the S-01 sketch correction
so the published record stops carrying the wrong-graph reading)
- review 011: closed (all seven pins implemented + gates landed)
- review 001 C-08: resolved note (odd/even + adopt, implemented)
- AGENTS.md: the 'Stub Guard' section — the not_implemented grep is part
of cargo test; the registration invariants and the implement-or-stop
ruling are release-blocking
Verified: cargo test (696+guard), clippy -D warnings, fmt, doc clean.
S-01 — the marked-pub open contract (ADR-047 amendment 4):
- ChannelCore::register_pub_openable + PubOpenHandler (the put path's
handler returns its result for the merged single response; the
wrapper awaits inline, teardown is EOF-driven, handler_task stays
None); register_openable* refuses Pub-typed specs; the wrapper entry
points refuse unmarked/non-Pub shapes
- the reserved input key `channel_id` (the initiator-allocated id):
stripped pre-validation by resolve_sink_handler (the single source of
truth, P-08), handed to the wrapper via OperationContext.metadata, a
missing key rejected INVALID_INPUT; adopt parity enforced
(ManagerError::InvalidAdopt) and adopt failures answer
channel:open_failed / adopt_failed
- zero call.published on marked ops: the first publish chunk on a
marked op is rejected loudly (channel:publish_chunks_rejected) in
both dispatch loops; the handler is never fed
- relay put-translation replaces RelayError::PubTypedOpen: hub
allocates odd on the producer leg, opens the spoke op in the
background (put-acks-in-result), one-direction pump, response-mirror
with the producer's reserved key stripped
- ChannelClient::open_pub_channel + PubOpenReply (the initiator-
allocates put open capability)
S-02 — channel/control implemented (ADR-052): establisher-contributed
ChannelControl (Establishment::with_control), manager-owned registry,
teardown removals, channel:no_control_handle capability answer.
S-03 — channel/resources/subscribe implemented (ADR-053): the
ResourceEnumerators registry (shared per peer), snapshot-then-changes
enumerators, scan-once aggregation, the empty seed; the
always-failing one-shot error stream removed.
S-04 — op/register forward-through (ADR-022 amendment): announced
unmarked Sub/Pub register the real streaming/sink forwarding shapes;
marked announcements refused with MARKED_SPEC_UNSUPPORTED; marked
specs refuse the generic registration path and register_imported
(Result-returning now).
Guard (review 010 action 3): tests/stub_guard.rs greps src/ for
not_implemented; the four pinned stub tests are deleted and the
marked-spec registration refusals are pinned by tests.
Verified: cargo test (696 + guard), clippy --all-targets -D warnings,
fmt --check, fuzz corpus replay.
Post-landing audit of the 0.7.1 -> 0.8.0 remediation diff: two
hardening guards, one rejection-posture fix, two log/message
corrections, and the deferred coverage debt filed as review 009.
- RelayPlan owns the producer-leg ChannelManager and reclaims the
adopted spoke channel_id via a Drop guard (replaces the pump
handler's post-pump_bidi explicit reclaim). Closes the leak
windows the pump's normal path cannot reach: the wrapper's
establishment bound expiring after the adopt, and the pump
handler's early-return arms (plan absent, downcast failure,
try_unwrap failure, accept_bi failure). The send-half drop still
EOFs the spoke leg via the mux pump's implicit-EOF sentinel, so
the spoke-side cascade is unchanged. ADR-051 §6 documents the
closed post-adopt window (the pre-adopt §6 window and the
inside-adopt_channel cancellation point stay as documented).
- rebuild_spec_for trims and rejects empty/whitespace
channel_open_alpn strings — an empty explicit string previously
overrode a sane name-derived ALPN.
- op_name_is_standard_channel_open_shape applies the same
empty-segment guard as the derivation: channels//sub no longer
serializes boolean-only and then reconstructs unmarked (silent
stub for a marked op); the explicit string rides instead.
- reserved_reply_key_call_error interpolates RESERVED_REPLY_KEY;
the establisher-bug log fires at warn! (programming error).
- Regression tests: the plan drop guard, the empty-ALPN fallback,
the empty-segment shape check (672 tests, 3 new).
- CHANGELOG [Unreleased] entry for the audit fixes.
- docs/reviews/009 — the audit's deferred test-coverage gaps
(template failure arms, filtered/only, batch reserved key,
wire failure path, golden pins, derivation edge shapes, builder
overwrite semantics), each with the test to add and gates.
Verification: cargo test 672 passed; clippy --all-targets -D
warnings clean; fmt --check clean; doc --no-deps clean; wasm32
check clean.
- src/channels/gate2_tests.rs (ADR-051 gates 6/7, review 008 gate 2):
the full consumer -> hub (HubLegTemplate) -> spoke relay e2e —
the open resolves with the hub-allocated channel_id, `bound`
survives the relay, data flows both directions with a fake 8-byte
chunk header riding verbatim (the hub never parses the data plane,
ADR-034/035), spoke-side close cascades to clean reclaim on both
legs; hub-side disconnect (the consumer's duplex end dropped via a
killable transport proxy) tears down both legs with the ledger
decremented; the mid-establishment window (ADR-051 §6) pinned with
its two reclaim signals — the consumer leg reclaims at its own
transport EOF, the spoke channel (allocated before the establisher
replied) is the honest residual, reclaimed when the spoke-leg
transport ends; the channels/tty/sub standard-shape companion pins
no derivation regression.
- src/channels/relay.rs: the relay's adopted producer-leg channel
entry now reclaims when the relayed pump completes (teardown after
pump_bidi) — the consumer-leg wrapper's teardown cannot see the
producer leg's manager; the RelayPlan carries the spoke id for the
reclaim.
- Release bookkeeping: 0.7.1 -> 0.8.0, the CHANGELOG entry covering
Units 1-3 (Establishment reply projection, open_channel_with_reply,
flavor-form discovery derivation, ChannelRelay, HubLegTemplate,
gate-2 harness); review 008 Status -> Resolved with the U-1/U-2
commit refs and the 955->945 errata note; ADR-051 Status ->
all units landed + the §6 mid-establishment residual expanded to
the two-reclaim-signal shape the gate pins; the stale "0.7.2"
version mentions in ADR-047/049 corrected to 0.8.0 (the units land
unreleased).
Verification: cargo test 669 passed / 0 failed; clippy --all-targets
-- -D warnings clean; fmt --check clean; cargo doc --no-deps clean;
cargo check + clippy on wasm32-unknown-unknown clean;
cargo publish --dry-run --allow-dirty passed.
- src/channels/relay.rs: ChannelRelay::register_relay_openable —
registers a from_call-imported marked spec on a consumer-leg
channel-0 registry via the full open-op wrapper (translate hop =
the ADR-049 establisher calling the producer leg with the
forwarded payload; byte-forward hop = pump_bidi, awaited inline).
The relay map dissolves (implicit per-channel mapping; ids are
per-connection), the spoke reply's channel_id is stripped, the
reply's other fields ride with_reply_fields (bound flows
end-to-end), reason mapping per ADR-051 §3 (spoke code+message
preserved; timeout → dial_failed).
- Rejection postures (ADR-051 §6): unmarked and Pub-typed marked
specs are loud assembly errors.
- Gate tests (9): registration rejections, reason mapping,
forwarded_for payload shape, the real-wire consumer → hub → spoke
round trip (bound survives, data both directions, the hub never
parses the data plane), spoke-failure teardown (ledger
decremented, no spoke channel leak), and a channels/tty/sub
standard-shape run pinning no regression.
Verification: cargo test (658 passed), clippy --all-targets
-D warnings, fmt --check, doc --no-deps — all clean.