Commit Graph
107 Commits
Author SHA1 Message Date
glm-5.3-flash a99cc67e76 chore(release): 0.10.1 — the adoption-window ordering fix
Changelog entry for review 013's fix (4dbd4bc); version bump 0.10.0 →
0.10.1 (patch — private fix surface, no API or wire-format change).

Verification: semver-checks 196 pass (no semver update required);
cargo test 700 + 724 (--all-features) pass; clippy --all-targets
--all-features -D warnings, fmt --check, wasm32-unknown-unknown check +
clippy, fuzz corpus replay (5/5), and cargo publish --dry-run clean.
Downstream gate: alkgit's flaking row re-verified green under
multi-process load against 4dbd4bc.
v0.10.1
2026-10-22 05:28:12 +00:00
glm-5.3-flash 4dbd4bc583 fix(channels): close the adopt-window ordering race (review 013) — atomic install+park-drain
A chunk routed by the demux inside the adopt_channel install→drain
window was delivered ahead of earlier-parked early arrivals: the mpsc
send order was inverted relative to wire-arrival order, misordering the
channel's byte stream (C-01, critical — downstream alkgit observed two
desync shapes under multi-process load). A related loss variant is also
closed: a chunk whose map miss parked it after the drain had removed
the queue sat parked forever.

The window closes by serialization, not by widening locks across
awaits — the resolution is fully synchronous:

- route_payload holds the channels-map lock across the miss → park
  decision (park_early_arrival runs nested; lock order channels →
  early_arrivals): a park can never straddle the install, and the
  installer that caused the miss always swaps the queue out.
- install_locked (new, shared by open_channel / adopt_channel /
  install_channel_zero) swaps the parked queue, inserts the state, and
  try_sends the parked queue into the fresh, empty receiver before
  releasing the channels lock — a direct route can only begin after
  release, so parked chunks always precede it in send order. No await
  runs inside the section: the effective park cap is now
  min(EARLY_ARRIVAL_CAP, buffer_cap), bounding the parked queue by the
  receiver's capacity so the drain never blocks. drain_early_arrivals
  remains as the defensive full-buffer fallback and is now called by
  all three install paths.

Regression tests: adopt_window_does_not_reorder_chunks (200 iterations
on a 2-worker runtime — a racer routing C the moment the install is
visible, receiver byte stream asserted byte-identical to the producer's;
catches the old window under genuine preemption, the alkgit repro
shape), adopt_drains_parked_and_raced_chunks_in_fifo, and
park_cap_bounded_by_receiver_buffer. rt-multi-thread added as a
dev-dependency for the runtime test.

Semver: patch (0.10.1) — private fix surface; no API, wire-format, or
documented-cap behavior change; behavior only strengthens.

Verification: cargo test 700/724 (--all-features) passed; clippy
--all-targets -D warnings clean; fmt --check clean; cargo doc --no-deps
generated; fuzz corpus replay passed; wasm32-unknown-unknown check
passed.
2026-10-22 04:47:42 +00:00
glm-5.3-flash 56e0f135d7 docs(review): find the adoption-window ordering race — routed from alkgit's wave-2 gate
Review 013 [critical]: a chunk routed in the adopt_channel
install->drain window overtakes earlier-parked early arrivals,
misordering the reassembled byte stream (and, combined with the
EARLY_ARRIVAL_CAP overflow branch, can drop chunks) on a freshly
adopted channel. Diagnosed downstream: alkgit's wave-2 gate caught its
channels open-op test flaking under load and traced both observed
desync shapes (mid-advertisement 'fetc' after 0 lines, '00ev' after 1)
to the window. Includes the fix-shape sketch (per-channel ordered
mailbox recommended), the chunk-granularity regression gate, and the
downstream re-verification requirement. The ordering half of review
006 E-04's adopt-race family; alkgit carries no workaround by design.
2026-10-21 13:51:09 +00:00
glm-5.3-flash 1a1e4eb7c0 chore(release): 0.10.0 — the gateway ownership seam
The review-012 batch rides this tag: the dispatch-spine ownership
provider threading (with_ownership_provider) and the loud default
(FORBIDDEN, pre-dispatch, for resource_type-gated ops on an unwired
spine) with the with_static_ownership_fallback escape hatch.

Verified: 698 tests (incl. stub guard), clippy --all-targets
--all-features -D warnings, fmt --check, cargo doc, wasm32
check+clippy, fuzz corpus replay 5/5, semver-checks (additive API diff;
two new builder methods only), publish --dry-run clean.
v0.10.0
2026-10-17 14:28:57 +00:00
glm-5.3-flash 1fda0d8587 fix(gateway): review-012 regression-pass cleanup on the loud ownership default
- deduplicate the thrice-repeated refusal block into
  GatewayDispatch::ownership_wiring_refusal(&self, op)
- drop the dead unwrap_or("") branch in the refusal predicate
  (let-else: the internal-visibility exemption and the resource_type
  predicate are now separate lets)
- pin the predicate refinement review 012 ruled on: a list-case op
  (resource_type set, resource_id_path None) is refused on an unwired
  spine and served through owns_any when a provider is wired

Verification: cargo test (697), cargo test --all-features (721),
clippy all-targets both configs, fmt --check
2026-10-17 14:17:06 +00:00
glm-5.3-flash 9899b37a82 feat(gateway): the loud ownership-wiring default (review 012 ruling)
- GatewayDispatch now refuses (FORBIDDEN, pre-dispatch) any op whose
  spec gates on access_control.resource_type when no ownership
  provider is wired — invoke, invoke_streaming, and invoke_sink alike
- Predicate is resource_type, not resource_id_path as review 012
  first drafted: AccessControl::check consults the provider whenever
  the resource type is set, including the list/owns_any case; the
  refusal message is operator-directed and names both opt-ins
- Exemptions: resource_action-only ACLs (no provider is consulted on
  the wire either) and Internal-visibility ops (spec-404, no
  acknowledgment leak)
- with_static_ownership_fallback(): declared opt-out to the ADR-011
  static fallback for deployments with no runtime ownership model —
  the door contract becomes enforceable, not just documented
- Superseded the pre-ruling pin
  gateway_without_provider_admits_only_the_static_claim with refusal/
  opt-out/exemption tests (all three entry points covered)
- ADR-048 amendment records the ruling; review 012 status updated

Blast-radius survey: alkhttp is the only live GatewayDispatch
consumer (unpublished, three unwired sites); alkblobs the only live
resource_type op producer (serves native-wire, providers wired);
no published 0.9.0 consumer relies on the silent fallback for such ops.
Ships in the same unreleased batch as the review-012 amendment.

Verification: cargo test (697 pass), cargo test --features gateway
(720 pass), cargo clippy --all-features --all-targets -- -D warnings,
cargo fmt --check, fuzz corpus replay (5 pass)
2026-10-17 14:09:16 +00:00
glm-5.3-flash d0b8124064 feat(gateway): thread the ownership provider through the dispatch spine (review 012)
- GatewayDispatch carries ownership_provider: Option<Arc<dyn
  OwnershipProvider>> + with_ownership_provider (dispatcher-identical
  builder); the shared root-context builder threads it, covering
  invoke / invoke_streaming / invoke_sink. Default stays None (the
  ADR-011 static fallback) — additive and opt-in, no context shape
  change, no behavior change for existing consumers.
