feat: verify ephemeris kernel integrity on load#12
Merged
Conversation
NAIF publishes no checksums for the generic kernels, so integrity is trust-on-first-use: the first load records a <kernel>.sha256 sidecar and every later load must match it. A KERNEL_SHA256_PINS table supports pinning a known-good digest from a trusted local copy, which takes precedence over the sidecar. load_ephemeris exposes allow_unverified to bypass mismatches explicitly, and EphemerisContext now carries kernel_sha256/kernel_verified so manifests can record the verification status.
13 tasks
wiyth00
added a commit
that referenced
this pull request
Jul 25, 2026
…--resume Item 15: - argparse --version prints package version, MODEL_VERSION, and kernel name. - Stage progress messages use the logging module (INFO default, --quiet for warnings only, --verbose for debug). Data outputs (json dumps, headline) stay on stdout. terminal_summary.txt is byte-identical. Deferred #12 follow-ups: - --allow-unverified-ephemeris is wired through every mode's load_ephemeris. - events.json records the kernel digest from the verified context (no re-hash) plus the new verified flag. - run_manifest.json command string reflects the real entry point (the old string referenced run_search.py, deleted in #10) and records resume use. Item 16: - --resume reuses per-stage artifacts in --output when a resume_manifest records matching model_version, config sha256, and kernel sha256; refuses to resume across any mismatch. Stages 1 (enumeration/screening), 2 (validation), 3 (optimized design), and 5 (stability) are checkpointable; stage 4 is always recomputed because fixed-system ground tracks are not serialized and downstream figures need them. - New tests cover parser flags, the version string, a --version subprocess run, and the pure resume-guard helper.
5 tasks
wiyth00
added a commit
that referenced
this pull request
Jul 25, 2026
#14) Item 15: - argparse --version prints package version, MODEL_VERSION, and kernel name. - Stage progress messages use the logging module (INFO default, --quiet for warnings only, --verbose for debug). Data outputs (json dumps, headline) stay on stdout. terminal_summary.txt is byte-identical. Deferred #12 follow-ups: - --allow-unverified-ephemeris is wired through every mode's load_ephemeris. - events.json records the kernel digest from the verified context (no re-hash) plus the new verified flag. - run_manifest.json command string reflects the real entry point (the old string referenced run_search.py, deleted in #10) and records resume use. Item 16: - --resume reuses per-stage artifacts in --output when a resume_manifest records matching model_version, config sha256, and kernel sha256; refuses to resume across any mismatch. Stages 1 (enumeration/screening), 2 (validation), 3 (optimized design), and 5 (stability) are checkpointable; stage 4 is always recomputed because fixed-system ground tracks are not serialized and downstream figures need them. - New tests cover parser flags, the version string, a --version subprocess run, and the pure resume-guard helper.
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
load_ephemeris()auto-downloadsde440s.bspwith no integrity check, yet the entire validation chain rests on kernel identity (work plan item P3 / 13).One honest deviation from the plan: the plan says "add a known-good SHA-256", but NAIF publishes no checksums for the generic kernels, and I refuse to pin a digest I couldn't independently verify. So the design is:
de440s.bsp.sha256sidecar next to the kernel; every later load recomputes the SHA-256 and must match it. A silently truncated or corrupted re-download now fails loudly instead of poisoning a multi-hour run.KERNEL_SHA256_PINS— an explicit pin table that takes precedence over the sidecar. It ships empty with instructions; fill it from your trusted local copy (sha256sum data/ephemeris/de440s.bsp) in a one-line follow-up commit. A fresh recording never counts as "verified"; only a match against a pre-existing pin or sidecar does.allow_unverified=Trueonload_ephemeris/verify_kernel_integrityis the escape hatch: mismatches are tolerated but reported as unverified.EphemerisContext.kernel_sha256/.kernel_verified(defaulted fields, so existing constructors are unaffected) expose the digest and status sorun_full's manifest can recordverified: true/false.Not included here: wiring
--allow-unverified-ephemerisand the manifestverifiedfield throughcli.py— that belongs with the item-15 CLI work and is noted on #9.Scientific impact
None. Verification happens after Skyfield loads the kernel and changes no numeric path. On an existing checkout the first load with this branch records the sidecar and proceeds exactly as before.
Checklist
ruff check .passespytestpasses locallytests/test_kernel_integrity.pycovers seven scenarios (first-load recording, sidecar verification, tamper detection,allow_unverifiedbypass, case-insensitive pin match, pin mismatch overriding a matching sidecar, pin+sidecar precedence) against small temp files — no kernel or network needed. The verification logic was additionally executed standalone in a sandbox before pushing: all scenarios pass. Fullpytest/ruffcould not be run locally, so CI is the first integrated execution.