Commit Graph
9 Commits
Author SHA1 Message Date
ClawHDF5 Coding Agent 3a30327f35 security(agent): chain WAL entry CRCs and restrict the legacy no-CRC reader
Two related gaps in the WAL format, both closed:

1. Each entry's CRC32 covered only its own bytes, with no sequence number
   or chaining — entries could be reordered, duplicated, or spliced (e.g.
   a Tombstone moved before/after its target Save) while every individual
   entry still passed its own CRC check, silently changing replayed cache
   state. Bump to WAL_VERSION 3: each entry's CRC32 trailer is now computed
   over its own bytes chained with the previous entry's stored CRC
   (crc32(entry_bytes ++ prev_crc)), seeded at 0 after a truncation. Moving,
   duplicating, or reordering an entry breaks the chain at that point, and
   replay stops there — same handling as a bit-flip or truncation. The
   previous per-entry-CRC-only format becomes WAL_VERSION_CRC_UNCHAINED (2)
   and remains fully readable (not restricted, since it still verifies each
   entry); WalFile::open migrates it to v3 by recreating the file fresh,
   same as the existing v1 migration.

   WalFile::open() on an existing v3 file scans it once to resume the CRC
   chain correctly for further appends — required because a process
   restart without an intervening flush reopens the same (non-truncated)
   WAL and keeps appending to it, so new entries must chain against the
   real last entry already on disk, not restart from 0.

2. WAL_VERSION_LEGACY_NO_CRC (v1, no integrity verification at all) was
   reachable through the public WalFile::read_entries — a version byte
   flipped from 2/3 down to 1 silently downgraded every entry to the
   fully-unverified pre-hardening parser for any caller, not just the
   one-time migration path. Split into WalFile::read_entries (rejects v1
   with a typed error; still reads v2/v3) and the pub(crate)
   read_entries_for_migration (accepts v1 too), used exclusively by
   HDF5Memory::open's migration flow.

INT-09
2026-08-17 01:01:29 +00:00
ClawHDF5 Coding Agent 5db1008eb7 security(format): wire provenance verify_dataset into the clawhdf5 read path
verify_dataset existed and was tested, but was only ever called from
clawhdf5-format's own test files — no reader path in clawhdf5-io or the
clawhdf5 facade called it, so a corrupted dataset was silently readable
even though the write-side SHA-256 hash machinery (gated on the
provenance feature) had already written what it needed to detect that.

Add Dataset::verify_provenance() to the clawhdf5 facade, gated behind a
new `provenance` feature (on by default, forwarding to
clawhdf5-format/provenance which is already default-on). It surfaces a
typed VerifyResult (Ok/Mismatch/NoHash) via the existing Error type
rather than panicking. Deliberately NOT called automatically on
open()/dataset() — it decodes and hashes the entire dataset, which would
regress every read path (including the zero-copy/mmap ones) if run
unconditionally; callers opt in per dataset where the cost is
acceptable (e.g. a periodic integrity sweep).

Also re-export clawhdf5_format::provenance from the facade crate so
VerifyResult is reachable without depending on clawhdf5-format directly.

INT-08
2026-08-17 00:54:44 +00:00
ClawHDF5 Coding Agent 2e8414e412 security(agent): wire provenance/anomaly detection into the real save path
ProvenanceStore, WriteAnomalyDetector, and their check_*/verify_integrity
methods had zero callers outside their own module/tests — lib.rs only
declared the modules. The 15 injection-pattern checks, rate limiting, and
content-hash integrity verification described as shipped in ROADMAP.md
Track 5 never executed during normal library usage.

HDF5Memory::save/save_batch/save_or_update now record a MemoryProvenance
entry (content hash, inferred MemorySource, session) for every write, run
check_rate_anomaly/check_pattern_anomaly/check_source_anomaly against it,
and queue any triggered AnomalyAlert for the caller to drain via the new
take_anomaly_alerts(). save_or_update's update path additionally verifies
the existing record's content against its last recorded hash before
overwriting, catching accidental in-session corruption.

Scope notes, stated plainly rather than overclaimed:
- There is no on-disk provenance ledger (see the CLAUDE.md note added
  here) — this is session-scoped bookkeeping, not a disk-integrity
  control. open() starts the store empty; there's no historical hash to
  verify loaded records against, so "verify on load" is implemented as
  "populate the store so subsequent updates in this session are
  checkable" rather than a check against nothing.
- MemorySource is inferred from source_channel via a plain string match
  (infer_memory_source) — a heuristic for bookkeeping, not the gated
  trust-boundary construction INT-05 asks for. That remains open.
- Alerts never block a save; this only makes detection real instead of
  dead code. Whether writes should ever be blocked is a policy decision
  left to the caller/a follow-up item.

INT-04
2026-08-17 00:45:04 +00:00
Omar Sobh 429c29b76b docs: sync README/ROADMAP/CLAUDE/CHANGELOG with Tier 1-4 hardening work
CI / test (push) Failing after 3s
README.md:
- Fix badly stale LongMemEval numbers (badge said Hit@5 46%, table showed
  fabricated ~46%/~0.34/~72% figures that never matched BENCHMARKS.md's
  actual results of Hit@5 100% session / 84.4% turn-level, MRR 1.0/0.6597)