- Door contract documented in the ADR-048 amendment: doors serving ops
  whose authorization truth is a revocable grant table must wire the
  same provider the wire path consults (visible-surface =
  authorized-surface). Anchored downstream by alkgit's LFS POC.
- The loud default (refuse resource_id_path ops with no provider
  wired) is deferred, not decided — tracked in review 012, ruled on
  after the door blast-radius survey; it belongs in the same release
  batch.
- Release placement: committed unreleased — additive work rides the
  next breaking batch (0.10.0's class) instead of publishing 0.9.1,
  keeping the six-consumer downstream churn to one coordinated update.

Verification:
- cargo test --all-features (717 + stub_guard); fuzz/shared corpus
  replay (5); clippy --all-features --all-targets -D warnings; fmt;
  cargo doc --no-deps
- in-crate regression tests pin static-fallback behavior, live-table
  override, revocation live on the gateway surface
- POC-L tests/gateway_gap.rs re-run against published 0.9.0 — green
2026-10-17 08:28:44 +00:00
glm-5.3-flash 03a6689c99 docs(review): 012 — gateway ownership seam, consumer input from alkgit's LFS POC
Report-only: GatewayDispatch::invoke hardwires ownership: None, so
External namespace-ACL ops through the HTTP gateway fall back to the
static Identity.resources model — token-carried claims admit without
consulting revocable grant tables (POC-L tests/gateway_gap.rs).
Three resolution shapes recorded; disposition is session-owned.
2026-10-17 07:28:44 +00:00
glm-5.3-flash 1a493e9748 chore(release): 0.9.0 — the stub sweep
- version 0.8.1 -> 0.9.0 (minor bump: 5 breaking lints vs 0.8.1 —
  ManagerError::InvalidAdopt variant, RelayError::PubTypedOpen
  removal, register_imported* Result return, Establishment Debug
  derive dropped; all pre-1.0 permitted)
- CHANGELOG 0.9.0: S-01..S-04 from reviews 010/011 (the marked-pub
  open contract, channel/control, channel/resources/subscribe,
  op/register forward-through), the stub guard, and the
  verification summary
- open_pub_channel: a non-object input tears down the freshly
  allocated id before the early return (the slot is not parked
  against the ADR-040 bound; regression test added)
- register_imported_all: atomic — a refusal leaves the overlay
  untouched; atomicity documented

Verified: cargo test (697 + stub guard), clippy --all-targets
--all-features -- -D warnings, fmt --check, cargo doc,
wasm32-unknown-unknown check, fuzz corpus replay 5/5,
cargo publish --dry-run --allow-dirty clean.
v0.9.0
2026-10-14 04:50:55 +00:00
glm-5.3-flash 4278c13b2d docs(research): phase-0 research — the topic broker's placement, shape, and the op-as-topic tangle
OQ-42 (the broker) is deferred(scope) on two uncommitted blockers: a
consumer crate committing to fan-out (its named candidate, alktrader,
drifted away) and the composition layer's ownership (OQ-43). With four
published dependents and alkgit/alkfs growing subscription surfaces on
alkblobs downstream, deferral now compounds: a later broker delivery
ripples 6-8 crates vs riding the v0.9 bump. This research disentangles
the fused 'op as topic' concept (topic identity vs the
schema/ACL-validated op surface), inventories the delivered primitives
the broker composes on, proposes the in-crate opt-in composition-module
placement amendment (ADR-047 Gap B) and the dependency-free TopicStore
durability seam (in-memory default; mem/sqlite/postgres adapters
downstream, never an engine dep in alkcall), and enumerates eight
proposed open questions (QP-1..8) with convergence criteria for Phase 1.

No behavior change; docs/research is excluded from the published package.

Verified: cargo test (697 ok), clippy -D warnings, fmt --check, cargo doc --no-deps
2026-10-13 19:47:42 +00:00
glm-5.3-flash 3ca7505abd docs(src): re-key live docs.rs comments off the alknet replacement
- src/channels/adapter.rs: OQ-41's QUIC-native substrate deferral now
  names the composition layer (owner OQ-43, today the alknet glue)
  instead of repo-pinning 'the downstream alknet crate' — matching the
  re-key convention already applied to docs/architecture
- src/client/mod.rs: AdapterError's downstream-adapter example renamed
  from the retired `alknet-http` to `alkhttp`
- src/client/from_call.rs: stale 'integration test in a later task'
  hedging replaced with the actual loopback coverage (relay_tests,
  hub_leg_tests, gate2_tests)

Verified: cargo test (697 ok incl. stub_guard), clippy -D warnings,
fmt --check
2026-10-13 11:32:12 +00:00
glm-5.3-flash ff07f92bdb docs(agents): fix stale references in architect.md and coordinator.md
architect.md:
- ADR-009 §"What this framework is NOT" → ADR-032 — the pointer was an
  alknet-numbering leftover; in-crate ADR-009 is BiStream-as-handler-leaf,
  the door-framework section lives in ADR-032. Same collision class the
  docs pass (5f019c0) fixed in the spec.
- OQ status list now includes deferred(scope), deferred(unclear),
  dissolved — matching the tracker's actual vocabulary and this prompt's
  own Safe-Exit section (they contradicted each other).
- tasks/architecture/ softened: this repo has no tasks/ dir; the OQ
  "Blocked on:" field is the tracker of record.
- Deferral-blocker examples re-keyed off alknet ("alknet-http crate
  spec" → the composition-layer crate spec, OQ-43; "alknet-agent crate
  spec" → "the agent crate's spec") — examples were teaching the exact
  repo-pinned blocker class just cleaned out of the OQs.

coordinator.md:
- Example spawn template said "implementation specialist for
  @alkdev/alknet" with alknet-era constraints ("feature flags for
  transports (tls, iroh, acme)") — agents copying the template would
  re-introduce the residue into every spawned prompt. Now names
  @alkdev/alkcall and points at AGENTS.md convention 11 (lean base
  crate, no quinn/iroh unless the feature is on).

Verification: repo-wide residue sweep — alknet mentions survive only in
AGENTS.md's intentional provenance/historical framing; no stale ADR
number pointers remain in .opencode/agents/; architect.md's internal
sections (Safe Exit, anti-patterns, status vocabulary) are mutually
consistent.
2026-10-13 11:16:31 +00:00
glm-5.3-flash f93ac3792d docs: align AGENTS.md with the alknet de-repo-pinning pass
AGENTS.md is auto-loaded by every agent, so its framing had to match the
re-keyed spec (5f019c0). Three alknet-era passages conflicted with it:

- Intro: "unification of alknet-call / alknet-channels" → "extraction
  and unification of the former ... crates" (same provenance framing as
  the spec docs).
- Convention 9: dropped "when the alknet mono-repo is reworked, it will
  consume alkcall's versions" — replaced with the current truth: the
  source-repo core crate is retired, the mono-repo is being replaced by
  thin glue (composition layer — OQ-43).
- Architecture Context: ADR range 001..054, OQ range OQ-01..43 with
  OQ-43 named; the porting bullet now states mono-repo = provenance not
  a live dependency, names the sibling host crates (alkhttp/alktls/
  alktty/alktunnels/alktrader) as the current homes of the alknet-era
  surfaces, and documents the citation convention ("alknet ADR-NNN
  (provenance)" / "alknet OQ-NN" — never in-crate authority).

Also lists ADR-054 (re-owned X.509 verifier-selection rule) in the key
ADR list so agents don't chase the demoted alknet ADR-034 as authority.

Verification: residual alknet-mention sweep of AGENTS.md (only marked
provenance/historical framing remains); section cross-check against
docs/architecture/README.md's provenance note and OQ-43 wording.
Docs-only change — no code paths touched.
2026-10-13 11:15:24 +00:00
glm-5.3-flash 5f019c02f1 docs: re-key architecture docs off the alknet mono-repo — speak as alkcall
The ported docs still framed alknet siblings (alknet-core/-call/-channels/
-http/-tls/-client) as live load-bearing context of this crate. With the
extraction complete and alknet headed for glue-level replacement, the docs
now speak as alkcall and cite the real sibling crates (alkhttp, alktls,
alktty, alktunnels, alktrader).

- ADR-054 (new): re-own the verifier-selection rule in-crate — three
  remote roles (public X.509 endpoint / transport relay / hub),
  ServerCertVerifier by PeerEntry presence, RemoteIdentity None
  load-bearing. Provenance: alknet ADR-034 (never ported), demoted to
  footnote. Resolves OQ-21's cross-repo authority gap.
- OQ-43 (new, deferred(scope)): composition-layer ownership and shape
  after the alknet replacement — the named receiver for the
  downstream-side deferrals (OQ-33 endpoint layer, OQ-41 QUIC-native
  substrate, OQ-42 hub broker, OQ-19 persistence adapters, ADR-045 dial
  seam). README layering diagram redrawn with the composition layer as
  TBD-ownership instead of "alknet / alknode" in concrete.
- Spec docs reframed: titles, self-references, dial/TLS/from_jsonschema
  homes, malformed legacy cite rows removed; dead relative research
  paths qualified as source-repo paths.
- ADR amendments (append-only): 027 (alknet-http -> alkhttp), 031 (post-
  extraction state), 044 (split landed as modules in alkcall), 045
  (name normalization; citation-space note).
- Citation hygiene: unprefixed/colliding source-repo cites prefixed
  ("alknet ADR-NNN (provenance)") across 009/011/022/034/035/038/040/
  043/044/045; stale OQ cites corrected (session registries OQ-04, batch
  semantics OQ-03, verifier rule ADR-054); stale anchors fixed.
- README provenance note consolidated; citation conventions documented.

Verification: markdown link check (all local links resolve, all in-crate
ADR cites point at existing decisions/ files); table integrity check
(uniform row widths across open-questions.md and edited tables); residual
alknet-mention sweep (only provenance/historical/intentional framing
remains); architecture review subagent pass with zero remaining criticals.
Docs-only change — no code paths touched.
2026-10-13 10:53:47 +00:00
glm-5.3-flash 7b8a3e7558 docs: spec-level sync with the single-publish fix + port-debt repair
The spec docs had not caught up with the stub-sweep fix commits
(4eae18f..3317ea0), and the ported docs still carried alknet
numbering that now collides with alkcall's own ADR range.

Spec sync with the landed code:
- call-protocol.md: register_imported/register_imported_all return
  Result and refuse marked specs; marked-spec registration refusal
  contract spelled out (ADR-047 am. 4 §4.8, ADR-022 am. 2026-10-13)
- client-and-adapters.md: from_call flow gains the Pub sink-forwarding
  branch and the marked-op refusal (resolves OQ-37 — no from_call
  relay wrapper; sanctioned compositions are
  ChannelRelay::register_relay_openable / ChannelClient)
- ADR-051: "channel/control is not implemented" stale sentence
  replaced with the ADR-052 per-leg control contract
- OQ-37 resolved; OQ-22 split (primitive resolved; broker placement
  out of scope) with new OQ-42 for the downstream hub broker
  (deferred(scope), concretely blocked); OQ-24 resolved by the shipped
  add/strip surface; OQ-41 → deferred(scope) with blocking condition
- README: OQ bullets renumbered to tracker IDs; alknet-collision note
  rewritten (range 001..053, alknet prefix convention); new principle
  11 (implement-or-stop-advertising); AGENTS.md ADR range 001..053

Port-debt repair:
- 149 broken decision links across 17 docs — ported with alknet
  numbers/paths, most now remapped to alkcall files by slug; the
  rest link the alknet repo per the README convention
- stale OQ numbering rewritten to tracker IDs in call-protocol.md,
  call-README.md, operation-registry.md, client-and-adapters.md,
  ADR-025, channels-overview/README/wire, channel-client
- unambiguous "alknet ADR-NNN" labels where an alknet number collides
  with an alkcall ADR (052 TTY vs channel/control, 033 storage vs
  rust-canonical, 025/026/027+020 vault vs PeerEntry/auth ADRs)

Verified: cargo test (697 + guard), fmt, clippy --all-targets -D
warnings; full markdown link scan clean.
2026-10-13 09:34:37 +00:00
glm-5.3-flash 3317ea0963 docs: step-3 rewrites — OQ-39/40 resolved, C-08 closed, channel-operations.md put/control/resources contracts, review 010/011 closed with the S-01 sketch corrected
- 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.
2026-10-13 09:04:13 +00:00
glm-5.3-flash 944c300c17 feat(channels): implement the single-publish fixes — S-01..S-04 (reviews 010/011; ADR-047 am. 4, ADR-052, ADR-053, ADR-022 am.)
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.
2026-10-13 09:00:21 +00:00
glm-5.3-flash df4d4d3a9e docs(adr): amendments pinning the single-publish fix — marked-pub contract (047 am.4), control surface (052), resource enumerators (053), op/register forward-through + marked refusal (022 am.)
Per review 011 §6 sequencing: the four amendment documents drafted
before code. All pins, no options — the hedged alternatives are stated
as rejected with rationale:
- ADR-047 amendment 4: the marked-pub open contract (review 011 §1/§2's
  seven pins — marker semantics, publish_schema refusal, reserved input
  key + dispatch strip, wrapper-as-responder-of-record, ack-timing
  sentence, relay translation, client put-open capability) plus the
  registration invariants that make stubs unregistrable (§4.8).
- ADR-052 (new): channel/control control-handle surface — establisher-
  contributed ChannelControl, wrapper-owned registry, channel:no_control_handle.
- ADR-053 (new): channel/resources/subscribe live resource enumerators —
  snapshot-then-changes, scan-once aggregation, empty seed.
- ADR-022 amendment: announced unmarked Sub/Pub forward through the real
  forwarding shapes; marked announcements refused (MARKED_SPEC_UNSUPPORTED).
2026-10-13 08:27:50 +00:00
glm-5.3-flash 4eae18f539 fix(core): unused map-key iteration in Capabilities::zeroize tripped the release gate
clippy::for_kv_map under -D warnings; main has been ungreen since before
the 0.8.1 publish. Folded into the 0.9.0 publish per review 011, but main
stays green from now.

Verified: cargo test (684), clippy --all-targets -D warnings, fmt --check.
2026-10-13 07:49:47 +00:00
glm-5.3-flash 549893cbbf docs(review 011): downstream input on review 010's S-01 — the marked-pub open contract and the single-publish amendment requirements
From alkblobs (paused on S-01; its ADR-014 is the reviewed downstream
ruling):

- S-01's option-1 sketch (hand the OpenHandler the PublishStream) is
  the wrong shape for marked ops — it imports ADR-046's unmarked
  call.published semantics into the ADR-047 §2 marker case. The
  settled shape: initiator allocates (odd) and writes immediately;
  responder adopts (channel id crosses the open invocation, reserved
  input key + dispatch-layer strip recommended); wrapper as responder
  of record (await the handler's JoinHandle, merge establishment
  reply fields + handler result into the single response); zero
  call.published on marked ops (nonempty publish chunks rejected
  loudly); relay PubTypedOpen lifted.
- Seven items the amendment-4 publish must pin (incl.
  publish_schema refused at registration for marked ops; the put
  acks-in-result sentence; the client-side stream-then-open
  capability absent from ChannelClient today).
- Verification gates list; S-02/S-03/S-04 downstream
  non-requirements and remedy preferences; per-crate impact for the
  four published consumers (none register Pub-typed openables —
  S-01 is capability-additive; semver risk concentrates in any
  stop-advertising removals).

Docs-only change.
2026-10-13 07:37:18 +00:00
glm-5.3-flash 1793265b04 docs(review 010): stub sweep — four invocation-failing stubs in the published surface 2026-10-13 06:40:10 +00:00
glm-5.3-flash 3bda29c419 chore(release): 0.8.1 — duplicate adopt/open fix + fuzz harness bookkeeping
- version 0.8.0 -> 0.8.1 (bug-fix release; semver-checks 196 pass vs 0.8.0)
- CHANGELOG 0.8.1: the manager_routing-found duplicate adopt/open fix,
  the fuzz harness, and the verification summary
- publish exclude gains docs/research/ (internal research notes;
  fuzz/ was already excluded — package verified clean of both)
- fuzzing.md §7.9: standing no-hosted-CI policy — corpus replay is the
  release-verification fuzz gate; campaigns manual via the detached
  runner; OSS-Fuzz out; no workflow files in this repo
- AGENTS.md: corpus replay added to the verification checklist
- lockfiles: alkcall 0.8.1 (root + fuzz)

Verification: 684 tests; clippy -D warnings (main, wasm, fuzz/shared);
fmt clean; doc clean; wasm32-unknown-unknown check+clippy clean;
semver-checks 196 pass; publish --dry-run 116 files (no fuzz/research/
reviews/sdd/AGENTS in the tarball); fuzz corpus replay 5/5 green
v0.8.1
2026-09-28 06:56:11 +00:00
glm-5.3-flash 77f7006e2e docs(research): fuzzing steps 1-3 complete; 10-min campaigns clean on all five targets
\u00a77.8 campaign results: manager_routing 1.06M execs (exact-counter and
parked-bytes invariants held across every adversarial sequence),
envelope_semantic 2.44M execs (coverage saturated, all event kinds
round-trip), spec_parse 10.8M execs (registry compiled every
attacker-shaped schema or rejected cleanly). All exited 0, zero
artifacts.

Also records the two harness-model defects the fuzzer caught in the
interim (per-receiver EOF-sentinel latch; odd/even Adopt range per
ADR-047 \u00a75). Doc-only + harness fixes; no crate changes.
2026-09-27 23:52:45 +00:00
glm-5.3-flash a1f257757b fix(channels): duplicate adopt/open must not destroy the live channel; fuzz targets 3-5
Found by the manager_routing fuzz target (docs/research/fuzzing.md \u00a77.8):

- ChannelManager::open_channel / adopt_channel used
  HashMap::insert(...).is_some() as a collision check \u2014 insert REPLACES
  the existing entry, so a duplicate adopt/open installed the new state,
  dropped the live channel's demux_sender (spurious EOF to its readers,
  subsequently routed chunks lost) and still returned
  Err(ChannelExists). Fixed with contains_key pre-check; map untouched
  on collision. Regression tests: adopt_channel_duplicate_id_leaves_
  live_channel_intact, open_channel_duplicate_id_leaves_live_channel_
  intact.

New fuzz targets (\u00a77.4 step 3):
- manager_routing: Arbitrary op sequences over ChannelManager; exact
  counter models (parked/dropped must equal the manager's monotonic
  counters), parked-bytes bound per \u00a76.2-1, clear_all ledger-vs-map
  semantics, drainer-byte reconciliation (lossless routing)
- envelope_semantic: constructors -> serde -> write_frame/read_frame
  structural round-trip; event-type constants; call.error parse-back
- spec_parse: OpRegisterRequest::from_json -> rebuild -> registry
  registration (attacker schemas compile at register, CF-003)
- fuzz/shared/src/arbitrary_value.rs: bounded Arbitrary for
  serde_json::Value; 20 spec_parse + 4 manager_routing seeds
- corpus replay for the new targets in fuzz/shared tests

Verification: cargo test 684 passed (682 + 2 regression); clippy
-D warnings clean (main + fuzz/shared); fmt clean (main + fuzz);
cargo fuzz build clean; 20 s smoke on all three new targets clean
(manager_routing 79k, envelope_semantic 141k, spec_parse 517k runs);
crash input replays clean post-fix
2026-09-27 23:19:18 +00:00
glm-5.3-flash c211c163fd docs(research): fuzzing step 1 complete — campaigns ran clean (fuzzing.md \u00a77.7)
chunk_header: saturated (203.9M execs, ~350k exec/s, 33 fork jobs clean);
envelope_frame: 2119 edges/1664 corpus entries, still growing at budget
end, 7.08M execs, 33 fork jobs clean. No crash/OOM/timeout artifacts in
either 10-min detached campaign; exit 0 both. Grown corpus not merged
(per \u00a77.1 corpus policy). Doc-only change.
2026-09-27 21:27:58 +00:00
glm-5.3-flash 80a37e94ab feat(fuzz): cargo-fuzz workspace, chunk_header + envelope_frame targets (fuzzing.md step 1)
- fuzz/ workspace (nightly-pinned via rust-toolchain.toml, excluded from
  the main workspace and the published package): chunk_header and
  envelope_frame targets per fuzzing.md \u00a77.1
- invariant logic in fuzz/shared (stable-toolchain crate): committed
  corpus replay as plain cargo test (quinn CI pattern, \u00a77.2 tier 3)
- envelope target adds FrameError shape-partition asserts, exact
  consumption accounting, structural write_frame round-trip, serde
  key-contract, and a trailing-byte probe (prefix counts body only)
- chunk_header target adds round-trip identity, TooLarge/short error
  shape, is_eof, 8-byte consumption, input-never-mutated
- committed seed corpora: 245 deterministic seeds via
  fuzz/gen_fuzz_seeds.py (truncations, len=0/MAX+1/u32::MAX, channel 0,
  invalid UTF-8, deep nesting); grown corpora + artifacts gitignored
- fuzz/run-detached.sh: \u00a77.6 detached runner (setsid+nohup+log, fork
  mode, rss/malloc limits) \u2014 campaigns never share fate with a session
- fuzz/json.dict; README; research doc \u00a77.7 records step-1 status

Verification: cargo fuzz build clean; stable side green (cargo test 682
passed, clippy -D warnings, fmt --check incl. fuzz/shared); corpus
replay 245 seeds green; detached 10-min campaigns on both targets
completed with zero crashes/OOMs/timeouts
2026-09-27 21:14:35 +00:00
glm-5.3-flash 7ae0315f19 docs(research): fuzzing must not share fate with agent sessions (detached runner)
- OOM in a fuzz target must cost the fuzzer, never the opencode host
- three defense layers: soft rss/malloc limits, fork-mode blast radius,
  setsid+nohup detachment with log-file polling (fuzz/run-detached.sh)
- no ulimit -v with ASAN; corpus replay + CI flag parity notes
- sequencing and summary updated to make the detached runner mandatory
2026-09-27 20:13:35 +00:00
glm-5.3-flash 791eea7298 docs(research): fuzzing evaluation — adopt cargo-fuzz, five targets, two-tier CI
- web survey of 2025/2026 Rust fuzzing tooling (cargo-fuzz/afl/bolero/libafl)
- practice survey: rustls, quinn, quiche, h2, prost, s2n-quic, yamux/libp2p
- parse-surface inventory of this crate (both wire formats, dispatch, manager)
- pre-fuzz code-review findings: unbounded early-arrival key-space
  (manager.rs early_arrivals), unbounded spawned-JoinHandle growth
  (dispatch.rs), 64 MiB pre-payload allocation window, O(n^2) abort cascade
- recommendation: cargo-fuzz + arbitrary, 5 targets (chunk_header,
  envelope_frame, manager_routing, envelope_semantic, spec_parse),
  committed seeds only, 10s/target smoke CI, OSS-Fuzz after stabilization
2026-09-27 20:01:29 +00:00
glm-5.3-flash 7bb76cd2b5 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.
v0.8.0
2026-09-18 13:23:56 +00:00
glm-5.3-flash 9620ee7b2a test(review 009): all seven coverage findings; errata on three as-filed claims
Review 009's coverage debt in full — the paths the review-008 gates
never walk. No wire or API changes.

- C-1: pin the plain-bundle install-failure arm (un-compilable
  input_schema; the as-filed duplicate-name route does not fail
  registration) — the install task ends before the dispatch loop,
  channel 0 never dispatches. ADR-051 §5 gains the loud-install
  coverage note: relay-openable + plain-bundle arms pinned,
  generic-ops + bootstrap-discovery arms documented as
  best-effort-loud (crate-internal specs compile by construction).
- C-2: the HubLegImports filter — filtered closure path + only
  partition unit-tested (errata: only was already pinned at filing);
  the empty-stash e2e gate (generic ops + discovery only, dropped
  ops resolve NOT_FOUND).
- C-3: the batch-form reserved-reply-key rejection pinned (reason
  handler_error, teardown, ledger decrement, no pump spawn).
- C-4: open_channel_with_reply's failure path pinned e2e (the typed
  error carries the channel:open_failed code + details reason/message).
