- Cargo.toml: alkcall 0.8.1 -> 0.9.0 (crates.io, the stub-sweep
release) and 0.2.1 -> 0.3.0 (breaking dep bump + public alkcall
re-exports -> minor, matching the 0.7.1 -> 0.8.0 ride on 0.2.0)
- fuzz/shared/Cargo.toml: alkcall 0.9.0 (path-linked alktunnels must
see one alkcall version)
- src/producer.rs + tests/producer_direct_op.rs: the only code contact
with the 0.9.0 breaking surface — Establishment no longer derives
Debug; two expect_err calls -> .err().expect, one untyped
panic!("{other:?}") fall-through -> typed Err/Ok arms
- CHANGELOG: 0.3.0 section + compare links
- README: the 0.3.0 note
- docs/architecture/overview.md: dep tree alkcall 0.9.0
Verification: cargo test (136 default / 163 with local), fuzz/shared
corpus replay (0 pass, empty target set — no regressions), clippy
--all-targets -D warnings (native + wasm32-unknown-unknown), fmt
--check, wasm32 check, and cargo publish --dry-run --allow-dirty all
green
- CHANGELOG: Unreleased cut to 0.2.1 (the fuzz/ workspace: three
cargo-fuzz targets + stable-toolchain corpus replay in fuzz/shared;
the two wave-2 diagnostics datagram_backlog/retained_bytes; the
alkcall 0.8.0 -> 0.8.1 bump — duplicate adopt no longer destroys the
live channel; compare links updated)
- README: the 0.2.1 hardening note (fuzzing + alkcall 0.8.1 + the two
additive diagnostics)
- docs/architecture/overview.md: dep tree alkcall 0.8.1
- Cargo.toml: 0.2.0 -> 0.2.1
Verification: cargo test (136 default / 163 with local), fuzz/shared
corpus replay (5 pass), clippy --all-targets -D warnings (default,
all-features, wasm32-unknown-unknown, fuzz/shared), fmt --check, doc,
wasm32 check, and cargo publish --dry-run --allow-dirty all green
(42 packaged files — fuzz/, docs/research|reviews|plans/, tasks/,
.opencode/, AGENTS.md all excluded)
Bump the substrate dependency to alkcall 0.8.1 — the bug-fix release
whose fix (duplicate adopt/open no longer destroying the live channel)
is directly relevant to this crate's reverse-path adopt flow.
Adopt fuzzing per docs/research/fuzzing.md, scoped smaller than
alkcall's (the envelope/chunk/demux/manager surfaces are upstream and
now fuzzed there; this crate fuzzes its own named downstream target —
the ADR-003 datagram codec — plus the params/reply parsers):
- fuzz/ workspace per the alkcall pattern: nightly-pinned subtree
(rust-toolchain.toml), thin fuzz_target! binaries, and a
stable-toolchain shared crate carrying the invariant logic so the
committed corpus replays as plain `cargo test` (the fuzz gate in
the release checklist — no hosted CI, alkcall §7.9 posture).
- Targets (both over already-pub APIs; no #[cfg(fuzzing)] exposure):
- datagram_codec — DatagramReader::feed + frame_datagram: no-panic,
infallible decode, size bound, F-2 sentinel layering (empty
datagram only from a length-0 header at a frame boundary),
3-byte-slice splitting transparency, re-frame round-trip,
oversize rejection at the bound, is_mid_datagram framing state,
and the decoder-state retained-bytes bound.
- params_parse — serde params/reply parsers + establishment_reason:
no-panic on raw bytes and bounded structured Values, clean typed
failure, round-trips, listen: 0 pin, loud/lenient projection-pair
agreement, pass-through reason extraction model.
- New public diagnostic: DatagramReader::retained_bytes() (decoder-
state byte count; the fuzz bound asserts against it).
- 96 committed seeds (gen_fuzz_seeds.py) + the campaign-found crash
input promoted as datagram_codec/seed-900; grown corpora gitignored.
- run-detached.sh: setsid+nohup runner so campaigns never share fate
with the agent session process tree (fuzzing.md §5).
Campaign findings this session were harness-model defects, not crate
bugs (both invisible to example-based review; the alkcall
"fuzzer as harness-checker" pattern confirmed):
- the F-2 empty-datagram invariant first counted [00 00] pairs in the
raw stream — a pair inside a payload region is payload, not a
header; corrected to walk the framing (crash artifact saved).
- establishment_reason is a pass-through extractor of details.reason,
not a validated table (harness first asserted a closed set).
- is_mid_datagram means a partial datagram, not buffered header bytes
(a 1-byte header fragment is buffered, not in flight).
Verification: cargo test 135 passed; clippy -D warnings and fmt clean
(main + fuzz/shared); corpus replay green; cargo fuzz build clean;
wasm32-unknown-unknown check clean. Wave-1 campaigns (10-min detached,
fork mode): params_parse 3.14M execs / datagram_codec 827k execs,
0 crashes/OOMs/timeouts; coverage saturated on the codec state space.
- README sync: the direct op (ADR-007), the bind-first establisher +
the forwarded op (ADR-008), TunnelListener + the reply-field
projection, the 0.2 summary section, the local bind-first helpers
- CHANGELOG: Unreleased cut to 0.2.0 (the graduation + the alkcall
0.8.0 bump; compare links updated)
- Cargo.toml: 0.1.0 -> 0.2.0
Verification: cargo test (135 pass default / 162 with local), clippy
(all targets, -D warnings, both feature sets), fmt, doc, the
wasm32-unknown-unknown check + clippy, and cargo publish --dry-run
--allow-dirty all green
The 0.7.1 lockfile resolution behind the MSRV floor raise. The
alkcall requirement in Cargo.toml stays "0.7.1" only after the floor
commit paired it there; the lockfile is the piece that actually moves
the resolved 0.7.x to the version whose MSRV (1.88) this crate now
declares. alkcall 0.7.1 changed no type alktunnels touches
(version-requirement- and patch-level only; full suite green on both
toolchains in the previous commit).
Closes the behavioral test gaps the 2026-09-09 coverage review found
(88.28% → 92.86% lines; details in tasks/tunnels/coverage-weak-spots.md):
- Datagram EOF paths (consumer.rs:377-382, 255) — previously
zero-covered documented contracts: a clean stream EOF resolves
`Ok(None)` (the pump-less session's shutdown signal), a mid-datagram
EOF fails loud with `TruncatedDatagram` (OQ-TN-13), both over a new
closable UDP echo dial (`closing_udp_echo_dial`, both shapes).
- UDP `take_halves` (consumer.rs:201-205) — pins the N-3 framing
contract: taken halves carry raw `[len: u16 BE]` wire bytes, and
the data-plane accessors fail `ChannelTaken` after the take.
- Reverse UDP `pump_against` (consumer.rs:289) — the framed side
round-trips end-to-end (payload + the F-2 empty datagram `len=0`
survives the pump), the N-11 boundary contract.
- `AcceptQueue::push` after close returns `Err(handle)`, closed pop
resolves `None`, and the accept loop's queue-closed mapping ends
the loop with the handler error (producer.rs:279-288, local
accept_loop).
- `establishment_reason` wrapper (params.rs) — unit test over the
typed surface (open_failed reason / non-establishment /
AdoptFailed); plus the schema-gate preemption probe in
producer_open_op (missing substrate is `INVALID_INPUT` before the
establisher runs).
- `UdpHalf` write machinery (local/mod.rs) — four poll-driven tests:
queue accept + flush drain to the wire + shutdown best-effort,
repeated flush cycles, the unconnected-socket error mapping
(deterministic EDESTADDRREQ), and the shutdown-drain-swallows-
errors posture. Host probes recorded in the task doc: no UDP
sender-blocking shape is reachable on this host (loopback/veth
drop silently; the fresh-socket try_send quirk is timing-tolerated,
never asserted), so the stash/high-water paths stay uncovered by
host limitation, not by oversight.
Verified: cargo test (default + --all-features), clippy --all-targets
-D warnings, fmt --check, wasm32 check + clippy, llvm-cov 92.86%.
alkcall 0.7.0 resolved every open downstream-consumer finding,
including this crate's reverse-flow POC W1 (filed as ledger CF-005,
with the CF-006 corollary):
- CF-005 (a): ServingConfig.identity — the explicit override
- CF-005 (b): transport Connection::identity() propagates to
channel 0 — set_identity before dialing is the mTLS/QUIC path
- CF-006: the establisher/pump handler receive the per-call opener
identity (dispatch-resolved), not the install-time context
- CF-007: ADR-016 code list completed (doc-only)
- F-1 (POC finding): the ChannelPlan type doc now carries the
Send + Sync payload constraint
alktunnels updates:
- Cargo.toml: alkcall 0.6.0 -> 0.7.0 (lockfile resolves 0.7.0)
- AGENTS.md convention 11: pin note updated; the 0.7.0 identity
surface marked load-bearing (precedence order + per-call opener)
- AGENTS.md architecture context: CF-005/CF-006 row added; the
'What the POC does NOT settle' list replaced with the accurate
settled state (Phase 0 complete; Phase 1 = the spec)
- reverse-poc-summary: W1 marked RESOLVED with the remediation
validated from the POC's topology (16 tests over 0.7.0: transport
identity alone authorizes, ServingConfig.identity overrides,
identity-less fails closed, CF-006 witness); F-1 marked documented
upstream; what-the-POC-does-not-validate and verification blocks
updated
- phase-0-findings OQ-TN-10: reverse POC entry notes the 0.7.0
re-validation and W1 resolution
The reverse POC (/workspace/alktunnels-reverse-poc, 8b35818) re-
validated: the default harness now authorizes on transport identity
alone — the 0.6.0-era auth_token workaround is dead code.
Verification: cargo test, clippy --all-targets -D warnings,
fmt --check, wasm32 check, doc --no-deps — all clean