7 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.
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 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 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
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 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