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:
1 parent
62cddade00
commit
67d1d7e34f
8 files changed
+685
-1
No files matched your search
@@ -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) |
|
||||
| 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) |
|
||||
| [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 |
|
||||
|
||||
## Wave 1 — Foundations
|
||||
@@ -398,6 +398,47 @@ workspace/publish-exclusion verification. Committed crash-input seeds
|
||||
promote into the corpus
|
||||
(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
|
||||
|
||||
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)
|
||||
retired with pointers, keeping the mem engine's fire posture written
|
||||
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
|
||||
review's findings decomposed into seven `pg-fix-*` tasks + a
|
||||
`review-wave-4-fixes` gate: Finding 1 → `pg-fix-forwarder-reconnect`
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user