agent-trust-plane 0.3.2__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.
- agent_trust_plane-0.3.2/.gitignore +40 -0
- agent_trust_plane-0.3.2/LICENSE +21 -0
- agent_trust_plane-0.3.2/PKG-INFO +143 -0
- agent_trust_plane-0.3.2/README.md +104 -0
- agent_trust_plane-0.3.2/adapters/http/pyproject.toml +20 -0
- agent_trust_plane-0.3.2/adapters/http/src/atp_adapter_http/__init__.py +19 -0
- agent_trust_plane-0.3.2/adapters/http/src/atp_adapter_http/client.py +334 -0
- agent_trust_plane-0.3.2/adapters/http/src/atp_adapter_http/py.typed +0 -0
- agent_trust_plane-0.3.2/adapters/mcp/pyproject.toml +23 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/__init__.py +30 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/__main__.py +6 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/config.py +187 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/discovery.py +189 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/mapping.py +138 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/proxy.py +389 -0
- agent_trust_plane-0.3.2/adapters/mcp/src/atp_adapter_mcp/py.typed +0 -0
- agent_trust_plane-0.3.2/examples/finance-agent/pyproject.toml +23 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/__init__.py +44 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/__main__.py +86 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/agent.py +155 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/invoices.py +89 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/py.typed +0 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/runner.py +172 -0
- agent_trust_plane-0.3.2/examples/finance-agent/src/finance_agent/scenario.py +157 -0
- agent_trust_plane-0.3.2/examples/github-action/README.md +28 -0
- agent_trust_plane-0.3.2/examples/notes-mcp-server/pyproject.toml +16 -0
- agent_trust_plane-0.3.2/examples/notes-mcp-server/src/notes_mcp_server/__init__.py +81 -0
- agent_trust_plane-0.3.2/examples/notes-mcp-server/src/notes_mcp_server/__main__.py +4 -0
- agent_trust_plane-0.3.2/examples/notes-mcp-server/src/notes_mcp_server/py.typed +0 -0
- agent_trust_plane-0.3.2/examples/regression-suite/README.md +18 -0
- agent_trust_plane-0.3.2/packages/audit/pyproject.toml +19 -0
- agent_trust_plane-0.3.2/packages/audit/src/atp_audit/__init__.py +22 -0
- agent_trust_plane-0.3.2/packages/audit/src/atp_audit/events.py +92 -0
- agent_trust_plane-0.3.2/packages/audit/src/atp_audit/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/audit/src/atp_audit/store.py +269 -0
- agent_trust_plane-0.3.2/packages/cli/pyproject.toml +35 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/__init__.py +1 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/demos.py +409 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/doctor.py +136 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/home.py +138 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/main.py +755 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/mcp_cmds.py +220 -0
- agent_trust_plane-0.3.2/packages/cli/src/atp_cli/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/core/pyproject.toml +18 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/__init__.py +64 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/authority.py +56 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/canonical.py +48 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/decision.py +126 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/envelope.py +145 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/errors.py +28 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/files.py +18 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/ids.py +14 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/money.py +60 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/principals.py +23 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/reasons.py +93 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/resources.py +14 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/sqlite.py +57 -0
- agent_trust_plane-0.3.2/packages/core/src/atp_core/timeutil.py +18 -0
- agent_trust_plane-0.3.2/packages/evals/pyproject.toml +25 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/__init__.py +20 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/__main__.py +62 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/analysis.py +454 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/harness.py +80 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/model.py +69 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/regression/__init__.py +43 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/regression/format.py +198 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/regression/record.py +156 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/regression/runner.py +300 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/runner.py +108 -0
- agent_trust_plane-0.3.2/packages/evals/src/atp_evals/scenarios.py +557 -0
- agent_trust_plane-0.3.2/packages/identity/pyproject.toml +19 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/__init__.py +40 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/credentials.py +254 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/grants.py +91 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/provider.py +68 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/scope.py +121 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/service.py +299 -0
- agent_trust_plane-0.3.2/packages/identity/src/atp_identity/store.py +127 -0
- agent_trust_plane-0.3.2/packages/policy/pyproject.toml +21 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/__init__.py +45 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/analysis.py +182 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/base.py +111 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/declarative.py +417 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/directory.py +45 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/engine.py +66 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/explain.py +256 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/policies/__init__.py +27 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/policies/authority.py +89 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/policies/payments.py +255 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/py.typed +0 -0
- agent_trust_plane-0.3.2/packages/policy/src/atp_policy/registry.py +119 -0
- agent_trust_plane-0.3.2/pyproject.toml +207 -0
- agent_trust_plane-0.3.2/services/gateway/pyproject.toml +30 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/__init__.py +25 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/__main__.py +66 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/api.py +330 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/app.py +99 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/auth.py +83 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/evidence.py +115 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/grants.py +277 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/local.py +169 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/py.typed +0 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/reports.py +66 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/schemas.py +116 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/service.py +753 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/settings.py +90 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/tools.py +177 -0
- agent_trust_plane-0.3.2/services/gateway/src/atp_gateway/wiring.py +140 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# python
|
|
2
|
+
.venv/
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.pyc
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.coverage
|
|
12
|
+
htmlcov/
|
|
13
|
+
|
|
14
|
+
# data
|
|
15
|
+
*.db
|
|
16
|
+
*.db-journal
|
|
17
|
+
*.sqlite
|
|
18
|
+
data/
|
|
19
|
+
eval-reports/
|
|
20
|
+
|
|
21
|
+
# node
|
|
22
|
+
node_modules/
|
|
23
|
+
apps/dashboard/.next/
|
|
24
|
+
apps/dashboard/out/
|
|
25
|
+
*.tsbuildinfo
|
|
26
|
+
next-env.d.ts
|
|
27
|
+
|
|
28
|
+
# env
|
|
29
|
+
.env
|
|
30
|
+
.env.local
|
|
31
|
+
|
|
32
|
+
# os / editors
|
|
33
|
+
.DS_Store
|
|
34
|
+
Thumbs.db
|
|
35
|
+
.idea/
|
|
36
|
+
.vscode/
|
|
37
|
+
.pytest-tmp/
|
|
38
|
+
|
|
39
|
+
# local ATP home (keys + evidence store)
|
|
40
|
+
.atp/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 George Gakravyi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agent-trust-plane
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: Authorization boundary and security regression testing for AI agent tool calls (MCP): decide on arguments against delegated authority, bind decisions to single-use grants, replay, and pin denials as CI tests. Experimental.
|
|
5
|
+
Project-URL: Homepage, https://github.com/TimelessVisions/agent-trust-plane
|
|
6
|
+
Project-URL: Repository, https://github.com/TimelessVisions/agent-trust-plane
|
|
7
|
+
Project-URL: Issues, https://github.com/TimelessVisions/agent-trust-plane/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/TimelessVisions/agent-trust-plane/tree/main/docs
|
|
9
|
+
Project-URL: Changelog, https://github.com/TimelessVisions/agent-trust-plane/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Security, https://github.com/TimelessVisions/agent-trust-plane/blob/main/SECURITY.md
|
|
11
|
+
Author-email: George Gakravyi <george@agentcommercegateway.com>
|
|
12
|
+
License-Expression: MIT
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: agent-security,ai-agents,authorization,llm-security,mcp,model-context-protocol,regression-testing,security-testing
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Environment :: Console
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Intended Audience :: Information Technology
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Topic :: Security
|
|
27
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
|
+
Classifier: Topic :: Software Development :: Testing
|
|
29
|
+
Classifier: Typing :: Typed
|
|
30
|
+
Requires-Python: >=3.12
|
|
31
|
+
Requires-Dist: fastapi>=0.115
|
|
32
|
+
Requires-Dist: httpx>=0.28
|
|
33
|
+
Requires-Dist: mcp<3,>=2.2
|
|
34
|
+
Requires-Dist: pydantic-settings>=2.7
|
|
35
|
+
Requires-Dist: pydantic>=2.10
|
|
36
|
+
Requires-Dist: pyyaml>=6.0
|
|
37
|
+
Requires-Dist: uvicorn[standard]>=0.34
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# Agent Trust Plane
|
|
41
|
+
|
|
42
|
+
**Put a real authorization boundary between your AI agent and its tools, and turn every dangerous action into a regression test so it cannot silently come back.**
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv run atp demo wrap # a real MCP server, wrapped; one ALLOW, one DENY, one regression test
|
|
48
|
+
uv run atp mcp init -- <your mcp server> # then: atp mcp wrap (Streamable HTTP upstreams: --url)
|
|
49
|
+
uv run atp regression add <trace> && uv run atp test atp-regression.yaml
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **Status: experimental, v0.3.2, no users yet, not independently audited.** Every claim below is backed by a test in this repository or says otherwise. What it does *not* protect is in [docs/security/threat-model.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/threat-model.md).
|
|
53
|
+
|
|
54
|
+
## Why this exists
|
|
55
|
+
|
|
56
|
+
Agents act on tool calls, and the tool call is where prompt injection turns into damage: pay this account, delete that file, move this repo. Gateways in front of MCP servers authenticate the caller and allow tools by *name*; most cannot decide on the *arguments* (amount, path, destination) and none replay a recorded decision or keep it fixed in CI ([research, with citations](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/research/competitive-code-review.md)). ATP does that part and only that part: it is a decision-and-evidence layer, not a gateway ([why-atp.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/why-atp.md)).
|
|
57
|
+
|
|
58
|
+
## How it works
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
agent / MCP client ──stdio──▶ atp mcp wrap ──▶ upstream MCP server (stdio or Streamable HTTP)
|
|
62
|
+
│
|
|
63
|
+
authenticate the agent; resolve HUMAN → agent delegation (capabilities,
|
|
64
|
+
resource scope, limits — a child can only narrow)
|
|
65
|
+
build an ActionEnvelope from the call (paths normalised, args bounded)
|
|
66
|
+
decide: kernel policies + your declared policy set → ALLOW / DENY / WOULD_DENY
|
|
67
|
+
ALLOW → single-use grant over the exact action hash → forward → record outcome
|
|
68
|
+
DENY → refuse (enforce) | forward and record WOULD_DENY (shadow)
|
|
69
|
+
everything on a hash-chained trace in .atp/
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Then, offline: `atp trace list` · `atp policy explain TRACE` · `atp regression add TRACE` · `atp test` · `atp policy impact --from A --to B` · `atp mutate TRACE` · `atp evidence export TRACE`.
|
|
73
|
+
|
|
74
|
+
## Quickstart (measured: [docs/first-user-test-v2.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/first-user-test-v2.md))
|
|
75
|
+
|
|
76
|
+
Prerequisites: Python ≥ 3.12 and [uv](https://docs.astral.sh/uv/). No API keys, no Docker, no database setup, no secrets to copy.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git clone <this repository> && cd agent-trust-plane
|
|
80
|
+
uv run atp demo wrap # syncs the workspace on first run; 37 s cold on the maintainer machine
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The same commands work in PowerShell. `uv run atp doctor` explains anything missing. Other demos: `atp demo injection` (an injected invoice tries to pay $12,500 on a $1,000 delegation), `atp demo regression` (a permitted payment reveals a policy hole; replay under the fix flips it), `atp demo mcp` (the proxy against a remote-style gateway) — [docs/demos.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/demos.md).
|
|
84
|
+
|
|
85
|
+
## Wrap your own MCP server
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv run atp mcp init --name fs -- npx -y @modelcontextprotocol/server-filesystem /abs/sandbox
|
|
89
|
+
# reads tools/list; proposes capabilities from the server's annotations (unverified: review them);
|
|
90
|
+
# writes atp-mcp.yaml and .atp/policies.yaml (declared set fs-v1)
|
|
91
|
+
uv run atp mcp wrap --mode shadow # observe first: denials are recorded as WOULD_DENY and forwarded
|
|
92
|
+
uv run atp mcp wrap # enforce
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Tools the server itself marks destructive (`write_file`, `edit_file`, `move_file` on the reference server) get `fs:destroy`, which is **not delegated by default**: the first write is denied with `CAPABILITY_NOT_GRANTED` until you add `fs:destroy` to `authority.capabilities` in `atp-mcp.yaml` — a deliberate fail-closed default, and the one thing the first-user test tripped over.
|
|
96
|
+
|
|
97
|
+
Point your MCP client at the wrap command instead of the server ([config example](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/integrations/frameworks.md)). Verified upstreams: this repo's notes server (stdio and Streamable HTTP, every CI run) and the reference `@modelcontextprotocol/server-filesystem` (opt-in test, run 2026-09-17). Everything else is listed as *not verified* in [docs/integrations/compatibility.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/integrations/compatibility.md).
|
|
98
|
+
|
|
99
|
+
Scope paths, not just tool names: `resource_scope: ["path:/abs/sandbox/*"]` with `..`, separators and (optionally) case normalised before matching. Argument limits go in [`.atp/policies.yaml`](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/policies/policies.md):
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
rules:
|
|
103
|
+
- id: no-large-writes
|
|
104
|
+
applies_to: {tool: mcp.fs, action: write_file}
|
|
105
|
+
kind: argument_max_length
|
|
106
|
+
argument: content
|
|
107
|
+
max_length: 20000
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Security regression tests
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
uv run atp trace list # what was ALLOWed / DENIED / WOULD_DENY
|
|
114
|
+
uv run atp policy explain 457328bdd4ef # which constraint failed, and what would need to change
|
|
115
|
+
uv run atp regression add 457328bdd4ef --name "delete stays denied"
|
|
116
|
+
uv run atp test atp-regression.yaml # exit 1 if the decision ever changes; --junit/--json for CI
|
|
117
|
+
uv run atp policy impact --from fs-v1 --to fs-v2 # which recorded actions flip; DENY -> ALLOW first
|
|
118
|
+
uv run atp mutate 457328bdd4ef # perturb the recorded action; authorize only, never execute
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
A suite is YAML: principals, a delegation graph, cases with the expected outcome / reason / policy. Runs use an ephemeral in-process gateway and call only `/authorize` — a spy on `execute` sees zero calls. CI example without secrets: [examples/regression-suite](https://github.com/TimelessVisions/agent-trust-plane/tree/main/examples/regression-suite/) and a copy-in [composite action](https://github.com/TimelessVisions/agent-trust-plane/tree/main/examples/github-action/). Guide: [docs/regression/regression-testing.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/regression/regression-testing.md).
|
|
122
|
+
|
|
123
|
+
## Architecture
|
|
124
|
+
|
|
125
|
+
Protocol-neutral kernel (`atp_core` envelope/decision, `atp_identity` credentials + delegation chains, `atp_policy` engine + declared sets, `atp_audit` hash chain, `atp_gateway` service/grants/API) with adapters on the edge (`atp_adapter_mcp` proxy, `atp_adapter_http` client) and the `atp` CLI. One distribution, `agent-trust-plane`, installs everything (`uvx --from <wheel-or-git-url> atp …`). The kernel imports nothing from MCP — a test enforces it. Details: [docs/architecture/architecture.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/architecture/architecture.md), [first principles](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/architecture/first-principles.md), [ADRs](https://github.com/TimelessVisions/agent-trust-plane/tree/main/docs/adr/).
|
|
126
|
+
|
|
127
|
+
Overhead ([docs/benchmarks.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/benchmarks.md), single machine, sequential): policy engine 0.26 ms; `atp mcp wrap` adds ~11 ms p50 to an MCP tool call with durable SQLite evidence; the HTTP-gateway proxy path adds ~21 ms.
|
|
128
|
+
|
|
129
|
+
## Security model and limitations
|
|
130
|
+
|
|
131
|
+
Guarantees, assumptions, deployment requirements, non-guarantees and known gaps are separated in [docs/security/threat-model.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/threat-model.md); attempted attacks and results in [docs/red-team/architecture-attacks.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/red-team/architecture-attacks.md); the self-review with severities in [docs/security/security-review.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/security-review.md). Headlines:
|
|
132
|
+
|
|
133
|
+
- **Only the mediated path is protected.** An agent that can reach the tool without the proxy is not stopped — a test shows it on purpose. Whether that can happen is a deployment property: [docs/security/enforcing-the-boundary.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/enforcing-the-boundary.md).
|
|
134
|
+
- **The operator (and `.atp/keys.env`) is omnipotent**; agent credentials are bearer tokens with expiry and revocation, no proof of possession.
|
|
135
|
+
- **Single-use grants prove one release, not exactly-once external effects**: [docs/security/idempotency.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/idempotency.md).
|
|
136
|
+
- The hash chain catches edits by non-writers; a DB writer can recompute it: [docs/security/trace-integrity.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/trace-integrity.md).
|
|
137
|
+
- Declared policies are limit/equality rules; use OPA/Cedar for more ([why-not-just-opa.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/policies/why-not-just-opa.md)). Prompt injection is bounded, not detected.
|
|
138
|
+
|
|
139
|
+
Evidence for what *is* handled: 439 tests including property-based tests (delegation monotonicity, scope-algebra soundness, a stateful grant lifecycle with tampering and revocation interleaved), an exhaustive check of the grant state machine ([spec](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/formal/grant-lifecycle.md)), eight adversarial evals, and real-protocol MCP end-to-end tests.
|
|
140
|
+
|
|
141
|
+
## Contributing
|
|
142
|
+
|
|
143
|
+
[CONTRIBUTING.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/CONTRIBUTING.md), [DEVELOPMENT.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/DEVELOPMENT.md) (module map, invariants not to break, how to add a policy or adapter), [ROADMAP.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/ROADMAP.md), [docs/good-first-issues.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/good-first-issues.md), [SECURITY.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/SECURITY.md) for reporting a vulnerability, [CHANGELOG.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/CHANGELOG.md). [MIT licensed](https://github.com/TimelessVisions/agent-trust-plane/blob/main/LICENSE) (dependency and copyright record: [docs/release/licensing.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/release/licensing.md)). No telemetry.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Agent Trust Plane
|
|
2
|
+
|
|
3
|
+
**Put a real authorization boundary between your AI agent and its tools, and turn every dangerous action into a regression test so it cannot silently come back.**
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv run atp demo wrap # a real MCP server, wrapped; one ALLOW, one DENY, one regression test
|
|
9
|
+
uv run atp mcp init -- <your mcp server> # then: atp mcp wrap (Streamable HTTP upstreams: --url)
|
|
10
|
+
uv run atp regression add <trace> && uv run atp test atp-regression.yaml
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> **Status: experimental, v0.3.2, no users yet, not independently audited.** Every claim below is backed by a test in this repository or says otherwise. What it does *not* protect is in [docs/security/threat-model.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/threat-model.md).
|
|
14
|
+
|
|
15
|
+
## Why this exists
|
|
16
|
+
|
|
17
|
+
Agents act on tool calls, and the tool call is where prompt injection turns into damage: pay this account, delete that file, move this repo. Gateways in front of MCP servers authenticate the caller and allow tools by *name*; most cannot decide on the *arguments* (amount, path, destination) and none replay a recorded decision or keep it fixed in CI ([research, with citations](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/research/competitive-code-review.md)). ATP does that part and only that part: it is a decision-and-evidence layer, not a gateway ([why-atp.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/why-atp.md)).
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
agent / MCP client ──stdio──▶ atp mcp wrap ──▶ upstream MCP server (stdio or Streamable HTTP)
|
|
23
|
+
│
|
|
24
|
+
authenticate the agent; resolve HUMAN → agent delegation (capabilities,
|
|
25
|
+
resource scope, limits — a child can only narrow)
|
|
26
|
+
build an ActionEnvelope from the call (paths normalised, args bounded)
|
|
27
|
+
decide: kernel policies + your declared policy set → ALLOW / DENY / WOULD_DENY
|
|
28
|
+
ALLOW → single-use grant over the exact action hash → forward → record outcome
|
|
29
|
+
DENY → refuse (enforce) | forward and record WOULD_DENY (shadow)
|
|
30
|
+
everything on a hash-chained trace in .atp/
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then, offline: `atp trace list` · `atp policy explain TRACE` · `atp regression add TRACE` · `atp test` · `atp policy impact --from A --to B` · `atp mutate TRACE` · `atp evidence export TRACE`.
|
|
34
|
+
|
|
35
|
+
## Quickstart (measured: [docs/first-user-test-v2.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/first-user-test-v2.md))
|
|
36
|
+
|
|
37
|
+
Prerequisites: Python ≥ 3.12 and [uv](https://docs.astral.sh/uv/). No API keys, no Docker, no database setup, no secrets to copy.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone <this repository> && cd agent-trust-plane
|
|
41
|
+
uv run atp demo wrap # syncs the workspace on first run; 37 s cold on the maintainer machine
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The same commands work in PowerShell. `uv run atp doctor` explains anything missing. Other demos: `atp demo injection` (an injected invoice tries to pay $12,500 on a $1,000 delegation), `atp demo regression` (a permitted payment reveals a policy hole; replay under the fix flips it), `atp demo mcp` (the proxy against a remote-style gateway) — [docs/demos.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/demos.md).
|
|
45
|
+
|
|
46
|
+
## Wrap your own MCP server
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv run atp mcp init --name fs -- npx -y @modelcontextprotocol/server-filesystem /abs/sandbox
|
|
50
|
+
# reads tools/list; proposes capabilities from the server's annotations (unverified: review them);
|
|
51
|
+
# writes atp-mcp.yaml and .atp/policies.yaml (declared set fs-v1)
|
|
52
|
+
uv run atp mcp wrap --mode shadow # observe first: denials are recorded as WOULD_DENY and forwarded
|
|
53
|
+
uv run atp mcp wrap # enforce
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Tools the server itself marks destructive (`write_file`, `edit_file`, `move_file` on the reference server) get `fs:destroy`, which is **not delegated by default**: the first write is denied with `CAPABILITY_NOT_GRANTED` until you add `fs:destroy` to `authority.capabilities` in `atp-mcp.yaml` — a deliberate fail-closed default, and the one thing the first-user test tripped over.
|
|
57
|
+
|
|
58
|
+
Point your MCP client at the wrap command instead of the server ([config example](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/integrations/frameworks.md)). Verified upstreams: this repo's notes server (stdio and Streamable HTTP, every CI run) and the reference `@modelcontextprotocol/server-filesystem` (opt-in test, run 2026-09-17). Everything else is listed as *not verified* in [docs/integrations/compatibility.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/integrations/compatibility.md).
|
|
59
|
+
|
|
60
|
+
Scope paths, not just tool names: `resource_scope: ["path:/abs/sandbox/*"]` with `..`, separators and (optionally) case normalised before matching. Argument limits go in [`.atp/policies.yaml`](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/policies/policies.md):
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
rules:
|
|
64
|
+
- id: no-large-writes
|
|
65
|
+
applies_to: {tool: mcp.fs, action: write_file}
|
|
66
|
+
kind: argument_max_length
|
|
67
|
+
argument: content
|
|
68
|
+
max_length: 20000
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Security regression tests
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv run atp trace list # what was ALLOWed / DENIED / WOULD_DENY
|
|
75
|
+
uv run atp policy explain 457328bdd4ef # which constraint failed, and what would need to change
|
|
76
|
+
uv run atp regression add 457328bdd4ef --name "delete stays denied"
|
|
77
|
+
uv run atp test atp-regression.yaml # exit 1 if the decision ever changes; --junit/--json for CI
|
|
78
|
+
uv run atp policy impact --from fs-v1 --to fs-v2 # which recorded actions flip; DENY -> ALLOW first
|
|
79
|
+
uv run atp mutate 457328bdd4ef # perturb the recorded action; authorize only, never execute
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A suite is YAML: principals, a delegation graph, cases with the expected outcome / reason / policy. Runs use an ephemeral in-process gateway and call only `/authorize` — a spy on `execute` sees zero calls. CI example without secrets: [examples/regression-suite](https://github.com/TimelessVisions/agent-trust-plane/tree/main/examples/regression-suite/) and a copy-in [composite action](https://github.com/TimelessVisions/agent-trust-plane/tree/main/examples/github-action/). Guide: [docs/regression/regression-testing.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/regression/regression-testing.md).
|
|
83
|
+
|
|
84
|
+
## Architecture
|
|
85
|
+
|
|
86
|
+
Protocol-neutral kernel (`atp_core` envelope/decision, `atp_identity` credentials + delegation chains, `atp_policy` engine + declared sets, `atp_audit` hash chain, `atp_gateway` service/grants/API) with adapters on the edge (`atp_adapter_mcp` proxy, `atp_adapter_http` client) and the `atp` CLI. One distribution, `agent-trust-plane`, installs everything (`uvx --from <wheel-or-git-url> atp …`). The kernel imports nothing from MCP — a test enforces it. Details: [docs/architecture/architecture.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/architecture/architecture.md), [first principles](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/architecture/first-principles.md), [ADRs](https://github.com/TimelessVisions/agent-trust-plane/tree/main/docs/adr/).
|
|
87
|
+
|
|
88
|
+
Overhead ([docs/benchmarks.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/benchmarks.md), single machine, sequential): policy engine 0.26 ms; `atp mcp wrap` adds ~11 ms p50 to an MCP tool call with durable SQLite evidence; the HTTP-gateway proxy path adds ~21 ms.
|
|
89
|
+
|
|
90
|
+
## Security model and limitations
|
|
91
|
+
|
|
92
|
+
Guarantees, assumptions, deployment requirements, non-guarantees and known gaps are separated in [docs/security/threat-model.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/threat-model.md); attempted attacks and results in [docs/red-team/architecture-attacks.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/red-team/architecture-attacks.md); the self-review with severities in [docs/security/security-review.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/security-review.md). Headlines:
|
|
93
|
+
|
|
94
|
+
- **Only the mediated path is protected.** An agent that can reach the tool without the proxy is not stopped — a test shows it on purpose. Whether that can happen is a deployment property: [docs/security/enforcing-the-boundary.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/enforcing-the-boundary.md).
|
|
95
|
+
- **The operator (and `.atp/keys.env`) is omnipotent**; agent credentials are bearer tokens with expiry and revocation, no proof of possession.
|
|
96
|
+
- **Single-use grants prove one release, not exactly-once external effects**: [docs/security/idempotency.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/idempotency.md).
|
|
97
|
+
- The hash chain catches edits by non-writers; a DB writer can recompute it: [docs/security/trace-integrity.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/security/trace-integrity.md).
|
|
98
|
+
- Declared policies are limit/equality rules; use OPA/Cedar for more ([why-not-just-opa.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/policies/why-not-just-opa.md)). Prompt injection is bounded, not detected.
|
|
99
|
+
|
|
100
|
+
Evidence for what *is* handled: 439 tests including property-based tests (delegation monotonicity, scope-algebra soundness, a stateful grant lifecycle with tampering and revocation interleaved), an exhaustive check of the grant state machine ([spec](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/formal/grant-lifecycle.md)), eight adversarial evals, and real-protocol MCP end-to-end tests.
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
[CONTRIBUTING.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/CONTRIBUTING.md), [DEVELOPMENT.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/DEVELOPMENT.md) (module map, invariants not to break, how to add a policy or adapter), [ROADMAP.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/ROADMAP.md), [docs/good-first-issues.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/good-first-issues.md), [SECURITY.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/SECURITY.md) for reporting a vulnerability, [CHANGELOG.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/CHANGELOG.md). [MIT licensed](https://github.com/TimelessVisions/agent-trust-plane/blob/main/LICENSE) (dependency and copyright record: [docs/release/licensing.md](https://github.com/TimelessVisions/agent-trust-plane/blob/main/docs/release/licensing.md)). No telemetry.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "atp-adapter-http"
|
|
3
|
+
version = "0.3.2"
|
|
4
|
+
description = "Agent Trust Plane: HTTP client SDK for agents"
|
|
5
|
+
requires-python = ">=3.12"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"atp-core",
|
|
9
|
+
"httpx>=0.28",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["hatchling>=1.27"]
|
|
14
|
+
build-backend = "hatchling.build"
|
|
15
|
+
|
|
16
|
+
[tool.hatch.build.targets.wheel]
|
|
17
|
+
packages = ["src/atp_adapter_http"]
|
|
18
|
+
|
|
19
|
+
[tool.uv.sources]
|
|
20
|
+
atp-core = { workspace = true }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""HTTP client SDK for agents talking to the trust gateway."""
|
|
2
|
+
|
|
3
|
+
from atp_adapter_http.client import (
|
|
4
|
+
AgentClient,
|
|
5
|
+
AuthorizeResponse,
|
|
6
|
+
ExecuteResponse,
|
|
7
|
+
ExecutionGrant,
|
|
8
|
+
GatewayError,
|
|
9
|
+
TrustPlaneClient,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"AgentClient",
|
|
14
|
+
"AuthorizeResponse",
|
|
15
|
+
"ExecuteResponse",
|
|
16
|
+
"ExecutionGrant",
|
|
17
|
+
"GatewayError",
|
|
18
|
+
"TrustPlaneClient",
|
|
19
|
+
]
|