Skip to content

feat(schema): add top-level manifest reference to v0.3 draft schema (#483) - #538

Open
drk-ram wants to merge 1 commit into
agentrust-io:mainfrom
drk-ram:drk-ram-feat-v03-draft-schema-manifest-ref-483
Open

drk-ram wants to merge 1 commit into
agentrust-io:mainfrom
drk-ram:drk-ram-feat-v03-draft-schema-manifest-ref-483

Conversation

@drk-ram

@drk-ram drk-ram commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

Refs #483
Contributor: Raghuvar Durga (@drk-ram)

Adds the optional top-level manifest object ({id, digest, media_type}) to schema/trace-claim-v0.3-draft.json per the reference-only ruling on #483 and updates scripts/gen_v03_draft_schema.py to preserve properties.manifest alongside properties.eat_profile and properties.runtime.properties.evidence:

  • schema/trace-claim-v0.3-draft.json:
    • Adds optional top-level manifest object with "required": ["id", "digest", "media_type"] and "additionalProperties": false:
      • id: {"type": "string", "minLength": 1}
      • digest: {"type": "string", "pattern": "^sha(256:[0-9a-f]{64}|384:[0-9a-f]{96})$"}, matching the digest pattern across schema/trace-claim.json and serving as the target of runtime.evidence.binds: "manifest-digest"
      • media_type: {"type": "string", "minLength": 1}
    • Leaves top-level manifest_verification_result out of the schema per v0.3: let a record name the agent manifest it ran under #483 and agentrust-io/agent-manifest#498 (reference-only: a producer-asserted verification result is not carried in the record).
  • scripts/gen_v03_draft_schema.py:
    • Extracts _copy_member() so build(canonical, draft) preserves both properties.runtime.properties.evidence and properties.manifest at their declared positions in schema/trace-claim-v0.3-draft.json.
  • tests/test_v03_draft_schema.py:
    • Updates test_draft_differs_from_canonical_only_in_its_declared_members to strip properties.manifest.
    • Verifies that fixtures 01, 02, 04, 05, and 06 from conformance/tests/vectors/manifest-ref-v0.3-draft/ (conformance: v0.3 draft fixtures for the manifest reference (#483) #487) validate against schema/trace-claim-v0.3-draft.json under the v0.3 profile while schema/trace-claim.json continues to reject manifest on v0.2 records.
    • Verifies that fixture 03-mismatch-with-asserted-result.json is rejected by schema/trace-claim-v0.3-draft.json on manifest_verification_result and validates once manifest_verification_result is removed.
    • Verifies every schema constraint inside manifest (type: "object", required id/digest/media_type, type: "string", minLength: 1, sha256/sha384 lowercase hex digest patterns, and additionalProperties: false).

Cold-reader review:
A separate code-review agent inspected the initial diff against #483, conformance/tests/vectors/manifest-ref-v0.3-draft/, and CONTRIBUTING.md and found four items that we updated before opening this PR:

  1. test_draft_rejects_malformed_manifest initially omitted non-string test cases for id, digest, and media_type; because JSON Schema minLength and pattern ignore non-strings, removing "type": "string" from any of those three properties would not have failed the test. Added non-string-id, non-string-digest, and non-string-media-type cases.
  2. test_draft_rejects_malformed_manifest tested sha384: positively (test_draft_accepts_sha384_manifest_digest) but only tested negative digest patterns on sha256: and sha512:. Added sha384-uppercase and sha384-wrong-length cases so weakening the 384:[0-9a-f]{96} alternation branch fails the test.
  3. In test_draft_accepts_manifest_reference_fixtures and test_draft_rejects_malformed_manifest, tightened assertions to verify that 06-control-no-manifest.json passes canonical (schema/trace-claim.json), that canonical errors on 01/02/04/05 specifically name manifest, and that draft errors on malformed manifest inputs occur at absolute_path[:1] == ["manifest"], with explicit pytest.param(..., id=...) names.
  4. Aligned manifest.properties.digest.description with manifest.description and manifest.properties.id.description ("the manifest bytes this execution ran under").

Type of change

  • Editorial (typo, link fix, clarification: no normative effect)
  • Non-breaking spec change (new optional field, new platform profile, informative addition)
  • Breaking spec change (requires 14-day comment period and Project Lead sign-off)
  • Schema change
  • Example addition

Spec section

None in spec/trace-v0.2.md. Targets schema/trace-claim-v0.3-draft.json for #483 alongside the #487 draft fixtures in conformance/tests/vectors/manifest-ref-v0.3-draft/.

Tests for a fix

Each constraint in schema/trace-claim-v0.3-draft.json under properties.manifest (and the top-level refusal of manifest_verification_result) has a corresponding test in tests/test_v03_draft_schema.py that fails when switched off:

  • Accepting valid manifest {id, digest, media_type} on v0.3 records (fails if properties.manifest is removed):
    • tests/test_v03_draft_schema.py::test_draft_accepts_manifest_reference_fixtures[01-digest-matches.json]
    • tests/test_v03_draft_schema.py::test_draft_accepts_manifest_reference_fixtures[02-digest-mismatch.json]
    • tests/test_v03_draft_schema.py::test_draft_accepts_manifest_reference_fixtures[04-unresolvable.json]
    • tests/test_v03_draft_schema.py::test_draft_accepts_manifest_reference_fixtures[05-added-after-signing.json]
    • tests/test_v03_draft_schema.py::test_draft_accepts_sha384_manifest_digest
  • Rejecting top-level manifest_verification_result on v0.3 records:
    • tests/test_v03_draft_schema.py::test_draft_rejects_asserted_manifest_verification_result
  • Rejecting malformed manifest values (each fails if the corresponding constraint in properties.manifest is switched off):
    • manifest.type: "object": tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[non-object]
    • manifest.required (id): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[missing-id]
    • manifest.required (digest): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[missing-digest]
    • manifest.required (media_type): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[missing-media-type]
    • manifest.properties.id.type: "string": tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[non-string-id]
    • manifest.properties.digest.type: "string": tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[non-string-digest]
    • manifest.properties.media_type.type: "string": tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[non-string-media-type]
    • manifest.properties.id.minLength: 1: tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[empty-id]
    • manifest.properties.media_type.minLength: 1: tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[empty-media-type]
    • manifest.properties.digest.pattern (sha256 lowercase hex and 64-char length): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[sha256-uppercase], tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[sha256-wrong-length]
    • manifest.properties.digest.pattern (sha384 lowercase hex and 96-char length): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[sha384-uppercase], tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[sha384-wrong-length]
    • manifest.properties.digest.pattern (supported algorithm prefix): tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[unsupported-digest-algorithm]
    • manifest.additionalProperties: false: tests/test_v03_draft_schema.py::test_draft_rejects_malformed_manifest[unexpected-property]

Validation commands run:

  • python scripts/gen_v03_draft_schema.py --check -> passed (exit 0)
  • pytest tests/test_v03_draft_schema.py tests/test_runtime_evidence_vectors.py tests/test_safe_integer_range.py -v -> passed (182 passed)
  • pytest conformance/tests -q --no-cov -> passed (778 passed, 5 xpassed)
  • ruff check src tests scripts -> passed (All checks passed!)
  • python tools/check_dashes.py -> passed (no dashes outside examples/, spec/trace-v0.1.md)
  • mypy src/agentrust_trace -> passed (Success: no issues found in 15 source files)

Checklist

  • DCO sign-off on all commits (git commit -s)
  • CHANGELOG.md updated (for any normative change)
  • Breaking changes marked with <!-- CHANGED: #NNN: description --> in spec text
  • Backward compatibility statement included (for breaking changes)

Refs: #483

…gentrust-io#483)

Add the optional top-level manifest {id, digest, media_type} object to schema/trace-claim-v0.3-draft.json per the reference-only ruling on agentrust-io#483, preserve properties.manifest in scripts/gen_v03_draft_schema.py, and validate the agentrust-io#487 fixtures and malformed manifest shapes in tests/test_v03_draft_schema.py.

Signed-off-by: Raghuvar Durga <177662415+drk-ram@users.noreply.github.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@drk-ram
drk-ram requested review from a team, lywinged and rajnisht7 as code owners October 15, 2026 22:11

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

Approving 75b5fbb. gen_v03_draft_schema.py --check passes and test_v03_draft_schema.py runs 27 of 27. I broke seven constraints in the manifest block one at a time (type on id, minLength on media_type, the digest pattern twice, additionalProperties, required, the whole member) and a targeted test failed for each. The shape matches the reference-only ruling on #483 and agent-manifest §6.3.2 as merged in 3c02529.

Two follow-ups, not blocking. §6.3.2 names the digest as sha256 only, and ManifestRef in trace-token-experimental-v1.json still requires version; #483 asked for one shape. Please change "Fixes: #483" to "Refs": no conformance module reads the reference yet.

},
"digest": {
"type": "string",
"pattern": "^sha(256:[0-9a-f]{64}|384:[0-9a-f]{96})$",

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.

sha384 is accepted here, while agent-manifest §6.3.2 says sha256:<64-hex-chars>. Fine for TRACE, but a sha384 reference will not satisfy a §6.3.2 verifier. Worth a sentence in the description.

This branch has not been deployed

No deployments
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.

2 participants