agentrust-trace 0.1.1__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentrust_trace-0.2.0/.github/workflows/docs.yml +43 -0
- agentrust_trace-0.2.0/ANTITRUST.md +26 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/CHANGELOG.md +19 -0
- agentrust_trace-0.2.0/LIMITATIONS.md +55 -0
- agentrust_trace-0.2.0/NOTICE +21 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/PKG-INFO +27 -5
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/README.md +24 -4
- agentrust_trace-0.2.0/docs/crosswalks/owasp-agentic-top-10.md +65 -0
- agentrust_trace-0.2.0/docs/stylesheets/extra.css +24 -0
- agentrust_trace-0.2.0/mkdocs.yml +125 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/pyproject.toml +2 -1
- agentrust_trace-0.2.0/requirements-docs.txt +6 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/schema/trace-claim.json +6 -5
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/spec/trace-v0.1.md +4 -4
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/src/agentrust_trace/__init__.py +14 -2
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/src/agentrust_trace/models.py +2 -2
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/src/agentrust_trace/schema/trace-v0.1.json +2 -1
- agentrust_trace-0.2.0/src/agentrust_trace/sign.py +80 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/tests/test_models.py +22 -1
- agentrust_trace-0.2.0/tests/test_sign.py +121 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/ISSUE_TEMPLATE/spec_change.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/ci.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/contributor-check.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/publish.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/require-maintainer-approval.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/sbom.yml +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/ADOPTERS.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/CHARTER.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/CODE_OF_CONDUCT.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/CONTRIBUTING.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/GOVERNANCE.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/LICENSE +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/MAINTAINERS.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/ROADMAP.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/SECURITY.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/docs/assets/icon.svg +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/examples/README.md +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/examples/amd-sev-snp.json +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/examples/intel-tdx.json +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/examples/nvidia-h100.json +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/src/agentrust_trace/py.typed +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/src/agentrust_trace/validate.py +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/tests/__init__.py +0 -0
- {agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/tests/test_validate.py +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "spec/**"
|
|
9
|
+
- "mkdocs.yml"
|
|
10
|
+
- "requirements-docs.txt"
|
|
11
|
+
- "README.md"
|
|
12
|
+
- "CHANGELOG.md"
|
|
13
|
+
- "CONTRIBUTING.md"
|
|
14
|
+
- "GOVERNANCE.md"
|
|
15
|
+
- "ROADMAP.md"
|
|
16
|
+
- "LIMITATIONS.md"
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
deploy:
|
|
24
|
+
name: Build and deploy docs
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
- uses: actions/setup-python@v6
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.11"
|
|
35
|
+
cache: pip
|
|
36
|
+
|
|
37
|
+
- name: Install docs dependencies
|
|
38
|
+
run: |
|
|
39
|
+
pip install -r requirements-docs.txt
|
|
40
|
+
pip install -e ".[dev]"
|
|
41
|
+
|
|
42
|
+
- name: Build and deploy to GitHub Pages
|
|
43
|
+
run: mkdocs gh-deploy --force --clean
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Antitrust Policy
|
|
2
|
+
|
|
3
|
+
TRACE is an open specification project hosted under the agentrust-io organization and targeting donation to the Agentic AI Foundation (AAIF) under the Linux Foundation. Participation in this project is subject to antitrust and competition laws.
|
|
4
|
+
|
|
5
|
+
## Prohibited topics
|
|
6
|
+
|
|
7
|
+
The following topics must not be discussed in any project forum, issue, PR, mailing list, meeting, or chat channel:
|
|
8
|
+
|
|
9
|
+
- Prices, pricing strategies, or cost structures of any product or service
|
|
10
|
+
- Market allocation, geographic territories, or customer segmentation
|
|
11
|
+
- Bids, contracts, or terms with any customer or competitor
|
|
12
|
+
- Whether to deal with, or boycott, any company or individual
|
|
13
|
+
- Production volumes, capacity plans, or sales forecasts
|
|
14
|
+
- Any other competitively sensitive business information
|
|
15
|
+
|
|
16
|
+
## What is appropriate
|
|
17
|
+
|
|
18
|
+
Project discussions must be limited to technical matters: specification design, cryptographic protocols, SDK implementation, conformance test coverage, and interoperability. Commercial decisions are for each organization to make independently.
|
|
19
|
+
|
|
20
|
+
## Reporting
|
|
21
|
+
|
|
22
|
+
If you observe discussion that appears to violate this policy, stop the discussion immediately and report it to the Project Lead via private GitHub message or email. Do not continue the discussion or document it further in project channels.
|
|
23
|
+
|
|
24
|
+
## Questions
|
|
25
|
+
|
|
26
|
+
If you are uncertain whether a topic is appropriate for project discussion, consult your organization's legal counsel before participating.
|
|
@@ -39,6 +39,25 @@ Seven open questions requiring founding-member input before v0.2 are documented
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.2.0] — TBD
|
|
43
|
+
|
|
44
|
+
### Specification
|
|
45
|
+
|
|
46
|
+
- Extend `subject` field to accept DID URIs (any `did:` method) in addition to SPIFFE SVIDs.
|
|
47
|
+
Previously `^spiffe://` only; now `^(spiffe://|did:)`. Additive, backward-compatible.
|
|
48
|
+
DID-native runtimes (e.g. AGT `did:mesh:` identities) no longer require a parallel SPIFFE identity.
|
|
49
|
+
Closes: microsoft/agent-governance-toolkit ADR-0032, agentrust-io/trace-spec#35.
|
|
50
|
+
|
|
51
|
+
### Schema
|
|
52
|
+
|
|
53
|
+
- `schema/trace-claim.json`: `subject` pattern updated to `^(spiffe://|did:)`, description updated.
|
|
54
|
+
|
|
55
|
+
### Reference Implementation
|
|
56
|
+
|
|
57
|
+
- `TrustRecord.subject` pattern updated to `r"^(spiffe://|did:)"`.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
42
61
|
## Upcoming
|
|
43
62
|
|
|
44
63
|
See [ROADMAP.md](ROADMAP.md) for planned changes in v0.2 and v1.0.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Known Limitations
|
|
2
|
+
|
|
3
|
+
This document describes what TRACE does not do, and where layered defenses are needed. Honest scope boundaries prevent misplaced trust.
|
|
4
|
+
|
|
5
|
+
## What a TRACE claim does not prevent
|
|
6
|
+
|
|
7
|
+
**Operator-forged software-only records**
|
|
8
|
+
A TRACE claim at Level 0 (software-only signing) is signed by a key held in software. A privileged operator with root access can produce a valid-looking Level 0 record for a run that never happened, or that violated policy. Level 0 is suitable for development and audit-trail tooling only — not for third-party verification.
|
|
9
|
+
|
|
10
|
+
**Replay of a valid past record**
|
|
11
|
+
A TRACE claim proves a specific run happened; it does not prevent a verifier from being shown a valid record from an earlier run. Verifiers that rely on recency must check the `iat` and `exp` claims, require nonce binding to a challenge, or anchor records to a public transparency log and check for freshness.
|
|
12
|
+
|
|
13
|
+
**Policy correctness**
|
|
14
|
+
The `policy.bundle_hash` field attests that a specific policy was in force at runtime. It does not attest that the policy achieves the intended security outcome. Policy review is a separate control.
|
|
15
|
+
|
|
16
|
+
**What happened inside the model**
|
|
17
|
+
The call transcript records tool invocations, arguments, and responses that are observable at the gateway boundary. It does not record the model's internal chain-of-thought, intermediate reasoning, or context window contents. Reasoning that influences behavior without producing a tool call is not captured.
|
|
18
|
+
|
|
19
|
+
**Cross-boundary data propagation**
|
|
20
|
+
The call graph summary uses temporal adjacency to approximate data flow between tool calls. It cannot definitively prove which specific data from one tool response influenced which subsequent call. The `provenance_disclaimer` field in every call graph summary is required for this reason.
|
|
21
|
+
|
|
22
|
+
**TEE side-channel attacks**
|
|
23
|
+
Hardware attestation proves the TRACE signing key and policy engine were measured in silicon before execution. It does not protect against side-channel attacks (cache timing, power analysis) targeting the TEE itself. TEE-level side-channel defense is the responsibility of the TEE platform vendor.
|
|
24
|
+
|
|
25
|
+
**Revocation of the signing key after issuance**
|
|
26
|
+
If the TRACE signing key is compromised after records are issued, existing records remain cryptographically valid. Key monitoring, rapid revocation, and transparency log integration are the required controls — TRACE provides the anchoring mechanism but cannot detect compromise itself.
|
|
27
|
+
|
|
28
|
+
## What Level 0 does not provide
|
|
29
|
+
|
|
30
|
+
Level 0 (software-only signing) is suitable for development, internal audit trails, and staging environments. It does not satisfy:
|
|
31
|
+
|
|
32
|
+
- EU AI Act Art. 12 (tamper-evident logging) — requires Level 1+
|
|
33
|
+
- DORA Art. 9 (ICT risk management) — requires Level 1+ with transparency log anchoring
|
|
34
|
+
- Any claim of hardware-rooted trust — the signing key is held in software and can be extracted by a privileged operator
|
|
35
|
+
|
|
36
|
+
## What the SDK does not do
|
|
37
|
+
|
|
38
|
+
- **Evaluate Cedar policy** — the SDK includes the Cedar policy field in the claim; evaluation requires the Cedar engine (included in AGT or cMCP)
|
|
39
|
+
- **Store or index records** — the SDK produces and verifies TRACE claim documents; storage, rotation, and retrieval are the caller's responsibility
|
|
40
|
+
- **Anchor to a transparency log** — the SDK generates records suitable for SCITT anchoring; submission to a transparency log requires a separate SCITT client
|
|
41
|
+
- **Replace a secrets manager** — signing private keys must be stored in a secrets manager (Azure Key Vault, AWS Secrets Manager, HSM); do not store them on disk without protection
|
|
42
|
+
- **Provide an authoritative verification service** — the self-hosted verifier confirms cryptographic validity against the issuer's key; authoritative third-party verification with SLA is a separate commercial service
|
|
43
|
+
|
|
44
|
+
## Performance
|
|
45
|
+
|
|
46
|
+
Hardware attestation adds latency at the point of claim generation (not per-tool-call):
|
|
47
|
+
|
|
48
|
+
| Provider | Typical claim signing latency |
|
|
49
|
+
|---|---|
|
|
50
|
+
| Software (Level 0) | < 1 ms |
|
|
51
|
+
| TPM | 50–200 ms |
|
|
52
|
+
| SEV-SNP | 10–50 ms |
|
|
53
|
+
| TDX | 10–50 ms |
|
|
54
|
+
|
|
55
|
+
Claim verification (signature check + schema validation) is < 5 ms in all cases.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
TRACE
|
|
2
|
+
Copyright 2026 AgentTrust Authors
|
|
3
|
+
|
|
4
|
+
This product includes software developed by the AgentTrust project
|
|
5
|
+
(https://github.com/agentrust-io/trace-spec).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Third-party components used by the Python SDK:
|
|
10
|
+
|
|
11
|
+
pydantic
|
|
12
|
+
License: MIT
|
|
13
|
+
https://github.com/pydantic/pydantic
|
|
14
|
+
|
|
15
|
+
jsonschema
|
|
16
|
+
License: MIT
|
|
17
|
+
https://github.com/python-jsonschema/jsonschema
|
|
18
|
+
|
|
19
|
+
jcs (dev dependency — RFC 8785 canonical JSON)
|
|
20
|
+
License: MIT
|
|
21
|
+
https://github.com/nicowillis/jcs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentrust-trace
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: TRACE v0.1 — hardware-attested governance records for AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentrust-io/trace-spec
|
|
6
6
|
Project-URL: Repository, https://github.com/agentrust-io/trace-spec
|
|
@@ -8,6 +8,7 @@ Project-URL: Issues, https://github.com/agentrust-io/trace-spec/issues
|
|
|
8
8
|
Project-URL: Changelog, https://github.com/agentrust-io/trace-spec/blob/main/CHANGELOG.md
|
|
9
9
|
License: Apache-2.0
|
|
10
10
|
License-File: LICENSE
|
|
11
|
+
License-File: NOTICE
|
|
11
12
|
Keywords: ai-governance,attestation,confidential-computing,eat,rats,tee,trace
|
|
12
13
|
Classifier: Development Status :: 3 - Alpha
|
|
13
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -19,6 +20,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
19
20
|
Classifier: Topic :: Security
|
|
20
21
|
Classifier: Typing :: Typed
|
|
21
22
|
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: cryptography>=42.0
|
|
22
24
|
Requires-Dist: jsonschema>=4.20
|
|
23
25
|
Requires-Dist: pydantic>=2.0
|
|
24
26
|
Provides-Extra: dev
|
|
@@ -37,7 +39,9 @@ Description-Content-Type: text/markdown
|
|
|
37
39
|
|
|
38
40
|
[](LICENSE)
|
|
39
41
|
[](https://agenticai.foundation)
|
|
40
|
-
[](spec/trace-v0.1.md)
|
|
43
|
+
[](https://pypi.org/project/agentrust-trace/)
|
|
44
|
+
[](https://discord.gg/9JWNpH7E)
|
|
41
45
|
|
|
42
46
|
> **Developer Preview.** Launching at Confidential Computing Summit, June 23 2026. May have breaking changes before v1.0.
|
|
43
47
|
|
|
@@ -57,7 +61,7 @@ An open specification for hardware-attested AI agent governance records. TRACE d
|
|
|
57
61
|
{
|
|
58
62
|
"eat_profile": "tag:agentrust.io,2026:trace-v0.1",
|
|
59
63
|
"iat": 1750676142,
|
|
60
|
-
"subject": "spiffe://trust.example.org/agent/payments-processor/prod",
|
|
64
|
+
"subject": "spiffe://trust.example.org/agent/payments-processor/prod", // or "did:mesh:spiffe://..."
|
|
61
65
|
"model": {
|
|
62
66
|
"provider": "anthropic",
|
|
63
67
|
"model_id": "claude-sonnet-4-6",
|
|
@@ -122,7 +126,7 @@ TRACE profiles existing standards rather than replacing them:
|
|
|
122
126
|
|---|---|
|
|
123
127
|
| RATS / EAT (RFC 9711) | Wire envelope and claim model |
|
|
124
128
|
| SLSA Provenance v1.0 | Build-time provenance (`build_provenance`) |
|
|
125
|
-
| SPIFFE SVID | Workload identity (`subject`) |
|
|
129
|
+
| SPIFFE SVID / DID URI | Workload identity (`subject`) |
|
|
126
130
|
| SCITT | Append-only transparency anchoring (`transparency`) |
|
|
127
131
|
| EAR (draft-ietf-rats-ar4si) | Verifier appraisal output (`appraisal`) |
|
|
128
132
|
| MCP / A2A | Agent tool-call transcript surface (`tool_transcript`) |
|
|
@@ -136,9 +140,27 @@ TRACE profiles existing standards rather than replacing them:
|
|
|
136
140
|
|
|
137
141
|
A public append-only Merkle registry of TRACE Trust Record anchors: [agentrust-io/trace-registry](https://github.com/agentrust-io/trace-registry).
|
|
138
142
|
|
|
143
|
+
## Install
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install agentrust-trace
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from agentrust_trace import TrustRecord, sign_record, load_signing_key
|
|
151
|
+
|
|
152
|
+
key = load_signing_key() # reads TRACE_PRIVATE_KEY_PEM or generates ephemeral
|
|
153
|
+
record = sign_record(payload, key)
|
|
154
|
+
TrustRecord.model_validate(record) # validate before writing
|
|
155
|
+
```
|
|
156
|
+
|
|
139
157
|
## Status
|
|
140
158
|
|
|
141
|
-
|
|
159
|
+
v0.2. `subject` now accepts DID URIs (`did:`) in addition to SPIFFE SVIDs. `slsa_level: 0` supported for software-only deployments. Published at Confidential Computing Summit, San Francisco, June 23 2026. Targeting submission to the [Agentic AI Foundation (AAIF)](https://agenticai.foundation) under the Linux Foundation.
|
|
160
|
+
|
|
161
|
+
## Community
|
|
162
|
+
|
|
163
|
+
Questions, feedback, integration help: [Discord](https://discord.gg/9JWNpH7E).
|
|
142
164
|
|
|
143
165
|
## License
|
|
144
166
|
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://agenticai.foundation)
|
|
9
|
-
[](spec/trace-v0.1.md)
|
|
10
|
+
[](https://pypi.org/project/agentrust-trace/)
|
|
11
|
+
[](https://discord.gg/9JWNpH7E)
|
|
10
12
|
|
|
11
13
|
> **Developer Preview.** Launching at Confidential Computing Summit, June 23 2026. May have breaking changes before v1.0.
|
|
12
14
|
|
|
@@ -26,7 +28,7 @@ An open specification for hardware-attested AI agent governance records. TRACE d
|
|
|
26
28
|
{
|
|
27
29
|
"eat_profile": "tag:agentrust.io,2026:trace-v0.1",
|
|
28
30
|
"iat": 1750676142,
|
|
29
|
-
"subject": "spiffe://trust.example.org/agent/payments-processor/prod",
|
|
31
|
+
"subject": "spiffe://trust.example.org/agent/payments-processor/prod", // or "did:mesh:spiffe://..."
|
|
30
32
|
"model": {
|
|
31
33
|
"provider": "anthropic",
|
|
32
34
|
"model_id": "claude-sonnet-4-6",
|
|
@@ -91,7 +93,7 @@ TRACE profiles existing standards rather than replacing them:
|
|
|
91
93
|
|---|---|
|
|
92
94
|
| RATS / EAT (RFC 9711) | Wire envelope and claim model |
|
|
93
95
|
| SLSA Provenance v1.0 | Build-time provenance (`build_provenance`) |
|
|
94
|
-
| SPIFFE SVID | Workload identity (`subject`) |
|
|
96
|
+
| SPIFFE SVID / DID URI | Workload identity (`subject`) |
|
|
95
97
|
| SCITT | Append-only transparency anchoring (`transparency`) |
|
|
96
98
|
| EAR (draft-ietf-rats-ar4si) | Verifier appraisal output (`appraisal`) |
|
|
97
99
|
| MCP / A2A | Agent tool-call transcript surface (`tool_transcript`) |
|
|
@@ -105,9 +107,27 @@ TRACE profiles existing standards rather than replacing them:
|
|
|
105
107
|
|
|
106
108
|
A public append-only Merkle registry of TRACE Trust Record anchors: [agentrust-io/trace-registry](https://github.com/agentrust-io/trace-registry).
|
|
107
109
|
|
|
110
|
+
## Install
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install agentrust-trace
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from agentrust_trace import TrustRecord, sign_record, load_signing_key
|
|
118
|
+
|
|
119
|
+
key = load_signing_key() # reads TRACE_PRIVATE_KEY_PEM or generates ephemeral
|
|
120
|
+
record = sign_record(payload, key)
|
|
121
|
+
TrustRecord.model_validate(record) # validate before writing
|
|
122
|
+
```
|
|
123
|
+
|
|
108
124
|
## Status
|
|
109
125
|
|
|
110
|
-
|
|
126
|
+
v0.2. `subject` now accepts DID URIs (`did:`) in addition to SPIFFE SVIDs. `slsa_level: 0` supported for software-only deployments. Published at Confidential Computing Summit, San Francisco, June 23 2026. Targeting submission to the [Agentic AI Foundation (AAIF)](https://agenticai.foundation) under the Linux Foundation.
|
|
127
|
+
|
|
128
|
+
## Community
|
|
129
|
+
|
|
130
|
+
Questions, feedback, integration help: [Discord](https://discord.gg/9JWNpH7E).
|
|
111
131
|
|
|
112
132
|
## License
|
|
113
133
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# OWASP Agentic AI Top 10 Evidence Cross-walk
|
|
2
|
+
|
|
3
|
+
> **Non-normative.** This document is informative only. Nothing here changes TRACE v0.1 schema fields, wire formats, required claims, or conformance requirements. References to "TRACE" mean the TRACE v0.1 Trust Record as defined in [`spec/trace-v0.1.md`](../../spec/trace-v0.1.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
OWASP's Agentic AI Top 10 (ASI01–ASI10) names the principal risk categories for autonomous AI agents. TRACE is an evidence and attestation layer: it does not prevent these risks, but it produces verifiable, hardware-rooted records that support audit, incident review, and governance verification after or during execution.
|
|
10
|
+
|
|
11
|
+
This page answers a concrete question for each OWASP risk: which TRACE Trust Record claims carry relevant evidence, what that evidence actually proves, and where TRACE v0.1 leaves a gap that a future profile would need to close.
|
|
12
|
+
|
|
13
|
+
Field names are exact TRACE v0.1 claim names as specified in §3.1 of the spec. Sub-field references such as `policy.bundle_hash`, `runtime.platform`, and `appraisal.status` refer to the nested fields shown in the §3.2 wire-format example.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Mapping table
|
|
18
|
+
|
|
19
|
+
| OWASP risk | Relevant TRACE claims | Evidence TRACE can provide | Limitations / out of scope | Future TRACE profile need |
|
|
20
|
+
|---|---|---|---|---|
|
|
21
|
+
| **ASI01: Agent Goal Hijack** | `policy`, `tool_transcript`, `data_class`, `runtime`, `transparency` | `policy.bundle_hash` shows which policy was bound at execution time; `policy.enforcement_mode` shows whether it ran in `enforce` or `silent`; `tool_transcript.hash` and `tool_transcript.call_count` show the scope of tool activity; `data_class` shows the sensitivity of data processed; `transparency` anchors the record to an append-only log for independent audit. | Does not capture the agent's internal goal representation or reasoning chain. Does not itself detect or block prompt injection. A hijacked goal that stays within recorded tool boundaries leaves no additional fingerprint in v0.1 claims. | MCP/A2A profile fields for intent binding, goal hash, prompt-to-plan linkage, and per-decision policy outcome records. |
|
|
22
|
+
| **ASI02: Tool Misuse and Exploitation** | `tool_transcript`, `policy`, `data_class`, `runtime`, `transparency` | `tool_transcript.hash` binds the transcript of tool invocations crossing a protocol boundary (MCP, A2A) into the signed record; `tool_transcript.call_count` bounds the observed call volume; `policy.bundle_hash` and `policy.enforcement_mode` show what rules were in force; `data_class` shows the sensitivity classification applied at the call layer; `runtime.platform` and `runtime.measurement` bind the execution environment. | `tool_transcript` covers calls crossing an instrumented protocol boundary. Functions embedded inside the deployed binary are bound only by `build_provenance` and `model`, not by per-invocation transcript records. Does not prove each call was semantically appropriate without per-call policy decision records. | MCP profile for per-call tool identity, parameters, egress data class, and allow/deny decision outcome per invocation. |
|
|
23
|
+
| **ASI03: Identity and Privilege Abuse** | `subject`, `cnf`, `signature`, `runtime`, `policy`, `appraisal` | `subject` carries the SPIFFE SVID binding workload identity to a TEE-held key; `cnf` binds the signing key to the TEE via the hardware measurement in `runtime`; `appraisal.status` records the verifier's judgment of the evidence against policy; `policy.bundle_hash` shows what authorization rules were bound. Together these allow a verifier to confirm that the claimed identity corresponded to a genuine, measured workload at record issuance time. | Does not replace IAM or RBAC systems. Does not prove that external permissions granted to the workload were correctly scoped. Does not cover lateral movement or privilege escalation that occurred at infrastructure layers outside the TEE boundary. | Delegation profile fields for scoped credentials, audience restriction, purpose binding, and per-action authorization evidence. |
|
|
24
|
+
| **ASI04: Agentic Supply Chain Vulnerabilities** | `build_provenance`, `model`, `runtime`, `transparency`, `appraisal` | `build_provenance.slsa_level`, `build_provenance.builder`, and `build_provenance.digest` bind build-time provenance to the running workload; `model.weights_digest` and `model.model_id` bind the model artifact; `runtime.measurement` and `runtime.rim_uri` bind the runtime image to vendor-published Reference Integrity Manifests; `transparency` provides an append-only anchor for the full record. | Does not enumerate every transitive dependency. Does not detect malicious code that was present at build time but is not reflected in measurement divergence. Does not prove model behavior is safe -- only that the identified artifact was the one that executed. | Richer AIBOM/SBOM linkage in the `model` sub-claim; vendor platform annexes specifying per-silicon supply-chain appraisal criteria. |
|
|
25
|
+
| **ASI05: Unexpected Code Execution** | `runtime`, `build_provenance`, `tool_transcript`, `policy`, `appraisal` | `runtime.measurement` shows what workload and container digest were loaded; `build_provenance.digest` and `build_provenance.slsa_level` bind the build artifact; `tool_transcript.hash` captures tool invocations at protocol boundaries; `appraisal.status` records whether the verifier accepted the runtime evidence against current RIMs. | Does not prevent code execution. Does not prove no code ran outside the recorded `tool_transcript` scope: inline code execution embedded in the workload binary is not captured at invocation granularity by v0.1 claims. | Tool and code-execution profile: sandbox identity, command execution transcript hash, filesystem and network boundary evidence per invocation. |
|
|
26
|
+
| **ASI06: Memory and Context Poisoning** | `model`, `data_class`, `tool_transcript`, `build_provenance`, `transparency` | `model.model_id` and `model.weights_digest` identify the model artifact; `data_class` records the sensitivity classification applied to inputs and outputs; `tool_transcript.hash` captures context-retrieval calls that crossed an instrumented boundary; `build_provenance.digest` binds the build artifact that includes any vector-store or RAG client code. | TRACE v0.1 does not bind memory snapshots, RAG corpus roots, embedding-store contents, or poisoning scan results. Context provenance -- where retrieved chunks originated and whether they were validated -- is not a v0.1 claim. | Memory and RAG profile: context source hashes, corpus Merkle roots, poisoning scan status, namespace and tenant boundary evidence. |
|
|
27
|
+
| **ASI07: Insecure Inter-Agent Communication** | `subject`, `cnf`, `signature`, `runtime`, `tool_transcript`, `transparency` | `subject` and `cnf` establish and bind workload identity for each participating agent; `signature` (or the enveloping-signature equivalent) proves record integrity; `runtime.measurement` binds the TEE that produced the record; `tool_transcript.hash` anchors the inter-agent call transcript; `transparency` anchors the record in an append-only log accessible to any verifier. | TRACE v0.1 does not define a normative A2A profile. Message-level semantic validation, nonce binding per message, and delegation chain records across multiple hops are not v0.1 claims. | A2A profile: peer agent identity, per-message hash, audience restriction, nonce, delegation chain, and protocol version binding. |
|
|
28
|
+
| **ASI08: Cascading Failures** | `tool_transcript`, `transparency`, `subject`, `appraisal`, `policy` | `tool_transcript.hash` and `tool_transcript.call_count` provide a bounded activity record for post-incident traceability; `subject` identifies the workload at each hop where a Trust Record was issued; `appraisal.status` and `appraisal.verifier` record the verification outcome; `policy.bundle_hash` shows what controls were bound; `transparency` provides an auditable anchor for reconstructing the sequence of records. | Does not itself detect cascade conditions, stop propagation, or reconstruct full multi-agent lineage unless every participating agent issued Trust Records and those records are correlated at analysis time. Lineage reconstruction requires out-of-band tooling. | Workflow provenance profile: parent/child record references, propagation lineage identifiers, blast-radius counters, and circuit-breaker event records. |
|
|
29
|
+
| **ASI09: Human-Agent Trust Exploitation** | `tool_transcript`, `policy`, `data_class`, `transparency`, `appraisal` | `tool_transcript.hash` records the set of actions the agent took at protocol boundaries; `policy.bundle_hash` and `policy.enforcement_mode` show what rules were in force; `data_class` records the sensitivity class of data involved; `appraisal.status` provides the verifier's assessment; `transparency` anchors the record for independent audit. Collectively these support a post-incident review of what the agent was authorized to do and what it did. | Does not prove what a human was shown in the UI, whether the explanation was accurate, or whether informed consent was obtained. Does not detect social engineering at the human layer. | HITL (human-in-the-loop) evidence profile: approval record, reviewer identity, hash of displayed risk summary, and human decision evidence bound into the Trust Record. |
|
|
30
|
+
| **ASI10: Rogue Agents** | `subject`, `runtime`, `cnf`, `signature`, `policy`, `tool_transcript`, `appraisal`, `transparency` | The full v0.1 claim set combines hardware-bound identity (`subject`, `cnf`), measured execution environment (`runtime`), policy binding (`policy.bundle_hash`, `policy.enforcement_mode`), tool activity (`tool_transcript`), verifier judgment (`appraisal.status`), and transparency anchoring (`transparency`) into one signed, independently verifiable record. A verifier can confirm that the agent presenting this record ran as a measured, policy-bound workload with a TEE-rooted identity at the stated time. | Does not determine behavioral intent. Does not detect rogue behavior that remained within the boundary of recorded claims. A workload can issue a valid Trust Record and still behave in ways the record does not constrain at inference time. | Behavioral integrity profile: declared capability manifest hash, expected tool set, execution baseline hash, and anomaly or quarantine event records. |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## What TRACE does not do
|
|
35
|
+
|
|
36
|
+
The table above surfaces per-risk scope boundaries. These apply across all ten risks:
|
|
37
|
+
|
|
38
|
+
**TRACE does not prevent OWASP Agentic AI risks.** TRACE is an evidence and attestation layer. It records what happened -- what executed, under what policy, in what environment, on what data class, invoking what tools -- and binds that record cryptographically to a hardware root of trust. Controls that act before, during, or around execution (firewalls, guardrails, RBAC, prompt filters, sandboxing) are out of scope.
|
|
39
|
+
|
|
40
|
+
**TRACE does not adjudicate model behavior.** As stated in §2.4 of the spec, prompt injection, jailbreaks, hallucination, and alignment drift are permanent scope boundaries. TRACE proves what model artifact executed and what countermeasures were bound; it does not evaluate whether the model's output was correct or intended.
|
|
41
|
+
|
|
42
|
+
**TRACE v0.1 does not cover intra-binary execution.** `tool_transcript` captures invocations crossing an instrumented protocol boundary (MCP, A2A, or equivalent). Code paths executed inside the deployed binary -- including embedded tool dispatch, in-process memory reads, or direct API calls -- are bound only by `build_provenance` and `model`, not at invocation granularity.
|
|
43
|
+
|
|
44
|
+
**TRACE does not replace IAM, RBAC, or network controls.** `subject` and `cnf` establish and bind workload identity, but the permissions granted to that identity by external systems are outside the Trust Record. A correctly identified workload can still hold excessive privileges.
|
|
45
|
+
|
|
46
|
+
**TRACE does not capture UI or human-layer interactions.** What a human sees, approves, or consents to is not a v0.1 claim. This affects ASI09 directly and is a gap for any risk that involves human oversight.
|
|
47
|
+
|
|
48
|
+
**TRACE does not reconstruct multi-agent lineage automatically.** Records from multiple agents can be correlated by a verifier using `subject`, `transparency`, and `tool_transcript` identifiers, but the v0.1 schema has no normative parent/child record pointer. Lineage reconstruction requires out-of-band analysis tooling and is addressed in the v0.2 workflow provenance profile item.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Relationship to the TRACE roadmap
|
|
53
|
+
|
|
54
|
+
This cross-walk is a v0.2 roadmap item listed in [`ROADMAP.md`](../../ROADMAP.md). The "Future TRACE profile need" column in the table above describes the additional claim structures that would close each gap; those profiles are separate roadmap items and will be specified in later releases.
|
|
55
|
+
|
|
56
|
+
The MITRE ATLAS cross-walk (a separate v0.2 item) will address tactics and techniques at a finer granularity than the OWASP risk categories here.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## References
|
|
61
|
+
|
|
62
|
+
- OWASP Agentic AI Top 10: <https://genai.owasp.org/>
|
|
63
|
+
- TRACE v0.1 specification: [`spec/trace-v0.1.md`](../../spec/trace-v0.1.md)
|
|
64
|
+
- TRACE roadmap: [`ROADMAP.md`](../../ROADMAP.md)
|
|
65
|
+
- MITRE ATLAS: <https://atlas.mitre.org/>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--md-primary-fg-color: #7c3aed;
|
|
3
|
+
--md-primary-fg-color--light: #a78bfa;
|
|
4
|
+
--md-primary-fg-color--dark: #5b21b6;
|
|
5
|
+
--md-accent-fg-color: #0ea5e9;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
[data-md-color-scheme="slate"] {
|
|
9
|
+
--md-primary-fg-color: #818cf8;
|
|
10
|
+
--md-primary-fg-color--light: #a5b4fc;
|
|
11
|
+
--md-primary-fg-color--dark: #6366f1;
|
|
12
|
+
--md-accent-fg-color: #38bdf8;
|
|
13
|
+
--md-default-bg-color: #0f0a1e;
|
|
14
|
+
--md-default-bg-color--light: #1a1033;
|
|
15
|
+
--md-code-bg-color: #1e1533;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.md-header {
|
|
19
|
+
background: linear-gradient(135deg, #0d0a1f 0%, #071828 100%);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.md-hero__inner {
|
|
23
|
+
padding-top: 2rem;
|
|
24
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
site_name: TRACE
|
|
2
|
+
site_description: Trust Runtime Attestation and Compliance Evidence — open attestation standard for agentic AI governance
|
|
3
|
+
site_url: https://agentrust-io.github.io/trace-spec
|
|
4
|
+
repo_url: https://github.com/agentrust-io/trace-spec
|
|
5
|
+
repo_name: agentrust-io/trace-spec
|
|
6
|
+
edit_uri: edit/main/
|
|
7
|
+
docs_dir: .
|
|
8
|
+
exclude_docs: |
|
|
9
|
+
.github/
|
|
10
|
+
node_modules/
|
|
11
|
+
src/
|
|
12
|
+
tests/
|
|
13
|
+
schema/
|
|
14
|
+
examples/
|
|
15
|
+
LICENSE
|
|
16
|
+
NOTICE
|
|
17
|
+
ANTITRUST.md
|
|
18
|
+
ADOPTERS.md
|
|
19
|
+
MAINTAINERS.md
|
|
20
|
+
SECURITY.md
|
|
21
|
+
CHARTER.md
|
|
22
|
+
CODE_OF_CONDUCT.md
|
|
23
|
+
pyproject.toml
|
|
24
|
+
|
|
25
|
+
theme:
|
|
26
|
+
name: material
|
|
27
|
+
logo: docs/assets/icon.svg
|
|
28
|
+
favicon: docs/assets/icon.svg
|
|
29
|
+
palette:
|
|
30
|
+
- scheme: slate
|
|
31
|
+
primary: custom
|
|
32
|
+
accent: custom
|
|
33
|
+
toggle:
|
|
34
|
+
icon: material/brightness-7
|
|
35
|
+
name: Switch to light mode
|
|
36
|
+
- scheme: default
|
|
37
|
+
primary: custom
|
|
38
|
+
accent: custom
|
|
39
|
+
toggle:
|
|
40
|
+
icon: material/brightness-4
|
|
41
|
+
name: Switch to dark mode
|
|
42
|
+
features:
|
|
43
|
+
- navigation.instant
|
|
44
|
+
- navigation.tracking
|
|
45
|
+
- navigation.tabs
|
|
46
|
+
- navigation.tabs.sticky
|
|
47
|
+
- navigation.sections
|
|
48
|
+
- navigation.top
|
|
49
|
+
- navigation.path
|
|
50
|
+
- search.suggest
|
|
51
|
+
- search.highlight
|
|
52
|
+
- content.code.copy
|
|
53
|
+
- content.tabs.link
|
|
54
|
+
- toc.follow
|
|
55
|
+
- header.autohide
|
|
56
|
+
icon:
|
|
57
|
+
repo: fontawesome/brands/github
|
|
58
|
+
font:
|
|
59
|
+
text: Inter, system-ui, -apple-system, sans-serif
|
|
60
|
+
code: JetBrains Mono, Cascadia Code, monospace
|
|
61
|
+
|
|
62
|
+
plugins:
|
|
63
|
+
- search
|
|
64
|
+
- minify:
|
|
65
|
+
minify_html: true
|
|
66
|
+
- mkdocstrings:
|
|
67
|
+
default_handler: python
|
|
68
|
+
handlers:
|
|
69
|
+
python:
|
|
70
|
+
paths: [src]
|
|
71
|
+
options:
|
|
72
|
+
docstring_style: google
|
|
73
|
+
show_source: false
|
|
74
|
+
show_root_heading: true
|
|
75
|
+
show_root_full_path: false
|
|
76
|
+
show_symbol_type_heading: true
|
|
77
|
+
show_symbol_type_toc: true
|
|
78
|
+
members_order: source
|
|
79
|
+
separate_signature: true
|
|
80
|
+
show_signature_annotations: true
|
|
81
|
+
unwrap_annotated: true
|
|
82
|
+
|
|
83
|
+
markdown_extensions:
|
|
84
|
+
- admonition
|
|
85
|
+
- pymdownx.details
|
|
86
|
+
- pymdownx.superfences:
|
|
87
|
+
custom_fences:
|
|
88
|
+
- name: mermaid
|
|
89
|
+
class: mermaid
|
|
90
|
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
|
91
|
+
- pymdownx.tabbed:
|
|
92
|
+
alternate_style: true
|
|
93
|
+
- pymdownx.highlight:
|
|
94
|
+
anchor_linenums: true
|
|
95
|
+
- pymdownx.inlinehilite
|
|
96
|
+
- pymdownx.snippets
|
|
97
|
+
- pymdownx.emoji:
|
|
98
|
+
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
|
99
|
+
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
|
100
|
+
- attr_list
|
|
101
|
+
- md_in_html
|
|
102
|
+
- tables
|
|
103
|
+
- toc:
|
|
104
|
+
permalink: true
|
|
105
|
+
|
|
106
|
+
extra:
|
|
107
|
+
social:
|
|
108
|
+
- icon: fontawesome/brands/github
|
|
109
|
+
link: https://github.com/agentrust-io/trace-spec
|
|
110
|
+
generator: false
|
|
111
|
+
|
|
112
|
+
extra_css:
|
|
113
|
+
- docs/stylesheets/extra.css
|
|
114
|
+
|
|
115
|
+
nav:
|
|
116
|
+
- Home: README.md
|
|
117
|
+
- Specification: spec/trace-v0.1.md
|
|
118
|
+
- Crosswalks:
|
|
119
|
+
- OWASP Agentic Top 10: docs/crosswalks/owasp-agentic-top-10.md
|
|
120
|
+
- Project:
|
|
121
|
+
- Limitations: LIMITATIONS.md
|
|
122
|
+
- Changelog: CHANGELOG.md
|
|
123
|
+
- Contributing: CONTRIBUTING.md
|
|
124
|
+
- Governance: GOVERNANCE.md
|
|
125
|
+
- Roadmap: ROADMAP.md
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentrust-trace"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "TRACE v0.1 — hardware-attested governance records for AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -24,6 +24,7 @@ classifiers = [
|
|
|
24
24
|
dependencies = [
|
|
25
25
|
"pydantic>=2.0",
|
|
26
26
|
"jsonschema>=4.20",
|
|
27
|
+
"cryptography>=42.0",
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
[project.optional-dependencies]
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"subject": {
|
|
32
32
|
"type": "string",
|
|
33
|
-
"description": "Workload identity as a SPIFFE SVID URI.",
|
|
34
|
-
"pattern": "^spiffe
|
|
33
|
+
"description": "Workload identity as a SPIFFE SVID URI or DID URI.",
|
|
34
|
+
"pattern": "^(spiffe://|did:)"
|
|
35
35
|
},
|
|
36
36
|
"model": {
|
|
37
37
|
"type": "object",
|
|
@@ -117,7 +117,8 @@
|
|
|
117
117
|
"enforcement_mode": {
|
|
118
118
|
"type": "string",
|
|
119
119
|
"enum": ["enforce", "advisory", "silent"],
|
|
120
|
-
"
|
|
120
|
+
"default": "enforce",
|
|
121
|
+
"description": "How policy decisions were applied: enforce (block on deny), advisory (log and allow), silent (allow and suppress operational logs; the audit chain still records every would-have-denied decision). Gateways MUST default to enforce. A deployment MUST explicitly configure silent mode; it MUST NOT be the default."
|
|
121
122
|
},
|
|
122
123
|
"version": {
|
|
123
124
|
"type": "string",
|
|
@@ -166,9 +167,9 @@
|
|
|
166
167
|
"properties": {
|
|
167
168
|
"slsa_level": {
|
|
168
169
|
"type": "integer",
|
|
169
|
-
"minimum":
|
|
170
|
+
"minimum": 0,
|
|
170
171
|
"maximum": 3,
|
|
171
|
-
"description": "SLSA Build Level achieved. Level 2 minimum for TRACE conformance; Level 3 for production mark."
|
|
172
|
+
"description": "SLSA Build Level achieved. Level 0 = software-only (development/staging); Level 2 minimum for TRACE conformance; Level 3 for production mark."
|
|
172
173
|
},
|
|
173
174
|
"builder": {
|
|
174
175
|
"type": "string",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
| Field | Value |
|
|
4
4
|
|---|---|
|
|
5
|
-
| Version | 0.
|
|
5
|
+
| Version | 0.2 — Draft |
|
|
6
6
|
| Status | RFC — Request for Comments |
|
|
7
7
|
| Authors | Rishabh Poddar, Aaron Fulkerson (OPAQUE Systems) |
|
|
8
8
|
| Target announcement | Confidential Computing Summit, San Francisco — 23 June 2026 |
|
|
@@ -103,10 +103,10 @@ The Trust Record is the unit of evidence. All fields are required unless marked
|
|
|
103
103
|
|
|
104
104
|
| Field | Description | Source primitive |
|
|
105
105
|
|---|---|---|
|
|
106
|
-
| `subject` | Workload identity (agent, tool, model invocation) | SPIFFE SVID |
|
|
106
|
+
| `subject` | Workload identity (agent, tool, model invocation) | SPIFFE SVID or DID URI |
|
|
107
107
|
| `model` | Model identity, weights digest, version | EAT claim + AIBOM reference |
|
|
108
108
|
| `runtime` | TEE measurement chain (firmware → kernel → image → workload) | RATS Evidence + vendor RIM |
|
|
109
|
-
| `policy` | Bound policy set hash + enforcement mode | Policy artifact hash sealed to TEE measurement |
|
|
109
|
+
| `policy` | Bound policy set hash + enforcement mode. `enforcement_mode` MUST default to `enforce`; a deployment MUST explicitly configure `silent` mode. | Policy artifact hash sealed to TEE measurement |
|
|
110
110
|
| `data_class` | Classification of inputs and outputs | Classification label bound to per-call execution |
|
|
111
111
|
| `tool_transcript` | MCP / A2A tool calls invoked, parameters classified, responses filtered | MCP / A2A protocol transcripts bound to TEE measurement |
|
|
112
112
|
| `build_provenance` | How the running code and model were built | SLSA Provenance v1.0 |
|
|
@@ -265,7 +265,7 @@ TRACE is a **profile**, not a parallel stack. It binds existing primitives into
|
|
|
265
265
|
|
|
266
266
|
These components exist in their respective ecosystems. TRACE adds the binding rule that places each into a hardware-attested envelope:
|
|
267
267
|
|
|
268
|
-
- **`policy` claim.** Policy artifacts (OPA bundles, Cedar policies, custom DSLs) and policy hashing are established. TRACE adds the binding: the policy bundle hash is sealed to the TEE measurement, the enforcement mode is recorded, and substituting the policy invalidates the runtime claim.
|
|
268
|
+
- **`policy` claim.** Policy artifacts (OPA bundles, Cedar policies, custom DSLs) and policy hashing are established. TRACE adds the binding: the policy bundle hash is sealed to the TEE measurement, the enforcement mode is recorded, and substituting the policy invalidates the runtime claim. Gateways MUST default `enforcement_mode` to `enforce`. A deployment MUST explicitly configure `silent` mode; `silent` MUST NOT be the default. In `silent` mode, the audit chain still records every would-have-denied decision; only operational log lines are suppressed.
|
|
269
269
|
- **`data_class` claim.** Data classification schemes are established (DLP labels, NIST SP 800-60, sensitivity tags). TRACE adds: a classification label is attached to inputs and outputs at the per-call layer and recorded in the Trust Record alongside the runtime evidence.
|
|
270
270
|
- **`tool_transcript` claim.** MCP and A2A transcripts exist at the protocol layer. TRACE adds cryptographic binding of the transcript hash into the EAT envelope and per-call parameter classification.
|
|
271
271
|
- **AI-agent execution profile.** A profile registry that pins the claim set, evidence requirements, and verification rules for AI-agent workloads specifically.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""agentrust-trace — TRACE
|
|
1
|
+
"""agentrust-trace — TRACE Trust Record models, validation, and signing."""
|
|
2
2
|
|
|
3
3
|
from agentrust_trace.models import (
|
|
4
4
|
Appraisal,
|
|
@@ -11,13 +11,20 @@ from agentrust_trace.models import (
|
|
|
11
11
|
ToolTranscript,
|
|
12
12
|
TrustRecord,
|
|
13
13
|
)
|
|
14
|
+
from agentrust_trace.sign import (
|
|
15
|
+
generate_key,
|
|
16
|
+
key_to_jwk,
|
|
17
|
+
load_key,
|
|
18
|
+
load_signing_key,
|
|
19
|
+
sign_record,
|
|
20
|
+
)
|
|
14
21
|
from agentrust_trace.validate import (
|
|
15
22
|
iter_errors,
|
|
16
23
|
SCHEMA,
|
|
17
24
|
validate_json,
|
|
18
25
|
)
|
|
19
26
|
|
|
20
|
-
__version__ = "0.
|
|
27
|
+
__version__ = "0.2.0"
|
|
21
28
|
|
|
22
29
|
__all__ = [
|
|
23
30
|
"__version__",
|
|
@@ -33,4 +40,9 @@ __all__ = [
|
|
|
33
40
|
"SCHEMA",
|
|
34
41
|
"iter_errors",
|
|
35
42
|
"validate_json",
|
|
43
|
+
"generate_key",
|
|
44
|
+
"key_to_jwk",
|
|
45
|
+
"load_key",
|
|
46
|
+
"load_signing_key",
|
|
47
|
+
"sign_record",
|
|
36
48
|
]
|
|
@@ -62,7 +62,7 @@ class ToolTranscript(BaseModel):
|
|
|
62
62
|
class BuildProvenance(BaseModel):
|
|
63
63
|
model_config = ConfigDict(extra="forbid")
|
|
64
64
|
|
|
65
|
-
slsa_level: Annotated[int, Field(ge=
|
|
65
|
+
slsa_level: Annotated[int, Field(ge=0, le=3)]
|
|
66
66
|
builder: str | None = None
|
|
67
67
|
digest: DigestStr
|
|
68
68
|
provenance_uri: str | None = None
|
|
@@ -113,7 +113,7 @@ class TrustRecord(BaseModel):
|
|
|
113
113
|
|
|
114
114
|
eat_profile: Literal["tag:agentrust.io,2026:trace-v0.1"]
|
|
115
115
|
iat: Annotated[int, Field(ge=1700000000)]
|
|
116
|
-
subject: Annotated[str, Field(pattern=r"^spiffe
|
|
116
|
+
subject: Annotated[str, Field(pattern=r"^(spiffe://|did:)")]
|
|
117
117
|
model: ModelInfo
|
|
118
118
|
runtime: RuntimeInfo
|
|
119
119
|
policy: PolicyInfo
|
|
@@ -117,7 +117,8 @@
|
|
|
117
117
|
"enforcement_mode": {
|
|
118
118
|
"type": "string",
|
|
119
119
|
"enum": ["enforce", "advisory", "silent"],
|
|
120
|
-
"
|
|
120
|
+
"default": "enforce",
|
|
121
|
+
"description": "How policy decisions were applied: enforce (block on deny), advisory (log and allow), silent (allow and suppress operational logs; the audit chain still records every would-have-denied decision). Gateways MUST default to enforce. A deployment MUST explicitly configure silent mode; it MUST NOT be the default."
|
|
121
122
|
},
|
|
122
123
|
"version": {
|
|
123
124
|
"type": "string",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Signing utilities for TRACE Trust Records.
|
|
2
|
+
|
|
3
|
+
Produces a signed record dict with an embedded ``signature`` field --
|
|
4
|
+
Ed25519 over the canonical JSON of the record with the signature field absent.
|
|
5
|
+
This is the same convention used by cMCP RuntimeClaim and verified by
|
|
6
|
+
trace-tests TR-SIG at all conformance levels.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import base64
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import warnings
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from cryptography.hazmat.primitives import serialization
|
|
18
|
+
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def generate_key() -> Ed25519PrivateKey:
|
|
22
|
+
"""Generate a new Ed25519 signing key."""
|
|
23
|
+
return Ed25519PrivateKey.generate()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_key(pem: str) -> Ed25519PrivateKey:
|
|
27
|
+
"""Load an Ed25519 private key from a PEM string."""
|
|
28
|
+
return serialization.load_pem_private_key(pem.encode(), password=None) # type: ignore[return-value]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def load_signing_key() -> Ed25519PrivateKey:
|
|
32
|
+
"""Load key from ``TRACE_PRIVATE_KEY_PEM`` env var, or generate an ephemeral one.
|
|
33
|
+
|
|
34
|
+
Emits a warning when falling back to an ephemeral key so callers notice
|
|
35
|
+
that the resulting records cannot be re-verified after the process exits.
|
|
36
|
+
"""
|
|
37
|
+
pem = os.environ.get("TRACE_PRIVATE_KEY_PEM")
|
|
38
|
+
if pem:
|
|
39
|
+
return load_key(pem)
|
|
40
|
+
warnings.warn(
|
|
41
|
+
"TRACE_PRIVATE_KEY_PEM not set -- generating ephemeral Ed25519 key. "
|
|
42
|
+
"The signed record cannot be re-verified after this process exits. "
|
|
43
|
+
"Set TRACE_PRIVATE_KEY_PEM to a persistent PEM for production use.",
|
|
44
|
+
stacklevel=2,
|
|
45
|
+
)
|
|
46
|
+
return generate_key()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def key_to_jwk(key: Ed25519PrivateKey) -> dict[str, str]:
|
|
50
|
+
"""Return the public JWK dict for *key* (OKP / Ed25519)."""
|
|
51
|
+
pub = key.public_key()
|
|
52
|
+
raw = pub.public_bytes(
|
|
53
|
+
encoding=serialization.Encoding.Raw,
|
|
54
|
+
format=serialization.PublicFormat.Raw,
|
|
55
|
+
)
|
|
56
|
+
x = base64.urlsafe_b64encode(raw).rstrip(b"=").decode()
|
|
57
|
+
return {"kty": "OKP", "crv": "Ed25519", "x": x}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _canonical_bytes(d: dict[str, Any]) -> bytes:
|
|
61
|
+
return json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def sign_record(record: dict[str, Any], key: Ed25519PrivateKey) -> dict[str, Any]:
|
|
65
|
+
"""Return a copy of *record* with ``cnf.jwk`` populated and a ``signature`` field added.
|
|
66
|
+
|
|
67
|
+
The signature is Ed25519 over the canonical JSON (sorted keys, no whitespace)
|
|
68
|
+
of the record with the ``signature`` field absent. ``cnf.jwk`` is set to the
|
|
69
|
+
public key derived from *key*.
|
|
70
|
+
|
|
71
|
+
The returned dict is a plain JSON-serialisable object. Pass it to
|
|
72
|
+
``json.dumps()`` to get the wire form, or to ``TrustRecord.model_validate()``
|
|
73
|
+
to confirm structural validity before writing.
|
|
74
|
+
"""
|
|
75
|
+
jwk = key_to_jwk(key)
|
|
76
|
+
payload: dict[str, Any] = {**record, "cnf": {"jwk": jwk}}
|
|
77
|
+
body = _canonical_bytes({k: v for k, v in payload.items() if k != "signature"})
|
|
78
|
+
sig_bytes = key.sign(body)
|
|
79
|
+
sig_b64 = base64.urlsafe_b64encode(sig_bytes).rstrip(b"=").decode()
|
|
80
|
+
return {**payload, "signature": sig_b64}
|
|
@@ -20,7 +20,7 @@ def _load(name: str) -> dict:
|
|
|
20
20
|
def test_example_parses(filename: str) -> None:
|
|
21
21
|
record = TrustRecord.model_validate(_load(filename))
|
|
22
22
|
assert record.eat_profile == "tag:agentrust.io,2026:trace-v0.1"
|
|
23
|
-
assert record.subject.startswith("spiffe://")
|
|
23
|
+
assert record.subject.startswith(("spiffe://", "did:"))
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def test_intel_tdx_fields() -> None:
|
|
@@ -105,6 +105,27 @@ def test_digest_sha512_rejected() -> None:
|
|
|
105
105
|
# cnf.jwk key material enforcement
|
|
106
106
|
|
|
107
107
|
|
|
108
|
+
def test_subject_accepts_did_uri() -> None:
|
|
109
|
+
data = _load("intel-tdx.json")
|
|
110
|
+
data["subject"] = "did:key:z6MkhaXgBZDvotzL8oCYaXeFuJArwvX6mDMsKTJVjtN7R"
|
|
111
|
+
record = TrustRecord.model_validate(data)
|
|
112
|
+
assert record.subject.startswith("did:")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_subject_accepts_did_web() -> None:
|
|
116
|
+
data = _load("intel-tdx.json")
|
|
117
|
+
data["subject"] = "did:web:example.org:agents:payments-processor"
|
|
118
|
+
record = TrustRecord.model_validate(data)
|
|
119
|
+
assert record.subject.startswith("did:")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_subject_rejects_http_scheme() -> None:
|
|
123
|
+
data = _load("intel-tdx.json")
|
|
124
|
+
data["subject"] = "https://example.org/agent"
|
|
125
|
+
with pytest.raises(ValidationError):
|
|
126
|
+
TrustRecord.model_validate(data)
|
|
127
|
+
|
|
128
|
+
|
|
108
129
|
def test_okp_jwk_without_key_material_rejected() -> None:
|
|
109
130
|
"""An OKP confirmation key with no crv/x carries no key material and binds nothing."""
|
|
110
131
|
data = _load("intel-tdx.json")
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Tests for agentrust_trace.sign."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from cryptography.exceptions import InvalidSignature
|
|
8
|
+
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
|
|
9
|
+
|
|
10
|
+
from agentrust_trace import TrustRecord, generate_key, key_to_jwk, sign_record
|
|
11
|
+
from agentrust_trace.sign import _canonical_bytes
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _b64url_decode(s: str) -> bytes:
|
|
15
|
+
pad = 4 - len(s) % 4
|
|
16
|
+
if pad != 4:
|
|
17
|
+
s += "=" * pad
|
|
18
|
+
return base64.urlsafe_b64decode(s)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _minimal_record() -> dict:
|
|
22
|
+
return {
|
|
23
|
+
"eat_profile": "tag:agentrust.io,2026:trace-v0.1",
|
|
24
|
+
"iat": 1750000000,
|
|
25
|
+
"subject": "did:mesh:spiffe://factory.example/agent/payments/prod",
|
|
26
|
+
"model": {"provider": "anthropic", "model_id": "claude-sonnet-4-6"},
|
|
27
|
+
"runtime": {
|
|
28
|
+
"platform": "software-only",
|
|
29
|
+
"measurement": "sha256:" + "0" * 64,
|
|
30
|
+
},
|
|
31
|
+
"policy": {
|
|
32
|
+
"bundle_hash": "sha256:" + "a" * 64,
|
|
33
|
+
"enforcement_mode": "enforce",
|
|
34
|
+
},
|
|
35
|
+
"data_class": "confidential",
|
|
36
|
+
"build_provenance": {
|
|
37
|
+
"slsa_level": 0,
|
|
38
|
+
"digest": "sha256:" + "b" * 64,
|
|
39
|
+
},
|
|
40
|
+
"appraisal": {
|
|
41
|
+
"status": "affirming",
|
|
42
|
+
"verifier": "https://agt.example.org/verifier",
|
|
43
|
+
},
|
|
44
|
+
"transparency": "",
|
|
45
|
+
"tool_transcript": {
|
|
46
|
+
"hash": "sha256:" + "c" * 64,
|
|
47
|
+
"call_count": 3,
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_sign_record_adds_signature_and_cnf():
|
|
53
|
+
key = generate_key()
|
|
54
|
+
record = sign_record(_minimal_record(), key)
|
|
55
|
+
assert "signature" in record
|
|
56
|
+
assert "cnf" in record
|
|
57
|
+
assert record["cnf"]["jwk"]["kty"] == "OKP"
|
|
58
|
+
assert record["cnf"]["jwk"]["crv"] == "Ed25519"
|
|
59
|
+
assert "x" in record["cnf"]["jwk"]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_sign_record_signature_verifies():
|
|
63
|
+
key = generate_key()
|
|
64
|
+
record = sign_record(_minimal_record(), key)
|
|
65
|
+
|
|
66
|
+
jwk = record["cnf"]["jwk"]
|
|
67
|
+
pub_bytes = _b64url_decode(jwk["x"])
|
|
68
|
+
pub_key = Ed25519PublicKey.from_public_bytes(pub_bytes)
|
|
69
|
+
|
|
70
|
+
body = _canonical_bytes({k: v for k, v in record.items() if k != "signature"})
|
|
71
|
+
sig_bytes = _b64url_decode(record["signature"])
|
|
72
|
+
pub_key.verify(sig_bytes, body) # raises InvalidSignature if wrong
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_tampered_record_fails_verification():
|
|
76
|
+
key = generate_key()
|
|
77
|
+
record = sign_record(_minimal_record(), key)
|
|
78
|
+
|
|
79
|
+
jwk = record["cnf"]["jwk"]
|
|
80
|
+
pub_bytes = _b64url_decode(jwk["x"])
|
|
81
|
+
pub_key = Ed25519PublicKey.from_public_bytes(pub_bytes)
|
|
82
|
+
|
|
83
|
+
tampered = {**record, "data_class": "public"}
|
|
84
|
+
body = _canonical_bytes({k: v for k, v in tampered.items() if k != "signature"})
|
|
85
|
+
sig_bytes = _b64url_decode(record["signature"])
|
|
86
|
+
with pytest.raises(InvalidSignature):
|
|
87
|
+
pub_key.verify(sig_bytes, body)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_signed_record_passes_trust_record_validation():
|
|
91
|
+
key = generate_key()
|
|
92
|
+
record = sign_record(_minimal_record(), key)
|
|
93
|
+
validated = TrustRecord.model_validate(record)
|
|
94
|
+
assert validated.appraisal.status == "affirming"
|
|
95
|
+
assert validated.subject.startswith("did:")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_key_to_jwk_shape():
|
|
99
|
+
key = generate_key()
|
|
100
|
+
jwk = key_to_jwk(key)
|
|
101
|
+
assert jwk["kty"] == "OKP"
|
|
102
|
+
assert jwk["crv"] == "Ed25519"
|
|
103
|
+
assert len(jwk["x"]) > 0
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_sign_record_did_subject():
|
|
107
|
+
key = generate_key()
|
|
108
|
+
record = _minimal_record()
|
|
109
|
+
record["subject"] = "did:key:z6MkhaXgBZDvotzL8oCYaXeFuJArwvX6mDMsKTJVjtN7R"
|
|
110
|
+
signed = sign_record(record, key)
|
|
111
|
+
validated = TrustRecord.model_validate(signed)
|
|
112
|
+
assert validated.subject.startswith("did:key:")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_sign_record_spiffe_subject():
|
|
116
|
+
key = generate_key()
|
|
117
|
+
record = _minimal_record()
|
|
118
|
+
record["subject"] = "spiffe://trust.example.org/agent/payments/prod"
|
|
119
|
+
signed = sign_record(record, key)
|
|
120
|
+
validated = TrustRecord.model_validate(signed)
|
|
121
|
+
assert validated.subject.startswith("spiffe://")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentrust_trace-0.1.1 → agentrust_trace-0.2.0}/.github/workflows/require-maintainer-approval.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|