- C-5: both byte-identical claims golden-pinned — the no-fields reply
  against {"channel_id": 2} and the standard-shape wire payload
  against the full 9-key literal.
- C-6: derivation edge shapes pinned — channels//sub, channels//direct,
  channels → None; the 4-segment strict superset annotated as the
  pre-amendment behavior change (errata: actual is Some("x/sub"), the
  multi-segment-ALPN rule, not the as-filed Some("alk/x/sub")).
- C-7: builder overwrite pinned last-win (single + batch) with the
  doc sentence on with_reply_field.

Verification: 682 tests pass, clippy -D warnings clean, fmt clean,
doc clean, wasm32 check clean.

File: docs/reviews/009 (resolved; errata marked per finding)
2026-09-18 08:02:13 +00:00
glm-5.3-flash 54c2a3f941 fix(review-008 audit): adopted-entry drop guard; explicit-ALPN guards; review 009
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.
2026-09-18 06:19:56 +00:00
glm-5.3-flash 50182d7298 feat(review 008 Unit 3c): the gate-2 e2e harness; 0.8.0 release bookkeeping
- 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.
2026-09-18 05:15:29 +00:00
glm-5.3-flash 4e52bd496c feat(review 008 Unit 3b): the hub-leg install template (ADR-051 §5)
- src/channels/hub_leg.rs: HubLegImports (the Clone discover/stash,
  bundles split by the channel_open marker, with the per-consumer
  filter) and HubLegTemplate (the hub-leg install hook: per-connection
  fork + generic channel ops + plain bundles as-is + marked specs via
  ChannelRelay::register_relay_openable + bootstrap discovery closed
  over the fork (review 004 F-06) + serving-identity resolution
  (CF-005) + the single-stream dispatch loop).
