fix(models): verify checksums for every model file, including already-installed files - #396
Merged
Merged
Conversation
…-installed files A model's checksum pin covered only its primary file: pull hashed only files[0], registry.verify checked only the primary artifact, and status() reported verified=True while a secondary file such as tokenizer.json went unchecked. When every file was already present and force was False, pull returned early without verifying at all. - ModelConfig gains file_sha256, a tuple of (name, sha256) pairs. sha256 stays the primary-file pin, so dataclasses.replace(cfg, sha256=...) keeps working. - registry.pinned_checksums(cfg) merges both fields into a per-file mapping and raises ModelChecksumError for a pin naming an unknown file or two conflicting pins for the same file. - Once a model has any pin, every file must be pinned; an unpinned file raises ModelChecksumError naming it. - verify() checks every file, so status() reports verified=True only when all files match. - pull() checks each downloaded file against its own pin before replacing the installed file, and calls verify() on the already-installed path. A mismatch there raises with a force=True hint and leaves the files in place. Models with no pins (every entry in today's registry) behave exactly as before. Closes #346
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
FreshData benchmark report —
|
| fixture | n_rows | n_cols | p50 s | p95 s | peak MB | repair % | false-repair % | preserve % | trust | monotonic | export % |
|---|
Authored-code reduction (Metric 6)
kevincostner17
added a commit
that referenced
this pull request
Sep 15, 2026
#403) #346 / PR #396 added ModelConfig.file_sha256 so every model file can be pinned, and registry.pinned_checksums(cfg) merges it with the primary-file sha256 pin. verify() and pull() use the merged pins, but OnnxEncoder.model_sha256 still read only cfg.sha256. A model whose primary file is pinned only through file_sha256 was reported as "unverified", and that value also keys the embedding cache and the model evidence metadata. model_sha256 now reports pinned_checksums(cfg).get(cfg.files[0]), falling back to "unverified". The other cfg.sha256 readers were checked and are already correct: pinned_checksums() is the merge itself, and the status() note tests "cfg.sha256 or cfg.file_sha256". Behaviour for the shipped registry, where nothing is pinned yet, is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Model checksum checks now cover every file of a model, and
fd.models.pullchecks files that are already installed before it reports success.Before this change, a pin covered only the primary file.
pullhashed onlyfiles[0],registry.verifychecked only the primary file, andstatus()reportedverified=Truewhile a secondary file such astokenizer.jsonwent unchecked. When every file already existed andforce=False,pullreturned early without verifying anything.ModelConfiggainsfile_sha256, a tuple of(name, sha256)pairs.sha256remains the pin for the primary file, sodataclasses.replace(cfg, sha256=...)keeps working.registry.pinned_checksums(cfg)merges both fields into one mapping per file. It raisesModelChecksumErrorwhen a pin names an unknown file or two pins for the same file conflict.ModelChecksumErrornaming it, before anything is downloaded.verify()checks every file, sostatus()reportsverified: Trueonly when all files match.pull()checks each downloaded file against its own pin before it replaces the installed file. When the files are already installed, it callsverify(): a mismatch raises with aforce=Truehint and leaves the files in place, and the CLI exits 2.docs/semantic-models.mddescribes the per-file checks and the newpullbehaviour.Models without pins, which is every entry in today's registry, behave exactly as before. Requiring
https://for the download base URL is out of scope.Follow-up (not in this PR):
OnnxEncoder.model_sha256still reads onlycfg.sha256, so a model pinned only throughfile_sha256reports "unverified" there.Tests
tests/test_models_download.py:.partfiles lefttests/test_models_registry.py:status()is false for a mismatched secondary file and true once it matchesverify()raises for a partially pinned modelpinned_checksumsmerging, unknown-file and conflicting-pin casestests/test_cli_models.py:freshdata models pullexits 2 when installed files don't match their pins.Verification
ruff check .: passed; changed files areruff format-cleanmypy src/freshdata: no issues (202 files)pytest -m "not online and not large": Python 3.12: 5150 passed, 13 skipped; Python 3.9 / pandas 1.5: 5146 passed, 17 skippedtokenizer.jsonis not installed; a pull over a corrupt installedmodel.onnxraisesModelChecksumErrorinstead of returning the path.Closes #346