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

175 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: fuzz-parser-exposure
name: Parser exposure — `#[doc(hidden)]` narrow surface for the three `@every` parsers + boundary arithmetic
status: completed
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
- [x] 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
- [x] `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`) untouched;
a PROVENANCE.md delta entry records the change
*(amended at implementation, 2026-10-10 — `mod.rs` was in this
list, but a second mechanical constraint forced one facade line
there: see Notes. No lineage-body file was touched.)*
- [x] pg/mem `scheduler.rs` diffs are visibility-only (two keywords
each: parser → `pub`, `skip_forward` → `pub`) plus nothing else
- [x] 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)
- [x] No behavior change: workspace gates green (`cargo build`,
`cargo test`, clippy `-D warnings`, fmt); the engines' own
scheduler/parser test suites untouched and green
- [x] `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
Decisions of record the implementation made that the description didn't
pin:
- **Second mechanical amendment — `mod.rs` could not stay untouched.**
Widening `queue_ops.rs`'s two functions to `pub` is necessary but not
sufficient: `lib.rs` cannot name the path `substrate::queue_ops::…`
at all — `mod substrate` is private *to `substrate`'s subtree* for
`queue_ops` purposes, so a through-the-path re-export fails E0603,
and `skip_forward` had **no `mod.rs` export** whatsoever (it was not
in the `pub(crate) use` list). The only route is the facade: `mod.rs`
gained `pub use queue_ops::{parse_every_interval, skip_forward};`
(one line; `parse_every_interval` moved out of the `pub(crate)` list
into it — a duplicate binding would be E0252), compile-probed clean.
This remains visibility-only — zero logic, zero signatures, zero
names; lineage body (`watcher.rs`/`connection.rs`/`ops.rs`/
`schema.rs`) untouched; containment holds (`mod substrate` private).
- **`mod.rs`'s boundary-doc sentence amended.** "Nothing here is
re-exported through the engine crate's public API" would have become
stale the moment the facade landed; the sentence now names this sole
exception inline, and the full story is registered as **PROVENANCE.md
D-37** (category `re-derivation`, per this task's amendment).
- **Reachability pin (criterion 4): compile-level test.** Each engine
gained `src/fuzz_surface_tests.rs` (`#[cfg(test)]`, declared in
`lib.rs`) — `doc_hidden_reexports_reach_the_crate_root` drives both
re-exports through the crate-root path (one accept case + one
`skip_forward` assertion each). Compile of the `pub use` itself is
the E0364-class pin; the true external-crate consumption arrives with
`fuzz-target-every-parse`'s build (its `shared` crate path-depends on
all three engines). Neither engine's existing suite files were
touched — the pin is a separate module.
- **Semver note (recorded per the description):** doc-hidden `pub`
items are still public API — removal is technically breaking; the
same commitment core's four `#[doc(hidden)]` constructors made,
bounded to a fuzz/test purpose.
## Summary
Landed (2026-10-10): the `#[doc(hidden)]` narrow fuzz/test surface for
the three engines — `parse_every_interval` + `skip_forward` re-exported
from each crate root with the one-line fuzz/test-only doc note
(`Job::from_row` doc-posture style).
- **alkstore-sqlite**: `substrate/queue_ops.rs` two keywords widened to
`pub`; `substrate/mod.rs` gained the facade `pub use` line + the
boundary-doc exception sentence; `substrate/PROVENANCE.md` D-37
registered; `lib.rs` `#[doc(hidden)] pub use substrate::…` ×2.
- **alkstore-postgres / alkstore-mem**: `scheduler.rs` two keywords
each widened to `pub`; `lib.rs` `#[doc(hidden)] pub use scheduler::…`
×2. No provenance concern (engine-owned files).
- **Reachability pins**: `src/fuzz_surface_tests.rs` ×3 — one test per
engine driving both crate-root re-exports.
Verified: `cargo build` clean; `cargo test` green (all suites; the
three new pins pass; no engine suite touched); `cargo clippy
--all-targets -- -D warnings` clean; `cargo fmt --check` clean;
`cargo check --target wasm32-unknown-unknown -p alkstore-mem` clean.
Diff audited against the (twice-amended) criteria: engine
`scheduler.rs`/`queue_ops.rs` diffs are visibility keywords only.