- The loud assembly posture holds at install: a Pub-typed (or
  unregistrable) marked spec ends the leg's install task — channel 0
  never dispatches, never a silent stub (ADR-051 §6).
- Assembly rule surfaced by the gate e2e: from_call discovers the
  spoke's bootstrap discovery ops like any plain op; the template
  skips BOOTSTRAP_DISCOVERY_OPS (new pub const, discovery.rs) when
  re-registering plain bundles — the template's own install, closed
  over the fork, supersedes the imported copies.
- Gate tests (7): stash split + filter, the full template e2e
  (services/list shows the re-exposed ops, a plain imported op
  round-trips through the hub, the marked op opens through the relay
  with bound surviving, data both directions), serving-identity
  precedence (scope-bearing override resolves, scope-less fails
  closed), the loud Pub-typed posture, and the filtered-stash subset
  run (NOT_FOUND for the filtered-out marked op).
- Docs: ADR-051 status (3a + 3b implemented, 3c remains); review 008
  Unit 3b landed note (the bootstrap-op skip rule).

Verification: cargo test (665 passed), clippy --all-targets
-D warnings, fmt --check, doc --no-deps — all clean.
2026-09-18 03:48:52 +00:00
glm-5.3-flash 90c182039e feat(review 008 Unit 3a): in-tree ChannelRelay (ADR-051, ADR-042 amendment)
- 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.
2026-09-17 23:27:17 +00:00
glm-5.3-flash 91765446b7 docs(review 008 Unit 3 planning): ADR-051 — in-tree ChannelRelay + hub-leg assembly; plan split into 3a/3b/3c
Design session outcome for the relay unit. The hub/spoke family (hub
or spoke may relay; the hub re-exposes spoke services by ACL without
binding ports) needs the call-half support too, so the unit's scope
grew beyond the as-pinned sketch and is now three sub-units.

