Skip to content

feat(snapshot): verify delivered snapshots against integrity receipts - #457

Merged
kstonekuan merged 1 commit into
Hebbian-Robotics:mainfrom
Sagar-024:feat/428-snapshot-verify
Sep 7, 2026
Merged

kstonekuan merged 1 commit into
Hebbian-Robotics:mainfrom
Sagar-024:feat/428-snapshot-verify

Conversation

@Sagar-024

@Sagar-024 Sagar-024 commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

feat(snapshot): verify delivered snapshots against integrity receipts

Closes #428.

Problem

#401 stamps every exported snapshot with an integrity receipt (per-file size and sha256, plus an inventory content_id), but nothing checks a delivered snapshot against it. A truncated transfer looks exactly like a clean one.

What this adds

verify_dataset_snapshot(<directory>) and hflow verify snapshot <directory> re-read every table and copied asset named in the integrity block and compare size first, then sha256 (the hash read is skipped when the size already differs).

  • Findings, not raises: a partial transfer usually damages more than one file, so one report carries every mismatch.
  • Exit codes: 0 clean, 1 damaged, 2 unreadable input, 3 unverifiable.
  • A valid pre-feat(snapshot): record table and copied-asset integrity in format.json (#397) #401 format.json with no integrity key is reported as a no-receipt finding (unverifiable), not corruption. A missing directory or an unparsable format.json raises to exit 2: the wrong input, not damage.
  • Extra files the receipt does not name are ignored.
  • Not a tamper defence: the receipt travels unsigned inside the same format.json it describes.

Shared types, landed here first

The report shape lives in src/hflow/verification.py: VerificationStatus (ok / damaged / unverifiable), VerificationFinding (uri, reason, detail), VerificationReport with .ok derived from the status, exit_code_for, and the reason constants missing, size-mismatch, content-id-mismatch, no-receipt. This is the shape agreed in the #432 contract with VARUN3WARE; #454 imports these types rather than redefining them.

Recorded receipt paths are joined only onto the handed directory, so a copied delivery verifies in place.

Moved-root proof

test_moved_root_verifies_from_the_new_root_alone exports a snapshot to root A, copies the whole delivery to root B, deletes A entirely, and verifies B clean, then damages one file under B and verifies B damaged. With A gone, any read outside the handed root would see nothing, so both reports can only come from B's own bytes. A variant keeps A alive while B is damaged and asserts the damage is still reported from B, not masked by A.

Cost

One streaming sha256 pass per receipted file, plus the size stats. A size mismatch short-circuits that file's hash read. No catalog, storage, or media fetch traffic: verification reads only the handed directory.

Tests

13 tests in tests/test_snapshot_verify.py: clean verifies in both media modes, same-size content damage, missing file, truncation reported by size with the hash read skipped (spy on _sha256_hex), copied-asset damage, pre-#401 no-receipt, unlisted extras ignored, multi-finding partial transfer, CLI exit codes 0/1/3/2 including empty and binary-garbage format.json, read-only verification, and the two moved-root tests.

Mutation check: with the size and sha256 comparisons disabled, the damage tests go red, including the spy assertion; restored, all green.

@kstonekuan kstonekuan left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, merging.

You carried the #454 finding across before I asked. Both branches hold under mutation.

@kstonekuan
kstonekuan merged commit 4ad9ed9 into Hebbian-Robotics:main Sep 7, 2026
8 checks passed
VARUN3WARE added a commit to VARUN3WARE/hflow that referenced this pull request Sep 7, 2026
Import VerificationReport from the landed verification module (Hebbian-Robotics#457) and keep
the import-delivery half in lerobot_verify: resolve landing/<basename> under
the verified root, treat empty episodes as ok, and cover Kevin's copy cases.
kstonekuan pushed a commit that referenced this pull request Sep 7, 2026
…454)

Import VerificationReport from the landed verification module (#457) and keep
the import-delivery half in lerobot_verify: resolve landing/<basename> under
the verified root, treat empty episodes as ok, and cover Kevin's copy cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Snapshot integrity receipts are written but nothing reads them: no way to verify a delivered snapshot

2 participants