dominus-sdk-python 2.1.6__tar.gz → 2.1.8__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.
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/PKG-INFO +568 -381
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/README.md +537 -350
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/__init__.py +47 -47
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/config/__init__.py +24 -24
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/config/endpoints.py +39 -39
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/errors.py +201 -201
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/helpers/__init__.py +2 -2
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/helpers/auth.py +23 -23
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/helpers/cache.py +192 -192
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/helpers/core.py +657 -657
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/helpers/crypto.py +118 -118
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/__init__.py +26 -26
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/_deprecated_crossover.py +10 -10
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/_deprecated_sql.py +1341 -1341
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/auth.py +1056 -1025
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/courier.py +251 -251
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/db.py +267 -267
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/ddl.py +590 -590
- dominus_sdk_python-2.1.8/dominus/namespaces/fastapi.py +252 -0
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/files.py +299 -299
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/health.py +59 -59
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/logs.py +367 -367
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/open.py +72 -72
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/portal.py +504 -504
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/redis.py +357 -357
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/namespaces/secrets.py +126 -126
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/services/__init__.py +2 -2
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/services/_deprecated_architect.py +323 -323
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/services/_deprecated_sovereign.py +93 -93
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus/start.py +1038 -1034
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus_sdk_python.egg-info/PKG-INFO +568 -381
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus_sdk_python.egg-info/SOURCES.txt +1 -0
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/pyproject.toml +51 -51
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/setup.cfg +4 -4
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-2.1.6 → dominus_sdk_python-2.1.8}/dominus_sdk_python.egg-info/top_level.txt +0 -0
|
@@ -1,381 +1,568 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: dominus-sdk-python
|
|
3
|
-
Version: 2.1.
|
|
4
|
-
Summary: Python SDK for the Dominus Orchestrator Platform
|
|
5
|
-
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
|
-
License: Proprietary
|
|
7
|
-
Project-URL: Homepage, https://github.com/carebridgesystems/dominus-sdk-python
|
|
8
|
-
Project-URL: Repository, https://github.com/carebridgesystems/dominus-sdk-python
|
|
9
|
-
Keywords: dominus,carebridge,sdk,orchestrator,api,async
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: Other/Proprietary License
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
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 :: Software Development :: Libraries :: Python Modules
|
|
20
|
-
Classifier: Framework :: AsyncIO
|
|
21
|
-
Requires-Python: >=3.9
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
Requires-Dist: httpx>=0.24.0
|
|
24
|
-
Requires-Dist: bcrypt>=4.0.0
|
|
25
|
-
Requires-Dist: cryptography>=41.0.0
|
|
26
|
-
Provides-Extra: jwt
|
|
27
|
-
Requires-Dist: PyJWT>=2.8.0; extra == "jwt"
|
|
28
|
-
Provides-Extra: dev
|
|
29
|
-
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
-
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
31
|
-
|
|
32
|
-
# CB Dominus SDK
|
|
33
|
-
|
|
34
|
-
**Python SDK for the Dominus Orchestrator Platform**
|
|
35
|
-
|
|
36
|
-
A unified, async-first Python SDK providing seamless access to all Dominus backend services including secrets management, database operations, caching, file storage, authentication, schema management, and structured logging.
|
|
37
|
-
|
|
38
|
-
## Features
|
|
39
|
-
|
|
40
|
-
- **Namespace-based API** - Intuitive access via `dominus.db`, `dominus.redis`, `dominus.files`, etc.
|
|
41
|
-
- **Async/Await** - Built for modern async Python applications
|
|
42
|
-
- **Automatic JWT Management** - Token minting, caching, and refresh handled transparently
|
|
43
|
-
- **Resilience Built-in** - Circuit breaker, exponential backoff, and retry logic
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
async def main():
|
|
58
|
-
# Secrets
|
|
59
|
-
db_url = await dominus.get("DATABASE_URL")
|
|
60
|
-
|
|
61
|
-
# Database queries
|
|
62
|
-
users = await dominus.db.query("users", filters={"status": "active"})
|
|
63
|
-
|
|
64
|
-
# Redis caching
|
|
65
|
-
await dominus.redis.set("session:123", {"user": "john"}, ttl=3600)
|
|
66
|
-
|
|
67
|
-
# File storage
|
|
68
|
-
result = await dominus.files.upload(data, "report.pdf", category="reports")
|
|
69
|
-
|
|
70
|
-
# Structured logging
|
|
71
|
-
await dominus.logs.info("User logged in", {"user_id": "123"})
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Installation
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# Clone or add as submodule
|
|
78
|
-
git clone https://github.com/carebridgesystems/cb-dominus-sdk.git
|
|
79
|
-
|
|
80
|
-
# Install dependencies
|
|
81
|
-
pip install httpx bcrypt cryptography
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
"
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
#
|
|
164
|
-
await dominus.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
#
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
await dominus.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
#
|
|
274
|
-
await dominus.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dominus-sdk-python
|
|
3
|
+
Version: 2.1.8
|
|
4
|
+
Summary: Python SDK for the Dominus Orchestrator Platform
|
|
5
|
+
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Project-URL: Homepage, https://github.com/carebridgesystems/dominus-sdk-python
|
|
8
|
+
Project-URL: Repository, https://github.com/carebridgesystems/dominus-sdk-python
|
|
9
|
+
Keywords: dominus,carebridge,sdk,orchestrator,api,async
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: Other/Proprietary License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
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 :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Framework :: AsyncIO
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Requires-Dist: bcrypt>=4.0.0
|
|
25
|
+
Requires-Dist: cryptography>=41.0.0
|
|
26
|
+
Provides-Extra: jwt
|
|
27
|
+
Requires-Dist: PyJWT>=2.8.0; extra == "jwt"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
31
|
+
|
|
32
|
+
# CB Dominus SDK for Python
|
|
33
|
+
|
|
34
|
+
**Async Python SDK for the Dominus Orchestrator Platform**
|
|
35
|
+
|
|
36
|
+
A unified, async-first Python SDK providing seamless access to all Dominus backend services including secrets management, database operations, caching, file storage, authentication, schema management, and structured logging.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Namespace-based API** - Intuitive access via `dominus.db`, `dominus.redis`, `dominus.files`, etc.
|
|
41
|
+
- **Async/Await** - Built for modern async Python applications (asyncio)
|
|
42
|
+
- **Automatic JWT Management** - Token minting, caching, and refresh handled transparently
|
|
43
|
+
- **Resilience Built-in** - Circuit breaker, exponential backoff, and retry logic
|
|
44
|
+
- **Cold Start Handling** - Special retry logic for orchestrator cold starts
|
|
45
|
+
- **Typed Errors** - 9 specific error classes for different failure modes
|
|
46
|
+
- **Secure by Default** - Client-side password hashing, encrypted cache, audit trail support
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from dominus import dominus
|
|
52
|
+
import os
|
|
53
|
+
|
|
54
|
+
# Set your token (or use DOMINUS_TOKEN environment variable)
|
|
55
|
+
os.environ["DOMINUS_TOKEN"] = "your-psk-token"
|
|
56
|
+
|
|
57
|
+
async def main():
|
|
58
|
+
# Secrets
|
|
59
|
+
db_url = await dominus.get("DATABASE_URL")
|
|
60
|
+
|
|
61
|
+
# Database queries
|
|
62
|
+
users = await dominus.db.query("users", filters={"status": "active"})
|
|
63
|
+
|
|
64
|
+
# Redis caching
|
|
65
|
+
await dominus.redis.set("session:123", {"user": "john"}, ttl=3600)
|
|
66
|
+
|
|
67
|
+
# File storage
|
|
68
|
+
result = await dominus.files.upload(data, "report.pdf", category="reports")
|
|
69
|
+
|
|
70
|
+
# Structured logging
|
|
71
|
+
await dominus.logs.info("User logged in", {"user_id": "123"})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Clone or add as submodule
|
|
78
|
+
git clone https://github.com/carebridgesystems/cb-dominus-sdk.git
|
|
79
|
+
|
|
80
|
+
# Install dependencies
|
|
81
|
+
pip install httpx bcrypt cryptography
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or install via pip (when published):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install dominus-sdk-python
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
91
|
+
|
|
92
|
+
- Python 3.9+
|
|
93
|
+
- `httpx` - Async HTTP client
|
|
94
|
+
- `bcrypt` - Password hashing
|
|
95
|
+
- `cryptography` - Cache encryption
|
|
96
|
+
|
|
97
|
+
## Namespaces
|
|
98
|
+
|
|
99
|
+
| Namespace | Service | Purpose |
|
|
100
|
+
|-----------|---------|---------|
|
|
101
|
+
| `dominus.secrets` | Warden | Secrets management |
|
|
102
|
+
| `dominus.db` | Scribe | Database CRUD operations |
|
|
103
|
+
| `dominus.secure` | Scribe | Secure table access with audit logging |
|
|
104
|
+
| `dominus.redis` | Whisperer | Redis caching & distributed locks |
|
|
105
|
+
| `dominus.files` | Archivist | Object storage (Backblaze B2) |
|
|
106
|
+
| `dominus.auth` | Guardian | Users, roles, scopes, tenants, pages, navigation |
|
|
107
|
+
| `dominus.ddl` | Smith | Schema DDL & migrations |
|
|
108
|
+
| `dominus.logs` | Herald | Structured logging (BetterStack) |
|
|
109
|
+
| `dominus.portal` | Portal | User auth, sessions, profiles, navigation |
|
|
110
|
+
| `dominus.courier` | Courier | Email delivery (Postmark) |
|
|
111
|
+
| `dominus.open` | Scribe | Direct database access |
|
|
112
|
+
| `dominus.health` | Health | Service health checks |
|
|
113
|
+
|
|
114
|
+
## Usage Examples
|
|
115
|
+
|
|
116
|
+
### Secrets Management
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# Root-level shortcuts
|
|
120
|
+
value = await dominus.get("API_KEY")
|
|
121
|
+
await dominus.upsert("API_KEY", "new-value", comment="Updated API key")
|
|
122
|
+
|
|
123
|
+
# Full namespace
|
|
124
|
+
secrets = await dominus.secrets.list(prefix="DB_")
|
|
125
|
+
await dominus.secrets.delete("OLD_KEY")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Database Operations
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# List tables
|
|
132
|
+
tables = await dominus.db.tables()
|
|
133
|
+
tenant_tables = await dominus.db.tables(schema="tenant_acme")
|
|
134
|
+
|
|
135
|
+
# Query with filters and pagination
|
|
136
|
+
users = await dominus.db.query(
|
|
137
|
+
"users",
|
|
138
|
+
filters={"status": "active", "role": ["admin", "manager"]},
|
|
139
|
+
sort_by="created_at",
|
|
140
|
+
sort_order="desc",
|
|
141
|
+
limit=50,
|
|
142
|
+
offset=0
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Insert
|
|
146
|
+
user = await dominus.db.insert("users", {
|
|
147
|
+
"email": "john@example.com",
|
|
148
|
+
"name": "John Doe"
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
# Update
|
|
152
|
+
await dominus.db.update("users", {"status": "inactive"}, filters={"id": user_id})
|
|
153
|
+
|
|
154
|
+
# Delete
|
|
155
|
+
await dominus.db.delete("users", filters={"id": user_id})
|
|
156
|
+
|
|
157
|
+
# Bulk insert
|
|
158
|
+
await dominus.db.bulk_insert("events", [
|
|
159
|
+
{"type": "login", "user_id": "123"},
|
|
160
|
+
{"type": "login", "user_id": "456"}
|
|
161
|
+
])
|
|
162
|
+
|
|
163
|
+
# Secure table access (requires audit reason)
|
|
164
|
+
patients = await dominus.db.query(
|
|
165
|
+
"patients",
|
|
166
|
+
schema="tenant_acme",
|
|
167
|
+
reason="Reviewing records for appointment #123",
|
|
168
|
+
actor="dr.smith"
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Redis Caching
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# Key-value operations (TTL: min 60s, max 24h)
|
|
176
|
+
await dominus.redis.set("user:123", {"name": "John"}, ttl=3600)
|
|
177
|
+
value = await dominus.redis.get("user:123")
|
|
178
|
+
await dominus.redis.delete("user:123")
|
|
179
|
+
|
|
180
|
+
# Distributed locks
|
|
181
|
+
if await dominus.redis.setnx("lock:job", "worker-1", ttl=60):
|
|
182
|
+
try:
|
|
183
|
+
# Do exclusive work
|
|
184
|
+
pass
|
|
185
|
+
finally:
|
|
186
|
+
await dominus.redis.delete("lock:job")
|
|
187
|
+
|
|
188
|
+
# Counters
|
|
189
|
+
await dominus.redis.incr("page:views", delta=1)
|
|
190
|
+
|
|
191
|
+
# Hash operations
|
|
192
|
+
await dominus.redis.hset("user:123", "email", "john@example.com", ttl=3600)
|
|
193
|
+
email = await dominus.redis.hget("user:123", "email")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### File Storage
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# Upload file
|
|
200
|
+
with open("report.pdf", "rb") as f:
|
|
201
|
+
result = await dominus.files.upload(
|
|
202
|
+
data=f.read(),
|
|
203
|
+
filename="report.pdf",
|
|
204
|
+
category="reports"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Get download URL
|
|
208
|
+
download = await dominus.files.download(file_id=result["id"])
|
|
209
|
+
url = download["download_url"]
|
|
210
|
+
|
|
211
|
+
# List files
|
|
212
|
+
files = await dominus.files.list(category="reports", prefix="2025/")
|
|
213
|
+
|
|
214
|
+
# Delete file
|
|
215
|
+
await dominus.files.delete(file_id=result["id"])
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Structured Logging
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
# Simple logging (auto-captures file and function)
|
|
222
|
+
await dominus.logs.info("User logged in", {"user_id": "123"})
|
|
223
|
+
await dominus.logs.error("Payment failed", {"order_id": "456"})
|
|
224
|
+
|
|
225
|
+
# All log levels
|
|
226
|
+
await dominus.logs.debug("Debug message", {"data": "..."})
|
|
227
|
+
await dominus.logs.notice("Important notice", {})
|
|
228
|
+
await dominus.logs.warn("Warning message", {})
|
|
229
|
+
await dominus.logs.critical("Critical error", {})
|
|
230
|
+
|
|
231
|
+
# With category
|
|
232
|
+
await dominus.logs.info("Cache hit", {"key": "user:123"}, category="cache")
|
|
233
|
+
|
|
234
|
+
# With exception context
|
|
235
|
+
try:
|
|
236
|
+
risky_operation()
|
|
237
|
+
except Exception as e:
|
|
238
|
+
await dominus.logs.error("Operation failed", {}, exception=e)
|
|
239
|
+
|
|
240
|
+
# Batch logging
|
|
241
|
+
await dominus.logs.batch([
|
|
242
|
+
{"level": "info", "message": "Step 1 complete", "data": {}},
|
|
243
|
+
{"level": "info", "message": "Step 2 complete", "data": {}}
|
|
244
|
+
])
|
|
245
|
+
|
|
246
|
+
# Query logs
|
|
247
|
+
errors = await dominus.logs.query(level="error", limit=100)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Authentication & Authorization (Guardian)
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
# User management
|
|
254
|
+
users = await dominus.auth.list_users()
|
|
255
|
+
user = await dominus.auth.get_user(user_id="uuid")
|
|
256
|
+
|
|
257
|
+
new_user = await dominus.auth.add_user(
|
|
258
|
+
username="john",
|
|
259
|
+
password="secure-password",
|
|
260
|
+
email="john@example.com"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
await dominus.auth.update_user("uuid", status="active")
|
|
264
|
+
await dominus.auth.delete_user("uuid")
|
|
265
|
+
|
|
266
|
+
# Role management
|
|
267
|
+
roles = await dominus.auth.list_roles()
|
|
268
|
+
role = await dominus.auth.add_role(
|
|
269
|
+
name="Editor",
|
|
270
|
+
scope_slugs=["read", "write", "publish"]
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Scope management
|
|
274
|
+
scopes = await dominus.auth.list_scopes()
|
|
275
|
+
|
|
276
|
+
# Tenant management
|
|
277
|
+
tenants = await dominus.auth.list_tenants()
|
|
278
|
+
categories = await dominus.auth.list_tenant_categories()
|
|
279
|
+
|
|
280
|
+
# JWT operations
|
|
281
|
+
jwt = await dominus.auth.mint_jwt(user_id=user["id"], expires_in=900)
|
|
282
|
+
claims = await dominus.auth.validate_jwt(token)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Schema Management (DDL)
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
# Create table
|
|
289
|
+
await dominus.ddl.add_table("orders", [
|
|
290
|
+
{"name": "id", "type": "UUID", "constraints": ["PRIMARY KEY"]},
|
|
291
|
+
{"name": "user_id", "type": "UUID", "constraints": ["NOT NULL"]},
|
|
292
|
+
{"name": "total", "type": "DECIMAL(10,2)"},
|
|
293
|
+
{"name": "created_at", "type": "TIMESTAMPTZ", "default": "NOW()"}
|
|
294
|
+
])
|
|
295
|
+
|
|
296
|
+
# Add column
|
|
297
|
+
await dominus.ddl.add_column("orders", "status", "VARCHAR(50)", default="'pending'")
|
|
298
|
+
|
|
299
|
+
# Provision tenant schema from category template
|
|
300
|
+
await dominus.ddl.provision_tenant("customer_acme", category_slug="healthcare")
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### User Authentication (Portal)
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
# User login (tenant_id is optional)
|
|
307
|
+
session = await dominus.portal.login(
|
|
308
|
+
username="john@example.com",
|
|
309
|
+
password="secret123",
|
|
310
|
+
tenant_id="tenant-uuid" # optional
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Client login with PSK (for service-to-service)
|
|
314
|
+
client_session = await dominus.portal.login_client(psk="psk-token")
|
|
315
|
+
|
|
316
|
+
# Get current user
|
|
317
|
+
me = await dominus.portal.me()
|
|
318
|
+
|
|
319
|
+
# Get navigation (access-filtered for current user)
|
|
320
|
+
nav = await dominus.portal.get_navigation()
|
|
321
|
+
|
|
322
|
+
# Check page access
|
|
323
|
+
has_access = await dominus.portal.check_page_access("/dashboard/admin/users")
|
|
324
|
+
|
|
325
|
+
# Switch tenant
|
|
326
|
+
await dominus.portal.switch_tenant("other-tenant-uuid")
|
|
327
|
+
|
|
328
|
+
# Profile & preferences
|
|
329
|
+
profile = await dominus.portal.get_profile()
|
|
330
|
+
await dominus.portal.update_profile(display_name="John Doe")
|
|
331
|
+
|
|
332
|
+
prefs = await dominus.portal.get_preferences()
|
|
333
|
+
await dominus.portal.update_preferences(theme="dark", timezone="America/New_York")
|
|
334
|
+
|
|
335
|
+
# Password management
|
|
336
|
+
await dominus.portal.change_password("old-password", "new-password")
|
|
337
|
+
await dominus.portal.request_password_reset("john@example.com")
|
|
338
|
+
await dominus.portal.confirm_password_reset("reset-token", "new-password")
|
|
339
|
+
|
|
340
|
+
# Session management
|
|
341
|
+
sessions = await dominus.portal.list_sessions()
|
|
342
|
+
await dominus.portal.revoke_session("session-id")
|
|
343
|
+
await dominus.portal.revoke_all_sessions()
|
|
344
|
+
|
|
345
|
+
# Registration & email verification
|
|
346
|
+
await dominus.portal.register("newuser", "new@example.com", "password", "tenant-id")
|
|
347
|
+
await dominus.portal.verify_email("verification-token")
|
|
348
|
+
await dominus.portal.resend_verification("new@example.com")
|
|
349
|
+
|
|
350
|
+
# Logout
|
|
351
|
+
await dominus.portal.logout()
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Email Delivery (Courier)
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
# Send email via Postmark template
|
|
358
|
+
result = await dominus.courier.send(
|
|
359
|
+
template_alias="welcome",
|
|
360
|
+
to="user@example.com",
|
|
361
|
+
from_email="noreply@myapp.com",
|
|
362
|
+
model={"name": "John", "product_name": "My App"}
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Convenience methods
|
|
366
|
+
await dominus.courier.send_welcome(
|
|
367
|
+
to="user@example.com",
|
|
368
|
+
from_email="noreply@myapp.com",
|
|
369
|
+
name="John",
|
|
370
|
+
action_url="https://myapp.com/start",
|
|
371
|
+
product_name="My App"
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
await dominus.courier.send_password_reset(
|
|
375
|
+
to="user@example.com",
|
|
376
|
+
from_email="noreply@myapp.com",
|
|
377
|
+
name="John",
|
|
378
|
+
reset_url="https://myapp.com/reset?token=abc",
|
|
379
|
+
product_name="My App"
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
await dominus.courier.send_email_verification(
|
|
383
|
+
to="user@example.com",
|
|
384
|
+
from_email="noreply@myapp.com",
|
|
385
|
+
name="John",
|
|
386
|
+
verify_url="https://myapp.com/verify?token=xyz",
|
|
387
|
+
product_name="My App"
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
await dominus.courier.send_invitation(
|
|
391
|
+
to="invited@example.com",
|
|
392
|
+
from_email="noreply@myapp.com",
|
|
393
|
+
name="Invited User",
|
|
394
|
+
invite_url="https://myapp.com/invite?token=abc",
|
|
395
|
+
inviter_name="John",
|
|
396
|
+
product_name="My App"
|
|
397
|
+
)
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Health Checks
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
# Basic health check
|
|
404
|
+
status = await dominus.health.check()
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Error Handling
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
from dominus import (
|
|
411
|
+
dominus,
|
|
412
|
+
DominusError,
|
|
413
|
+
AuthenticationError,
|
|
414
|
+
AuthorizationError,
|
|
415
|
+
NotFoundError,
|
|
416
|
+
ValidationError,
|
|
417
|
+
ConflictError,
|
|
418
|
+
ServiceError,
|
|
419
|
+
SecureTableError,
|
|
420
|
+
ConnectionError,
|
|
421
|
+
TimeoutError,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
try:
|
|
425
|
+
user = await dominus.auth.get_user(user_id="invalid")
|
|
426
|
+
except NotFoundError as e:
|
|
427
|
+
print(f"User not found: {e.message}")
|
|
428
|
+
except SecureTableError as e:
|
|
429
|
+
print("Secure table requires 'reason' and 'actor' parameters")
|
|
430
|
+
except AuthenticationError as e:
|
|
431
|
+
print("Invalid or expired token")
|
|
432
|
+
except AuthorizationError as e:
|
|
433
|
+
print("Insufficient permissions")
|
|
434
|
+
except ValidationError as e:
|
|
435
|
+
print(f"Invalid request: {e.message}")
|
|
436
|
+
except TimeoutError as e:
|
|
437
|
+
print("Request timed out")
|
|
438
|
+
except DominusError as e:
|
|
439
|
+
print(f"Error {e.status_code}: {e.message}")
|
|
440
|
+
if e.details:
|
|
441
|
+
print(f"Details: {e.details}")
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Error Types
|
|
445
|
+
|
|
446
|
+
| Error | Status | Description |
|
|
447
|
+
|-------|--------|-------------|
|
|
448
|
+
| `AuthenticationError` | 401 | Invalid or missing token |
|
|
449
|
+
| `AuthorizationError` | 403 | Insufficient permissions |
|
|
450
|
+
| `NotFoundError` | 404 | Resource not found |
|
|
451
|
+
| `ValidationError` | 400 | Invalid request data |
|
|
452
|
+
| `ConflictError` | 409 | Duplicate or version conflict |
|
|
453
|
+
| `ServiceError` | 5xx | Backend service error |
|
|
454
|
+
| `SecureTableError` | 403 | Missing reason for secure table |
|
|
455
|
+
| `ConnectionError` | - | Network connection failed |
|
|
456
|
+
| `TimeoutError` | 504 | Request timed out |
|
|
457
|
+
|
|
458
|
+
## Configuration
|
|
459
|
+
|
|
460
|
+
### Environment Variables
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
# Required: PSK token for authentication
|
|
464
|
+
export DOMINUS_TOKEN="your-psk-token"
|
|
465
|
+
|
|
466
|
+
# Optional: Project configuration
|
|
467
|
+
export CB_PROJECT_SLUG="my-project"
|
|
468
|
+
export CB_ENVIRONMENT="production"
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Token Resolution
|
|
472
|
+
|
|
473
|
+
The SDK resolves the authentication token in this order:
|
|
474
|
+
1. `DOMINUS_TOKEN` environment variable
|
|
475
|
+
2. Hardcoded fallback in `dominus/start.py` (development only)
|
|
476
|
+
|
|
477
|
+
## Architecture
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
┌─────────────────┐
|
|
481
|
+
│ Your App │
|
|
482
|
+
│ (async Python) │
|
|
483
|
+
└────────┬────────┘
|
|
484
|
+
│ await dominus.db.query(...)
|
|
485
|
+
▼
|
|
486
|
+
┌─────────────────┐
|
|
487
|
+
│ Dominus SDK │ ← JWT caching, circuit breaker, retries
|
|
488
|
+
│ (this package) │
|
|
489
|
+
└────────┬────────┘
|
|
490
|
+
│ HTTPS (base64-encoded JSON)
|
|
491
|
+
▼
|
|
492
|
+
┌─────────────────────────────────┐
|
|
493
|
+
│ Dominus Orchestrator │
|
|
494
|
+
│ (Cloud Run FastAPI backend) │
|
|
495
|
+
│ │
|
|
496
|
+
│ ┌─────────┬─────────┬────────┐ │
|
|
497
|
+
│ │ Warden │Guardian │Archivist│ │
|
|
498
|
+
│ │ Scribe │ Smith │Whisperer│ │
|
|
499
|
+
│ │ Herald │ Portal │ Courier │ │
|
|
500
|
+
│ └─────────┴─────────┴────────┘ │
|
|
501
|
+
└─────────────────────────────────┘
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
## FastAPI Integration
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
from fastapi import FastAPI, HTTPException
|
|
508
|
+
from dominus import dominus, NotFoundError
|
|
509
|
+
|
|
510
|
+
app = FastAPI()
|
|
511
|
+
|
|
512
|
+
@app.get("/users")
|
|
513
|
+
async def list_users():
|
|
514
|
+
try:
|
|
515
|
+
users = await dominus.db.query("users", filters={"status": "active"}, limit=50)
|
|
516
|
+
return users
|
|
517
|
+
except NotFoundError:
|
|
518
|
+
raise HTTPException(status_code=404, detail="Not found")
|
|
519
|
+
except Exception as e:
|
|
520
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
521
|
+
|
|
522
|
+
@app.get("/users/{user_id}")
|
|
523
|
+
async def get_user(user_id: str):
|
|
524
|
+
try:
|
|
525
|
+
user = await dominus.auth.get_user(user_id)
|
|
526
|
+
return user
|
|
527
|
+
except NotFoundError:
|
|
528
|
+
raise HTTPException(status_code=404, detail="User not found")
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## Pagination Pattern
|
|
532
|
+
|
|
533
|
+
```python
|
|
534
|
+
async def get_all_users(page_size: int = 100):
|
|
535
|
+
offset = 0
|
|
536
|
+
all_users = []
|
|
537
|
+
while True:
|
|
538
|
+
result = await dominus.db.query("users", limit=page_size, offset=offset)
|
|
539
|
+
rows = result.get("rows", [])
|
|
540
|
+
all_users.extend(rows)
|
|
541
|
+
if len(rows) < page_size:
|
|
542
|
+
break
|
|
543
|
+
offset += page_size
|
|
544
|
+
return all_users
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## Documentation
|
|
548
|
+
|
|
549
|
+
- [Installation & Quick Start](dominus/QUICKSTART.md)
|
|
550
|
+
- [LLM Usage Guide](dominus/LLM-GUIDE.md)
|
|
551
|
+
|
|
552
|
+
## Version
|
|
553
|
+
|
|
554
|
+
**v2.1.6** - Latest release with navigation routes and page scope methods
|
|
555
|
+
|
|
556
|
+
### Changelog
|
|
557
|
+
|
|
558
|
+
- **v2.1.6** - Fix navigation routes and add page scope methods
|
|
559
|
+
- **v2.1.5** - Add PSK-only client login
|
|
560
|
+
- **v2.1.4** - Make `tenant_id` optional in login methods
|
|
561
|
+
- **v2.1.2** - Remove `/verify` endpoint call, keep health warmup
|
|
562
|
+
- **v2.1.1** - Fix hardcoded orchestrator base URL
|
|
563
|
+
- **v2.1.0** - Fix SDK routes and remove hardcoded token support
|
|
564
|
+
- **v2.0.0** - Complete namespace-based API rewrite
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
Proprietary - CareBridge Systems
|