- ADR-051 (new): the relay is the wrapper composition — translate hop
  = the ADR-049 establisher shape, byte-forward hop = pump_bidi per
  ADR-050; the relay holds Arc<CallConnection> + ChannelManager per
  producer leg (not a ChannelClient — take_call_connection's detach
  is wrong for a hub with three CallConnection claimants); the reason
  mapping preserves the spoke's code+message (timeout is the one
  non-1:1 case, mapping to dial_failed); the registration seam is
  two-phase (discover/stash → per-connection fork-register — the
  ADR-047 §4 fork mechanism makes a one-call import impossible); the
  ADR-042 relay map dissolves (implicit per-channel mapping) and
  channel/close needs no translation surface (EOF cascade propagates
  with correct ledger accounting on both legs); Pub-typed marked
  specs are a loud assembly error; establishment bounds compound per
  hop (noted, no fix); the ACL layering note is pinned (the spoke's
  AccessControl sees only the hub identity; forwarded_for is never
  checked).
- ADR-042 amended: the §Scope note is revised (implementation is an
  alkcall export; hub crates compose it) and the two mechanism
  supersessions are recorded — the contract and auth-model rationale
  unchanged.
- ADR-047 amendment 3's forward reference and the README ADR index
  updated (001..051).
- Review 008 remediation plan: Unit 3 split into 3a (ChannelRelay
  component + gates), 3b (hub-leg install template — the call-half
  support), 3c (gate-2 e2e incl. the mid-establishment disconnect
  window); sequencing note updated; adoption note records the
  session's decisions.

