docs: fold [Unreleased] into [0.8.0] for publish

The post-landing-audit fixes (relay plan Drop guard, empty-ALPN
guards, reserved-reply-key message/log corrections) and the review
009 coverage work were recorded under [Unreleased] after the 0.8.0
section was written, but 0.8.0 has not shipped — folded both into
the release entry with proper Added/Changed/Fixed/Testing/Verified
ordering. Verified test count corrected 669 → 682 (the audit and
coverage commits added 13 tests after that count was recorded).
Bottom link refs gained the missing [0.8.0] and [0.7.1] entries.

Verification: cargo test 682 passed; clippy --all-targets -D
warnings clean; fmt --check clean; doc --no-deps clean; semver-checks
(no update required, 0.7.1 baseline); wasm32 check + clippy clean;
test --all-features 699 passed; publish --dry-run packaged and
verified clean.
This commit is contained in:
2026-09-18 13:23:56 +00:00
parent 9620ee7b2a
commit 7bb76cd2b5
+78 -77
View File
@@ -4,88 +4,18 @@ All notable changes to this crate are documented here. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
this crate adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
Post-landing audit of review 008's remediation (0.7.1 → 0.8.0) — two
hardening guards, two log/error-message corrections, one
rejection-posture fix, and the ADR-051 §6 residual update. No wire
changes; all behavior deltas are failure-path.
### Fixed
- **Adopted-entry teardown on every relay plan path** (ADR-051 §6) —
the relay's `RelayPlan` now owns the producer-leg
`ChannelManager` and reclaims the adopted spoke `channel_id` via a
`Drop` guard, instead of the pump handler's post-`pump_bidi`
explicit reclaim. This closes the leak windows the pump's normal
path cannot reach: the open wrapper's establishment bound expiring
after the adopt (the plan dropped before the pump ever spawns) and
the pump handler's early-return arms (plan absent, downcast
failure, `try_unwrap` failure, `accept_bi` failure). Dropping the
plan's send half still EOFs the spoke side via the mux pump's
implicit-EOF sentinel, so the spoke handler reclaims through the
same cascade as before. Regression test:
`relay_plan_drop_reclaims_the_adopted_producer_leg_entry`.
- **Empty/whitespace `channel_open_alpn` rejected at rebuild** — an
explicit string of `""` (or whitespace-only) previously overrode a
sane name-derived ALPN, poisoning the marker for every consumer
from one misconfigured producer; `rebuild_spec_for` now trims and
rejects empties, falling back to the derivation.
- **Empty-segment standard-shape names** — `channels//sub` was
serialized boolean-only (the standard-shape check saw flavor
`sub`) but reconstructed UNMARKED (the derivation's empty-segment
guard returned `None`) — a silent stub for a marked op. The
standard-shape check now applies the same empty-segment guard, so
the explicit `channel_open_alpn` string rides the wire and the
marker reconstructs.
- **Reserved-reply-key error text and log level** — the
`channel:open_failed` message interpolates `RESERVED_REPLY_KEY`
instead of hardcoding `"channel_id"` (the two could drift), and the
establisher-bug log fires at `warn!` (a programming error), not
`debug!`.
### Testing
Review 009's coverage debt (all seven findings, no wire or API
changes; three as-filed errata recorded in the review):
- **C-1** — the template's plain-bundle install-failure arm is pinned
(un-compilable `input_schema` → the install task ends before the
dispatch loop, channel 0 never dispatches); ADR-051 §5 carries the
loud-install coverage note (relay-openable + plain-bundle arms
pinned; generic-ops + bootstrap-discovery arms documented as
best-effort-loud).
- **C-2** — the `HubLegImports` filter: the `filtered` closure path
and the `only` marked/plain partition unit-tested; the empty-stash
e2e gate (serves only the generic ops + discovery, dropped ops
resolve `NOT_FOUND`).
- **C-3** — the batch-form reserved-reply-key rejection
(`with_reply_fields` smuggling `channel_id`) pinned: reason
`handler_error`, channel torn down, ledger decremented, pump never
spawns.
- **C-4** — `open_channel_with_reply`'s failure path pinned e2e: the
typed error carries the `channel:open_failed` code and the full
`details` shape (`reason` + `message`) through the new API.
- **C-5** — both "byte-identical" claims are golden-pinned: the
no-fields reply against the exact `{"channel_id": 2}` literal, and
the standard-shape wire payload against the full 9-key literal.
- **C-6** — the derivation's edge shapes pinned: `channels//sub` /
`channels//direct` / `channels``None`; the 4-segment strict
superset (`channels/x/sub/extra``Some("x/sub")`) annotated as the
pre-amendment behavior change; the verbatim `channels/alk/tty/sub`
case.
- **C-7** — the builder's overwrite semantics pinned last-win (single
and batch forms) with the doc sentence on `with_reply_field`.
## [0.8.0] - 2026-09-18
Review 008's remediation lands in full — the graduation upstream asks
(U-1 flavor-form open-op ids in discovery; U-2 the establisher → reply
projection) plus the in-tree channel relay they demanded
(`ChannelRelay`, the hub-leg install template, and the review's gate-2
e2e harness). The channels data plane is untouched (ADR-034/035's
one-way doors stay closed); the new surfaces are additive on the
call-plane JSON and the registry seams.
e2e harness). A post-landing audit of that diff hardened the relay's
adopted-entry teardown and the discovery ALPN guards, corrected two
log/error messages, and review 009's coverage debt is paid in full —
all failure-path; no wire or API changes. The channels data plane is
untouched (ADR-034/035's one-way doors stay closed); the new surfaces
are additive on the call-plane JSON and the registry seams.
### Added
@@ -153,9 +83,78 @@ call-plane JSON and the registry seams.
re-exported from `channels`**; the relay's teardown fix is part of
this landing (no pre-relay behavior to preserve).
### Fixed
Post-landing audit of the remediation diff — hardening guards,
message corrections, and one rejection-posture fix; all failure-path.
- **Adopted-entry teardown on every relay plan path** (ADR-051 §6) —
the relay's `RelayPlan` now owns the producer-leg
`ChannelManager` and reclaims the adopted spoke `channel_id` via a
`Drop` guard, instead of the pump handler's post-`pump_bidi`
explicit reclaim. This closes the leak windows the pump's normal
path cannot reach: the open wrapper's establishment bound expiring
after the adopt (the plan dropped before the pump ever spawns) and
the pump handler's early-return arms (plan absent, downcast
failure, `try_unwrap` failure, `accept_bi` failure). Dropping the
plan's send half still EOFs the spoke side via the mux pump's
implicit-EOF sentinel, so the spoke handler reclaims through the
same cascade as before. Regression test:
`relay_plan_drop_reclaims_the_adopted_producer_leg_entry`.
- **Empty/whitespace `channel_open_alpn` rejected at rebuild** — an
explicit string of `""` (or whitespace-only) previously overrode a
sane name-derived ALPN, poisoning the marker for every consumer
from one misconfigured producer; `rebuild_spec_for` now trims and
rejects empties, falling back to the derivation.
- **Empty-segment standard-shape names** — `channels//sub` was
serialized boolean-only (the standard-shape check saw flavor
`sub`) but reconstructed UNMARKED (the derivation's empty-segment
guard returned `None`) — a silent stub for a marked op. The
standard-shape check now applies the same empty-segment guard, so
the explicit `channel_open_alpn` string rides the wire and the
marker reconstructs.
- **Reserved-reply-key error text and log level** — the
`channel:open_failed` message interpolates `RESERVED_REPLY_KEY`
instead of hardcoding `"channel_id"` (the two could drift), and the
establisher-bug log fires at `warn!` (a programming error), not
`debug!`.
### Testing
Review 009's coverage debt (all seven findings, no wire or API
changes; three as-filed errata recorded in the review):
- **C-1** — the template's plain-bundle install-failure arm is pinned
(un-compilable `input_schema` → the install task ends before the
dispatch loop, channel 0 never dispatches); ADR-051 §5 carries the
loud-install coverage note (relay-openable + plain-bundle arms
pinned; generic-ops + bootstrap-discovery arms documented as
best-effort-loud).
- **C-2** — the `HubLegImports` filter: the `filtered` closure path
and the `only` marked/plain partition unit-tested; the empty-stash
e2e gate (serves only the generic ops + discovery, dropped ops
resolve `NOT_FOUND`).
- **C-3** — the batch-form reserved-reply-key rejection
(`with_reply_fields` smuggling `channel_id`) pinned: reason
`handler_error`, channel torn down, ledger decremented, pump never
spawns.
- **C-4** — `open_channel_with_reply`'s failure path pinned e2e: the
typed error carries the `channel:open_failed` code and the full
`details` shape (`reason` + `message`) through the new API.
- **C-5** — both "byte-identical" claims are golden-pinned: the
no-fields reply against the exact `{"channel_id": 2}` literal, and
the standard-shape wire payload against the full 9-key literal.
- **C-6** — the derivation's edge shapes pinned: `channels//sub` /
`channels//direct` / `channels``None`; the 4-segment strict
superset (`channels/x/sub/extra``Some("x/sub")`) annotated as the
pre-amendment behavior change; the verbatim `channels/alk/tty/sub`
case.
- **C-7** — the builder's overwrite semantics pinned last-win (single
and batch forms) with the doc sentence on `with_reply_field`.
### Verified
- 669 tests pass (`cargo test`), `clippy --all-targets -- -D warnings`
- 682 tests pass (`cargo test`), `clippy --all-targets -- -D warnings`
and `fmt --check` clean. The gate-2 e2e harness
(`src/channels/gate2_tests.rs`) pins the review's gate 2: the full
consumer → hub → producer relay through the template (hub-allocated
@@ -679,6 +678,8 @@ Vendored core types (`Connection`, `ProtocolHandler`, `BiStream`,
(ADR-046), the channels protocol with openable-ALPNs-as-operations
(ADR-047), and the `ChannelClient` transport-agnostic client.
[0.8.0]: https://git.alk.dev/alkdev/alkcall/releases/tag/v0.8.0
[0.7.1]: https://git.alk.dev/alkdev/alkcall/releases/tag/v0.7.1
[0.7.0]: https://git.alk.dev/alkdev/alkcall/releases/tag/v0.7.0
[0.6.0]: https://git.alk.dev/alkdev/alkcall/releases/tag/v0.6.0
[0.5.0]: https://git.alk.dev/alkdev/alkcall/releases/tag/v0.5.0