bastion-sdk 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.
@@ -0,0 +1,24 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.*
5
+ !.env.example
6
+ *.tsbuildinfo
7
+
8
+ # Python
9
+ __pycache__/
10
+ *.egg-info/
11
+ .venv/
12
+ *.pyc
13
+
14
+ # IDE
15
+ .vscode/
16
+ .idea/
17
+ *.swp
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Prisma
24
+ packages/api/prisma/*.db
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: bastion-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the Bastion trust proxy
5
+ Project-URL: Homepage, https://github.com/Matthieuhakim/Bastion
6
+ Project-URL: Repository, https://github.com/Matthieuhakim/Bastion
7
+ Project-URL: Issues, https://github.com/Matthieuhakim/Bastion/issues
8
+ Author: Matthieu Hakim
9
+ License-Expression: MIT
10
+ Keywords: agents,ai,audit,proxy,python,security
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.27.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest-asyncio>=0.25.0; extra == 'dev'
24
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
25
+ Requires-Dist: respx>=0.22.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # bastion-sdk
30
+
31
+ Python SDK for the [Bastion](../../README.md) trust proxy. Supports both sync and async usage.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install bastion-sdk
37
+ ```
38
+
39
+ Requires Python 3.10+.
40
+
41
+ ## Quick Start
42
+
43
+ ```python
44
+ from bastion_sdk import BastionClient
45
+
46
+ with BastionClient("http://localhost:3000", api_key="your-project-api-key") as client:
47
+ print(client.health())
48
+ ```
49
+
50
+ ### Async
51
+
52
+ ```python
53
+ from bastion_sdk import AsyncBastionClient
54
+
55
+ async with AsyncBastionClient("http://localhost:3000", api_key="your-key") as client:
56
+ print(await client.health())
57
+ ```
58
+
59
+ ## Admin Operations
60
+
61
+ Use the admin API key (`PROJECT_API_KEY`) to manage agents, credentials, and policies.
62
+
63
+ ### Agents
64
+
65
+ ```python
66
+ # Create an agent (returns one-time agentSecret)
67
+ agent = client.create_agent("Support Bot", description="Handles refund requests")
68
+ agent_secret = agent["agentSecret"] # save this — shown only once
69
+
70
+ # List, get, update, delete
71
+ agents = client.list_agents()
72
+ agent = client.get_agent(agent["id"])
73
+ client.update_agent(agent["id"], isActive=False)
74
+ client.delete_agent(agent["id"]) # soft-delete
75
+ ```
76
+
77
+ ### Credentials
78
+
79
+ ```python
80
+ # Store a credential (encrypted at rest, raw value never returned)
81
+ credential = client.create_credential(
82
+ name="Stripe Production",
83
+ type="API_KEY",
84
+ value="sk_live_...",
85
+ agent_id=agent["id"],
86
+ )
87
+
88
+ credentials = client.list_credentials(agent_id=agent["id"])
89
+ client.revoke_credential(credential["id"])
90
+ ```
91
+
92
+ ### Policies
93
+
94
+ ```python
95
+ policy = client.create_policy(
96
+ agent_id=agent["id"],
97
+ credential_id=credential["id"],
98
+ allowed_actions=["charges.*"],
99
+ denied_actions=["transfers.*"],
100
+ constraints={
101
+ "maxAmountPerTransaction": 1000,
102
+ "maxDailySpend": 5000,
103
+ "rateLimit": {"maxRequests": 100, "windowSeconds": 3600},
104
+ },
105
+ requires_approval_above=500,
106
+ )
107
+
108
+ # Dry-run evaluation (no side effects)
109
+ result = client.evaluate_policy(
110
+ agent_id=agent["id"],
111
+ credential_id=credential["id"],
112
+ action="charges.create",
113
+ params={"amount": 750},
114
+ )
115
+ # result["decision"] → "ESCALATE"
116
+ ```
117
+
118
+ ## Agent Operations
119
+
120
+ Use an agent secret (`bst_...`) for proxy execution.
121
+
122
+ ```python
123
+ agent_client = BastionClient("http://localhost:3000", api_key=agent_secret)
124
+
125
+ result = agent_client.execute(
126
+ credential_id=credential["id"],
127
+ action="charges.create",
128
+ target={
129
+ "url": "https://api.stripe.com/v1/charges",
130
+ "method": "POST",
131
+ "body": {"amount": 5000, "currency": "usd"},
132
+ },
133
+ params={"amount": 50},
134
+ )
135
+
136
+ # result["upstream"]["status"] → 200
137
+ # result["upstream"]["body"] → Stripe's response
138
+ # result["meta"]["policyDecision"] → "ALLOW"
139
+ ```
140
+
141
+ ### Custom Credential Injection
142
+
143
+ ```python
144
+ agent_client.execute(
145
+ credential_id=credential["id"],
146
+ action="test",
147
+ target={"url": "https://api.example.com"},
148
+ injection={"location": "header", "key": "X-Api-Key"},
149
+ )
150
+ ```
151
+
152
+ ## HITL (Human-in-the-Loop)
153
+
154
+ ```python
155
+ pending = client.list_pending_requests()
156
+ client.approve_request(pending[0]["requestId"])
157
+ client.deny_request(request_id, "Too risky")
158
+ ```
159
+
160
+ ## Audit
161
+
162
+ ```python
163
+ records = client.query_audit_records(
164
+ agent["id"],
165
+ from_="2026-01-01",
166
+ policy_decision="DENY",
167
+ limit=10,
168
+ )
169
+
170
+ verification = client.verify_chain(agent["id"])
171
+ # verification["valid"] → True
172
+ ```
173
+
174
+ ## Error Handling
175
+
176
+ All API errors raise typed exceptions:
177
+
178
+ ```python
179
+ from bastion_sdk import BastionForbiddenError, BastionNotFoundError
180
+
181
+ try:
182
+ agent_client.execute(...)
183
+ except BastionForbiddenError as e:
184
+ print(f"Policy denied: {e.message}")
185
+ ```
186
+
187
+ | Error Class | Status | When |
188
+ |------------|--------|------|
189
+ | `BastionValidationError` | 400 | Invalid input |
190
+ | `BastionUnauthorizedError` | 401 | Bad or missing auth |
191
+ | `BastionForbiddenError` | 403 | Policy DENY or HITL timeout |
192
+ | `BastionNotFoundError` | 404 | Resource not found |
193
+ | `BastionConflictError` | 409 | State conflict |
194
+ | `BastionBadGatewayError` | 502 | Upstream API failure |
195
+
196
+ ## License
197
+
198
+ [MIT](../../LICENSE)
@@ -0,0 +1,170 @@
1
+ # bastion-sdk
2
+
3
+ Python SDK for the [Bastion](../../README.md) trust proxy. Supports both sync and async usage.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install bastion-sdk
9
+ ```
10
+
11
+ Requires Python 3.10+.
12
+
13
+ ## Quick Start
14
+
15
+ ```python
16
+ from bastion_sdk import BastionClient
17
+
18
+ with BastionClient("http://localhost:3000", api_key="your-project-api-key") as client:
19
+ print(client.health())
20
+ ```
21
+
22
+ ### Async
23
+
24
+ ```python
25
+ from bastion_sdk import AsyncBastionClient
26
+
27
+ async with AsyncBastionClient("http://localhost:3000", api_key="your-key") as client:
28
+ print(await client.health())
29
+ ```
30
+
31
+ ## Admin Operations
32
+
33
+ Use the admin API key (`PROJECT_API_KEY`) to manage agents, credentials, and policies.
34
+
35
+ ### Agents
36
+
37
+ ```python
38
+ # Create an agent (returns one-time agentSecret)
39
+ agent = client.create_agent("Support Bot", description="Handles refund requests")
40
+ agent_secret = agent["agentSecret"] # save this — shown only once
41
+
42
+ # List, get, update, delete
43
+ agents = client.list_agents()
44
+ agent = client.get_agent(agent["id"])
45
+ client.update_agent(agent["id"], isActive=False)
46
+ client.delete_agent(agent["id"]) # soft-delete
47
+ ```
48
+
49
+ ### Credentials
50
+
51
+ ```python
52
+ # Store a credential (encrypted at rest, raw value never returned)
53
+ credential = client.create_credential(
54
+ name="Stripe Production",
55
+ type="API_KEY",
56
+ value="sk_live_...",
57
+ agent_id=agent["id"],
58
+ )
59
+
60
+ credentials = client.list_credentials(agent_id=agent["id"])
61
+ client.revoke_credential(credential["id"])
62
+ ```
63
+
64
+ ### Policies
65
+
66
+ ```python
67
+ policy = client.create_policy(
68
+ agent_id=agent["id"],
69
+ credential_id=credential["id"],
70
+ allowed_actions=["charges.*"],
71
+ denied_actions=["transfers.*"],
72
+ constraints={
73
+ "maxAmountPerTransaction": 1000,
74
+ "maxDailySpend": 5000,
75
+ "rateLimit": {"maxRequests": 100, "windowSeconds": 3600},
76
+ },
77
+ requires_approval_above=500,
78
+ )
79
+
80
+ # Dry-run evaluation (no side effects)
81
+ result = client.evaluate_policy(
82
+ agent_id=agent["id"],
83
+ credential_id=credential["id"],
84
+ action="charges.create",
85
+ params={"amount": 750},
86
+ )
87
+ # result["decision"] → "ESCALATE"
88
+ ```
89
+
90
+ ## Agent Operations
91
+
92
+ Use an agent secret (`bst_...`) for proxy execution.
93
+
94
+ ```python
95
+ agent_client = BastionClient("http://localhost:3000", api_key=agent_secret)
96
+
97
+ result = agent_client.execute(
98
+ credential_id=credential["id"],
99
+ action="charges.create",
100
+ target={
101
+ "url": "https://api.stripe.com/v1/charges",
102
+ "method": "POST",
103
+ "body": {"amount": 5000, "currency": "usd"},
104
+ },
105
+ params={"amount": 50},
106
+ )
107
+
108
+ # result["upstream"]["status"] → 200
109
+ # result["upstream"]["body"] → Stripe's response
110
+ # result["meta"]["policyDecision"] → "ALLOW"
111
+ ```
112
+
113
+ ### Custom Credential Injection
114
+
115
+ ```python
116
+ agent_client.execute(
117
+ credential_id=credential["id"],
118
+ action="test",
119
+ target={"url": "https://api.example.com"},
120
+ injection={"location": "header", "key": "X-Api-Key"},
121
+ )
122
+ ```
123
+
124
+ ## HITL (Human-in-the-Loop)
125
+
126
+ ```python
127
+ pending = client.list_pending_requests()
128
+ client.approve_request(pending[0]["requestId"])
129
+ client.deny_request(request_id, "Too risky")
130
+ ```
131
+
132
+ ## Audit
133
+
134
+ ```python
135
+ records = client.query_audit_records(
136
+ agent["id"],
137
+ from_="2026-01-01",
138
+ policy_decision="DENY",
139
+ limit=10,
140
+ )
141
+
142
+ verification = client.verify_chain(agent["id"])
143
+ # verification["valid"] → True
144
+ ```
145
+
146
+ ## Error Handling
147
+
148
+ All API errors raise typed exceptions:
149
+
150
+ ```python
151
+ from bastion_sdk import BastionForbiddenError, BastionNotFoundError
152
+
153
+ try:
154
+ agent_client.execute(...)
155
+ except BastionForbiddenError as e:
156
+ print(f"Policy denied: {e.message}")
157
+ ```
158
+
159
+ | Error Class | Status | When |
160
+ |------------|--------|------|
161
+ | `BastionValidationError` | 400 | Invalid input |
162
+ | `BastionUnauthorizedError` | 401 | Bad or missing auth |
163
+ | `BastionForbiddenError` | 403 | Policy DENY or HITL timeout |
164
+ | `BastionNotFoundError` | 404 | Resource not found |
165
+ | `BastionConflictError` | 409 | State conflict |
166
+ | `BastionBadGatewayError` | 502 | Upstream API failure |
167
+
168
+ ## License
169
+
170
+ [MIT](../../LICENSE)
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "bastion-sdk"
7
+ version = "0.1.0"
8
+ description = "Python SDK for the Bastion trust proxy"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Matthieu Hakim" },
14
+ ]
15
+ keywords = ["ai", "agents", "security", "proxy", "audit", "python"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Security",
25
+ "Topic :: Software Development :: Libraries :: Python Modules",
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27.0",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/Matthieuhakim/Bastion"
33
+ Repository = "https://github.com/Matthieuhakim/Bastion"
34
+ Issues = "https://github.com/Matthieuhakim/Bastion/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=8.0.0",
39
+ "pytest-asyncio>=0.25.0",
40
+ "respx>=0.22.0",
41
+ "ruff>=0.8.0",
42
+ ]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/bastion_sdk"]
46
+
47
+ [tool.pytest.ini_options]
48
+ asyncio_mode = "auto"
@@ -0,0 +1,25 @@
1
+ """Bastion SDK - Python client for the Bastion trust proxy."""
2
+
3
+ from .client import AsyncBastionClient, BastionClient
4
+ from .errors import (
5
+ BastionBadGatewayError,
6
+ BastionConflictError,
7
+ BastionError,
8
+ BastionForbiddenError,
9
+ BastionNotFoundError,
10
+ BastionUnauthorizedError,
11
+ BastionValidationError,
12
+ )
13
+
14
+ __all__ = [
15
+ "AsyncBastionClient",
16
+ "BastionBadGatewayError",
17
+ "BastionClient",
18
+ "BastionConflictError",
19
+ "BastionError",
20
+ "BastionForbiddenError",
21
+ "BastionNotFoundError",
22
+ "BastionUnauthorizedError",
23
+ "BastionValidationError",
24
+ ]
25
+ __version__ = "0.1.0"