Files
alkstore/tasks/fuzz-parser-exposure.md
T

119 lines
5.7 KiB
Markdown

---
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 — `#[doc(hidden)] pub use` re-exports at
the engine crate root:
- **alkstore-sqlite**: `parse_every_interval` (`Result<i64, String>`)
and `skip_forward` from `substrate::queue_ops`, widened to `pub` in
place and re-exported from `lib.rs`.
- **alkstore-postgres**: `parse_every_interval` (`Result<i64>` →
`InvalidSpec`) and `skip_forward` from `scheduler.rs`, widened to
`pub` in place and re-exported from `lib.rs`.
- **alkstore-mem**: same shape as pg (`scheduler.rs`'s parser +
`skip_forward`).
**The mechanical constraint this task was decomposed against (resolved
2026-10-10 with the user — do not re-derive):** `pub use` re-exports
require the item itself to carry `pub` — `pub(crate)` and module-private
items fail with E0364/E0603 (compile-probed). The decomposition's
original "substrate files untouched" criterion was therefore
unsatisfiable for SQLite and was amended: the substrate delta is
**visibility-only** (`pub(crate)`→`pub` on the parser, private→`pub` on
`skip_forward` — two keywords in `queue_ops.rs`), which is legitimate
because `substrate/mod.rs` itself classifies `queue_ops.rs` as *the
re-derived half — owned contract-v1 code, not lineage body*; the
ADR-012 §3 lineage-fidelity discipline governs the ported honker body
(`watcher.rs`, `connection.rs`, …), untouched here. Containment holds:
`mod substrate` is private (`lib.rs`), so `pub` items inside leak
nothing until re-exported. The delta **must** be recorded as a
PROVENANCE.md register entry (the D-31 one-line-delta precedent —
category `re-derivation`-adjacent; a visibility-only delta on
re-derived code, registered so the story stays complete). pg/mem widen
to `pub` (not `pub(crate)`) for the same E0364 reason — their
`scheduler.rs` files are engine-owned, no provenance concern.
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
keywords plus re-exports. The semver note is recorded, not hidden:
doc-hidden `pub` items are still public API (removal is technically
breaking) — the same commitment the four core `#[doc(hidden)]`
constructors already made, bounded here to a fuzz/test purpose.
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 **visibility-only**:
exactly the two keywords in `queue_ops.rs` (`parse_every_interval`
→ `pub`, `skip_forward` → `pub`); the lineage body
(`watcher.rs`, `connection.rs`, `ops.rs`, `schema.rs`, `mod.rs`)
untouched; a PROVENANCE.md delta entry records the change
- [ ] pg/mem `scheduler.rs` diffs are visibility-only (two keywords
each: parser → `pub`, `skip_forward` → `pub`) plus nothing else
- [ ] 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 — and its boundary:
the re-derived half is alkstore-owned)
- alkstore-sqlite/src/substrate/mod.rs (the module doc's own
classification: `queue_ops.rs` is "owned contract-v1 code, not
lineage body")
- alkstore-sqlite/src/substrate/PROVENANCE.md (the delta register the
visibility delta is recorded in; D-31 — the one-line-delta precedent)
- 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