wave-7 decomposition — seven fuzzing tasks: scaffold, parser exposure (§3.2 resolved as option b), three targets, campaigns + gate wiring, review gate

This commit is contained in:
glm-5.3-flash committed 2026-10-10 20:51:49 +00:00
1 parent 62cddade00
commit 67d1d7e34f
8 files changed
+685 -1

No files matched your search

+48 -1
View File
@@ -49,7 +49,7 @@ readiness is wave 8.
| 4 | [Postgres engine](#wave-4--postgres-engine): schema bootstrap, pool/open, listener/forwarder, all mechanisms, tx seam, pg backlog column | wave 1 | implemented + reviewed (2026-10-08) | | 4 | [Postgres engine](#wave-4--postgres-engine): schema bootstrap, pool/open, listener/forwarder, all mechanisms, tx seam, pg backlog column | wave 1 | implemented + reviewed (2026-10-08) |
| 5 | [Contract suite](#wave-5--contract-suite): the cross-engine equivalence properties (core-contract.md §Verification backlog), version-stamped per ADR-017 | waves 3 + 4 | implemented + reviewed (2026-10-10) | | 5 | [Contract suite](#wave-5--contract-suite): the cross-engine equivalence properties (core-contract.md §Verification backlog), version-stamped per ADR-017 | waves 3 + 4 | implemented + reviewed (2026-10-10) |
| 6 | [Mem engine](#wave-6--mem-engine): separate `alkstore-mem` crate, full contract v1 over in-memory mechanisms (tx overlay, queue/scheduler/streams/locks/wakes), the suite's third factory column (born pinned), wasm32 compile-clean acceptance | waves 1 + 5 | implemented + reviewed (2026-10-10) | | 6 | [Mem engine](#wave-6--mem-engine): separate `alkstore-mem` crate, full contract v1 over in-memory mechanisms (tx overlay, queue/scheduler/streams/locks/wakes), the suite's third factory column (born pinned), wasm32 compile-clean acceptance | waves 1 + 5 | implemented + reviewed (2026-10-10) |
| [7](#wave-7--fuzzing) | [Fuzzing](#wave-7--fuzzing): the `fuzz/` sidecar workspace (cargo-fuzz targets over the payload codec, the three `@every` parsers, name validation), committed seed corpora + the corpus-replay gate, detached campaigns | wave 6 | decided (2026-10-10, `docs/research/fuzzing.md`), not yet decomposed | | [7](#wave-7--fuzzing) | [Fuzzing](#wave-7--fuzzing): the `fuzz/` sidecar workspace (cargo-fuzz targets over the payload codec, the three `@every` parsers, name validation), committed seed corpora + the corpus-replay gate, detached campaigns | wave 6 | decomposed (2026-10-10) |
| [8](#wave-8--release-readiness) | [Release readiness](#wave-8--release-readiness): crate docs, deployment matrix final pass, README (written last, honestly), publish prep | wave 7 | not yet decomposed | | [8](#wave-8--release-readiness) | [Release readiness](#wave-8--release-readiness): crate docs, deployment matrix final pass, README (written last, honestly), publish prep | wave 7 | not yet decomposed |
## Wave 1 — Foundations ## Wave 1 — Foundations
@@ -398,6 +398,47 @@ workspace/publish-exclusion verification. Committed crash-input seeds
promote into the corpus promote into the corpus
(the alksocks seed-900/901 posture); grown corpora stay gitignored. (the alksocks seed-900/901 posture); grown corpora stay gitignored.
**Wave 7's task set** (the decomposition, 2026-10-10 — the doc's §4
sequencing: scaffold → exposure → targets in parallel → campaigns +
gate wiring → review gate):
- `fuzz-scaffold` — the `fuzz/` sidecar workspace per §2's layout,
copied from alksocks (nightly pin inside `fuzz/` only, the stable
`fuzz/shared` skeleton, `run-detached.sh` verbatim, `json.dict`,
`gen_fuzz_seeds.py` skeleton, the `fuzz/.gitignore` corpus pattern),
plus the root workspace's defensive `exclude = ["fuzz"]`.
- `fuzz-parser-exposure` — §3.2's design point, resolved: **option
(b)**, `#[doc(hidden)]` narrow re-exports of the three
`parse_every_interval` implementations + the three `skip_forward`
boundary functions at each engine crate root (substrate untouched —
lineage fidelity), with (a) as the recorded in-suite companion and
(c) rejected per the family's no-`#[cfg(fuzzing)]` experience.
- `fuzz-target-payload-codec` — the §3.1 target (core payload
encode/decode invariants: no-panic, the typed-failure partition,
deep-input loudness, Value + typed round-trips) + its seeds.
- `fuzz-target-every-parse` — the §3.2 differential target over the
three parsers + boundary arithmetic (three-way agreement, overflow
posture, the giant-`n` arms) + its seeds; the wave's load-bearing
target (the wave-6 finding class lives here).
- `fuzz-target-name-validation` — the §3.3 target (totality,
determinism, typed rejections, reserved-prefix rule, cap-boundary
exactness) + its seeds.
- `fuzz-campaigns-and-gate` — detached campaigns per target (§5's
rule, §7's flags), findings dispositioned (crate-side fixed +
promoted to seeds; harness-model into the research doc's
implementation log), the corpus policy's final state, the
AGENTS.md verification-list flip (the corpus-replay gate joins the
merge gates), `fuzz/README.md` finalized.
- `review-wave-7` — the gate (campaigns audit, replay-gate re-run,
corpus policy, the named design points audited resolved, the wasm
posture, records).
Parallelism note: the scaffold and the exposure task are independent
of each other; the three targets are mutually parallel once their
dependencies land (payload-codec and name-validation need only the
scaffold; every-parse needs scaffold + exposure); campaigns gate on
all three targets.
## Wave 8 — Release readiness ## Wave 8 — Release readiness
The original wave 6, renumbered twice: wave 7 when the mem engine The original wave 6, renumbered twice: wave 7 when the mem engine
@@ -609,6 +650,12 @@ decomposes. Specific gates:
disposition note + Notes bullet, `review-wave-5` §Notes 4's audit row) disposition note + Notes bullet, `review-wave-5` §Notes 4's audit row)
retired with pointers, keeping the mem engine's fire posture written retired with pointers, keeping the mem engine's fire posture written
against a closed gap before wave 6. against a closed gap before wave 6.
- **Wave-7 decomposition** (2026-10-10) — the fuzzing decision's
task set: scaffold → exposure (§3.2 resolved as option (b) with the
(a) companion) → three targets in parallel → campaigns + gate
wiring (the AGENTS.md flip) → review gate. Seven tasks; the
every-parse differential is the load-bearing one (the wave-6
finding class). See the Wave 7 section.
- **Wave-4 fix-batch decomposition** (2026-10-09) — the general - **Wave-4 fix-batch decomposition** (2026-10-09) — the general
review's findings decomposed into seven `pg-fix-*` tasks + a review's findings decomposed into seven `pg-fix-*` tasks + a
`review-wave-4-fixes` gate: Finding 1 → `pg-fix-forwarder-reconnect` `review-wave-4-fixes` gate: Finding 1 → `pg-fix-forwarder-reconnect`
+89
View File
@@ -0,0 +1,89 @@
---
id: fuzz-campaigns-and-gate
name: Fuzz campaigns (detached) + corpus-replay gate wiring + AGENTS.md verification-list flip
status: pending
depends_on: [fuzz-target-payload-codec, fuzz-target-every-parse, fuzz-target-name-validation]
scope: moderate
risk: medium
impact: phase
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The wave's operational close (§4's sequencing tail: seeds committed →
campaigns → fix anything found → corpus replay green) plus the two
wiring deliverables the plan names:
- **Campaigns, detached only** (§5 inherited verbatim): per target, via
`fuzz/run-detached.sh` — **never a foreground child of an agent
session**. Budget 10–30 min per target (`FUZZ_RUNTIME_SECS`), flags
per §7's starting points: `payload_codec -max_len=65536
-dict=json.dict`; `every_parse -max_len=4096 -use_value_profile=1`;
`name_validation -max_len=4096 -use_value_profile=1`. Poll per §5
(`tail` the log, `ls` the artifacts dir, `pgrep -af` to LIST, kill by
explicit pid from the runner's echoed `pid=` — never
pattern-kill-and-recheck in one call).
- **Findings disposition**: crate-side bugs are fixed (the fix rides
this task when small; crash inputs are promoted to committed seeds —
the alksocks seed-900/901 posture — and the campaign re-run clean);
large or design-shaped findings escalate to the user before any
postulate-and-fix. Harness-model findings (no crate bug) are
documented in the research doc's implementation log (a new §
appended to `docs/research/fuzzing.md` — the alksocks §7
successful-negative-result disposition applies if campaigns find
nothing crate-side).
- **Corpus policy final state** (§2): committed hand-made seeds +
promoted crash inputs; grown corpora and artifacts gitignored (the
scaffold's `fuzz/.gitignore` pattern); verify `git status` shows no
grown-corpus noise after campaigns.
- **The AGENTS.md verification-list flip**: the corpus-replay gate
joins the Verification Commands —
`cargo test --manifest-path fuzz/shared/Cargo.toml` — with the
one-line note that campaigns run only via the detached runner (the
AGENTS.md fuzzing paragraph's "until then there is no fuzz gate"
clause updated to the landed state). This is the plan's named design
point ("joins the verification list when the wave lands").
- **`fuzz/README.md` finalized**: targets table complete, campaign
commands, corpus policy.
- **Research doc §7's verification list** already carries the gate —
no edit needed there beyond the implementation log.
## Acceptance Criteria
- [ ] Every target has had a detached campaign (≥10 min) via
`run-detached.sh`; logs + artifact state recorded in Notes
- [ ] Campaigns clean, or findings fixed + crash inputs promoted to
committed seeds + re-run clean; dispositions recorded (crate-side
vs harness-model; the latter in the research doc's log)
- [ ] Corpus policy verified: committed seeds only in git; grown
corpora/artifacts ignored; `gen_fuzz_seeds.py` re-run is a no-op
diff on the committed set
- [ ] `cargo test --manifest-path fuzz/shared/Cargo.toml` green
(the gate, on stable)
- [ ] AGENTS.md Verification Commands carry the gate line; the fuzzing
paragraph reflects the landed state
- [ ] `fuzz/README.md` finalized (targets table, commands, corpus
policy)
- [ ] Root workspace gates + `shared` clippy/fmt gates green; mem wasm
check still clean
## References
- docs/research/fuzzing.md §4 (sequencing), §5 (detached-runner rule),
§6 (no-CI / the gate), §7 (flags + verification commands)
- docs/plans/implementation.md §Wave 7 (the named design points this
task closes: the AGENTS.md flip)
- /workspace/@alkdev/alksocks/docs/research/fuzzing.md §5, §7 (the
inherited operational posture + the successful-negative-result
disposition)
- tasks/fuzz-scaffold.md (the runner + gitignore this task exercises)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion
+89
View File
@@ -0,0 +1,89 @@
---
id: fuzz-parser-exposure
name: Parser exposure — `#[doc(hidden)]` narrow surface for the three `@every` parsers + boundary arithmetic
status: pending
depends_on: []
scope: narrow
risk: low
impact: component
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The §3.2 exposure design point, resolved by this decomposition: **option
(b)** — a `#[doc(hidden)]` narrow exposure mirroring the existing
`Job::from_row` / `Schedule::new` constructor precedent — with **(a)**
(the public-`schedule()` path) as the in-suite companion, no new suite
rows. Option (c) (a `fuzzing` feature flag) is rejected per the family's
no-`#[cfg(fuzzing)]` experience. Rationale: the fast byte-level
differential target the upstream docs favor needs direct parser access;
the parsers are engine-internal test surfaces, not contract surface
(ADR-017 §3's consumer-read policy governs core types, not these); and
the `#[doc(hidden)]` precedent already exists in-repo for exactly this
shape of narrow, undocumented-but-public access.
What gets exposed, per engine — **at the engine crate root only;
substrate files untouched** (the SQLite parser and its `skip_forward`
live in the lineage-governed `substrate/queue_ops.rs`, ADR-012 §3 — the
exposure is a re-export in the engine's `lib.rs`, never a substrate
edit):
- **alkstore-sqlite**: `#[doc(hidden)] pub use` of
`parse_every_interval` (`Result<i64, String>`) and `skip_forward`
from `substrate::queue_ops`.
- **alkstore-postgres**: `parse_every_interval` (`Result<i64>` →
`InvalidSpec`, currently `pub(crate)`) and `skip_forward` (currently
private) widened to `pub(crate)` as needed and `#[doc(hidden)] pub
use`-re-exported from `lib.rs`.
- **alkstore-mem**: same shape as pg (`scheduler.rs`'s parser +
`skip_forward`).
Doc posture: each re-export carries a one-line doc note marking it a
fuzz/test-only surface (not contract surface, not consumer API, no
stability guarantee) — the `Job::from_row` precedent's doc style. No
engine behavior changes; no parser logic moves; the diff is visibility
plus re-exports.
The **(a) companion** is recorded, not built: the public `schedule()`
path against the mem and SQLite factories remains the suite's behavioral
pin (already green, three-way); the `every_parse` target may optionally
drive `schedule()` for register-path posture seeds, but the byte-level
differential runs on the exposed functions.
## Acceptance Criteria
- [ ] All three engines re-export their `parse_every_interval` and
`skip_forward` from the crate root, `#[doc(hidden)]`, with the
fuzz/test-only doc note
- [ ] `alkstore-sqlite/src/substrate/**` diff is empty (lineage
fidelity preserved — the exposure is engine-side only)
- [ ] The re-exports are reachable from an external crate (pinned by a
compile-level test or the `fuzz-target-every-parse` build itself;
record which)
- [ ] No behavior change: workspace gates green (`cargo build`,
`cargo test`, clippy `-D warnings`, fmt); the engines' own
scheduler/parser test suites untouched and green
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
still clean (visibility widening is wasm-neutral, pinned anyway)
## References
- docs/research/fuzzing.md §3.2 (the design point this resolves —
options (a)/(b)/(c) and the lean)
- docs/architecture/decisions/012-forked-substrate-design.md §2–§3
(one-owner parsers; substrate lineage fidelity)
- docs/architecture/decisions/017-contract-versioning.md §3 (the
`#[doc(hidden)]` precedent's policy boundary — engine-internal
surfaces sit outside it)
- alkstore/src/job.rs (`Job::from_row` — the in-repo doc-hidden
precedent)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion
+106
View File
@@ -0,0 +1,106 @@
---
id: fuzz-scaffold
name: Fuzz sidecar scaffold — `fuzz/` workspace, runner, dict, seed generator, shared-crate skeleton
status: pending
depends_on: []
scope: moderate
risk: low
impact: phase
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The wave-7 scaffold ([docs/research/fuzzing.md](../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-shared` path dep; `[[bin]]` entries land with the
target tasks, not here), `fuzz/rust-toolchain.toml` pinning
`channel = "nightly"` + `llvm-tools-preview` **inside `fuzz/` 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): skeleton `lib.rs` with the crate doc carrying the quinn-CI
pattern rationale, plus the `arbitrary_value.rs` `JsonValue`
bounded-depth helper copied from alksocks (the structured-generation
path §3.1's targets share). Dependencies: `alkstore` (path), plus
`serde_json` + `arbitrary` (derive feature). Engine-crate deps land
with the targets that need them. `shared` consumes 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_SECS` override). 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 at
`fuzz/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 shared `seed_name`/`write_seed` plumbing and an empty
target registry.
- **`fuzz/.gitignore`** — the alksocks pattern: `target`, `artifacts`,
`coverage`, and `corpus/*` 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`**: add `exclude = ["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: sidecar `Cargo.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/.gitignore`
- [ ] `fuzz/shared` compiles and tests green on **stable** via
`cargo test --manifest-path fuzz/shared/Cargo.toml` (the gate
command works from the wave's first task onward)
- [ ] `cargo fuzz build` succeeds from `fuzz/` (nightly selected by the
pin; zero targets yet is acceptable if cargo-fuzz tolerates it —
otherwise a placeholder target documents the check; record which)
- [ ] Root workspace unaffected: `cargo build` / `cargo test` /
`clippy -D warnings` / `fmt --check` green from the root, and the
root toolchain is still stable (the pin did not leak upward)
- [ ] `exclude = ["fuzz"]` present on the root `[workspace]` table
- [ ] `run-detached.sh` is byte-identical to alksocks' modulo the
usage-line naming (no behavior drift)
- [ ] `shared` is not referenced by any workspace crate manifest
(wasm posture intact: `cargo check --target
wasm32-unknown-unknown -p alkstore-mem` still clean)
## 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
> To be filled by implementation agent
## Summary
> To be filled on completion
+108
View File
@@ -0,0 +1,108 @@
---
id: fuzz-target-every-parse
name: Fuzz target — `every_parse` (the three `@every` parsers, differential)
status: pending
depends_on: [fuzz-scaffold, fuzz-parser-exposure]
scope: moderate
risk: medium
impact: component
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The §3.2 target: `every_parse` — the wave's load-bearing target, since
the crate's own track record (the wave-6 gate's three edge-domain
findings) lives exactly here. Drives the three per-engine
`parse_every_interval` implementations **differentially** through the
`fuzz-parser-exposure` surfaces, plus each engine's next-boundary
arithmetic (`skip_forward`):
- SQLite: `alkstore-sqlite`'s re-export (substrate-owned,
`Result<i64, String>`),
- Postgres: `alkstore-postgres`'s re-export (`Result<i64>` →
`InvalidSpec`),
- Mem: `alkstore-mem`'s re-export (`Result<i64>` → `InvalidSpec`).
Input: arbitrary `&[u8]` → UTF-8-lossy `String`s (lossy is deliberate —
the engines receive `&str`, always valid UTF-8; the generator still
stresses the grammar's edge shapes). Invariants (§3.2, verbatim):
- **no-panic on any string** (each parser, each boundary path);
- **typed rejection**: every rejection is the parser's own typed error
(`InvalidSpec` on pg/mem; the substrate's typed error under the
engine's mapping on SQLite) — never a panic, never a silent `Ok` on
a grammar-violating shape the authored tests already reject;
- **three-way agreement**: the accept-set and the interval value are
identical across the three parsers for every input. Error *identity*
is NOT pinned equal (the substrate's `String` vs `InvalidSpec` is a
known, typed asymmetry) — the differential pins the Ok/Err partition
and the `Ok` value;
- **overflow posture**: the boundary paths (`skip_forward` driven with
adversarial `(next_fire_at, now, interval)` triples — the
`i64::MAX` neighborhood, negative shapes, `d`-unit multiplier
blowups) reject-or-saturate per each engine's pinned semantics,
never wrap or panic — the wave-6 scheduler-register fix's invariant
over the whole domain;
- **the `n <= 0` and giant-`n` arms**: leading-zero forms, digit
overflow at exactly `i64::MAX/86400`, positive-zero rejection.
The register-path posture (parse → first-boundary `checked_add` →
reject with `InvalidSpec`, the wave-6 alignment) is suite-pinned
already; the target's optional `(a)`-companion leg may drive the public
`schedule()` on the mem/SQLite factories for register-path seeds —
optional, recorded if used.
- **`fuzz_targets/every_parse.rs`** + **`shared/src/every_parse.rs`**
(invariants + `#[cfg(test)]` replay), `[[bin]]` entry, `shared`
manifest gains the three engine crates (path deps — stable-buildable,
they already are).
- **Seeds** via `gen_fuzz_seeds.py`'s `every_parse` function: every
grammar-valid unit form (`s|m|h|d`), multi-digit and leading-zero
forms, `@every 0s` / `@every -5s` shapes, the `i64::MAX`-neighborhood
and `i64::MAX/86400` digit-overflow forms, `d`-multiplier blowups,
whitespace/garbage/truncation shapes, non-grammar prefixes (`@once`,
`@hourly`-adjacent strings). Corpus committed; gitignore negation.
- **`fuzz/README.md`** targets-table row.
Risk note: medium because the differential may surface a real
three-way divergence (that is the target's purpose) — a finding is
*success*, dispositioned per the campaign task's posture (fix inline or
escalate), not a task failure.
## Acceptance Criteria
- [ ] `fuzz_targets/every_parse.rs` + `shared/src/every_parse.rs`
exist; `cargo fuzz build` builds the target
- [ ] All five §3.2 invariant classes implemented and exercised by both
the fuzz path and the replay module; the three-way agreement
asserted on every input (fuzz) and every seed (replay)
- [ ] Seed corpus committed, deterministic-generated, gitignore
negation in place
- [ ] `cargo test --manifest-path fuzz/shared/Cargo.toml` green;
`shared` clippy/fmt gates green
- [ ] Root workspace gates still green; substrate diff still empty
- [ ] Any three-way divergence found during target development is
recorded in Notes with its disposition (fixed / escalated), not
silently absorbed
## References
- docs/research/fuzzing.md §3.2 (target spec + the exposure decision
this target consumes), §4, §7
- docs/architecture/decisions/009-queue-and-scheduler.md §2 (the
`@every` grammar the three parsers implement)
- docs/architecture/decisions/012-forked-substrate-design.md §2
(one-owner rule — why there are three parsers to differ)
- tasks/review-wave-6.md (the wave-6 finding class this target
generalizes; the register-overflow alignment)
- tasks/fuzz-parser-exposure.md (the surfaces this target drives)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion
+71
View File
@@ -0,0 +1,71 @@
---
id: fuzz-target-name-validation
name: Fuzz target — `name_validation` (core name validation)
status: pending
depends_on: [fuzz-scaffold]
scope: narrow
risk: trivial
impact: component
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The §3.3 target: `name_validation` — the cheapest target, driving core's
already-`pub` validation surface (`alkstore/src/validation.rs`:
`validate_name` over all `NameKind`s, `validate_shared_name`,
`validate_local_name`). No exposure needed.
- **`fuzz_targets/name_validation.rs`** + **`shared/src/
name_validation.rs`** (invariants + `#[cfg(test)]` replay),
`[[bin]]` entry. Input: arbitrary `&[u8]` → strings (lossy + a
structured path), lengths spanning the caps, all `NameKind`s.
- **Invariants** (§3.3, verbatim): total (no panic on any input);
deterministic accept/reject (same input → same verdict, pinned by
double-invocation in the invariant fn); rejection only via typed
`Error::InvalidName` (or `ReservedName` where the reserved-prefix
rule fires — both are the taxonomy's typed rejections; nothing else,
no panic); the reserved-prefix rule (`__alkstore_`, ADR-014 §1's
shared namespace) rejects in every casing/boundary form the fuzzer
finds; length-boundary exactness at the cap (the ±1 neighborhood —
a name at the cap is accepted, one past it rejected, per the pinned
rule).
- **Seeds** via `gen_fuzz_seeds.py`'s `name_validation` function:
cap-boundary lengths (±1, ±2), the reserved prefix in plain /
suffixed / embedded forms, empty and whitespace-only strings, unicode
and control-char shapes, the reserved listener-reconnected string.
Corpus committed; gitignore negation.
- **`fuzz/README.md`** targets-table row.
Low expected yield (the doc says so) — the value is the entry-point
domain guard demonstrated over the whole string space, the gate's
guard-order discipline made continuous.
## Acceptance Criteria
- [ ] `fuzz_targets/name_validation.rs` + `shared/src/
name_validation.rs` exist; `cargo fuzz build` builds the target
- [ ] All §3.3 invariants implemented and exercised by both the fuzz
path and the replay module
- [ ] Seed corpus committed, deterministic-generated, gitignore
negation in place
- [ ] `cargo test --manifest-path fuzz/shared/Cargo.toml` green;
`shared` clippy/fmt gates green
- [ ] Root workspace gates still green
## References
- docs/research/fuzzing.md §3.3 (target spec), §4, §7
- docs/architecture/core-contract.md §Naming / reserved namespace
- docs/architecture/decisions/014-naming-and-reserved-namespace.md §1
(the reserved-prefix rule the target demonstrates)
- alkstore/src/validation.rs (the surface)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion
+88
View File
@@ -0,0 +1,88 @@
---
id: fuzz-target-payload-codec
name: Fuzz target — `payload_codec` (core payload encode/decode invariants)
status: pending
depends_on: [fuzz-scaffold]
scope: moderate
risk: low
impact: component
level: implementation
tags: [wave-7, fuzzing]
---
## Description
The §3.1 target: `payload_codec`, driving core's payload surface
(`alkstore/src/payload.rs` — `encode_payload`, `payload_as::<T>`) —
already-`pub` API, no exposure needed.
- **`fuzz_targets/payload_codec.rs`** — the thin `fuzz_target!`
wrapper (3-line pattern) delegating to
`alkstore_fuzz_shared::payload_codec::fuzz_payload_codec(data)`;
the `[[bin]]` entry lands in `fuzz/Cargo.toml`.
- **`shared/src/payload_codec.rs`** — the invariant logic, with the
`#[cfg(test)]` corpus-replay module (the gate). Input: raw `&[u8]`
plus `arbitrary`-derived `serde_json::Value`s (the
`JsonValue` bounded-depth helper from the scaffold). Invariants
(§3.1, verbatim):
- **no-panic on any byte sequence** (the baseline);
- **typed-failure partition**: every decode failure is
`Error::Codec` — no other variant, no panic (the ADR-023 §1
fallibility pin, demonstrated across the input space);
- **deep-input loudness**: serde_json's recursion limit surfaces as
typed `Codec`, never a stack overflow;
- **Value round-trip**: `encode_payload(v)` → `payload_as::<Value>`
yields `v` for every arbitrary `Value` (canonicalization is
serde_json's, pinned-not-regressed);
- **typed round-trip**: for a representative typed-payload set,
`encode(Value::from(t))` decodes back to `t` (the ADR-020 §4
decode side).
- **Seeds** (§3.1's list, via `gen_fuzz_seeds.py` gaining the
`payload_codec` function): valid JSON of every Value variant,
truncations, deep nesting at and past the recursion limit, non-UTF-8
bytes, trailing garbage, oversized numbers, duplicate keys, the
`Null`-decode shape (ADR-023 §1's empty-byte-store corruption note).
Corpus committed under `fuzz/corpus/payload_codec/`; the
`fuzz/.gitignore` gains the `!corpus/payload_codec` negation.
- **`fuzz/README.md`** targets-table row.
- `shared`'s manifest gains `alkstore` (path) if the scaffold didn't
already carry it, plus `serde_json` + `arbitrary`.
Campaign flags are the campaign task's concern (`-max_len=65536
-dict=json.dict` starting point, §7); this task lands target + seeds +
replay.
## Acceptance Criteria
- [ ] `fuzz_targets/payload_codec.rs` + `shared/src/payload_codec.rs`
exist; `cargo fuzz build` builds the target (nightly, ASAN)
- [ ] All five §3.1 invariants implemented in `shared` and exercised by
both the fuzz path and the `#[cfg(test)]` replay module
- [ ] Seed corpus committed (`fuzz/corpus/payload_codec/`), generated
by `python3 fuzz/gen_fuzz_seeds.py` (deterministic — re-running
is a no-op diff); gitignore negation in place
- [ ] `cargo test --manifest-path fuzz/shared/Cargo.toml` green
(replays the committed corpus through the invariants)
- [ ] `shared` clippy/fmt gates green
(`cargo clippy --manifest-path fuzz/shared/Cargo.toml
--all-targets -- -D warnings`, `fmt --check`)
- [ ] Root workspace gates still green
## References
- docs/research/fuzzing.md §3.1 (target spec), §4 (wave-1 scope), §7
(flags)
- docs/architecture/decisions/020-payload-encoding.md §4 (the encoding
posture the round-trips pin)
- docs/architecture/decisions/023-fourth-review-round.md §1 (encode
fallibility)
- /workspace/@alkdev/alksocks/fuzz/shared/src/datagram_codec.rs (the
invariant-module + replay-test pattern)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion
+86
View File
@@ -0,0 +1,86 @@
---
id: review-wave-7
name: Review gate — wave 7 (fuzzing)
status: pending
depends_on: [fuzz-campaigns-and-gate]
scope: moderate
risk: low
impact: phase
level: review
tags: [wave-7, review]
---
## Description
The wave-7 review gate (the plan's §Review gates, wave-7 entry). Audit
the fuzz wave as landed:
1. **Campaigns audit**: each target's campaign ran via the detached
runner (logs in `fuzz/artifacts/`), clean — or its findings fixed
and crash inputs promoted to committed seeds with the re-run clean.
Verify no campaign was run foreground (the §5 rule — process
hygiene, checked by reading the logs' provenance and the task
Notes).
2. **Corpus-replay gate green on stable**:
`cargo test --manifest-path fuzz/shared/Cargo.toml` re-run this
session; the replay modules exercise the same invariant functions
the fuzz targets run (the §2 load-bearing layout rule — read one
target's wiring end to end to confirm no drift between fuzz path
and replay path).
3. **Corpus policy audit**: committed seeds per policy (hand-made +
promoted crash inputs; deterministic generator re-run is a no-op
diff); grown corpora + artifacts gitignored; nothing
campaign-generated leaked into git.
4. **Named design points audited as resolved** (the plan's wave-7
list): §3.2's parser exposure (option (b) landed, substrate diff
empty, the (a)-companion disposition recorded); the AGENTS.md
verification-list flip (gate line present, fuzzing paragraph
truthful); the workspace/publish-exclusion mechanism (`exclude =
["fuzz"]` on the root workspace table — the *verification* that no
published package leaks the sidecar stays wave 8's, per §2).
5. **Harness-model findings**: documented in the research doc's
implementation log (or the successful-negative-result disposition
recorded there); any crate-side finding's fix verified against the
invariant that caught it.
6. **wasm posture**: `cargo check --target wasm32-unknown-unknown -p
alkstore-mem` still clean; `shared` is referenced by no workspace
crate.
7. **Workspace gates re-run green this session** (`cargo build`,
`cargo test`, clippy `-D warnings`, fmt) + the `shared` clippy/fmt
gates.
8. **Records**: `implementation.md`'s wave-7 row updated
(implemented + reviewed); the research doc's Status header updated
(targets implemented, campaigns run); task files audited (all
wave-7 dependency tasks completed, Notes/Summary filled).
## Acceptance Criteria
- [ ] Campaign audit recorded per target (runtime, flags, outcome,
findings + dispositions)
- [ ] Corpus-replay gate re-run green this session; fuzz-path/replay
drift check recorded for at least one target end to end
- [ ] Corpus policy verified (committed set, gitignore posture,
generator determinism)
- [ ] The three named design points audited resolved, each with its
evidence
- [ ] Research doc implementation log present (findings or the
negative-result disposition)
- [ ] wasm check + all gates re-run green this session
- [ ] `implementation.md` wave-7 row updated; task files audited
## References
- docs/plans/implementation.md §Wave 7, §Review gates (wave-7 entry)
- docs/research/fuzzing.md (§2 layout rules, §4 scope, §5 runner rule,
§6 gate, §7 verification)
- tasks/review-wave-6.md (the gate pattern this mirrors)
- /workspace/@alkdev/alksocks/docs/research/fuzzing.md §7 (the
negative-result disposition precedent)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion