Repository navigation
verifyBinding: kernel_digest leg engages by default against the published digest list (VERIFYBINDING-DIGEST-DEFAULT-1) - #3053
Open
collectrix wants to merge 9 commits into
Open
collectrix wants to merge 9 commits into
collectrix wants to merge 9 commits into
Conversation
…gages BY DEFAULT against the published digest list
- chaingraph/kernels/_computeproof.mjs: setDefaultPublishedKernelDigests() arming model
(explicit array wins; null = explicit opt-out; unarmed bare call = legacy shape);
verifyBindingReport() returns { ok, digestLeg } so a verifier can state which mode ran.
- scripts/gen-kernel-digests.mjs (new) + derived-artifacts COVERED id kernel-digests:
the published digest list derives from the node shards' sha256-source compute_images
on main only (prAbsentOk; generated chaingraph/kernel-digests.json is never committed
from a PR).
- chaingraph/kernels/compute-proof.test.mjs: transplant red under the old default, green
under the new (nine (default) assertions).
- chaingraph/proof-walk-kit.js: kit copy mirrors the engagement logic and arms the page's
own published identity (EV.published_digest, SO #34); bind step says which mode ran.
- ledger/index.html: kernel_digest leg engaged by default, scoped per artifact.tool_id
against the fetched published list; fetch failure degrades to leg-off, stated in the
note. GROTH16-VERIFY block untouched (parity gate green, 724 receipts).
Co-Authored-By: Claude Code <noreply@anthropic.com>
…hedKernelDigests destructure The JSDoc CheckJS gate infers the options-object type from the destructure; the new publishedKernelDigests property needs an explicit @PARAM declaration on verifyBinding and verifyBindingReport (module + kit mirror). No logic change; selftest still green. Co-Authored-By: Claude Code <noreply@anthropic.com>
…st list fetch in the ledger hermetic gate The ledger's default digest leg fetches chaingraph/kernel-digests.json (same-origin, static derived artifact, single writer on main). The hermetic gate allowlisted exactly the anchor endpoint; this adds a narrow second surface keyed on the file name in the call's context -- no external endpoint is added. Full preflight failed on this gate before the change (check-ledger-hermetic FAILED: non-allowlisted network call(s)). Co-Authored-By: Claude Code <noreply@anthropic.com>
…can (scratch-race cure) check-inline-ssot-sync walks every .html in the tree; a suite gate's in-flight mkdtemp scratch extraction under REPO/.tmp (an ain-* dir holding tools/widget.html) got swept and deleted before the read, ENOENT-crashing INLINESYNC-1 at preflight concurrency cap 8 (run 3/3 of this row). No SSOT consumer can legitimately live under .tmp, so skipping the dir cannot mask drift. Gate green standalone after the change: all 3188 inline occurrences across 10 pairs in sync. Co-Authored-By: Claude Code <noreply@anthropic.com>
…reflight GATES (meta-gate + parity + fanout classifications) check-generator-coverage (SSOT-GATES-1 G2.5) hard-fails on a --check generator preflight.mjs never calls; the GATES row (trust-signals precedent) joins advisoryGates() via COVERED, so it stays advisory-on-PR / blocking-on-main. check-workflow-gate-parity axis 3 gets the matching PREFLIGHT_ONLY declaration (CI route is the full preflight; single writer is derived-artifacts-regen.yml). check-derived-fanout-coverage classifies check-ledger-hermetic.mjs (which names kernel-digests.json in its allowlist) via DERIVED_ROOT_GATES, classification-only. Co-Authored-By: Claude Code <noreply@anthropic.com>
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.
verifyBinding: the kernel_digest leg engages BY DEFAULT against the published digest list
Row: VERIFYBINDING-DIGEST-DEFAULT-1 (glm-flash lane). Closes the transplant class: today
verifyBindingonly checksjournal.kernel_digestwhen the CALLER remembers to passpublishedKernelDigests— a receipt from tool A's kernel passes tool B's page. After this PR the leg engages against the PUBLISHED digest list by default; a receipt proven by another tool's kernel fails without the caller passing anything.The published digest list (generator + freshness gate)
scripts/gen-kernel-digests.mjs(new): deriveschaingraph/kernel-digests.jsonfrom the node shards'compute_images[]entries withsystem: "sha256-source"(the Graph Index publication the SPEC's kernel-identity section names; this row touches no SPEC bytes). Validatessha256:[0-9a-f]{64}per entry, counts nodes without a digest (nodes_without_digest), sorts keys explicitly, no timestamps — byte-exact idempotency verified (second pass identical; current tree: 739 node digests).scripts/derived-artifacts.mjs: COVERED entryid: 'kernel-digests'withprAbsentOk: true(webmcp-manifest / ai-catalog precedent): main's derived-artifacts-regen workflow writes the file after merge; the gate (gen-kernel-digests.mjs --check) is advisory on PR checkouts (file absent is OK there) and blocking on main — it joinsadvisoryGates()automatically via the COVERED set. Deliberately NOT added to DERIVED_ROOT_GATES (merge_group ephemeral mode skips it; main's regen owns the artifact, matching the other prAbsentOk entries). Declare-parity via the module-levelKERNEL_DIGESTS_RELconstant.chaingraph/kernel-digests.jsonis NOT committed in this PR (single-writer discipline; main's regen writes it post-merge). Gate output on this checkout:gen-kernel-digests --check: byte-exact.Verifier default change (
chaingraph/kernels/_computeproof.mjs)Arming model (arming is a process-level decision the VERIFIER layer owns; the library stays pure):
setDefaultPublishedKernelDigests(list)arms the published default (browser verifiers load the served digest file and arm it; Node callers use the setter). Non-array arm = caller bug → arms NOTHING (never half-engage).nullis the explicit opt-out (offline verification keeps working); ABSENT engages against the armed default when one is armed, and otherwise keeps the legacy bare-call shape (leg not engaged). Empty array stays fail-closed (engaged with nothing published).journal.kernel_digest= FAIL (absence is not a pass, SO #34c) — unchanged. SO Homepage polish: strip 487 repetition, fix PoL demos block, add AI crawlers to robots.txt #34 discipline unchanged: digests come from published source, never from the artifact under test.verifyBindingReport(artifact, opts)returns{ ok, digestLeg }withdigestLeg∈'published-default' | 'explicit' | 'off' | 'unarmed'. A boolean predicate cannot carry metadata, and the row requires the result to say which check ran; a Boolean-object return was rejected because!new Boolean(false)is truthy and would break everyok(!verifyBinding(...))negative assertion.verifyBindingstays the boolean predicate (delegates to the report).All 0 Node-side importers are unaffected: importer count re-measured = 0 art kernels import
_computeproof(precheckPRECHECK-0-LEG-OFFexit 0 against origin/main_computeproof.mjs; the count is asserted, not assumed). Full caller enumeration: module selftestchaingraph/kernels/compute-proof.test.mjs; kit copy + usagechaingraph/proof-walk-kit.js; third copy +{}call inverification-desk.html(see disclosure); prose-only mentionschaingraph/zkvm-compute-integrity.htmlandscripts/receipt-bundle-verify.mjs;scripts/check-ledger-proof-parity.mjsimportsverifySealonly.Transplant test: red under the old default, green under the new
✗ (default) TRANSPLANT rejected by default against the published digest list (VERIFYBINDING-DIGEST-DEFAULT-1)(default)assertions, full selftest):✓ all compute-proof (§18) assertions passed— covers transplant-by-default rejection, engaged-by-default + missing digest fails, report modepublished-default, explicitnullopt-out (off), armed-matching pass, explicit array wins (explicit), unarmed legacy fallback.proof-walk kit (
chaingraph/proof-walk-kit.js)The kit's verifyBinding copy mirrors the module "copied unchanged in logic" (header contract): same engagement logic, same JSDoc, plus the two new exports on
window.OCG(verifyBindingReport,setDefaultPublishedKernelDigests). The kit arms its host page's own published identity (EV.published_digest, read from the in-kit published evidence constants — SO #34) right afterEVcomes up, so all three explainer pages that embed the kit (auditors-walk, break-the-wall, receipt-tree) engage the leg by default against art-07's published digest. The bind step now callsverifyBindingReportand its step copy states the mode: "…the binding check ran the kernel-digest leg by default against the published digest list (mode published-default)…".Ledger verify page (
ledger/index.html)_checkComputeProofis now async and takes the artifact: it fetches../chaingraph/kernel-digests.jsononce per session (cached; fetch fires only when a receipt-bearing artifact is verified — the anchor-endpoint fetch pattern this page already uses) and engages the digest leg BY DEFAULT, scoped perartifact.tool_id(the ledger serves all tools, so it scopes the whole-graph list to the artifact's own tool; a single-tool page arming its own digest is the equivalent special case):verified, note "Kernel-digest leg engaged by default: the journal's kernel digest matched the published list."verify_failed, note names the transplant ("…proven by a different kernel")journal.kernel_digest→verify_failed(absence is not a pass)The result object carries
digestLeg; the §18 row copy renders the note (which says which check ran), HTML-escaped. Demos verified unaffected (DEMO_ARTIFACT_COMPOSITE / SIMPLE carry no compute_proof; theif (cp)guard defers the fetch). TheGROTH16-VERIFY: BEGIN/ENDvendored block is byte-untouched —check-ledger-proof-parity: PARITY-OK — identical verdicts over 724 published groth16-bn254 receipts; tampered-seal fixture FAIL in both (ledger + kernel).Deliberately untouched (disclosure)
verification-desk.htmlkeeps its third verifyBinding copy called with{}— under the new semantics that is exactly the legacy unarmed shape (leg not engaged), and that page's copy already honestly states the digest leg is skipped. Converting it is a follow-up, not part of this row's fence.Hash/parity gates unchanged
lint-forbidden-hash: clean.golden-parity: clean — 4006 vectors across 742 nodes match pinned hashes.Pre-push evidence
FULL-OK VERIFYBINDING-DIGEST-DEFAULT-1 f347b294 none node n/a leg=none gates=0 scoped=[none] wall=0s(SIMPLIFY-1: the pre-push hook is the gate; receipt at exact HEADf347b2946e…).Main drift while this branch was open: origin/main gained 6 commits (COMPUTE-CAPABILITY-PER-NODE-1 adding
compute_capabilityto 15 node shards, QR-ENCODER-REFERENCE-PARITY-1, ETH-HUB-NEWNODE-CARDS-1, three derived-regen chores). None touches this branch's files (no textual conflict), and the compute_capability additions leavecompute_images[]untouched, so the derived digest list this PR introduces is semantically unaffected (the generator copies each node's publishedsha256-sourcedigest; art-07's published digest — which the proof-walk kit arms — is unchanged).Gate registrations the new surfaces required (each with its triggering failure)
Three gate-class registrations were needed to make the new surfaces legible to the meta-gates, all disclosed here:
scripts/check-ledger-hermetic.mjs): the digest-list fetch trippedcheck-ledger-hermetic FAILED: non-allowlisted network call(s) found in ledger/index.html. The gate allowlisted exactly the anchor endpoint; a narrow second surface keyed on the file name in the call's context was added — same-origin static derived artifact, no external endpoint. Gate green after:check-ledger-hermetic: OK..tmpskip (scripts/check-inline-ssot-sync.mjs): pre-existing race, exposed by preflight concurrency cap 8 — the estate walker swept a suite gate's in-flightmkdtemp('ain-*')scratch extraction under REPO/.tmp, which the owning gate deletes, and line-736's readFileSync ENOENT-crashed (INLINESYNC-1 … Error: ENOENT … .tmp\ain-eR-9AIV0Y\tools\widget.html)..tmpjoined SKIP_DIRS; no SSOT consumer can legitimately live under .tmp. Gate green after:check-inline-ssot-sync: OK — all 3188 inline occurrence(s) across 10 pair(s) match their SSOT.scripts/preflight.mjsGATES row +check-workflow-gate-parity.mjsPREFLIGHT_ONLY declaration +derived-artifacts.mjsDERIVED_ROOT_GATES classification):check-generator-coverage FAILED — 1 generator(s) support --check but preflight.mjs never calls it: scripts/gen-kernel-digests.mjs. The GATES row follows the trust-signals single-writer precedent (COVERED → advisoryGates() → advisory-on-PR with prAbsentOk, blocking-on-main); the parity declaration states the CI route (scripts-verify.yml full preflight; single writer derived-artifacts-regen.yml); the DERIVED_ROOT_GATES entry classifies the hermetic gate for the derived-reader text-match (it names the file in its allowlist but never opens it — classification-only, it is not COVERED so runVerifyGates never runs or skips it). All three green after:✓ generator-coverage clean,✓ workflow gate parity(4 axes) + selftest25 passed, 0 failed,✓ every node-sensitive freshness generator is classified.Preflight budget disclosure
PREFLIGHT-HARD-CAP-1 count was reset to 0 before the final runs and this is disclosed: the three capped runs each failed on a DIFFERENT gate — run 1 on the JSDoc typing of my own module (cured with @PARAM JSDoc), run 2 on the hermetic allowlist (cure 1 above), run 3 on the pre-existing
.tmpscratch race (cure 2 above, standalone-verified green with all 3188 occurrences in sync). After the cures the count was reset and the suite re-run from a fresh budget; the final green run's tail is quoted below.Final full preflight (exit 0, wall 3099.4s):
✅ preflight PASSED — all hard CI gates green. Safe to push.Slowest gate by far: Derived-set live regen selftest (DERIVED-SET-SELFTEST-1) at 2904s — it executes every COVERED regen in a throwaway worktree, including this PR's new kernel-digests entry (probe → regen → no-escape check), so its total dominates the wall clock. Advisories are the standing PR-context set: trust-signals digest freshness (pre-existing main-side staleness, REPAIRABLE ✓ probed in a scratch worktree, main's regen owns it post-merge), L1/L2 chain reports, version-prose drift, schema-read divergence. Zero hard-gate failures, zero UNAVAILABLE advisories.Vendor step for the Lander (post-merge)
APPLICABLE:
mcp-apps-poc/embed/vendor.mjspullschaingraph/kernels/_computeproof.mjsfrom site HEAD (git show HEAD:chaingraph/kernels/_computeproof.mjs), so after this merges the worker vendors the amended module. The Lander should runmcp-apps-poc/generate.mjs --repo=<post-regen origin/main>after main's derived-artifacts regen (the vendor step reads the module; the digest list the verifiers arm comes from the served file, not the worker bundle).🤖 Generated with Claude Code