feat(verify): record a caller-supplied appraiser's per-layer report on runtime.measurement (#279, #431) - #457
Conversation
|
@revenue7-eng CI's mypy does not narrow |
|
The 3.11 job failed at the mypy step: |
…n runtime.measurement (agentrust-io#279, agentrust-io#431) Signed-off-by: Andrey Lazarev <lazarev@tactiqedge.com>
Signed-off-by: Andrey Lazarev <lazarev@tactiqedge.com>
16328df to
77c6562
Compare
|
@revenue7-eng CI is green on 77c6562 and both #431 conditions hold. One gap: an appraiser returning |
…alid Signed-off-by: Andrey Lazarev <lazarev@tactiqedge.com>
|
Done in the latest commit: an empty |
imran-siddique
left a comment
There was a problem hiding this comment.
The empty layers case is refused as appraiser_returned_invalid with the regression beside "extra": 1, which was the one remaining condition.
Implements the platform-measurement row of #279, in the shape agreed in #431.
What it does
verify_recordhasruntime.platformand one digest,runtime.measurement. For a measured-boot platform that digest is a composite over many layers, and a match says nothing about which layers were measured, which were appraised, or whether the evidence describes one boot.verify_recordnever sees the quote, log or reference values, so it cannot decide that itself.Following
citation.py, this addsagentrust_trace.platform_measurementand aplatform_appraiserargument toverify_record. The appraiser is caller-supplied, called last with a copy ofruntime, and returns the measurement it appraised and a status per layer. The result's newplatform_measurementfield carries the report:appraised, with aLayerCheckper layer:established, ornot_establishedwithlayer_not_measured,measured_not_appraisedorevidence_spans_multiple_boots;appraisal_rejectedwithappraiser_raised,appraiser_returned_invalidormeasurement_mismatch(a report about another measurement is never attached);not_attemptedwithno_appraiserwhen none is supplied.The module asserts nothing about the platform, derives no layer outcome, upgrades nothing, and produces no
appraisal.status. No outcome movesrevocation, the thumbprint,citationsor whetherverify_recordraises. The names are not accepted normative text. No schema or wire-format change.The two conditions from #431
examples/platform-measurement/: seven causes, each with atwin_ofvector carrying the same signed record and the same context except the appraisal table.test_every_cause_has_a_twin_that_differs_only_in_its_conditionfails if a cause loses its twin or a twin differs in anything else. Every vector without asourcecarries"synthetic": true;evidence_spans_multiple_bootsexists only in the synthetic pair 013/014, because the board behind the real vectors resets its TPM in SPL and does not produce it.not_attemptedstays distinct from a pass wherever the result is summarised. Nothing in this repository summarises aVerificationResulttoday; the rule is stated in the module docstring and held bytest_P4b_not_attempted_is_never_a_pass, so a future summary cannot collapse it.Evidence
Vectors 015 and 016 carry measurements from published quotes on a physical board with a discrete TPM (Rock 5A, Infineon SLB9670), registered AK:
layer_not_measured). Evidence and checker: https://github.com/revenue7-eng/tactiq-os/releases/tag/v2.1.0-rc13measured_not_appraised). Evidence and offline checker: https://github.com/revenue7-eng/tactiq-os/blob/main/measurements/tpm-quotes-dev-20261002.mdNothing in this repository reads that evidence; the vectors carry the appraiser's report as the input.
Checks
pytest(3406 passed, 48 skipped),ruff check src tests scripts,tools/check_dashes.py. The generator reproduces the set byte-for-byte and is picked up bytest_generators_reproduce_fixtures; the set is registered intest_adequacy_all_setsand the new function and parameter intest_public_functions_raise_what_they_document.