agent-manifest 0.1.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.
Files changed (34) hide show
  1. agent_manifest-0.1.0/PKG-INFO +196 -0
  2. agent_manifest-0.1.0/README.md +142 -0
  3. agent_manifest-0.1.0/pyproject.toml +89 -0
  4. agent_manifest-0.1.0/src/agent_manifest/__init__.py +47 -0
  5. agent_manifest-0.1.0/src/agent_manifest/_auto_provider.py +85 -0
  6. agent_manifest-0.1.0/src/agent_manifest/_canonicalize.py +160 -0
  7. agent_manifest-0.1.0/src/agent_manifest/_delegation.py +291 -0
  8. agent_manifest-0.1.0/src/agent_manifest/_hw_providers.py +336 -0
  9. agent_manifest-0.1.0/src/agent_manifest/_merkle.py +329 -0
  10. agent_manifest-0.1.0/src/agent_manifest/_providers.py +234 -0
  11. agent_manifest-0.1.0/src/agent_manifest/_revocation.py +252 -0
  12. agent_manifest-0.1.0/src/agent_manifest/_signing.py +446 -0
  13. agent_manifest-0.1.0/src/agent_manifest/_transparency.py +191 -0
  14. agent_manifest-0.1.0/src/agent_manifest/_types.py +95 -0
  15. agent_manifest-0.1.0/src/agent_manifest/_verify.py +680 -0
  16. agent_manifest-0.1.0/src/agent_manifest/cli.py +339 -0
  17. agent_manifest-0.1.0/src/agent_manifest/models.py +720 -0
  18. agent_manifest-0.1.0/tests/__init__.py +0 -0
  19. agent_manifest-0.1.0/tests/test_am_attest.py +238 -0
  20. agent_manifest-0.1.0/tests/test_am_bind.py +479 -0
  21. agent_manifest-0.1.0/tests/test_am_compat.py +354 -0
  22. agent_manifest-0.1.0/tests/test_am_crypto.py +268 -0
  23. agent_manifest-0.1.0/tests/test_am_verify.py +433 -0
  24. agent_manifest-0.1.0/tests/test_canonicalize.py +235 -0
  25. agent_manifest-0.1.0/tests/test_delegation_hitl.py +282 -0
  26. agent_manifest-0.1.0/tests/test_examples.py +112 -0
  27. agent_manifest-0.1.0/tests/test_hw_providers.py +496 -0
  28. agent_manifest-0.1.0/tests/test_merkle.py +260 -0
  29. agent_manifest-0.1.0/tests/test_poisoning_scan.py +171 -0
  30. agent_manifest-0.1.0/tests/test_providers.py +173 -0
  31. agent_manifest-0.1.0/tests/test_revocation.py +307 -0
  32. agent_manifest-0.1.0/tests/test_signing.py +525 -0
  33. agent_manifest-0.1.0/tests/test_transparency.py +404 -0
  34. agent_manifest-0.1.0/tests/test_verify.py +412 -0
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-manifest
3
+ Version: 0.1.0
4
+ Summary: Agent Manifest SDK — cryptographically anchor all 10 artifacts defining an AI agent at deployment
5
+ Project-URL: Homepage, https://github.com/agentrust-io/agent-manifest
6
+ Project-URL: Repository, https://github.com/agentrust-io/agent-manifest
7
+ Project-URL: Documentation, https://github.com/agentrust-io/agent-manifest/tree/main/spec
8
+ Project-URL: Bug Tracker, https://github.com/agentrust-io/agent-manifest/issues
9
+ Project-URL: Changelog, https://github.com/agentrust-io/agent-manifest/releases
10
+ Author-email: Imran Siddique <maintainers@agentrust.io>
11
+ License: Apache-2.0
12
+ Keywords: agent-manifest,ai-agents,attestation,confidential-computing,governance,hardware-attestation,mcp,pydantic,tee,trust
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Security :: Cryptography
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: System :: Monitoring
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: cryptography<50,>=42
26
+ Requires-Dist: pydantic<3,>=2.7
27
+ Provides-Extra: all
28
+ Requires-Dist: click>=8.1; extra == 'all'
29
+ Requires-Dist: fastapi>=0.111; extra == 'all'
30
+ Requires-Dist: httpx>=0.27; extra == 'all'
31
+ Requires-Dist: pyoqs>=0.10; extra == 'all'
32
+ Requires-Dist: uvicorn[standard]>=0.29; extra == 'all'
33
+ Provides-Extra: cli
34
+ Requires-Dist: click>=8.1; extra == 'cli'
35
+ Provides-Extra: dev
36
+ Requires-Dist: bandit[toml]>=1.7; extra == 'dev'
37
+ Requires-Dist: click>=8.1; extra == 'dev'
38
+ Requires-Dist: fastapi>=0.111; extra == 'dev'
39
+ Requires-Dist: httpx>=0.27; extra == 'dev'
40
+ Requires-Dist: jcs>=0.2; extra == 'dev'
41
+ Requires-Dist: mypy>=1.10; extra == 'dev'
42
+ Requires-Dist: pip-audit>=2.7; extra == 'dev'
43
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
44
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
45
+ Requires-Dist: pytest>=8; extra == 'dev'
46
+ Requires-Dist: uvicorn[standard]>=0.29; extra == 'dev'
47
+ Provides-Extra: pq
48
+ Requires-Dist: pyoqs>=0.10; extra == 'pq'
49
+ Provides-Extra: server
50
+ Requires-Dist: fastapi>=0.111; extra == 'server'
51
+ Requires-Dist: httpx>=0.27; extra == 'server'
52
+ Requires-Dist: uvicorn[standard]>=0.29; extra == 'server'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # agent-manifest
56
+
57
+ **Cryptographically anchor all 10 artifacts defining an AI agent at deployment.**
58
+
59
+ The Agent Manifest SDK implements the Agent Manifest Specification v0.1 - a hardware-attestable document that binds every artifact defining an agent's behavior (system prompt, policy bundle, tool schemas, model identity, RAG corpus, memory state, audit chain, delegation chain, supply chain, and human approvals) into a single tamper-evident identity primitive.
60
+
61
+ ```
62
+ pip install agent-manifest
63
+ ```
64
+
65
+ ## Why
66
+
67
+ A signed JWT proves who called an API. An Agent Manifest proves who the agent **was**, what it was **allowed to do**, how it was **built**, what it **decided**, who **approved** it, and whether any of that changed between approval and execution.
68
+
69
+ ```python
70
+ from agent_manifest import (
71
+ Manifest, ArtifactBindings,
72
+ SystemPromptBinding, PolicyBundleBinding, ModelIdentityBinding,
73
+ CryptoProfile, DeploymentType, EnforcementMode, PolicyLanguage,
74
+ generate_ed25519, Ed25519Signer,
75
+ )
76
+ from agent_manifest._types import HashValue, ManifestId
77
+ from datetime import datetime, timedelta, timezone
78
+
79
+ now = datetime.now(timezone.utc)
80
+
81
+ manifest = Manifest(
82
+ manifest_id=ManifestId("018f4a3b-2c1d-7e5f-a8b9-0d1e2f3a4b5c"),
83
+ agent_id="spiffe://trust.example/agent/kyc/prod",
84
+ issued_at=now,
85
+ expires_at=now + timedelta(days=90),
86
+ issuer="spiffe://trust.example/signing-authority",
87
+ crypto_profile=CryptoProfile.standard,
88
+ artifacts=ArtifactBindings(
89
+ system_prompt=SystemPromptBinding(
90
+ hash=HashValue("sha256:" + "a" * 64),
91
+ bound_at=now,
92
+ ),
93
+ policy_bundle=PolicyBundleBinding(
94
+ hash=HashValue("sha256:" + "b" * 64),
95
+ policy_language=PolicyLanguage.cedar,
96
+ version="1.0.0",
97
+ enforcement_mode=EnforcementMode.enforce,
98
+ bound_at=now,
99
+ ),
100
+ model_identity=ModelIdentityBinding(
101
+ provider="anthropic",
102
+ model_id="claude-sonnet-4-6",
103
+ version="20251001",
104
+ deployment_type=DeploymentType.api,
105
+ bound_at=now,
106
+ ),
107
+ ),
108
+ )
109
+
110
+ keypair = generate_ed25519()
111
+ signer = Ed25519Signer(keypair)
112
+ sig_block = signer.sign(manifest.model_dump(mode="json", by_alias=True))
113
+ print(sig_block["algorithm"]) # Ed25519
114
+ print(sig_block["key_id"]) # sha256:<hex>
115
+ ```
116
+
117
+ ## The 10 Attested Artifacts
118
+
119
+ | # | Artifact | What it proves |
120
+ |---|----------|---------------|
121
+ | 1 | System Prompt | The exact prompt that defines the agent's persona and safety constraints |
122
+ | 2 | Policy Bundle | The Cedar/Rego/YAML governance rules that were in force |
123
+ | 3 | Tool Manifest | Every tool schema and description the agent was authorized to call |
124
+ | 4 | Model Identity | Which model and version ran (binary hash for local, version for API) |
125
+ | 5 | RAG Corpus | The knowledge base the agent was grounded on (Merkle root) |
126
+ | 6 | Memory Baseline | Approved agent memory state with TTL-based re-approval |
127
+ | 7 | Decision Trace | Hardware-signed audit chain root for all agent decisions |
128
+ | 8 | A2A Delegation | Signed delegation chain from human principal to current agent |
129
+ | 9 | Supply Chain | Container digest, SLSA provenance, SBOM, MCP server supply chain |
130
+ | 10 | HITL Approvals | Hardware-signed human oversight records (EU AI Act Art. 14) |
131
+
132
+ ## Hardware Attestation
133
+
134
+ ```python
135
+ from agent_manifest._auto_provider import select_provider
136
+
137
+ # auto-selects: SEV-SNP → TDX → TPM → software (OPAQUE is explicit opt-in via OPAQUE_ATTESTATION_URL)
138
+ provider = select_provider(level=1) # Level 1+ requires hardware
139
+ provider.extend_manifest_hash(manifest_dict)
140
+ report = provider.get_attestation_report()
141
+ # report.platform: "amd-sev-snp" | "intel-tdx" | "tpm" | "opaque" | "software"
142
+ ```
143
+
144
+ | Provider | Hardware | Level | Install |
145
+ |----------|----------|-------|---------|
146
+ | `TPMProvider` | TPM 2.0 / AWS Nitro | 1 | `apt install tpm2-tools` |
147
+ | `SEVSNPProvider` | AMD SEV-SNP | 2 | Needs `/dev/sev-guest` |
148
+ | `TDXProvider` | Intel TDX | 2 | Needs `/dev/tdx-guest` |
149
+ | `OPAQUEProvider` | Opaque Runtime | 3 | Set `OPAQUE_ATTESTATION_URL` |
150
+
151
+ ## Verification
152
+
153
+ ```python
154
+ from agent_manifest._verify import verify_manifest, VerificationContext, RevocationStore
155
+
156
+ result = verify_manifest(
157
+ manifest_dict,
158
+ VerificationContext(
159
+ system_prompt_hash="sha256:...",
160
+ policy_bundle_hash="sha256:...",
161
+ enforce_hitl=True,
162
+ ),
163
+ RevocationStore(),
164
+ )
165
+ print(result.result) # VALID | MISMATCH | EXPIRED | REVOKED | ...
166
+ ```
167
+
168
+ ## CLI
169
+
170
+ ```bash
171
+ pip install "agent-manifest[cli]"
172
+
173
+ manifest keygen -d ./keys/
174
+ manifest create config.json -o draft.json
175
+ manifest sign draft.json --key keys/private.hex -o signed.json
176
+ manifest attest signed.json --provider auto --level 1 -o attested.json
177
+ manifest verify attested.json
178
+ manifest revoke <manifest-id> --reason "key compromise" --revoked-by security@example.com
179
+ ```
180
+
181
+ ## Cryptography
182
+
183
+ - **Standard profile**: Ed25519 (RFC 8032), SHA-256, RFC 8785 canonical JSON
184
+ - **Post-quantum profile**: ML-DSA-65 (NIST FIPS 204), SHAKE-256 - `pip install "agent-manifest[pq]"`
185
+ - **Hybrid**: Both signatures required, identical pre-image
186
+ - **Transparency**: Rekor/Sigstore integration for non-repudiation
187
+
188
+ ## Specification
189
+
190
+ The full Agent Manifest Specification v0.1 is at [`spec/agent-manifest-spec-v0.1.md`](https://github.com/agentrust-io/agent-manifest/blob/main/spec/agent-manifest-spec-v0.1.md).
191
+
192
+ Being submitted to the [Agentic AI Foundation (AAIF)](https://agenticai.foundation) under the Linux Foundation alongside AGT.
193
+
194
+ ## License
195
+
196
+ Apache 2.0
@@ -0,0 +1,142 @@
1
+ # agent-manifest
2
+
3
+ **Cryptographically anchor all 10 artifacts defining an AI agent at deployment.**
4
+
5
+ The Agent Manifest SDK implements the Agent Manifest Specification v0.1 - a hardware-attestable document that binds every artifact defining an agent's behavior (system prompt, policy bundle, tool schemas, model identity, RAG corpus, memory state, audit chain, delegation chain, supply chain, and human approvals) into a single tamper-evident identity primitive.
6
+
7
+ ```
8
+ pip install agent-manifest
9
+ ```
10
+
11
+ ## Why
12
+
13
+ A signed JWT proves who called an API. An Agent Manifest proves who the agent **was**, what it was **allowed to do**, how it was **built**, what it **decided**, who **approved** it, and whether any of that changed between approval and execution.
14
+
15
+ ```python
16
+ from agent_manifest import (
17
+ Manifest, ArtifactBindings,
18
+ SystemPromptBinding, PolicyBundleBinding, ModelIdentityBinding,
19
+ CryptoProfile, DeploymentType, EnforcementMode, PolicyLanguage,
20
+ generate_ed25519, Ed25519Signer,
21
+ )
22
+ from agent_manifest._types import HashValue, ManifestId
23
+ from datetime import datetime, timedelta, timezone
24
+
25
+ now = datetime.now(timezone.utc)
26
+
27
+ manifest = Manifest(
28
+ manifest_id=ManifestId("018f4a3b-2c1d-7e5f-a8b9-0d1e2f3a4b5c"),
29
+ agent_id="spiffe://trust.example/agent/kyc/prod",
30
+ issued_at=now,
31
+ expires_at=now + timedelta(days=90),
32
+ issuer="spiffe://trust.example/signing-authority",
33
+ crypto_profile=CryptoProfile.standard,
34
+ artifacts=ArtifactBindings(
35
+ system_prompt=SystemPromptBinding(
36
+ hash=HashValue("sha256:" + "a" * 64),
37
+ bound_at=now,
38
+ ),
39
+ policy_bundle=PolicyBundleBinding(
40
+ hash=HashValue("sha256:" + "b" * 64),
41
+ policy_language=PolicyLanguage.cedar,
42
+ version="1.0.0",
43
+ enforcement_mode=EnforcementMode.enforce,
44
+ bound_at=now,
45
+ ),
46
+ model_identity=ModelIdentityBinding(
47
+ provider="anthropic",
48
+ model_id="claude-sonnet-4-6",
49
+ version="20251001",
50
+ deployment_type=DeploymentType.api,
51
+ bound_at=now,
52
+ ),
53
+ ),
54
+ )
55
+
56
+ keypair = generate_ed25519()
57
+ signer = Ed25519Signer(keypair)
58
+ sig_block = signer.sign(manifest.model_dump(mode="json", by_alias=True))
59
+ print(sig_block["algorithm"]) # Ed25519
60
+ print(sig_block["key_id"]) # sha256:<hex>
61
+ ```
62
+
63
+ ## The 10 Attested Artifacts
64
+
65
+ | # | Artifact | What it proves |
66
+ |---|----------|---------------|
67
+ | 1 | System Prompt | The exact prompt that defines the agent's persona and safety constraints |
68
+ | 2 | Policy Bundle | The Cedar/Rego/YAML governance rules that were in force |
69
+ | 3 | Tool Manifest | Every tool schema and description the agent was authorized to call |
70
+ | 4 | Model Identity | Which model and version ran (binary hash for local, version for API) |
71
+ | 5 | RAG Corpus | The knowledge base the agent was grounded on (Merkle root) |
72
+ | 6 | Memory Baseline | Approved agent memory state with TTL-based re-approval |
73
+ | 7 | Decision Trace | Hardware-signed audit chain root for all agent decisions |
74
+ | 8 | A2A Delegation | Signed delegation chain from human principal to current agent |
75
+ | 9 | Supply Chain | Container digest, SLSA provenance, SBOM, MCP server supply chain |
76
+ | 10 | HITL Approvals | Hardware-signed human oversight records (EU AI Act Art. 14) |
77
+
78
+ ## Hardware Attestation
79
+
80
+ ```python
81
+ from agent_manifest._auto_provider import select_provider
82
+
83
+ # auto-selects: SEV-SNP → TDX → TPM → software (OPAQUE is explicit opt-in via OPAQUE_ATTESTATION_URL)
84
+ provider = select_provider(level=1) # Level 1+ requires hardware
85
+ provider.extend_manifest_hash(manifest_dict)
86
+ report = provider.get_attestation_report()
87
+ # report.platform: "amd-sev-snp" | "intel-tdx" | "tpm" | "opaque" | "software"
88
+ ```
89
+
90
+ | Provider | Hardware | Level | Install |
91
+ |----------|----------|-------|---------|
92
+ | `TPMProvider` | TPM 2.0 / AWS Nitro | 1 | `apt install tpm2-tools` |
93
+ | `SEVSNPProvider` | AMD SEV-SNP | 2 | Needs `/dev/sev-guest` |
94
+ | `TDXProvider` | Intel TDX | 2 | Needs `/dev/tdx-guest` |
95
+ | `OPAQUEProvider` | Opaque Runtime | 3 | Set `OPAQUE_ATTESTATION_URL` |
96
+
97
+ ## Verification
98
+
99
+ ```python
100
+ from agent_manifest._verify import verify_manifest, VerificationContext, RevocationStore
101
+
102
+ result = verify_manifest(
103
+ manifest_dict,
104
+ VerificationContext(
105
+ system_prompt_hash="sha256:...",
106
+ policy_bundle_hash="sha256:...",
107
+ enforce_hitl=True,
108
+ ),
109
+ RevocationStore(),
110
+ )
111
+ print(result.result) # VALID | MISMATCH | EXPIRED | REVOKED | ...
112
+ ```
113
+
114
+ ## CLI
115
+
116
+ ```bash
117
+ pip install "agent-manifest[cli]"
118
+
119
+ manifest keygen -d ./keys/
120
+ manifest create config.json -o draft.json
121
+ manifest sign draft.json --key keys/private.hex -o signed.json
122
+ manifest attest signed.json --provider auto --level 1 -o attested.json
123
+ manifest verify attested.json
124
+ manifest revoke <manifest-id> --reason "key compromise" --revoked-by security@example.com
125
+ ```
126
+
127
+ ## Cryptography
128
+
129
+ - **Standard profile**: Ed25519 (RFC 8032), SHA-256, RFC 8785 canonical JSON
130
+ - **Post-quantum profile**: ML-DSA-65 (NIST FIPS 204), SHAKE-256 - `pip install "agent-manifest[pq]"`
131
+ - **Hybrid**: Both signatures required, identical pre-image
132
+ - **Transparency**: Rekor/Sigstore integration for non-repudiation
133
+
134
+ ## Specification
135
+
136
+ The full Agent Manifest Specification v0.1 is at [`spec/agent-manifest-spec-v0.1.md`](https://github.com/agentrust-io/agent-manifest/blob/main/spec/agent-manifest-spec-v0.1.md).
137
+
138
+ Being submitted to the [Agentic AI Foundation (AAIF)](https://agenticai.foundation) under the Linux Foundation alongside AGT.
139
+
140
+ ## License
141
+
142
+ Apache 2.0
@@ -0,0 +1,89 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agent-manifest"
7
+ version = "0.1.0"
8
+ description = "Agent Manifest SDK — cryptographically anchor all 10 artifacts defining an AI agent at deployment"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = {text = "Apache-2.0"}
12
+ authors = [{name = "Imran Siddique", email = "maintainers@agentrust.io"}]
13
+ keywords = [
14
+ "ai-agents", "attestation", "governance", "tee", "confidential-computing",
15
+ "mcp", "agent-manifest", "trust", "hardware-attestation", "pydantic",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: Apache Software License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Security :: Cryptography",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Topic :: System :: Monitoring",
28
+ "Typing :: Typed",
29
+ ]
30
+ dependencies = [
31
+ "pydantic>=2.7,<3",
32
+ "cryptography>=42,<50",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ pq = ["pyoqs>=0.10"]
37
+ server = ["fastapi>=0.111", "uvicorn[standard]>=0.29", "httpx>=0.27"]
38
+ cli = ["click>=8.1"]
39
+ all = ["pyoqs>=0.10", "fastapi>=0.111", "uvicorn[standard]>=0.29", "httpx>=0.27", "click>=8.1"]
40
+ dev = ["pytest>=8", "pytest-asyncio>=0.23", "pytest-cov>=5", "httpx>=0.27",
41
+ "jcs>=0.2", "fastapi>=0.111", "uvicorn[standard]>=0.29",
42
+ "click>=8.1", "mypy>=1.10", "bandit[toml]>=1.7", "pip-audit>=2.7"]
43
+
44
+ [project.scripts]
45
+ manifest = "agent_manifest.cli:main"
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/agentrust-io/agent-manifest"
49
+ Repository = "https://github.com/agentrust-io/agent-manifest"
50
+ Documentation = "https://github.com/agentrust-io/agent-manifest/tree/main/spec"
51
+ "Bug Tracker" = "https://github.com/agentrust-io/agent-manifest/issues"
52
+ Changelog = "https://github.com/agentrust-io/agent-manifest/releases"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/agent_manifest"]
56
+
57
+ [tool.hatch.build.targets.sdist]
58
+ include = ["src/", "tests/", "README.md", "LICENSE"]
59
+
60
+ [tool.pytest.ini_options]
61
+ asyncio_mode = "auto"
62
+ testpaths = ["tests"]
63
+
64
+ [tool.hatch.version]
65
+ path = "src/agent_manifest/__init__.py"
66
+
67
+ [tool.mypy]
68
+ python_version = "3.11"
69
+ strict = true
70
+ ignore_missing_imports = true
71
+
72
+ [[tool.mypy.overrides]]
73
+ module = "agent_manifest._hw_providers"
74
+ warn_unused_ignores = false
75
+
76
+ [tool.coverage.run]
77
+ source = ["src/agent_manifest"]
78
+ omit = ["src/agent_manifest/cli.py"]
79
+
80
+ [tool.coverage.report]
81
+ fail_under = 80
82
+ show_missing = true
83
+
84
+ [tool.bandit]
85
+ exclude_dirs = ["tests"]
86
+ # B101: assert statements (test helpers); B404/B603/B607: TPM attestation
87
+ # providers require subprocess — inputs are validated before the call and
88
+ # never include user-controlled data, so these are false positives.
89
+ skips = ["B101", "B404", "B603", "B607"]
@@ -0,0 +1,47 @@
1
+ """Agent Manifest SDK - public API."""
2
+ from .models import (
3
+ Manifest, ArtifactBindings,
4
+ SystemPromptBinding, PolicyBundleBinding, ToolManifestBinding,
5
+ ModelIdentityBinding, RagCorpusBinding, MemoryBaselineBinding,
6
+ DecisionTraceBinding, SupplyChainBinding,
7
+ DelegationHop, HitlRecord, HitlApproval, ManifestSignature,
8
+ ToolEntry, ScopeGrant, ApprovedScope, PoisoningScan, SlsaProvenance,
9
+ Sbom, McpServer,
10
+ EscalationPolicy, HitlRuntime,
11
+ TransparencyLogEntry, InclusionProof,
12
+ LogRetention, DataScope, OperationalLifecycle,
13
+ PolicyLanguage, EnforcementMode, DeploymentType, MemoryType, DriftPolicy,
14
+ RugPullPolicy, TraceType, SbomFormat, SlsaLevel, PoisoningResult,
15
+ ApprovalMethod, ApproverIdentityType, PrincipalType, DataClassification,
16
+ CryptoProfile, SignatureAlgorithm, KeyType, RiskTier,
17
+ ModelAttestationType, OverrideMechanism, TimeoutAction,
18
+ )
19
+ from ._types import HashValue, ManifestId
20
+ from ._canonicalize import canonicalize, canonical_hash
21
+ from ._signing import (
22
+ SIGNED_FIELDS,
23
+ signing_pre_image,
24
+ generate_ed25519, Ed25519KeyPair, Ed25519Signer, Ed25519Verifier,
25
+ )
26
+
27
+ __all__ = [
28
+ "Manifest", "ArtifactBindings",
29
+ "SystemPromptBinding", "PolicyBundleBinding", "ToolManifestBinding",
30
+ "ModelIdentityBinding", "RagCorpusBinding", "MemoryBaselineBinding",
31
+ "DecisionTraceBinding", "SupplyChainBinding",
32
+ "DelegationHop", "HitlRecord", "HitlApproval", "ManifestSignature",
33
+ "ToolEntry", "ScopeGrant", "ApprovedScope", "PoisoningScan", "SlsaProvenance",
34
+ "Sbom", "McpServer",
35
+ "EscalationPolicy", "HitlRuntime",
36
+ "TransparencyLogEntry", "InclusionProof",
37
+ "LogRetention", "DataScope", "OperationalLifecycle",
38
+ "PolicyLanguage", "EnforcementMode", "DeploymentType", "MemoryType", "DriftPolicy",
39
+ "RugPullPolicy", "TraceType", "SbomFormat", "SlsaLevel", "PoisoningResult",
40
+ "ApprovalMethod", "ApproverIdentityType", "PrincipalType", "DataClassification",
41
+ "CryptoProfile", "SignatureAlgorithm", "KeyType", "RiskTier",
42
+ "ModelAttestationType", "OverrideMechanism", "TimeoutAction",
43
+ "HashValue", "ManifestId",
44
+ "canonicalize", "canonical_hash",
45
+ "SIGNED_FIELDS", "signing_pre_image",
46
+ "generate_ed25519", "Ed25519KeyPair", "Ed25519Signer", "Ed25519Verifier",
47
+ ]
@@ -0,0 +1,85 @@
1
+ """provider='auto' attestation backend selection.
2
+
3
+ Auto-selection order (first locally-verifiable silicon wins):
4
+ 1. SEVSNPProvider — if /dev/sev-guest exists
5
+ 2. TDXProvider — if /dev/tdx-guest exists
6
+ 3. TPMProvider — if tpm2_extend is in PATH
7
+ 4. SoftwareProvider — fallback, Level 0 only (no hardware attestation)
8
+
9
+ OPAQUEProvider is explicit opt-in: selected only when OPAQUE_ATTESTATION_URL
10
+ is set. It is never auto-detected.
11
+
12
+ The SoftwareProvider is never selected automatically for Level 1+ contexts.
13
+ Callers that require Level 1+ MUST explicitly check provider.level >= 1.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ import shutil
19
+ from typing import Any, cast
20
+
21
+ from ._providers import AttestationProvider, AttestationReport, AttestationUnavailableError, TPMProvider
22
+
23
+
24
+ class SoftwareProvider(AttestationProvider):
25
+ """Level 0 software-only fallback — no hardware attestation.
26
+
27
+ Produces a manifest hash using pure software SHA-256. Suitable for
28
+ development and staging. MUST NOT be used for Level 1+ conformance.
29
+ """
30
+
31
+ LEVEL = 0
32
+
33
+ def extend_manifest_hash(self, manifest_json: dict[str, Any]) -> None:
34
+ # No hardware to extend into — record the hash for report generation
35
+ self._manifest_hash = self.manifest_hash_value(manifest_json)
36
+
37
+ def get_attestation_report(self) -> AttestationReport:
38
+ if not hasattr(self, "_manifest_hash"):
39
+ raise AttestationUnavailableError(
40
+ "Call extend_manifest_hash() before get_attestation_report()."
41
+ )
42
+ return AttestationReport(platform="software", manifest_hash=self._manifest_hash)
43
+
44
+ def verify_manifest_in_report(self, report: AttestationReport, manifest_json: dict[str, Any]) -> bool:
45
+ return bool(report.manifest_hash == self.manifest_hash_value(manifest_json))
46
+
47
+
48
+ def select_provider(level: int = 0) -> AttestationProvider:
49
+ """Return the best available attestation provider for *level*.
50
+
51
+ Args:
52
+ level: Minimum conformance level required (0-3).
53
+
54
+ Raises:
55
+ AttestationUnavailableError: If *level* > 0 and no hardware provider
56
+ is available.
57
+ """
58
+ # OPAQUE managed runtime — explicit opt-in only, not auto-detected
59
+ if os.environ.get("OPAQUE_ATTESTATION_URL"):
60
+ from ._hw_providers import OPAQUEProvider
61
+ return cast(AttestationProvider, OPAQUEProvider())
62
+
63
+ # AMD SEV-SNP
64
+ if os.path.exists("/dev/sev-guest"):
65
+ from ._hw_providers import SEVSNPProvider
66
+ return cast(AttestationProvider, SEVSNPProvider())
67
+
68
+ # Intel TDX
69
+ if os.path.exists("/dev/tdx-guest"):
70
+ from ._hw_providers import TDXProvider
71
+ return cast(AttestationProvider, TDXProvider())
72
+
73
+ # Generic TPM / AWS Nitro
74
+ if shutil.which("tpm2_extend"):
75
+ return TPMProvider()
76
+
77
+ # Software fallback
78
+ if level >= 1:
79
+ raise AttestationUnavailableError(
80
+ "No hardware attestation provider available. "
81
+ "Level 1+ conformance requires TPM 2.0, AMD SEV-SNP, or Intel TDX. "
82
+ "To use the OPAQUE managed runtime, set OPAQUE_ATTESTATION_URL. "
83
+ "For development use, set level=0 explicitly."
84
+ )
85
+ return SoftwareProvider()