Verified: cargo doc --no-deps (markdown-only change).
2026-09-17 06:47:48 +00:00
glm-5.3-flash 620180d615 feat(review 008 Unit 2): flavor-form open-op ids in discovery (U-1, ADR-047 amendment 3)
Flavor-form open op ids (channels/tunnel/direct, channels/tunnel/
forwarded — alktunnels ADR-007/008) now survive discovery + the
op/register announce path: the marker reconstructs, so a hub consuming
through discovery wraps the op with relay machinery instead of the
silent plain-forwarding-stub failure.

Per the review-008 plan's combined (b)+(c) shape:

- derive_alpn_from_op_name generalizes from strip-/sub|/pub to
  strip-last-segment (rsplit_once) — a strict superset: standard
  two-suffix shapes derive identically, multi-segment ALPNs survive
  the same way, and the flavor form derives. The boolean marker
  remains the gate (consulted only for marked ops in
  rebuild_spec_for) — a plain op named channels/tty/query is
  unaffected.
- spec_to_json_pub emits channel_open_alpn (the explicit string)
  beside the boolean when the op name is not the standard
  channels/<seg>/(sub|pub) shape; standard shapes stay byte-identical
  to the pre-amendment payload. The advertised operation_spec_schema
  documents the optional ["string","null"] property.
- rebuild_spec_for prefers the explicit string, else boolean →
  generalized derivation. Both wire consumers (from_call import,
  op/register announce) parse through the same parser, so one change
  covers both. A channel_open_alpn without the boolean never marks an
  op (the boolean is the dispatch hint).

Residual ambiguity pinned in the ADR: an ALPN segment colliding with
a flavor name (channels/x/direct → alk/x vs alk/x/direct) is
undecidable from the name alone; the explicit string is the
disambiguator.

Tests (review gates 1 + 3; gate 2 lands with the Unit 3 relay):
- channels/tunnel/direct reconstructs WITH channel_open = alk/tunnel,
  both via the explicit string and via the boolean alone (the
  deployment-skew case: old producer, new consumer)
- standard shapes (channels/tty/sub, multi-segment
  channels/custom/proto/sub) round-trip byte-stable — no new key
- explicit string overrides a colliding derivation; string without
  boolean is ignored
- op/register announced flavor-form spec round-trips with the marker
- derivation unit tests: flavor form, non-op-type suffix not
  special-cased, prior shapes unchanged

Docs: ADR-047 amendment 3 — the convention sentence (mirroring
alktunnels ADR-002 Amendment 1: flavors are new op ids, additive, the
.../sub op is never reused), the wire shape, the preference order,
the residual-ambiguity note, one-way-door timing.

