Skip to content

fix(gridfs): respect direct upload SHA provenance during recovery (MZ-19) - #14

Merged
rockyshi1993 merged 12 commits into
mainfrom
fix/mz19-recovery-sha-provenance
Nov 12, 2026
Merged

rockyshi1993 merged 12 commits into
mainfrom
fix/mz19-recovery-sha-provenance

Conversation

@rockyshi1993

@rockyshi1993 rockyshi1993 commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

MZ-19 — direct upload SHA provenance in crash recovery

Problem

The recovery tool treated every visible direct file's metadata.sha256 as a trusted digest. This conflicts with the public contract:

  • upload() with top-level options.sha256 verifies bytes before writing.
  • uploadStream() stores the top-level SHA as metadata only.
  • upload() with metadata.sha256 but no top-level options.sha256 also does not verify that arbitrary metadata value.

A complete visible uploadStream could therefore remain permanently fenced after a crash solely because caller-supplied metadata did not match its bytes.

Changes

  • Persist direct-owner provenance: uploadMethod, sha256Verified, expectedSha256, and claimedSha256.
  • Always verify visible file chunk order, chunk count, per-chunk lengths and total length.
  • Strictly enforce actual SHA for resumable sessions and direct upload() owners that pre-verified top-level options.sha256.
  • Treat uploadStream / arbitrary metadata SHA as an untrusted claim: mismatch becomes an auditable warning, not a reason to strand a physically complete file.
  • Preserve fail-closed behavior for malformed/missing/extra chunks and trusted SHA mismatch.
  • Audit completion records actual SHA, claim provenance and warnings.
  • Clarify public TypeScript docs and English/Chinese recovery runbooks.
  • Add the new recovery runbook to the documentation example coverage matrix.

Deterministic coverage

  • Actual uploadStream with wrong metadata-only SHA + simulated crash before owner release -> recovery succeeds, bytes/chunks preserved, audit warning recorded.
  • Actual upload() metadata.sha256 without top-level options.sha256 -> treated as unverified claim.
  • upload() top-level SHA mismatch -> rejected before files/chunks/owner creation.
  • Pre-verified upload() expected SHA mismatch during recovery -> remains fenced.
  • Existing resumable finalizing actual-byte SHA checks remain strict.

Current HEAD verification

HEAD: 7b68c6a5aeb0a9c7b563f7edd2590b979894cf3b

  • GridFS safety matrix #43174706534:
    • MongoDB 7.0.37: 57/57 pass
    • MongoDB 8.0.26: 57/57 pass
  • Full CI #43174706523:
    • Node 18 full suite: passed (1461 tests, 1460 pass, 0 fail; remaining test skipped)
    • Node 20: passed
    • Node 22: passed
    • Release Preflight: still running at time of update.

The initial full CI exposed a missing documentation matrix entry for the new gridfs-recovery page. That entry was added and the latest HEAD reran all checks. The earlier failed run was on an older SHA and is not being treated as current evidence.

Merge gate

  • GridFS MongoDB 7.0.37 / 8.0.26 tests
  • Node 18 / 20 / 22 full tests and compatibility guards
  • Docs matrix entry
  • Latest-HEAD release preflight success
  • Final independent review

No package version bump, tag, merge or npm publish is included in this PR.


Note

Medium Risk
Changes GridFS ownership records, recovery unlock rules, and crash-recovery behavior for SHA metadata—safety-critical storage paths that require coordinated writer drain and operator discipline.

Overview
MZ-19 aligns GridFS crash recovery with how SHA-256 is actually trusted at upload time.

Direct upload() and uploadStream() now persist owner provenance (uploadMethod, sha256Verified, expectedSha256, claimedSha256) in <bucket>.uploads when claiming ownership; claimOwner enforces consistency for verified upload() digests.

The recovery script verifyVisibleFile always checks visible chunk order, per-chunk lengths, and total length. It strictly enforces SHA only for resumable sessions and direct upload() owners that pre-verified top-level options.sha256. uploadStream() and arbitrary metadata.sha256 are treated as untrusted: mismatches become audit warnings so a physically complete file is not left permanently fenced. Trusted provenance mismatches still fail closed.

Completed recovery audits and CLI receipts include SHA policy, actual/claimed digests, and warnings. Public types and EN/ZH GridFS/recovery docs clarify that byte verification requires top-level upload() sha256, not metadata.sha256. The doc example matrix adds gridfs-recovery. Integration tests cover the new provenance and warning paths; ownership regression tests handle MongoDB driver 6 vs 7.8 chunk delete filter shapes.

Reviewed by Cursor Bugbot for commit 962d026. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Contributor Author

Static merge review: MZ-19 and MongoDB Driver 7.8 MZ-18 race fixture

Reviewed PR #14's source, recovery SHA provenance, audit integrity, type/docs changes and regression fixtures. The direct SHA trust boundary is preserved: only top-level preverified upload() SHA and resumable session SHA are enforced; metadata-only uploadStream SHA mismatches produce an audit warning after verifying physical chunks. No new P0/P1 source blocker was identified.

Found and fixed a CI-only regression in the MZ-18 race test that previously caused release preflight to hit 60 minutes: MongoDB Node driver v7.8 now uses {files_id:{$eq:id}} while the test interceptor assumed a bare ObjectId and called filesId?.equals(id). The new guard recognizes both shapes, asserts the barrier really fired, and fails early if a driver delete completes without interception.

Evidence on exact PR SHA 962d02695da60695f51ef638ff2cab3210158239:

  • GridFS Ownership Safety Validation run #43185533349: MongoDB 7.0.37 58/58 and MongoDB 8.0.26 58/58 PASS (includes actual MZ-18 race).
  • Full Node 18/20/22 CI and release preflight run #43185533356 had not completed at static review time.
  • Earlier release preflight run #43174706523 was canceled at 60 minutes; its logs show the Driver 7.8 exact-match test fixture failure followed by a hung test, not proof of a production GridFS failure.

User-approved merge exception: user explicitly instructed to merge after static review with no blockers, rather than wait for full release preflight. Any subsequent full CI findings must be tracked and repaired promptly; do not describe these pending jobs as passed. No npm release, tag or version bump.

@rockyshi1993
rockyshi1993 marked this pull request as ready for review November 12, 2026 08:47
@rockyshi1993
rockyshi1993 merged commit 80da4d7 into main Nov 12, 2026
6 of 7 checks passed
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.

1 participant