8.1 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | ||
|---|---|---|---|---|---|---|---|---|---|---|
| fuzz-scaffold | Fuzz sidecar scaffold — `fuzz/` workspace, runner, dict, seed generator, shared-crate skeleton | completed | moderate | low | phase | implementation |
|
Description
The wave-7 scaffold (docs/research/fuzzing.md
§2 — the layout is inherited wholesale from the four upstream siblings,
not re-decided): the fuzz/ sidecar workspace and its stable-toolchain
gate crate, copied from alksocks' working edition with only naming
substitutions.
fuzz/sidecar workspace:fuzz/Cargo.toml(alkstore-fuzz,publish = false, own[workspace]table,libfuzzer-sys+alkstore-fuzz-sharedpath dep;[[bin]]entries land with the target tasks, not here),fuzz/rust-toolchain.tomlpinningchannel = "nightly"+llvm-tools-previewinsidefuzz/only — the crates themselves stay on stable, and the root workspace's toolchain behavior must be unaffected.fuzz/shared/—alkstore-fuzz-shared, the STABLE-toolchain library whose#[cfg(test)]corpus-replay modules are the fuzz gate (§6): skeletonlib.rswith the crate doc carrying the quinn-CI pattern rationale, plus thearbitrary_value.rsJsonValuebounded-depth helper copied from alksocks (the structured-generation path §3.1's targets share). Dependencies:alkstore(path), plusserde_json+arbitrary(derive feature). Engine-crate deps land with the targets that need them.sharedconsumes public API only — it must never become a dependency of any workspace crate (the wasm note, §2).fuzz/run-detached.sh— copied verbatim from alksocks (CWD-independent,setsid+nohup+ full redirection,pid=echo,FUZZ_RUNTIME_SECSoverride). The §5 isolation rule is inherited unchanged: campaigns never run as a foreground child of an agent session.fuzz/json.dict— copied from a sibling (alksocks has it atfuzz/json.dict).fuzz/gen_fuzz_seeds.py— the deterministic seed generator (quiche pattern): alksocks' script as the structural template, alkstore's own seed functions land per-target. Skeleton lands here with the sharedseed_name/write_seedplumbing and an empty target registry.fuzz/.gitignore— the alksocks pattern:target,artifacts,coverage, andcorpus/*with!-negations for the committed seed dirs (each target task adds its negation line when its corpus lands).fuzz/README.md— skeleton modeled on alksocks' (layout, targets table filled by the target tasks, commands incl. the run-from-fuzz/-so-rustup-selects-nightly rule).- Root
Cargo.toml: addexclude = ["fuzz"]to the[workspace]table — defensive insurance against auto-discovery (the alkcall §2 lesson; this repo's explicit-members list already prevents it, the exclude makes it structural). The publish-exclusion verification stays wave 8's (§2); this task lands the mechanism. - Corpus dirs:
fuzz/corpus/<target>/scaffolding lands per-target with the seeds; nothing to commit here.
Toolchain prerequisites verified present in the dev environment
(2026-10-10): nightly + cargo-fuzz 0.13.2 installed; alksocks'
fuzz/Cargo.lock exists as the copy reference.
Acceptance Criteria
fuzz/exists with the §2 layout: sidecarCargo.toml(own[workspace],publish = false),rust-toolchain.toml(nightly + llvm-tools-preview),shared/crate,run-detached.sh(executable),json.dict,gen_fuzz_seeds.py,README.md,fuzz/.gitignorefuzz/sharedcompiles and tests green on stable viacargo test --manifest-path fuzz/shared/Cargo.toml(the gate command works from the wave's first task onward)cargo fuzz buildsucceeds fromfuzz/(nightly selected by the pin; cargo-fuzz does NOT tolerate zero targets here — a bins-only package with no[[bin]]fails manifest parse, which also blocks the shared gate's workspace discovery; a placeholder targetfuzz_targets/placeholder.rsdocuments the check and is replaced by the wave-1 target tasks — recorded, as this AC asked)- Root workspace unaffected:
cargo build/cargo test/clippy -D warnings/fmt --checkgreen from the root, and the root toolchain is still stable (the pin did not leak upward) exclude = ["fuzz"]present on the root[workspace]tablerun-detached.shis byte-identical to alksocks' modulo the usage-line naming (cmpclean — the usage line is already repo-agnostic, so no diff at all)sharedis not referenced by any workspace crate manifest (only the root'sexclude = ["fuzz"]mentions fuzz at all;cargo check --target wasm32-unknown-unknown -p alkstore-memclean)
References
- docs/research/fuzzing.md §2 (layout + toolchain), §5 (runner), §6 (no-CI / replay gate)
- /workspace/@alkdev/alksocks/fuzz/ (the copy source: Cargo.toml, rust-toolchain.toml, run-detached.sh, json.dict, gen_fuzz_seeds.py, .gitignore, README.md)
- docs/plans/implementation.md §Wave 7
Notes
- Zero targets are NOT tolerated by cargo-fuzz / cargo here — the
AC's "if tolerated" branch failed: a bins-only package with no
[[bin]]entries cannot manifest-parse ("no targets specified"), and that parse failure also breaks the shared gate's workspace discovery (cargo test --manifest-path fuzz/shared/Cargo.tomlresolves the workspace root atfuzz/). Placeholder route taken (as the AC's otherwise-branch prescribed):fuzz_targets/placeholder.rs— a minimalfuzz_target!stub with a doc comment saying the wave-1 target tasks replace it — plus its[[bin]]entry infuzz/Cargo.toml. - Repo-layout substitution beyond naming: alksocks has its package
at the repo root (
alksocks = { path = "../.." }); alkstore is the ADR-001 workspace split, so the core crate sits in thealkstore/subdir — shared's dep isalkstore = { path = "../../alkstore" }and the fuzz package's ispath = "../alkstore". json.dictis byte-identical across alkcall / alktunnels / alksocks (md5-verified), so it was copied verbatim (alkcall-envelope tokens). Whether any alkstore-specific tokens should be added is a target-task concern, not scaffold scope.fuzz/Cargo.lockis committed (alksocks pattern); generated fresh — alksocks' lock is not portable across dep sets.arbitrary_value.rscopied verbatim except one intra-comment stale reference: alksocks'envelope_frame→ "the payload targets".fuzz/.gitignorehas no!corpus/<target>negation lines yet — each target task adds its own when its corpus lands (task spec).gen_fuzz_seeds.pyis the plumbing-only skeleton (seed_name/write_seed, emptymain()registry); runs clean as a no-op.
Summary
Landed the wave-7 scaffold: fuzz/ sidecar workspace
(alkstore-fuzz, publish = false, own [workspace], libfuzzer-sys +
path-dep shared crate) with rust-toolchain.toml pinning
nightly + llvm-tools-preview inside fuzz/ only; stable-toolchain
fuzz/shared (alkstore-fuzz-shared) with the quinn-CI-pattern crate
doc and the alksocks arbitrary_value.rs JsonValue bounded-depth
helper; run-detached.sh (byte-identical to alksocks', executable);
json.dict; gen_fuzz_seeds.py skeleton; .gitignore (no corpus
negations yet); README.md skeleton; exclude = ["fuzz"] on the root
workspace; and the placeholder fuzz target so the toolchain check and
the shared gate work before the real targets land.
Verified: cargo test --manifest-path fuzz/shared/Cargo.toml green on
stable from the root; cargo fuzz build green from fuzz/ (nightly
pin selected; placeholder + shared + alkstore compile under ASAN);
shared clippy -D warnings + fmt --check green; root cargo build /
cargo test (all suites pass) / clippy -D warnings / fmt --check
green with the stable toolchain still active at the root (rustc 1.99.0
stable; no upward pin leak); cargo check -p alkstore-mem --target wasm32-unknown-unknown clean; no workspace manifest references
alkstore-fuzz-shared (only the root exclude mentions fuzz).