fix(models): transparency is optional below Level 2 - #109
Merged
Conversation
The model required a non-empty transparency URI on every record. That was stricter than both of the repo's other normative artifacts: schema/trace-claim.json requires the field but sets no minLength, and the conformance suite runs TR-ANC at Level 2 only, where its own message reads "transparency field is required at Level 2". A Level 0 or Level 1 record is not anchored, so it has no receipt to name, and the model left that unrepresentable. AGT hit it: its documented Phase 1 design emits an unanchored record and could not construct one. None now means unanchored. Empty string stays rejected, deliberately: "" is not a URI, and a field that looks populated but resolves to nothing is worse in a trust record than an absent one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Merged
imran-siddique
added a commit
to microsoft/agent-governance-toolkit
that referenced
this pull request
Jul 28, 2026
Both emitters hardcoded transparency="". agentrust-trace 0.5.0 rejects it, so every TRACE record raised ValidationError and the agent-mesh and docker-compose suites failed. ADR-0032 chose the empty string for Phase 1 because SCITT anchoring is out of scope there. None is the honest form of that same choice: a Level 0 or Level 1 record has no receipt URI to name, and an empty string looks populated while resolving to nothing. Conformance requires transparency at Level 2 only, where TR-ANC runs, so a Phase 1 record stays conformant at the level it claims. The library was also stricter than the spec's own schema and conformance suite; that is fixed in agentrust-trace 0.5.1 (agentrust-io/trace-spec#109), which this branch's pin already admits. Two emitters, not one: trace_model.py and trace_sink.py both built the field, and only running the tests surfaced the second. Also moves the two verifier.agentrust.io test fixtures to agentrust-io.com, which is the same wrong-domain correction as the profile URI in this branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
This was referenced Jul 28, 2026
MohammadHaroonAbuomar
pushed a commit
to microsoft/agent-governance-toolkit
that referenced
this pull request
Jul 30, 2026
* fix(trace): emit the TRACE v0.2 profile URI AGT emitted tag:agentrust.io,2026:trace-v0.1. RFC 4151 permits a tag URI only where the minting authority controlled the named domain on the date in the URI, and agentrust.io was never controlled by the TRACE project; it resolves to third-party parked addresses. The identifier asserted authority over a name belonging to someone else. TRACE v0.2 corrects it to tag:agentrust-io.com,2026:trace-v0.2 and changes nothing else about the record format, so this is one constant plus its tests. ADR-0032 gets an amendment rather than an edit, per the ADR immutability convention: the original Decision text and the v01 file name stay. Records AGT has already emitted remain verifiable as v0.1 records against agentrust-trace-tests 0.3.x, which stays published. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(deps): bump agentrust-trace to the v0.2-profile release The emitter change alone failed CI: ValidationError: 1 validation error for TrustRecord eat_profile Both packages pinned agentrust-trace>=0.2.0,<0.3.0, whose TrustRecord Literal still requires the v0.1 profile, so emitting v0.2 could not validate. Pins move to >=0.5.0,<0.6.0. Also records the pin change in the amendment rather than editing the References section, which cites v0.2.0 because that is what the ADR was accepted against. That section is a historical record, not a statement of the current pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(trace): emit transparency as None when unanchored Both emitters hardcoded transparency="". agentrust-trace 0.5.0 rejects it, so every TRACE record raised ValidationError and the agent-mesh and docker-compose suites failed. ADR-0032 chose the empty string for Phase 1 because SCITT anchoring is out of scope there. None is the honest form of that same choice: a Level 0 or Level 1 record has no receipt URI to name, and an empty string looks populated while resolving to nothing. Conformance requires transparency at Level 2 only, where TR-ANC runs, so a Phase 1 record stays conformant at the level it claims. The library was also stricter than the spec's own schema and conformance suite; that is fixed in agentrust-trace 0.5.1 (agentrust-io/trace-spec#109), which this branch's pin already admits. Two emitters, not one: trace_model.py and trace_sink.py both built the field, and only running the tests surfaced the second. Also moves the two verifier.agentrust.io test fixtures to agentrust-io.com, which is the same wrong-domain correction as the profile URI in this branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * docs(adr): disclose the canonicalization break in the library jump Review feedback from @MohammadHaroonAbuomar, and he is right. The amendment said the jump "changes nothing else about the record format ... one constant and its tests". That is true of the specification change and false of the library jump. AGT moves agentrust-trace 0.2.0 to 0.5.x, which crosses 0.3.0, whose changelog reads: BREAKING: Canonicalization is now RFC 8785 (JCS). Trust records are NOT cross-verifiable with 0.2.0. So records AGT signs after this bump cannot be verified by a 0.2.0-era verifier: the signature covers a different byte sequence. Disclosed, along with a second consequence he did not mention, that 0.3.0 also stopped self-verifying from the embedded cnf.jwk by default, so anything verifying AGT records by trusting the key inside them needs updating. 0.4.0 is additive only and imposes nothing. Also makes the version references precise. agentrust-trace 0.4.x (the library) and agentrust-trace-tests 0.3.x (the conformance suite) are different packages on different version lines, and citing one of each read as an inconsistency. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * refactor(trace): hoist the profile URI; correct stale install guidance Review feedback from @MohammadHaroonAbuomar and Copilot, all of it fair. The EAT profile URI was duplicated between trace_model.py and trace_sink.py, and this PR had to edit six literals to move it, which is the drift cost demonstrated rather than argued. It is now TRACE_EAT_PROFILE in trace_model.py, imported by trace_sink.py. The tests keep asserting the literal string on purpose: a test comparing against the constant would pass even if the constant were changed wrongly, and this is a wire-format value. The ImportError guidance still told users to install agentrust-trace>=0.2.0, which after the pin bump points at a version that cannot satisfy the dependency and produces a confusing second failure. It now names the real range. Two ADR points: The amendment heading used a double-spaced separator. I had believed that was house style, but it is the convention in agent-manifest, not here; in this repo it was the only heading of its kind, so Copilot was right and it is normalized. The References entry citing agentrust-trace v0.2.0 stays, because that is what this ADR was accepted against and rewriting it would claim otherwise. Annotated instead, so a reader is not sent to an uninstallable version, and pointed at the amendment for what changed in between. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(deps): raise the agentrust-trace floor to 0.5.1 @MohammadHaroonAbuomar caught a floor that admits a broken version. Both pyprojects pinned >=0.5.0,<0.6.0 while the ADR states transparency=None needs 0.5.1 or later. 0.5.0 still required a non-empty transparency, so any resolve landing on it rejects the None this PR emits and reproduces the exact ValidationError the PR exists to fix. CI passed only because it happened to install the latest. Verified rather than assumed: installed 0.5.0 in a clean venv and model_validate rejects transparency=None; 0.5.1 accepts it. Floors raised in agent-mesh and agent-governance-toolkit-core, and in the runtime install hint at trace_sink.py:189, which quoted the same too-low range. The ADR's two statements of the pin move with them and now say why the floor is 0.5.1, so the next person does not relax it back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> --------- Signed-off-by: Imran Siddique <imran.siddique@opaque.co> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
SemTiOne
pushed a commit
to SemTiOne/agent-governance-toolkit
that referenced
this pull request
Jul 30, 2026
* fix(trace): emit the TRACE v0.2 profile URI AGT emitted tag:agentrust.io,2026:trace-v0.1. RFC 4151 permits a tag URI only where the minting authority controlled the named domain on the date in the URI, and agentrust.io was never controlled by the TRACE project; it resolves to third-party parked addresses. The identifier asserted authority over a name belonging to someone else. TRACE v0.2 corrects it to tag:agentrust-io.com,2026:trace-v0.2 and changes nothing else about the record format, so this is one constant plus its tests. ADR-0032 gets an amendment rather than an edit, per the ADR immutability convention: the original Decision text and the v01 file name stay. Records AGT has already emitted remain verifiable as v0.1 records against agentrust-trace-tests 0.3.x, which stays published. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(deps): bump agentrust-trace to the v0.2-profile release The emitter change alone failed CI: ValidationError: 1 validation error for TrustRecord eat_profile Both packages pinned agentrust-trace>=0.2.0,<0.3.0, whose TrustRecord Literal still requires the v0.1 profile, so emitting v0.2 could not validate. Pins move to >=0.5.0,<0.6.0. Also records the pin change in the amendment rather than editing the References section, which cites v0.2.0 because that is what the ADR was accepted against. That section is a historical record, not a statement of the current pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(trace): emit transparency as None when unanchored Both emitters hardcoded transparency="". agentrust-trace 0.5.0 rejects it, so every TRACE record raised ValidationError and the agent-mesh and docker-compose suites failed. ADR-0032 chose the empty string for Phase 1 because SCITT anchoring is out of scope there. None is the honest form of that same choice: a Level 0 or Level 1 record has no receipt URI to name, and an empty string looks populated while resolving to nothing. Conformance requires transparency at Level 2 only, where TR-ANC runs, so a Phase 1 record stays conformant at the level it claims. The library was also stricter than the spec's own schema and conformance suite; that is fixed in agentrust-trace 0.5.1 (agentrust-io/trace-spec#109), which this branch's pin already admits. Two emitters, not one: trace_model.py and trace_sink.py both built the field, and only running the tests surfaced the second. Also moves the two verifier.agentrust.io test fixtures to agentrust-io.com, which is the same wrong-domain correction as the profile URI in this branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * docs(adr): disclose the canonicalization break in the library jump Review feedback from @MohammadHaroonAbuomar, and he is right. The amendment said the jump "changes nothing else about the record format ... one constant and its tests". That is true of the specification change and false of the library jump. AGT moves agentrust-trace 0.2.0 to 0.5.x, which crosses 0.3.0, whose changelog reads: BREAKING: Canonicalization is now RFC 8785 (JCS). Trust records are NOT cross-verifiable with 0.2.0. So records AGT signs after this bump cannot be verified by a 0.2.0-era verifier: the signature covers a different byte sequence. Disclosed, along with a second consequence he did not mention, that 0.3.0 also stopped self-verifying from the embedded cnf.jwk by default, so anything verifying AGT records by trusting the key inside them needs updating. 0.4.0 is additive only and imposes nothing. Also makes the version references precise. agentrust-trace 0.4.x (the library) and agentrust-trace-tests 0.3.x (the conformance suite) are different packages on different version lines, and citing one of each read as an inconsistency. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * refactor(trace): hoist the profile URI; correct stale install guidance Review feedback from @MohammadHaroonAbuomar and Copilot, all of it fair. The EAT profile URI was duplicated between trace_model.py and trace_sink.py, and this PR had to edit six literals to move it, which is the drift cost demonstrated rather than argued. It is now TRACE_EAT_PROFILE in trace_model.py, imported by trace_sink.py. The tests keep asserting the literal string on purpose: a test comparing against the constant would pass even if the constant were changed wrongly, and this is a wire-format value. The ImportError guidance still told users to install agentrust-trace>=0.2.0, which after the pin bump points at a version that cannot satisfy the dependency and produces a confusing second failure. It now names the real range. Two ADR points: The amendment heading used a double-spaced separator. I had believed that was house style, but it is the convention in agent-manifest, not here; in this repo it was the only heading of its kind, so Copilot was right and it is normalized. The References entry citing agentrust-trace v0.2.0 stays, because that is what this ADR was accepted against and rewriting it would claim otherwise. Annotated instead, so a reader is not sent to an uninstallable version, and pointed at the amendment for what changed in between. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> * fix(deps): raise the agentrust-trace floor to 0.5.1 @MohammadHaroonAbuomar caught a floor that admits a broken version. Both pyprojects pinned >=0.5.0,<0.6.0 while the ADR states transparency=None needs 0.5.1 or later. 0.5.0 still required a non-empty transparency, so any resolve landing on it rejects the None this PR emits and reproduces the exact ValidationError the PR exists to fix. CI passed only because it happened to install the latest. Verified rather than assumed: installed 0.5.0 in a clean venv and model_validate rejects transparency=None; 0.5.1 accepts it. Floors raised in agent-mesh and agent-governance-toolkit-core, and in the runtime install hint at trace_sink.py:189, which quoted the same too-low range. The ADR's two statements of the pin move with them and now say why the floor is 0.5.1, so the next person does not relax it back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Imran Siddique <imran.siddique@opaque.co> --------- Signed-off-by: Imran Siddique <imran.siddique@opaque.co> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: SemTiOne <emphyst80@gmail.com>
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.
Found while fixing microsoft/agent-governance-toolkit#3454, which could not construct a Trust Record at all.
Three artifacts disagreed, and the model was the outlier
transparencyschema/trace-claim.jsonminLength, so""passesagentrust-trace-testsrunnerTR-ANCruns at Level 2 only; its message reads "transparency field is required at Level 2"models.pymin_length=1unconditionallyA Level 0 or Level 1 record is not anchored to a transparency log, so it has no receipt URI to name, and the model left that state unrepresentable. AGT hit it directly: its documented Phase 1 design emits an unanchored record, and after moving to 0.5.0 every emit raised
ValidationError: transparency String should have at least 1 character.The change
transparency: Annotated[str, Field(min_length=1)] | None = NoneNonemeans unanchored. Empty string stays rejected, deliberately:""is not a URI, and a field that looks populated but resolves to nothing is worse in a trust record than an absent one. That distinction is what the second test pins.The layering this restores is the one the suite already assumes: the model expresses structure, the conformance suite enforces level requirements.
signatureis already optional in the model for the same reason, with the spec requiring the binding.Verification
91 pass. Confirmed against a real record that
Noneand an omitted field both validate while""raises, then confirmed AGT's own emitters produce a valid record against this build (156 governance tests, including the four that were failing).Needs a 0.5.1 release: AGT pins
>=0.5.0,<0.6.0and cannot go green until this is on PyPI.