Verification: cargo test 649 passed (12 new); clippy -D warnings
clean; cargo fmt --check clean; cargo doc --no-deps clean.
2026-09-16 10:34:45 +00:00
glm-5.3-flash 82ddddf986 feat(review 008 Unit 1): establisher reply projection (U-2, ADR-049 amendment 3)
The establisher can now contribute to the open-op success reply — the
establisher → opener direction amendment 2 left empty. First consumer:
alktunnels ADR-008's bind-first listen establisher, whose observed
OS-chosen bound address rides the reply as an additive `bound` field
(the SOCKS5 BIND reply#1 BND.ADDR fidelity ask).

- Establishment gains reply_fields (private, builder-constructed):
  with_reply_field / with_reply_fields / reply_fields. The map shape
  generalizes beyond `bound` without a fourth amendment; the
  #[non_exhaustive] carrier (amendment 2) makes the extension additive
  — no construction-site break.
- run_open_wrapper merges contributed fields into the success output
  after reserving `channel_id`. The key is wrapper-owned: an
  establisher supplying it fails the open loudly
  (channel:open_failed, reason handler_error, message naming the
  reserved key), tearing the just-allocated channel down — never
  shadowing. Absent fields leave the reply byte-identical to the
  pre-amendment shape (asserted exactly).
- ChannelClient::open_channel_with_reply returns
  (channel_id, reply, send, recv) — the full success output — so
  consumers read `bound` first-class; open_channel delegates and
  discards the fields, signature unchanged.

Tests (all gates from the review + plan):
- projection produces { channel_id, bound } on the wire; no-fields
  replies are byte-identical (establisher and no-establisher shapes)
- reserved-key establisher fails with reason handler_error; channel
  torn down, ledger decremented, pump handler never spawned
- registry-level register_openable_with_establisher projects fields
- e2e over a real channels connection: bound reaches
  open_channel_with_reply; open_channel unchanged against the same
  accept side
- existing establishment tests (establisher-success round-trip,
  plan-flow, no-establisher compat) pass unchanged

Docs: ADR-049 amendment 3 (projection, reservation, read path,
compatibility posture, door type).

Verification: cargo test 637 passed; clippy -D warnings clean;
cargo fmt --check clean; cargo doc --no-deps clean.
2026-09-16 10:27:12 +00:00
glm-5.3-flash 1bc937c061 docs(review 008): remediation plan — findings verified, three units pinned
Both findings verified against HEAD 3b36b40 (0.7.1); all citations
check out (one line drift: U-2 reply construction is operations.rs:945,
errata noted rather than silently edited).

Plan decisions recorded above the as-filed option lists:

- U-1 shape: combined (b)+(c) — explicit channel_open_alpn string for
  non-standard shapes; derivation generalized to strip-last-segment,
  gated on the boolean marker. As-filed option (a) is unsound (the
  derivation runs consumer-side; a registration-threaded allowlist has
  no path to rebuild_spec_for).
- U-1 gate 2 escalated to an in-tree relay component (src/channels/
  relay.rs), amending ADR-042's downstream-implementation scope note —
  the re-produce/relay shape is general (alkhttp fallback hub, alknodes)
  and a real consumer now requires it.
- U-2 adds open_channel_with_reply (ergonomic read path for `bound`);
  open_channel unchanged.

Units, sequenced 1 -> 2 -> 3, one minor release:
1. U-2 reply projection (ADR-049 am. 3) — lands first; the relay's
   establisher projects spoke reply fields through it.
2. U-1 derivation + wire field (ADR-047 am.) — standard shapes
   byte-stable; round-trip gates for flavor-form and boolean shapes.
3. Relay component + gate-2 e2e (ADR-042 am.) — establisher = translate
   hop (forwarded_for, adopt_channel, reason-code mapping, bound
   projection), OpenHandler = inline-await byte-forward hop;
   consumer -> hub -> producer e2e asserting bound survives the relay.

As-filed findings retained untouched above the divider (the review-007
pattern).

Verification: docs-only change; no build/lint/test impact.
2026-09-16 09:58:17 +00:00
glm-5.3-flash 3b36b4074f docs: review 008 — graduation upstream asks (flavor-form discovery derivation; establisher reply projection)
Filed from the alktunnels graduation spec work (ADRs 007/008):
U-1 extends ADR-047's op-name → ALPN derivation to flavor-form open
op ids (channels/tunnel/direct, channels/tunnel/forwarded) so the
marker survives discovery and hub relay wraps them as channels, not
plain forwarding stubs; U-2 (ADR-049 amendment 3 sketch) gives the
establisher a path to contribute additive reply fields (the bind-first
listen 'bound' address — BND.ADDR fidelity). Both additive; data
plane untouched. alktunnels implementation is sequenced after these
land.
2026-09-16 08:32:19 +00:00
glm-5.3-flash 098090d564 chore: bump to 0.7.1, changelog for the MSRV floor raise (1.85 -> 1.88)
Verification: 631 default / 648 all-features tests on stable, 1.88
toolchain test + clippy clean, clippy (all-targets, wasm32) clean,
fmt clean, doc clean, semver-checks clean, publish dry-run OK.
v0.7.1
2026-09-09 19:36:25 +00:00
glm-5.3-flash e2ca981eb6 chore: raise rust-version floor to 1.88; fix 1.88 clippy lints
The 1.85 claim was already false at the dependency level: the resolved
lockfile pulls icu_* 2.x (MSRV 1.86) and wasip2 1.87 transitively via
jsonschema -> idna, so 1.85 toolchains cannot build 0.7.0 regardless of
what Cargo.toml declares. Raising the floor to 1.88 aligns with the
noq QUIC path (per the ecosystem MSRV audit) and breaks no downstream
that could build the crate before.

- Cargo.toml: rust-version 1.85 -> 1.88 (version-line bump deferred to
  release time; semver-checks passes either way)
- src/channels/mux.rs: collapse else { if .. } (collapsible_else_if)
- src/core/types.rs, src/registry/registration.rs: inline format args
  (uninlined_format_args)

Verification:
- 1.88: cargo test --locked (631 pass), clippy --all-targets -D warnings
- stable 1.94: test --locked, clippy -D warnings, --all-features, fmt,
  doc --no-deps
- wasm32-unknown-unknown: cargo check
- cargo semver-checks check-release: no semver update required
2026-09-09 19:32:50 +00:00
glm-5.3-flash ed741c34e0 feat(cf-006/cf-007): per-call opener identity for open-op hooks; ADR-016 code-list sweep
Batch-fixes every remaining open alkcall-side finding from downstream
consumers so 0.7.0 is the only release they need to absorb.

- CF-006 (the CF-005 corollary): run_open_wrapper derives a per-call
  AuthContext — the opener's dispatch-resolved identity (the same
  identity the ACL gate and cap check saw) overlaid onto the
  install-time context — and passes it to both the establisher and
  the pump handler. Identity-less calls keep the install-time
  identity (no synthetic-anonymous rewrite); transport-truthful
  fields are never rewritten. Signatures unchanged — behavior-only;
  identical on per-connection registries, hub-forwarded opens now
  show the end client. Gates:
  open_wrapper_overlays_per_call_identity_on_install_time_auth +
  open_wrapper_keeps_install_time_identity_when_call_identityless.
- CF-007 (alkhttp review 006 Part C doc drift): ADR-016 amended to
  the eight-code list — ALREADY_EXISTS + CONNECTION_CLOSED in the
  Context, §3 table, and from_openapi collision rule; new §2a
  documents the undelivered-vs-ambiguous write-failure distinction.
- ChannelPlan type doc now states the Send + Sync payload constraint
  (alktunnels POC F-1 re-derived it by compiler error).
- Ledger: CF-006 and CF-007 filed + resolved; CF-005's corollary
  note points at CF-006; the Open section is empty. ADR-049 gains
  the per-call-identity note. Changelog 0.7.0 covers the batch.

Sweep result (all downstream reviews): no other open alkcall items —
alktunnels W3/F-2 are downstream-by-design, alktty R3/P14 are closed
constraints, alknet has none; OQ-24/37/39/40/41 stay
deferred-by-design (no consumer pull yet).

Verification: cargo test (631) + --all-features (648), clippy
(all-targets, all-features, -D warnings), fmt --check, doc
--no-deps, wasm32 check, semver-checks (no update required),
publish --dry-run.
v0.7.0
2026-09-07 11:26:12 +00:00
glm-5.3-flash db5530ed34 feat(cf-005): connect-side serving identity — ServingConfig.identity + transport-identity propagation
Verifies and fixes CF-005 (alktunnels reverse-flow POC W1): the
connect-side serving path built channel 0 internally and never set an
identity, so a scope-gated serving op could only be satisfied via the
payload auth_token. Token is now the fallback (hub-forwarding /
browser path); transport/key-based identity is the primary path.

- ServingConfig gains identity: Option<Identity> — the explicit
  override (remediation a). Semver-relevant struct-literal change →
  0.7.0 (minor bump at 0.x, wire surface unchanged).
- from_connection_with_serving propagates the transport
  Connection::identity() to the channel-0 connection via set_identity
  before the serving loop starts (remediation b) — mirrors the accept
  side's install-hook set_identity; process-local, nothing new on the
  wire.
- Dispatch identity precedence on the serving loop: payload
  auth_token → identity_provider, then ServingConfig.identity, then
  transport identity; identity-less dispatch still fails closed
  (FORBIDDEN).
- Public core::auth::NoopIdentityProvider (resolves nothing; the
  ServingConfig::default() provider — three private test copies
  existed).
- Regression gates: four cf005_* e2e tests (transport propagation,
  override precedence, identity-less denial, token fallback +
  precedence).
- Ledger CF-005 → resolved; ADR-022 §connect-side-serving amended;
  README example updated; changelog 0.7.0.

Verification: cargo test (629) + --all-features (646), clippy
(all-targets, all-features, -D warnings), fmt --check, doc
--no-deps, wasm32 check, semver-checks (no update required at
0.7.0), publish --dry-run.
2026-09-07 11:00:47 +00:00
glm-5.3-flash 0d287a97b0 docs(ledger): CF-005 — connect-side serving path has no caller-identity capture (alktunnels reverse-flow POC W1) 2026-09-07 10:06:30 +00:00
glm-5.3-flash d22cecd317 docs: ADR-049/050 in indexes; changelog link refs; ported-ADR range 001..048
- architecture README: index rows for ADR-049 (establishment phase) and
  ADR-050 (pump_bidi); stale ADR-001..045 range labels corrected
