kavachos 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,45 @@
1
+ # Dependencies
2
+ node_modules/
3
+ .pnpm-store/
4
+
5
+ # Build outputs
6
+ dist/
7
+ build/
8
+ *.tsbuildinfo
9
+ .next/
10
+ .source/
11
+
12
+ # Test & coverage
13
+ coverage/
14
+ .nyc_output/
15
+
16
+ # IDE
17
+ .vscode/
18
+ .idea/
19
+ *.swp
20
+ *.swo
21
+ *~
22
+
23
+ # OS
24
+ .DS_Store
25
+ Thumbs.db
26
+
27
+ # Env
28
+ .env
29
+ .env.*
30
+ !.env.example
31
+
32
+ # Turbo
33
+ .turbo/
34
+
35
+ # Misc
36
+ *.log
37
+ tmp/
38
+ .tmp/
39
+ .cache/
40
+
41
+ # Docs local (research, reference repos, not shipped)
42
+ docs-local/
43
+
44
+ # Claude instructions (project-specific, not shipped)
45
+ CLAUDE.md
@@ -0,0 +1,342 @@
1
+ Metadata-Version: 2.4
2
+ Name: kavachos
3
+ Version: 0.1.0
4
+ Summary: Python SDK for KavachOS — auth OS for AI agents and humans
5
+ Project-URL: Homepage, https://kavachos.com
6
+ Project-URL: Repository, https://github.com/kavachos/kavachos
7
+ Project-URL: Documentation, https://kavachos.com/docs
8
+ Project-URL: Issues, https://github.com/kavachos/kavachos/issues
9
+ License: MIT
10
+ Keywords: agents,ai,auth,identity,mcp,permissions
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Security
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: httpx>=0.27
24
+ Provides-Extra: dev
25
+ Requires-Dist: mypy>=1.9; extra == 'dev'
26
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
27
+ Requires-Dist: pytest>=8.0; extra == 'dev'
28
+ Requires-Dist: respx>=0.21; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # kavachos
32
+
33
+ Python SDK for [KavachOS](https://kavachos.dev) — auth OS for AI agents and humans.
34
+
35
+ [![PyPI](https://img.shields.io/pypi/v/kavachos)](https://pypi.org/project/kavachos/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/kavachos)](https://pypi.org/project/kavachos/)
37
+ [![License](https://img.shields.io/badge/license-MIT-blue)](../../LICENSE)
38
+
39
+ ---
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install kavachos
45
+ ```
46
+
47
+ Requires Python 3.9+ and `httpx`.
48
+
49
+ ---
50
+
51
+ ## Quick start
52
+
53
+ ### Async (recommended)
54
+
55
+ ```python
56
+ import asyncio
57
+ from kavachos import KavachClient
58
+ from kavachos.types import CreateAgentInput
59
+ from kavachos.permissions import read, with_approval, execute
60
+
61
+ async def main():
62
+ async with KavachClient(
63
+ base_url="https://your-app.com/api/kavach",
64
+ token="kv_...",
65
+ ) as client:
66
+ # Create an agent
67
+ agent = await client.agents.create(
68
+ CreateAgentInput(
69
+ owner_id="user-123",
70
+ name="github-reader",
71
+ type="autonomous",
72
+ permissions=[
73
+ read("mcp:github:*"),
74
+ with_approval(execute("mcp:deploy:production")),
75
+ ],
76
+ )
77
+ )
78
+
79
+ # Check authorization
80
+ result = await client.authorize(
81
+ agent.id,
82
+ AuthorizeRequest(action="read", resource="mcp:github:repos"),
83
+ )
84
+ print(result.allowed) # True
85
+
86
+ asyncio.run(main())
87
+ ```
88
+
89
+ ### Sync
90
+
91
+ ```python
92
+ from kavachos import KavachSyncClient
93
+ from kavachos.types import CreateAgentInput
94
+ from kavachos.permissions import read
95
+
96
+ with KavachSyncClient(
97
+ base_url="https://your-app.com/api/kavach",
98
+ token="kv_...",
99
+ ) as client:
100
+ agent = client.agents.create(
101
+ CreateAgentInput(
102
+ owner_id="user-123",
103
+ name="github-reader",
104
+ type="autonomous",
105
+ permissions=[read("mcp:github:*")],
106
+ )
107
+ )
108
+ print(agent.id, agent.token)
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Authentication
114
+
115
+ Sign in and sign up with email and password.
116
+
117
+ ```python
118
+ async with KavachClient(base_url="https://your-app.com/api/kavach") as client:
119
+ # Sign up
120
+ auth = await client.auth.sign_up(
121
+ email="user@example.com",
122
+ password="secure-password",
123
+ name="Alice",
124
+ )
125
+ print(auth.user.id)
126
+ print(auth.session.token)
127
+
128
+ # Sign in later
129
+ auth = await client.auth.sign_in(
130
+ email="user@example.com",
131
+ password="secure-password",
132
+ )
133
+
134
+ # Get current session
135
+ session = await client.auth.get_session(token=auth.session.token)
136
+
137
+ # Sign out
138
+ await client.auth.sign_out()
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Agent management
144
+
145
+ ```python
146
+ from kavachos.types import AgentFilters, UpdateAgentInput
147
+
148
+ # List agents for a user
149
+ agents = await client.agents.list(AgentFilters(user_id="user-123", status="active"))
150
+
151
+ # Get a single agent (returns None if not found)
152
+ agent = await client.agents.get("agent-abc123")
153
+
154
+ # Update name or permissions
155
+ agent = await client.agents.update(
156
+ "agent-abc123",
157
+ UpdateAgentInput(name="better-name"),
158
+ )
159
+
160
+ # Rotate the token (old token is immediately invalidated)
161
+ agent = await client.agents.rotate("agent-abc123")
162
+ print(agent.token) # kv_new_...
163
+
164
+ # Revoke (delete) an agent
165
+ await client.agents.revoke("agent-abc123")
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Authorization
171
+
172
+ ```python
173
+ from kavachos.types import AuthorizeRequest
174
+
175
+ # Authorize by agent ID (requires admin/service token on the client)
176
+ result = await client.authorize(
177
+ "agent-abc123",
178
+ AuthorizeRequest(
179
+ action="execute",
180
+ resource="mcp:deploy:production",
181
+ arguments={"version": "1.2.3"},
182
+ ),
183
+ )
184
+ print(result.allowed) # True / False
185
+ print(result.audit_id) # "aud_..."
186
+
187
+ # Authorize using the agent's own bearer token (no admin token needed)
188
+ result = await client.auth.authorize_by_token(
189
+ agent_token="kv_agent_xyz",
190
+ request=AuthorizeRequest(action="read", resource="mcp:github:repos"),
191
+ )
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Permissions helpers
197
+
198
+ The `kavachos.permissions` module provides shorthand constructors.
199
+
200
+ ```python
201
+ from kavachos.permissions import (
202
+ read,
203
+ write,
204
+ execute,
205
+ read_write,
206
+ full_access,
207
+ with_approval,
208
+ rate_limited,
209
+ )
210
+ from kavachos.types import PermissionConstraints
211
+
212
+ # Simple read permission
213
+ perm = read("mcp:github:*")
214
+
215
+ # Require human approval before execution
216
+ perm = with_approval(execute("mcp:deploy:production"))
217
+
218
+ # Limit to 100 calls per hour
219
+ perm = rate_limited(read("mcp:github:*"), max_calls_per_hour=100)
220
+
221
+ # Full manual construction
222
+ from kavachos.types import Permission
223
+ perm = Permission(
224
+ resource="mcp:github:*",
225
+ actions=["read", "write"],
226
+ constraints=PermissionConstraints(
227
+ max_calls_per_hour=200,
228
+ ip_allowlist=["10.0.0.0/8"],
229
+ ),
230
+ )
231
+ ```
232
+
233
+ ---
234
+
235
+ ## Audit log
236
+
237
+ ```python
238
+ from kavachos.types import AuditFilters, ExportOptions
239
+
240
+ # Query the audit log
241
+ entries = await client.audit.query(
242
+ AuditFilters(
243
+ agent_id="agent-abc123",
244
+ result="allowed",
245
+ limit=50,
246
+ )
247
+ )
248
+ for entry in entries:
249
+ print(entry.timestamp, entry.action, entry.resource, entry.result)
250
+
251
+ # Paginated response (includes total count)
252
+ page = await client.audit.query_paginated(AuditFilters(limit=20, offset=0))
253
+ print(f"{len(page.entries)} of {page.total}")
254
+
255
+ # Export as JSON or CSV
256
+ csv_text = await client.audit.export(
257
+ ExportOptions(
258
+ format="csv",
259
+ since="2024-01-01T00:00:00Z",
260
+ )
261
+ )
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Delegation
267
+
268
+ Delegate a subset of an agent's permissions to another agent, with an optional
269
+ depth limit.
270
+
271
+ ```python
272
+ from kavachos.types import DelegateInput
273
+ from kavachos.permissions import read
274
+
275
+ # Create a delegation
276
+ chain = await client.delegation.create(
277
+ DelegateInput(
278
+ from_agent="agent-abc123",
279
+ to_agent="agent-def456",
280
+ permissions=[read("mcp:github:repos")],
281
+ expires_at="2025-12-31T00:00:00Z",
282
+ max_depth=2,
283
+ )
284
+ )
285
+
286
+ # List all chains for an agent
287
+ chains = await client.delegation.list_chains("agent-abc123")
288
+
289
+ # Get the effective (merged) permissions for an agent
290
+ perms = await client.delegation.get_effective_permissions("agent-def456")
291
+
292
+ # Revoke a delegation
293
+ await client.delegation.revoke(chain.id)
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Error handling
299
+
300
+ All exceptions inherit from `kavachos.KavachError`.
301
+
302
+ ```python
303
+ from kavachos.errors import (
304
+ KavachError,
305
+ AuthenticationError, # 401
306
+ PermissionError, # 403
307
+ NotFoundError, # 404
308
+ RateLimitError, # 429 — has .retry_after
309
+ ServerError, # 5xx
310
+ NetworkError, # Transport failure
311
+ )
312
+
313
+ try:
314
+ agent = await client.agents.get("agent-missing")
315
+ except NotFoundError:
316
+ print("Agent does not exist")
317
+ except RateLimitError as e:
318
+ print(f"Rate limited. Retry after {e.retry_after}s")
319
+ except AuthenticationError:
320
+ print("Check your token")
321
+ except KavachError as e:
322
+ print(f"[{e.code}] {e.message} (HTTP {e.status_code})")
323
+ ```
324
+
325
+ ---
326
+
327
+ ## Configuration
328
+
329
+ ```python
330
+ KavachClient(
331
+ base_url="https://your-app.com/api/kavach", # required
332
+ token="kv_...", # optional bearer token
333
+ headers={"X-Tenant": "acme"}, # extra headers on every request
334
+ timeout=30.0, # seconds (default 30)
335
+ )
336
+ ```
337
+
338
+ ---
339
+
340
+ ## License
341
+
342
+ MIT
@@ -0,0 +1,312 @@
1
+ # kavachos
2
+
3
+ Python SDK for [KavachOS](https://kavachos.dev) — auth OS for AI agents and humans.
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/kavachos)](https://pypi.org/project/kavachos/)
6
+ [![Python](https://img.shields.io/pypi/pyversions/kavachos)](https://pypi.org/project/kavachos/)
7
+ [![License](https://img.shields.io/badge/license-MIT-blue)](../../LICENSE)
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install kavachos
15
+ ```
16
+
17
+ Requires Python 3.9+ and `httpx`.
18
+
19
+ ---
20
+
21
+ ## Quick start
22
+
23
+ ### Async (recommended)
24
+
25
+ ```python
26
+ import asyncio
27
+ from kavachos import KavachClient
28
+ from kavachos.types import CreateAgentInput
29
+ from kavachos.permissions import read, with_approval, execute
30
+
31
+ async def main():
32
+ async with KavachClient(
33
+ base_url="https://your-app.com/api/kavach",
34
+ token="kv_...",
35
+ ) as client:
36
+ # Create an agent
37
+ agent = await client.agents.create(
38
+ CreateAgentInput(
39
+ owner_id="user-123",
40
+ name="github-reader",
41
+ type="autonomous",
42
+ permissions=[
43
+ read("mcp:github:*"),
44
+ with_approval(execute("mcp:deploy:production")),
45
+ ],
46
+ )
47
+ )
48
+
49
+ # Check authorization
50
+ result = await client.authorize(
51
+ agent.id,
52
+ AuthorizeRequest(action="read", resource="mcp:github:repos"),
53
+ )
54
+ print(result.allowed) # True
55
+
56
+ asyncio.run(main())
57
+ ```
58
+
59
+ ### Sync
60
+
61
+ ```python
62
+ from kavachos import KavachSyncClient
63
+ from kavachos.types import CreateAgentInput
64
+ from kavachos.permissions import read
65
+
66
+ with KavachSyncClient(
67
+ base_url="https://your-app.com/api/kavach",
68
+ token="kv_...",
69
+ ) as client:
70
+ agent = client.agents.create(
71
+ CreateAgentInput(
72
+ owner_id="user-123",
73
+ name="github-reader",
74
+ type="autonomous",
75
+ permissions=[read("mcp:github:*")],
76
+ )
77
+ )
78
+ print(agent.id, agent.token)
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Authentication
84
+
85
+ Sign in and sign up with email and password.
86
+
87
+ ```python
88
+ async with KavachClient(base_url="https://your-app.com/api/kavach") as client:
89
+ # Sign up
90
+ auth = await client.auth.sign_up(
91
+ email="user@example.com",
92
+ password="secure-password",
93
+ name="Alice",
94
+ )
95
+ print(auth.user.id)
96
+ print(auth.session.token)
97
+
98
+ # Sign in later
99
+ auth = await client.auth.sign_in(
100
+ email="user@example.com",
101
+ password="secure-password",
102
+ )
103
+
104
+ # Get current session
105
+ session = await client.auth.get_session(token=auth.session.token)
106
+
107
+ # Sign out
108
+ await client.auth.sign_out()
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Agent management
114
+
115
+ ```python
116
+ from kavachos.types import AgentFilters, UpdateAgentInput
117
+
118
+ # List agents for a user
119
+ agents = await client.agents.list(AgentFilters(user_id="user-123", status="active"))
120
+
121
+ # Get a single agent (returns None if not found)
122
+ agent = await client.agents.get("agent-abc123")
123
+
124
+ # Update name or permissions
125
+ agent = await client.agents.update(
126
+ "agent-abc123",
127
+ UpdateAgentInput(name="better-name"),
128
+ )
129
+
130
+ # Rotate the token (old token is immediately invalidated)
131
+ agent = await client.agents.rotate("agent-abc123")
132
+ print(agent.token) # kv_new_...
133
+
134
+ # Revoke (delete) an agent
135
+ await client.agents.revoke("agent-abc123")
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Authorization
141
+
142
+ ```python
143
+ from kavachos.types import AuthorizeRequest
144
+
145
+ # Authorize by agent ID (requires admin/service token on the client)
146
+ result = await client.authorize(
147
+ "agent-abc123",
148
+ AuthorizeRequest(
149
+ action="execute",
150
+ resource="mcp:deploy:production",
151
+ arguments={"version": "1.2.3"},
152
+ ),
153
+ )
154
+ print(result.allowed) # True / False
155
+ print(result.audit_id) # "aud_..."
156
+
157
+ # Authorize using the agent's own bearer token (no admin token needed)
158
+ result = await client.auth.authorize_by_token(
159
+ agent_token="kv_agent_xyz",
160
+ request=AuthorizeRequest(action="read", resource="mcp:github:repos"),
161
+ )
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Permissions helpers
167
+
168
+ The `kavachos.permissions` module provides shorthand constructors.
169
+
170
+ ```python
171
+ from kavachos.permissions import (
172
+ read,
173
+ write,
174
+ execute,
175
+ read_write,
176
+ full_access,
177
+ with_approval,
178
+ rate_limited,
179
+ )
180
+ from kavachos.types import PermissionConstraints
181
+
182
+ # Simple read permission
183
+ perm = read("mcp:github:*")
184
+
185
+ # Require human approval before execution
186
+ perm = with_approval(execute("mcp:deploy:production"))
187
+
188
+ # Limit to 100 calls per hour
189
+ perm = rate_limited(read("mcp:github:*"), max_calls_per_hour=100)
190
+
191
+ # Full manual construction
192
+ from kavachos.types import Permission
193
+ perm = Permission(
194
+ resource="mcp:github:*",
195
+ actions=["read", "write"],
196
+ constraints=PermissionConstraints(
197
+ max_calls_per_hour=200,
198
+ ip_allowlist=["10.0.0.0/8"],
199
+ ),
200
+ )
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Audit log
206
+
207
+ ```python
208
+ from kavachos.types import AuditFilters, ExportOptions
209
+
210
+ # Query the audit log
211
+ entries = await client.audit.query(
212
+ AuditFilters(
213
+ agent_id="agent-abc123",
214
+ result="allowed",
215
+ limit=50,
216
+ )
217
+ )
218
+ for entry in entries:
219
+ print(entry.timestamp, entry.action, entry.resource, entry.result)
220
+
221
+ # Paginated response (includes total count)
222
+ page = await client.audit.query_paginated(AuditFilters(limit=20, offset=0))
223
+ print(f"{len(page.entries)} of {page.total}")
224
+
225
+ # Export as JSON or CSV
226
+ csv_text = await client.audit.export(
227
+ ExportOptions(
228
+ format="csv",
229
+ since="2024-01-01T00:00:00Z",
230
+ )
231
+ )
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Delegation
237
+
238
+ Delegate a subset of an agent's permissions to another agent, with an optional
239
+ depth limit.
240
+
241
+ ```python
242
+ from kavachos.types import DelegateInput
243
+ from kavachos.permissions import read
244
+
245
+ # Create a delegation
246
+ chain = await client.delegation.create(
247
+ DelegateInput(
248
+ from_agent="agent-abc123",
249
+ to_agent="agent-def456",
250
+ permissions=[read("mcp:github:repos")],
251
+ expires_at="2025-12-31T00:00:00Z",
252
+ max_depth=2,
253
+ )
254
+ )
255
+
256
+ # List all chains for an agent
257
+ chains = await client.delegation.list_chains("agent-abc123")
258
+
259
+ # Get the effective (merged) permissions for an agent
260
+ perms = await client.delegation.get_effective_permissions("agent-def456")
261
+
262
+ # Revoke a delegation
263
+ await client.delegation.revoke(chain.id)
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Error handling
269
+
270
+ All exceptions inherit from `kavachos.KavachError`.
271
+
272
+ ```python
273
+ from kavachos.errors import (
274
+ KavachError,
275
+ AuthenticationError, # 401
276
+ PermissionError, # 403
277
+ NotFoundError, # 404
278
+ RateLimitError, # 429 — has .retry_after
279
+ ServerError, # 5xx
280
+ NetworkError, # Transport failure
281
+ )
282
+
283
+ try:
284
+ agent = await client.agents.get("agent-missing")
285
+ except NotFoundError:
286
+ print("Agent does not exist")
287
+ except RateLimitError as e:
288
+ print(f"Rate limited. Retry after {e.retry_after}s")
289
+ except AuthenticationError:
290
+ print("Check your token")
291
+ except KavachError as e:
292
+ print(f"[{e.code}] {e.message} (HTTP {e.status_code})")
293
+ ```
294
+
295
+ ---
296
+
297
+ ## Configuration
298
+
299
+ ```python
300
+ KavachClient(
301
+ base_url="https://your-app.com/api/kavach", # required
302
+ token="kv_...", # optional bearer token
303
+ headers={"X-Tenant": "acme"}, # extra headers on every request
304
+ timeout=30.0, # seconds (default 30)
305
+ )
306
+ ```
307
+
308
+ ---
309
+
310
+ ## License
311
+
312
+ MIT