- Remove clawhdf5-types from the Crate Map — that crate was removed in an
  earlier cleanup pass but the README diagram was never updated; fix the
  crate count (16, not 17) and stale line-of-code figures (72,087/84K -> ~92K)
- Fix a dead #benchmarks badge anchor (no such heading exists) -> #performance
- Document the new clawhdf5-ann `parallel` feature (had no Feature Flags entry)
- Note WAL's CRC32 per-entry check, link the new tank LongMemEval/SIMD/
  vector-search reproduction section, update stale test-count comment
  (417+ -> 1,650+) and Phase 2 roadmap blurb (LongMemEval is now done)

ROADMAP.md:
- Check off "Academic benchmark cross-validation" (done via the tank
  LongMemEval re-run) and add a new "Recently closed out" section
  summarizing the Tier 3-4 hardening pass (Android JNI validation, pyo3
  bump, WAL CRC32, bounds-check audit + fuzz harness that found 3 real
  bugs, HNSW optional parallel feature, workspace.dependencies)
- Update stale test count (1,546 -> 1,650+) and last-updated date

CLAUDE.md: mention WAL's per-entry CRC32 check

CHANGELOG.md: add Security/Performance/Architecture/Documentation entries
under Unreleased summarizing all of Tiers 1-4 (this had not been touched
since 2026-06-04, predating the entire hardening pass)
2026-08-05 15:26:47 -07:00
Omar Sobh 62595d5ac0 chore: Tier 2 quick wins — version skew, docs, cleanup, overflow-safe bounds
CI / test (push) Failing after 14s
- Fix version skew: clawhdf5-py (pyproject.toml 1.93.0 -> 2.1.0) and
  packages/clawhdf5-node (package.json 2.0.0 -> 2.1.0) were both behind
  the actual crate version.
- Correct stale ROADMAP.md claims: the TypeScript bridge already has a
  complete napi-rs package (not "no package.json"); CI/CD is now wired
  up via .gitea/workflows/ci.yml.
- Fix CLAUDE.md: clawhdf5-gpu uses wgpu with hand-written WGSL compute
  shaders, not CubeCL.
- chunked_read.rs: drop 12 unnecessary chunk_dimensions[..rank].to_vec()
  allocations — all three callees already accept &[u32].
- btree_v1.rs: add an overflow-safe ensure_len(data, offset, needed)
  helper (checked_add) and use it at the two plain-arithmetic bounds
  guards, closing a usize-overflow edge case reachable from a crafted
  near-usize::MAX B-tree offset. Add a regression test.
- Clarify that the integrity hashes in clawhdf5-agent/provenance.rs
  (FNV-1a) and clawhdf5-format/provenance.rs (SHA-256) are unkeyed and
  only detect accidental corruption, not tampering — doc-only change.
- README.md: document that the mpi-io feature's read/write paths are
  root-read+broadcast / gather-to-rank-0, not true collective I/O.
2026-08-05 12:02:23 -07:00
Omar SobhandClaude Sonnet 5 6b1ea450f5 chore: cleanup pass — remove empty types stub, implement superblock v4, reconcile plan docs
- Remove clawhdf5-types (empty 1-line stub crate; type defs already live in
  clawhdf5-format). Update workspace Cargo.toml and CLAUDE.md accordingly.
- Implement HDF5 superblock v4 (page-buffer mode) read and write support in
  clawhdf5-format: Superblock::parse_v4, page_size field, v4 serialize
  branch, and FileWriter::with_page_size. This was the one task left
  unimplemented from docs/superpowers/plans/2026-06-29-format-write-extensions.md.
- Reconcile the three docs/superpowers/plans/*.md docs (filter codecs,
  format write extensions, MPI-IO VOL) against actual shipped code: they
  were pre-work plans for d6c4d4f (2026-06-30) committed to git late on
  2026-08-03 with all checkboxes still unchecked. Mark completed tasks done
  and add a status note so they read as historical records, not open work.
- Refresh ROADMAP.md's "What's Next" section against current repo state.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-03 08:11:31 -07:00
osobhandClaude Opus 4.8 f1762f82a7 docs: fix stale package names, counts, and CLI subcommands
Sweep of the docs after the v2.0.0 rename and recent changes:
- Per-crate READMEs (13 files): rename leftover rustyhdf5-*/edgehdf5-*
  package names and badges to clawhdf5-*, bump usage versions to 2.1.0.
- README: update stale test badge (417 -> 1500+), workspace stats
  (15 crates/72K -> 17 crates/84K), agent crate stats (20.7K/32 modules),
  and add the missing clawhdf5-napi and clawhdf5-bench crates to the tree.
- CLAUDE.md: correct the CLI subcommand list (inspect/dump/index/search ->
  the actual create/save/search/recall/stats/flush-wal/agents-md/export/snapshot).

No code changes. Verified there are zero todo!()/unimplemented!() macros and
no TODO/FIXME comments in the tree.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-03 11:17:04 +00:00
osobhandClaude Opus 4.8 5f5626e47f docs: note HNSW is the default agent search backend in CLAUDE.md
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-03 10:03:10 +00:00
redclawsystems 3f222f6956 Merge pull request 'docs(clawhdf5): document DType variants, fix unresolved doc links' (#17) from sdlc-docs/clawhdf5-types-20260514-165210 into main 2026-05-14 23:54:48 +00:00