- channel-operations.md: design-decision table + references list the
  two new ADRs
- CHANGELOG: missing link references for 0.4.0/0.4.1/0.5.0/0.6.0
- AGENTS.md: ADR range 001..050
v0.6.0
2026-09-07 09:03:10 +00:00
glm-5.3-flash d25deb5eaf docs(review 007): mark R-01/R-02/R-03 resolved; record the two sketch deviations
Status → Resolved with the three unit commits; both deviations from
the review's sketches (typed-opaque ChannelPlan over Option<Value>;
(u64, u64) over io::Result) recorded up top with their rationale, as
the ADRs carry them.
2026-09-07 08:48:06 +00:00
glm-5.3-flash 9c6fec17ca feat(review 007 Unit 3): pump_bidi two-pump helper (R-03, ADR-050)
Extracts the two-pump data-plane helper alknet ADR-078 deferred until
the shapes converged (they have: alktunnels POC pump_halves + alktty's
channels session). Purely additive.

- channels::pump::pump_bidi(channel, peer_read, peer_write) -> (u64, u64):
  two joined pumps, shutdown-on-completion per direction; copy counts
  for observability. The channel side is a single AsyncRead +
  AsyncWrite value (the accept_bi BiStream); the peer side takes split
  halves — the establisher's natural dial result (into_split).
- Return (u64, u64), not the review sketch's io::Result<(u64, u64)>:
  both pumps swallow copy errors by contract (mid-stream error =
  abrupt close, no error channel mid-stream per ADR-049 §6), so an
  Err state would be dead code. Deviation recorded in ADR-050.
- alktty's three-pump session does not fit (exit future as a third
  signal) and stays as-is, per the review's scope.
- Tests reproduce the POC's two-pump semantics through the helper:
  bidirectional flow with exact counts, EOF-from-one-side completes
  the other's shutdown (clean EOF at the far end), dead-source =
  EOF-shaped teardown.
- ADR-050 records the decision, deviations, and two-way door type.

Verification: cargo test (625 passed, +2), clippy -D warnings, fmt
--check, doc clean, test --all-features clean, wasm32-unknown-unknown
check clean.
2026-09-07 08:47:46 +00:00
glm-5.3-flash 8f122b0a38 feat(review 007 Unit 2): birth-teardown telemetry — unaccepted-stream debug hint (R-02)
The optional hardening half of R-02 (the doc notes landed with Unit 1,
dc4ad2b). The wrapper's teardown task now observes whether the pump
handler ever accepted the channel's stream:

- ChannelBidiStreamSource gains a shared acceptance flag
  (with_accepted_flag / accepted()); channel_source_with_accepted_flag
  threads it from run_open_wrapper.
- On handler exit without accept, the teardown task logs a debug!
  naming the contract: "the returned JoinHandle must track the
  data-plane lifetime ... await pumps inline" — the telemetry hint for
  the teardown-at-birth shape the alktunnels POC hit empirically.
- Telemetry only: no behavior change; the benign no-data close still
  tears down identically.

Verification: cargo test (623 passed, +2: accepted-flag flip on the
yield-once accept; accepting vs non-accepting handler teardown
behavior), clippy -D warnings, fmt.
2026-09-07 08:45:09 +00:00
glm-5.3-flash dc4ad2bc6d feat(review 007 Unit 1): Establishment carries the channel plan (R-01) + lifetime doc (R-02)
Implements ADR-049 amendment 2 — the reserved Establishment payload is
filled, and the OpenHandler lifetime contract is documented.

- Establishment { plan: Option<ChannelPlan> } with ChannelPlan =
  Arc<dyn Any + Send + Sync>: typed-opaque, because the payload an
  establisher hands the pump handler is a live handle (dialed socket,
  TTY handle), not JSON — the review's Option<Value> sketch could not
  satisfy its own verification gate. #[non_exhaustive] keeps a future
  carrier change from being another break. Construction:
  Establishment::new(plan) / Establishment::default().
- OpenHandler gains the plan parameter:
  Fn(Value, Option<ChannelPlan>, Connection, AuthContext) ->
  JoinHandle<()>. Separate parameter (not merged into input) — a
  typed payload cannot ride the JSON input; no schema collision.
  Wire surface unchanged: the plan is process-local (establisher ->
  wrapper -> handler).
- run_open_wrapper threads establishment.plan to the handler; None
  when no establisher is registered. Kills the alktunnels-POC
  side-channel handoff (resource-keyed slot + poll loop) whose
  concurrent same-resource race is now unreachable — each open's
  establisher result flows to its own handler.
- Lifetime contract documented (R-02, doc-only half): the returned
  JoinHandle must track the data-plane lifetime — the wrapper awaits
  it and its completion triggers teardown; early return = teardown
  at birth. Noted on the OpenHandler type docs and both registration
  entry points.
- Breaking at 0.6.0 (the point of landing it before alktunnels
  Phase 1): Ok(Establishment {}) sites become
  Ok(Establishment::default()) mechanically.

Verification: cargo test (621 passed, +4: plan-flows-to-handler,
concurrent same-resource opens get distinct plans, no-establisher
None plan, Establishment construction), clippy -D warnings, fmt
--check, doc clean, test --all-features clean.
2026-09-07 08:43:17 +00:00
glm-5.3-flash 6590ab005f docs: review 007 — establishment follow-ups (from the alktunnels UDP POC)
Findings filed to prevent a second fix->publish->update-dependents
cycle; each was reached by building working code against 0.5.0:

- R-01 [major] — Establishment is payloadless but the channel plan
  is exactly what establishers need to hand to the pump handler
  (ADR-049's own 'reserved for a channel plan' note). Costs verified
  in two consumers: alktunnels POC side-channel handoff (same-resource
  opens race the slot), alktty forced to keep backend allocate
  post-open in-band (allocate_failed stays an in-band frame — the
  shape ADR-049 eliminates, alive one layer down). Ask: fill the
  reserved field (plan: Option<Value>, process-local, wire unchanged)
  in a 0.6.0 sweep; the break is mechanical (Establishment::default).
- R-02 [minor] — the OpenHandler JoinHandle lifetime contract is
  undocumented and load-bearing: the wrapper's await of the returned
  handle IS the teardown trigger; a handler that returns before its
  pumps finish tears the channel down at birth (the POC found this
  empirically — every tunnel EOF'd instantly). Doc note + ADR-049
  amendment; optional debug warning.
- R-03 [minor, optional] — the ADR-078 two-pump helper's convergence
  test is satisfied (POC gives both shapes); extracting pump_bidi
  now is additive (no break) and pins the contract upstream. Decide
  in the same 0.6 sweep.

Non-findings: reverse-flow (-R) needs no upstream mechanism
(from_connection_with_serving + serving-side allocation, verified by
trace); establisher receives registry-validated input; typed
establishment errors complete on the wire; early-arrival cap
unchanged; EstablishmentError reason set sufficient.

Goal stated in the review: 0.6 is the last breaking sweep forced by
known work. alkcall tests: 617 passed (docs-only change; baseline
check).
2026-09-07 08:18:11 +00:00