Skip to content

feat(verify-quote): verify harvest records directly - #261

Merged
samlaf merged 1 commit into
seismicfrom
sl/sei-321-featverify-quote-verify-harvest-records-directly-replacing
Aug 19, 2026
Merged

feat(verify-quote): verify harvest records directly#261
samlaf merged 1 commit into
seismicfrom
sl/sei-321-featverify-quote-verify-harvest-records-directly-replacing

Conversation

@samlaf

@samlaf samlaf commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

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/.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.

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
samlaf requested a review from cdrappi as a code owner August 19, 2026 21:34
@linear-code

linear-code Bot commented Aug 19, 2026

Copy link
Copy Markdown

SEI-321

@samlaf
samlaf merged commit 6b15db8 into seismic Aug 19, 2026
9 of 10 checks passed
@samlaf
samlaf deleted the sl/sei-321-featverify-quote-verify-harvest-records-directly-replacing branch August 19, 2026 21:57
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