Skip to content

test: guard the hand-written enum copies against the packaged schema - #62

Merged
imran-siddique merged 1 commit into
agentrust-io:mainfrom
lywinged:fix/enum-drift-declared-and-software-only
Aug 14, 2026
Merged

test: guard the hand-written enum copies against the packaged schema#62
imran-siddique merged 1 commit into
agentrust-io:mainfrom
lywinged:fix/enum-drift-declared-and-software-only

Conversation

@lywinged

Copy link
Copy Markdown
Collaborator

Closes #53.

#57 closed the first half of that issue — the ten unguarded conformance failure paths are guarded now, 33 of 33 sites verified. This is the second half, which was still open.

The drift

tests/test_level0.py:7 restates the runtime.platform enum and holds nine of the schema's ten values. software-only is missing.

That is the value docs/trust-levels.md requires for Level 0:

Level 0 records are signed with an Ed25519 key held by the agent process… The runtime.platform field must be software-only.

So a Level 0 record as documented fails test_runtime_platform_registered. Nothing noticed because valid_level0.json uses intel-tdx.

The guard

Adding the value fixes today. Five set literals in this repository restate a schema enum, and any of them can drift the same way:

tr_rte._VALID_PLATFORMS         runtime.platform
tr_pol._VALID_ENFORCEMENT       policy.enforcement_mode
test_level0.VALID_PLATFORMS     runtime.platform
test_level0.VALID_ENFORCEMENT   policy.enforcement_mode
test_level0.VALID_APPRAISAL     appraisal.status

tests/test_enum_parity.py asserts each against schemas/trace-claim.json on every run, by equality rather than containment — a superset means the copy accepts a value the schema does not define, which is the same drift pointing the other way.

Load-bearing rather than decorative: removing software-only again fails exactly that parametrized case, which I checked rather than assumed.

measurement/scripts/enum_drift.py already reports this and exits 1. It walks the AST, which is the right tool for finding a copy nobody has listed yet; this file is the other half, so a known copy fails in the suite instead of waiting for someone to run the script.

Verification

Fresh clone, directory that has never held the repository: 167 pass, 5 xpass. ruff reports the same 68 pre-existing errors either side of this change, and none in the new file.

Deliberately not in this PR

enum_drift.py reports two further drifts, both against the normative schema rather than the packaged copy — it fetches trace-claim.json from trace-spec main, and the copy in schemas/ is behind it. policy.enforcement_mode gained declared upstream and neither tr_pol.py nor the packaged copy has it.

That is a different problem with a wider blast radius than an enum, and I would rather raise it separately than widen this one. Filing it next.

Closes agentrust-io#53.

agentrust-io#57 closed the first half of that issue: the ten unguarded conformance
failure paths are now guarded, 33 of 33 sites verified. The second half was
still open - tests/test_level0.py:7 restates the runtime.platform enum and
holds nine of the schema's ten values, missing software-only.

That is the value docs/trust-levels.md requires for Level 0. A Level 0 record
as documented would fail test_runtime_platform_registered; nothing noticed
because valid_level0.json uses intel-tdx.

The value is added, and so is the general guard. Five set literals in this
repository restate a schema enum:

    tr_rte._VALID_PLATFORMS         runtime.platform
    tr_pol._VALID_ENFORCEMENT       policy.enforcement_mode
    test_level0.VALID_PLATFORMS     runtime.platform
    test_level0.VALID_ENFORCEMENT   policy.enforcement_mode
    test_level0.VALID_APPRAISAL     appraisal.status

tests/test_enum_parity.py asserts each against schemas/trace-claim.json on
every run, by equality rather than containment: a superset means the copy
accepts a value the schema does not define, which is the same drift pointing
the other way. Load-bearing, checked rather than assumed - removing
software-only again fails exactly that parametrized case.

measurement/scripts/enum_drift.py already reported this and exits 1. It walks
the AST, which is what finds a copy nobody has listed yet; this file is the
other half, so a known copy fails in the suite rather than waiting for someone
to run the script.

167 pass. ruff reports the same 68 pre-existing errors either side of this
change and none in the new file.

