dominus-sdk-python 9.0.14__tar.gz → 9.0.16__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-9.0.14 → dominus_sdk_python-9.0.16}/PKG-INFO +5 -4
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/README.md +4 -3
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/__init__.py +1 -1
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/cache.py +6 -6
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/secrets.py +16 -6
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/PKG-INFO +5 -4
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/SOURCES.txt +1 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/pyproject.toml +1 -1
- dominus_sdk_python-9.0.16/tests/test_cache_contracts.py +115 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_secrets_presence_contract.py +36 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/config/__init__.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/config/endpoints.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/contract/__init__.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/contract/envelope.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/contract/projections.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/errors.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/__init__.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/auth.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/console_capture.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/core.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/crypto.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/sse.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/helpers/trace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/__init__.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/admin.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/ai.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/artifacts.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/auth.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/authority.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/browser.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/coder.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/courier.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/db.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/ddl.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/deployer.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/fastapi.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/files.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/health.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/jobs.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/logs.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/platform.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/portal.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/processor.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/publisher.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/recipes.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/redis.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/secure.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/stash.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/sync.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/usage.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/warden.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/namespaces/workflow.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/py.typed +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/services/__init__.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus/start.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/top_level.txt +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/setup.cfg +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_ai_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_artifacts_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_auth.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_authority_public_vocabulary.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_browser_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_contract.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_control_plane_namespaces.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_error_recovery_action.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_errors.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_errors_aliases.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_flat_commands.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_health.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_logs.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_namespace_barrel_exports.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_platform_coder_namespaces.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_provisioning_parity.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_public_exports.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_publisher_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_readme_quickstart_catalog.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_recipes_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_recipes_stash_routing.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_stash_artifact_facade.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_stash_tables_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_token_precedence.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_transport_compat.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_usage_namespace.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_version_consistency.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_workflow_lifecycle.py +0 -0
- {dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_workflow_refs.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python
|
|
3
|
-
Version: 9.0.
|
|
3
|
+
Version: 9.0.16
|
|
4
4
|
Summary: Python SDK for the Dominus gateway-first platform
|
|
5
5
|
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
6
|
License-Expression: LicenseRef-Proprietary
|
|
@@ -38,8 +38,9 @@ Async Python SDK for the Dominus gateway-first service plane.
|
|
|
38
38
|
## Agent Guide
|
|
39
39
|
|
|
40
40
|
Start with `docs/agent-guide/INDEX.md`. The current snapshot is
|
|
41
|
-
`docs/agent-guide/2026-
|
|
42
|
-
cleanup audit is `docs/janitor/2026-
|
|
41
|
+
`docs/agent-guide/2026-10-16-1300-sdk-python/00-reading-order.md`; the latest
|
|
42
|
+
cleanup audit is `docs/janitor/2026-10-16-1300-sdk-python-cleanup-audit.md`.
|
|
43
|
+
Knowledge graph: graphify-out/GRAPH_REPORT.md — query with `graphify-run query "<question>"` before grepping.
|
|
43
44
|
|
|
44
45
|
## What This Repo Ships
|
|
45
46
|
|
|
@@ -48,7 +49,7 @@ cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
|
|
|
48
49
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
49
50
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
50
51
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
51
|
-
- Current package version: `9.0.
|
|
52
|
+
- Current package version: `9.0.16`
|
|
52
53
|
|
|
53
54
|
## Install
|
|
54
55
|
|
|
@@ -5,8 +5,9 @@ Async Python SDK for the Dominus gateway-first service plane.
|
|
|
5
5
|
## Agent Guide
|
|
6
6
|
|
|
7
7
|
Start with `docs/agent-guide/INDEX.md`. The current snapshot is
|
|
8
|
-
`docs/agent-guide/2026-
|
|
9
|
-
cleanup audit is `docs/janitor/2026-
|
|
8
|
+
`docs/agent-guide/2026-10-16-1300-sdk-python/00-reading-order.md`; the latest
|
|
9
|
+
cleanup audit is `docs/janitor/2026-10-16-1300-sdk-python-cleanup-audit.md`.
|
|
10
|
+
Knowledge graph: graphify-out/GRAPH_REPORT.md — query with `graphify-run query "<question>"` before grepping.
|
|
10
11
|
|
|
11
12
|
## What This Repo Ships
|
|
12
13
|
|
|
@@ -15,7 +16,7 @@ cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
|
|
|
15
16
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
16
17
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
17
18
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
18
|
-
- Current package version: `9.0.
|
|
19
|
+
- Current package version: `9.0.16`
|
|
19
20
|
|
|
20
21
|
## Install
|
|
21
22
|
|
|
@@ -108,7 +108,7 @@ def exponential_backoff_with_jitter(
|
|
|
108
108
|
"""
|
|
109
109
|
delay = min(base_delay * (2 ** attempt), max_delay)
|
|
110
110
|
jitter_range = delay * jitter
|
|
111
|
-
return delay + random.uniform(-jitter_range, jitter_range)
|
|
111
|
+
return min(max_delay, delay + random.uniform(-jitter_range, jitter_range))
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
class DominusCache:
|
|
@@ -124,7 +124,7 @@ class DominusCache:
|
|
|
124
124
|
"""
|
|
125
125
|
|
|
126
126
|
def __init__(self, default_ttl: int = 300):
|
|
127
|
-
self._store: Dict[str, Tuple[bytes, float]] = {}
|
|
127
|
+
self._store: Dict[str, Tuple[bytes, float, int]] = {}
|
|
128
128
|
self._default_ttl = default_ttl
|
|
129
129
|
self._cipher: Optional[Fernet] = None
|
|
130
130
|
|
|
@@ -141,7 +141,7 @@ class DominusCache:
|
|
|
141
141
|
if not entry:
|
|
142
142
|
return None
|
|
143
143
|
|
|
144
|
-
encrypted_value, expires_at = entry
|
|
144
|
+
encrypted_value, expires_at, duration = entry
|
|
145
145
|
|
|
146
146
|
# Check expiry
|
|
147
147
|
if time.time() >= expires_at:
|
|
@@ -159,8 +159,8 @@ class DominusCache:
|
|
|
159
159
|
else:
|
|
160
160
|
value = json.loads(encrypted_value.decode())
|
|
161
161
|
|
|
162
|
-
# Touch TTL
|
|
163
|
-
self._store[key] = (encrypted_value, time.time() +
|
|
162
|
+
# Touch TTL using the entry's own duration
|
|
163
|
+
self._store[key] = (encrypted_value, time.time() + duration, duration)
|
|
164
164
|
return value
|
|
165
165
|
|
|
166
166
|
def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
|
|
@@ -173,7 +173,7 @@ class DominusCache:
|
|
|
173
173
|
else:
|
|
174
174
|
encrypted_value = json.dumps(value).encode()
|
|
175
175
|
|
|
176
|
-
self._store[key] = (encrypted_value, time.time() + duration)
|
|
176
|
+
self._store[key] = (encrypted_value, time.time() + duration, duration)
|
|
177
177
|
|
|
178
178
|
def delete(self, key: str) -> bool:
|
|
179
179
|
"""Delete key."""
|
|
@@ -262,15 +262,22 @@ class SecretsNamespace:
|
|
|
262
262
|
environment: str,
|
|
263
263
|
project_id: str,
|
|
264
264
|
) -> Dict[str, Any]:
|
|
265
|
-
"""Set one Infisical secret for an environment (``POST /api/secrets/set``).
|
|
265
|
+
"""Set one Infisical secret for an environment (``POST /api/secrets/set``).
|
|
266
|
+
|
|
267
|
+
The wire keys are the canonical ``target_org_id`` / ``target_env``
|
|
268
|
+
(PLAN T6 / board T7); secrets-core rejects the retired
|
|
269
|
+
``target_project_id`` / ``environment`` aliases with a typed
|
|
270
|
+
``invalid_wire_key`` validation error. The Python parameter names are
|
|
271
|
+
unchanged — only the request body vocabulary is canonical.
|
|
272
|
+
"""
|
|
266
273
|
return await self._client._request(
|
|
267
274
|
endpoint="/api/secrets/set",
|
|
268
275
|
method="POST",
|
|
269
276
|
body={
|
|
270
277
|
"key": key,
|
|
271
278
|
"value": value,
|
|
272
|
-
"
|
|
273
|
-
"
|
|
279
|
+
"target_env": environment,
|
|
280
|
+
"target_org_id": project_id,
|
|
274
281
|
},
|
|
275
282
|
use_gateway=True,
|
|
276
283
|
)
|
|
@@ -282,14 +289,17 @@ class SecretsNamespace:
|
|
|
282
289
|
environment: str,
|
|
283
290
|
project_id: str,
|
|
284
291
|
) -> Dict[str, Any]:
|
|
285
|
-
"""Delete one Infisical secret for an environment (``POST /api/secrets/delete``).
|
|
292
|
+
"""Delete one Infisical secret for an environment (``POST /api/secrets/delete``).
|
|
293
|
+
|
|
294
|
+
Canonical wire keys only — see :meth:`set_project_secret`.
|
|
295
|
+
"""
|
|
286
296
|
return await self._client._request(
|
|
287
297
|
endpoint="/api/secrets/delete",
|
|
288
298
|
method="POST",
|
|
289
299
|
body={
|
|
290
300
|
"key": key,
|
|
291
|
-
"
|
|
292
|
-
"
|
|
301
|
+
"target_env": environment,
|
|
302
|
+
"target_org_id": project_id,
|
|
293
303
|
},
|
|
294
304
|
use_gateway=True,
|
|
295
305
|
)
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python
|
|
3
|
-
Version: 9.0.
|
|
3
|
+
Version: 9.0.16
|
|
4
4
|
Summary: Python SDK for the Dominus gateway-first platform
|
|
5
5
|
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
6
|
License-Expression: LicenseRef-Proprietary
|
|
@@ -38,8 +38,9 @@ Async Python SDK for the Dominus gateway-first service plane.
|
|
|
38
38
|
## Agent Guide
|
|
39
39
|
|
|
40
40
|
Start with `docs/agent-guide/INDEX.md`. The current snapshot is
|
|
41
|
-
`docs/agent-guide/2026-
|
|
42
|
-
cleanup audit is `docs/janitor/2026-
|
|
41
|
+
`docs/agent-guide/2026-10-16-1300-sdk-python/00-reading-order.md`; the latest
|
|
42
|
+
cleanup audit is `docs/janitor/2026-10-16-1300-sdk-python-cleanup-audit.md`.
|
|
43
|
+
Knowledge graph: graphify-out/GRAPH_REPORT.md — query with `graphify-run query "<question>"` before grepping.
|
|
43
44
|
|
|
44
45
|
## What This Repo Ships
|
|
45
46
|
|
|
@@ -48,7 +49,7 @@ cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
|
|
|
48
49
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
49
50
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
50
51
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
51
|
-
- Current package version: `9.0.
|
|
52
|
+
- Current package version: `9.0.16`
|
|
52
53
|
|
|
53
54
|
## Install
|
|
54
55
|
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/SOURCES.txt
RENAMED
|
@@ -58,6 +58,7 @@ tests/test_artifacts_namespace.py
|
|
|
58
58
|
tests/test_auth.py
|
|
59
59
|
tests/test_authority_public_vocabulary.py
|
|
60
60
|
tests/test_browser_namespace.py
|
|
61
|
+
tests/test_cache_contracts.py
|
|
61
62
|
tests/test_contract.py
|
|
62
63
|
tests/test_control_plane_namespaces.py
|
|
63
64
|
tests/test_error_recovery_action.py
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Regression contracts for dominus.helpers.cache.
|
|
2
|
+
|
|
3
|
+
Pins two documented behaviours that the implementation previously broke:
|
|
4
|
+
|
|
5
|
+
1. ``exponential_backoff_with_jitter`` must never return a delay above the
|
|
6
|
+
``max_delay`` cap, including when the exponential term already equals the
|
|
7
|
+
cap and positive jitter would otherwise push it over.
|
|
8
|
+
2. ``DominusCache.get`` refreshes an entry using the TTL that ``set`` was
|
|
9
|
+
given (or ``default_ttl`` when none was supplied), never silently swapping
|
|
10
|
+
a short per-entry TTL for the cache default.
|
|
11
|
+
|
|
12
|
+
Randomness is seeded so the backoff assertions are fully deterministic.
|
|
13
|
+
"""
|
|
14
|
+
import random
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
import dominus.helpers.cache as cache_module
|
|
19
|
+
from dominus.helpers.cache import (
|
|
20
|
+
DominusCache,
|
|
21
|
+
exponential_backoff_with_jitter,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _Clock:
|
|
26
|
+
"""Deterministic, advanceable replacement for ``time.time``."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, start: float = 1000.0):
|
|
29
|
+
self.now = start
|
|
30
|
+
|
|
31
|
+
def __call__(self) -> float:
|
|
32
|
+
return self.now
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_backoff_never_exceeds_max_delay_across_attempts():
|
|
36
|
+
random.seed(1234)
|
|
37
|
+
|
|
38
|
+
samples = [
|
|
39
|
+
exponential_backoff_with_jitter(attempt, base_delay=1.0, max_delay=8.0, jitter=0.5)
|
|
40
|
+
for attempt in range(0, 8)
|
|
41
|
+
for _ in range(200)
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
assert samples, "expected backoff samples"
|
|
45
|
+
assert all(delay <= 8.0 for delay in samples)
|
|
46
|
+
assert all(delay >= 0.0 for delay in samples)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_backoff_caps_at_boundary_where_exponential_equals_max_delay():
|
|
50
|
+
# base_delay * 2 ** attempt == max_delay exactly at attempt 3 (1.0 * 8 == 8.0).
|
|
51
|
+
random.seed(7)
|
|
52
|
+
|
|
53
|
+
samples = [
|
|
54
|
+
exponential_backoff_with_jitter(3, base_delay=1.0, max_delay=8.0, jitter=0.5)
|
|
55
|
+
for _ in range(500)
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
assert max(samples) <= 8.0
|
|
59
|
+
# Jitter must still be applied below the cap: some draws land under it.
|
|
60
|
+
assert min(samples) < 8.0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_backoff_preserves_growth_and_jitter_below_cap():
|
|
64
|
+
# attempt 2 -> exponential term 4.0, strictly below the 8.0 cap, so the
|
|
65
|
+
# +/-50% jitter band must be intact and unclamped.
|
|
66
|
+
random.seed(99)
|
|
67
|
+
|
|
68
|
+
samples = [
|
|
69
|
+
exponential_backoff_with_jitter(2, base_delay=1.0, max_delay=8.0, jitter=0.5)
|
|
70
|
+
for _ in range(300)
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
assert all(2.0 <= delay <= 6.0 for delay in samples)
|
|
74
|
+
assert any(delay < 4.0 for delay in samples)
|
|
75
|
+
assert any(delay > 4.0 for delay in samples)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_get_refresh_preserves_explicit_per_entry_ttl(monkeypatch):
|
|
79
|
+
clock = _Clock()
|
|
80
|
+
monkeypatch.setattr(cache_module.time, "time", clock)
|
|
81
|
+
|
|
82
|
+
cache = DominusCache(default_ttl=300)
|
|
83
|
+
cache.set("short", "value", ttl=10)
|
|
84
|
+
|
|
85
|
+
clock.now += 5
|
|
86
|
+
assert cache.get("short") == "value" # refresh must reuse the 10s TTL
|
|
87
|
+
|
|
88
|
+
clock.now += 11 # 1016s > refreshed expiry 1015s (5 + 10)
|
|
89
|
+
assert cache.get("short") is None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_get_refresh_uses_default_ttl_when_entry_has_none(monkeypatch):
|
|
93
|
+
clock = _Clock()
|
|
94
|
+
monkeypatch.setattr(cache_module.time, "time", clock)
|
|
95
|
+
|
|
96
|
+
cache = DominusCache(default_ttl=300)
|
|
97
|
+
cache.set("default", "value")
|
|
98
|
+
|
|
99
|
+
clock.now += 100
|
|
100
|
+
assert cache.get("default") == "value" # refresh to now + 300s
|
|
101
|
+
|
|
102
|
+
clock.now += 301 # 1401s > refreshed expiry 1400s (1100 + 300)
|
|
103
|
+
assert cache.get("default") is None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_encrypted_cache_round_trips():
|
|
107
|
+
cache = DominusCache(default_ttl=300)
|
|
108
|
+
cache.set_encryption_key("super-secret-token")
|
|
109
|
+
|
|
110
|
+
assert cache._cipher is not None
|
|
111
|
+
|
|
112
|
+
payload = {"nested": {"a": 1, "b": [1, 2, 3]}, "text": "value"}
|
|
113
|
+
cache.set("encrypted", payload, ttl=30)
|
|
114
|
+
|
|
115
|
+
assert cache.get("encrypted") == payload
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_secrets_presence_contract.py
RENAMED
|
@@ -120,6 +120,42 @@ async def test_malformed_responses_fail_without_raw_cell_in_error_or_logs(caplog
|
|
|
120
120
|
assert RAW_SENTINEL not in caplog.text
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
@pytest.mark.asyncio
|
|
124
|
+
async def test_project_secret_mutations_speak_the_canonical_wire_vocabulary():
|
|
125
|
+
"""T7 contracts the secrets request surface onto target_org_id/target_env.
|
|
126
|
+
|
|
127
|
+
dominus-secrets-core rejects the retired `target_project_id` / `environment`
|
|
128
|
+
aliases with a typed `invalid_wire_key` validation error instead of
|
|
129
|
+
silently ignoring them, so emitting either key here would 400 the call.
|
|
130
|
+
The Python method signatures keep their own parameter names; only the wire
|
|
131
|
+
body keys are canonical.
|
|
132
|
+
"""
|
|
133
|
+
client = Client({"ok": True})
|
|
134
|
+
ns = SecretsNamespace(client)
|
|
135
|
+
|
|
136
|
+
await ns.set_project_secret(key="K", value="V", environment="production", project_id="org-1")
|
|
137
|
+
await ns.delete_project_secret(key="K", environment="production", project_id="org-1")
|
|
138
|
+
|
|
139
|
+
assert client.calls == [
|
|
140
|
+
{
|
|
141
|
+
"endpoint": "/api/secrets/set",
|
|
142
|
+
"method": "POST",
|
|
143
|
+
"body": {"key": "K", "value": "V", "target_env": "production", "target_org_id": "org-1"},
|
|
144
|
+
"use_gateway": True,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"endpoint": "/api/secrets/delete",
|
|
148
|
+
"method": "POST",
|
|
149
|
+
"body": {"key": "K", "target_env": "production", "target_org_id": "org-1"},
|
|
150
|
+
"use_gateway": True,
|
|
151
|
+
},
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
for call in client.calls:
|
|
155
|
+
assert "target_project_id" not in call["body"]
|
|
156
|
+
assert "environment" not in call["body"]
|
|
157
|
+
|
|
158
|
+
|
|
123
159
|
def test_public_types_and_return_annotation_are_exact():
|
|
124
160
|
from dominus import SecretEnvironment, SecretPresenceCell, SecretPresenceGrid
|
|
125
161
|
from dominus.namespaces import (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_authority_public_vocabulary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_control_plane_namespaces.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_namespace_barrel_exports.py
RENAMED
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_platform_coder_namespaces.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_readme_quickstart_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.14 → dominus_sdk_python-9.0.16}/tests/test_stash_tables_namespace.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|