fix(schema): resync the packaged copy, and a vector that uses the field whose absence hid it - #68
Merged
imran-siddique merged 2 commits intoAug 20, 2026
Conversation
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 agentrust-io#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>
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>
Contributor
|
❔ Contributor Check: UNKNOWN
Automated check by AgenTrust Contributor Check. |
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.
What is wrong
schemas/trace-claim.jsonsits at$idhttps://agentrust-io.com/schema/trace-v0.1.jsonand pinseat_profileto the v0.2 sentinel. So it requires a record to declare v0.2, and then rejects two properties v0.2 defines:signatureanddelegation.additionalPropertiesisfalse— deliberately;test_unknown_fields_rejectedasserts it. Measured againsttrace-spec's corpus:mainAdditional properties are not allowed ('signature' was unexpected)('delegation', 'signature' were unexpected)Where this does and does not reach
Stated precisely, because it is easy to overstate and I did in a first draft.
[tool.hatch.build.targets.wheel] packages = ["src/trace_tests"]. The directory is not in the distribution, so no installed consumer sees it.grep jsonschema src/trace_tests/returns nothing;TR-ENVchecks fields by hand. No record anyone has scored was validated against this file.tests/conftest.py:23, which feedstests/test_schema.py— the tests carrying thelevel0marker, defined inpyproject.tomlas "Level 0 conformance — structural and schema validity".🗂 Test schemas | 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 it 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 one.
Why 176 tests never noticed
Not one vector carries a
signature. The schema forbade a field the corpus never used.The fix, and the half that is not the fix
The first commit resyncs the packaged copy from the normative schema. Verified: parsed as JSON it is now equal to
trace-spec'sschema/trace-claim.json, and both records above validate.The second commit adds what would have caught it. Two signed vectors — one root, one delegated hop — copied from
trace-spec'sexamples/delegation-link/, which is 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, asserted directly, so a vector edited into something unsigned fails loudly rather than quietly.
A fourth test checks
$idnames the version the records it validates declare. The inconsistency was visible in one line the whole time.Verified by reverting
A regression test that passes before and after the fix is not one. With the schema reverted to
main's copy:The one that still passes is the vector self-validation, which correctly does not depend on the fix.
The shape, which is the part worth arguing about
This is the second defect in this repository found the same way this month, and both have the same structure: the corpus avoided the case the defect lived in, so the suite stayed green while the thing it scores was wrong.
The other is
#66—TR-SIGcanonicalized withjson.dumps(sort_keys=True, ...), and every vector was ASCII, on which that form and RFC 8785 agree byte-for-byte. Here the schema forbadesignature, and no vector had one.Recorded as an observation rather than a dependency: the two branches touch no file in common and neither needs the other. But two instances is a pattern, and the answer to both was the same — a vector that uses the field.
Checks
The 5 xpassed are pre-existing and unchanged by this branch.
ruffis clean on the files touched here; this repository's CI runs no lint step.Require maintainer approvalwill fail on this as it does on every PR from outside the allowlist. Nothing to do with the change.Generated by Claude Code