Signed-off-by: lywinged <48041247+lywinged@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Contributor Check: UNKNOWN

Check Result
Profile UNKNOWN
Credential LOW
Overall UNKNOWN

Automated check by AgenTrust Contributor Check.

@github-actions github-actions Bot added the needs-review:UNKNOWN Contributor check flagged UNKNOWN risk label Aug 12, 2026

@imran-siddique imran-siddique left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parity test derives enum values from the packaged schema and checks each known hand-written copy, while the production enforcement set is now explicitly named and the level-0 platform copy gains the schema's software-only value.

@imran-siddique
imran-siddique merged commit 9929a39 into agentrust-io:main Aug 14, 2026
7 of 8 checks passed
@lywinged
lywinged deleted the fix/enum-drift-declared-and-software-only branch August 18, 2026 04:59
imran-siddique pushed a commit that referenced this pull request Aug 20, 2026
…ld whose absence hid it (#68)

* fix(schema): resync the packaged copy from the normative schema

The packaged schemas/trace-claim.json was a v0.1 body under a v0.2
label: 13 top-level properties, no delegation block, no
provenance_depth. Records signed against the normative schema were
rejected by the packaged one. Since this branch was first written the
gap widened - the normative source gained the delegation link block
and the provenance depth field (trace-spec #173) - so the resync now
carries those too. Packaged copy is byte-identical to
schema/trace-claim.json at trace-spec 1c5a9b9.

The hand-written enforcement enums gain 'declared' to match, which
keeps the #62 parity guard green on the moved schema rather than
green on the stale one. 183 passed, 5 xpassed (the TEE-hardware
smoke set, strict=False by design, unrelated).

Signed-off-by: lywinged <48041247+lywinged@users.noreply.github.com>

* test(schema): a vector that uses the field whose absence hid the drift

The resync in the previous commit fixes the packaged schema. This adds what
would have caught it, because the reason nothing caught it is still here
otherwise.

`schemas/trace-claim.json` sits at `$id` trace-v0.1.json and pins `eat_profile`
to the v0.2 sentinel, so it requires a record to declare v0.2 and then rejects
two properties v0.2 defines: `signature` and `delegation`. additionalProperties
is false, deliberately -- test_unknown_fields_rejected asserts it. Measured
against trace-spec's corpus before writing anything: a signed record fails with
"'signature' was unexpected" and a signed delegated hop with "'delegation',
'signature' were unexpected".

Where that does and does not reach, stated precisely because the first draft of
this message overstated it. The file is not shipped -- the wheel packages
src/trace_tests only -- and no code under src/ reads it; grep for jsonschema
there returns nothing, and TR-ENV checks fields by hand. Its one reader is
tests/conftest.py, which feeds tests/test_schema.py, the suite's own Level 0
"structural and schema validity" tests. README.md also links the directory as
"Test schemas", so a reader browsing the suite for a reference copy gets the
stale one.

So the cost is to what this suite can assert, not to any record anyone has
scored. A conformance suite whose schema tests run a version behind cannot accept
a signed record in them -- which is self-reinforcing, and is why no vector here
has a signature.

Nothing failed because not one of the six vectors carried a `signature` at all.
The schema forbade a field the corpus never used. That is the same shape as the
canonicalization defect in tr_sig: the corpus avoided the case the defect lived
in. Two in one repository is a pattern, and the answer to both is a vector that
uses the field.

The two vectors are copied from trace-spec's examples/delegation-link/, generated
from a published seed and reproducible by anyone. Nothing compares them to the
originals -- a guard that needs another repository checked out is a guard that
gets skipped. They are held instead to the property that makes them worth having:
they carry the fields whose absence hid the defect, so a vector edited into
something unsigned fails loudly rather than quietly.

Verified by reverting the schema: the two validation tests and the `$id` check
fail, and the self-validation test passes, which is the shape a regression test
should have. 180 passed.

Signed-off-by: lywinged <48041247+lywinged@users.noreply.github.com>

---------

Signed-off-by: lywinged <48041247+lywinged@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:UNKNOWN Contributor check flagged UNKNOWN risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: ten of thirty-three conformance failure paths are unguarded against regression

2 participants