feat(verify-quote): verify harvest records directly - #261
Merged
samlaf merged 1 commit intoAug 19, 2026
Merged
Conversation
Fixes SEI-321 #260 gave `harvest` its claims as four flags — --nonce, --node-pubkey, --consensus-pubkey, --evidence — because verification ran before any record file existed. It exists now: deploy archives exactly those four facts together as inputs/harvest/<node>.json, then explodes that file back into flags to re-verify it, and a third party re-verifying the archive has to reassemble five hex strings out of it first. So the record becomes the input format. `harvest --record <file|->` reads the four fields from one JSON document, and HarvestRecord pins that schema here: harvest_nonce, node_public_key, consensus_public_key, evidence. This is the natural home for it — founding_summit_keys_binding already commits to exactly those three claims, one binding per node. Whatever the archive keeps alongside them (when the harvest ran, the report of the verification that passed) is ignored, so an archived file verifies as-is: verify-quote harvest --record inputs/harvest/node-1.json \ --policy measurement-policy-bootstrap.json That one command is the point. The founding archive exists so future users and joiners can re-run this verification themselves instead of trusting the founder's verdict, and it now takes one file, this binary, and the published policy — no deploy-repo tooling in the path. No security change: the claims were untrusted input as flags and stay untrusted as fields, because the quote's report_data is what decides whether the node's keys really are these. A wrong claim still surfaces as a binding mismatch — which is why each field is decoded up front and rejected by name, before DCAP spends a collateral round-trip on a document that was malformed all along. Tests move with the interface: record fixtures around the same frozen binding vectors, an archived record carrying harvested_at and a verification report (the ignored-fields contract), and a record whose evidence field is not an envelope. Cargo.lock follows the serde derive the record needs. Deploy is the only caller and cuts over in the same stroke, so the flag form is gone with no back-compat path. The holder's response is unchanged — it never sees the nonce it quotes over as data it owns — and its comments now name the record its bytes travel inside.
samlaf
deleted the
sl/sei-321-featverify-quote-verify-harvest-records-directly-replacing
branch
August 19, 2026 21:57
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.
Fixes SEI-321
#260 gave
harvestits claims as four flags — --nonce, --node-pubkey, --consensus-pubkey, --evidence — because verification ran before any record file existed. It exists now: deploy archives exactly those four facts together as inputs/harvest/.json, then explodes that file back into flags to re-verify it, and a third party re-verifying the archive has to reassemble five hex strings out of it first.So the record becomes the input format.
harvest --record <file|->reads the four fields from one JSON document, and HarvestRecord pins that schema here: harvest_nonce, node_public_key, consensus_public_key, evidence. This is the natural home for it — founding_summit_keys_binding already commits to exactly those three claims, one binding per node. Whatever the archive keeps alongside them (when the harvest ran, the report of the verification that passed) is ignored, so an archived file verifies as-is:That one command is the point. The founding archive exists so future users and joiners can re-run this verification themselves instead of trusting the founder's verdict, and it now takes one file, this binary, and the published policy — no deploy-repo tooling in the path.
No security change: the claims were untrusted input as flags and stay untrusted as fields, because the quote's report_data is what decides whether the node's keys really are these. A wrong claim still surfaces as a binding mismatch — which is why each field is decoded up front and rejected by name, before DCAP spends a collateral round-trip on a document that was malformed all along.
Tests move with the interface: record fixtures around the same frozen binding vectors, an archived record carrying harvested_at and a verification report (the ignored-fields contract), and a record whose evidence field is not an envelope. Cargo.lock follows the serde derive the record needs.
Deploy is the only caller and cuts over in the same stroke, so the flag form is gone with no back-compat path. The holder's response is unchanged — it never sees the nonce it quotes over as data it owns — and its comments now name the record its bytes travel inside.