dominus-sdk-python 9.0.15__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.
Files changed (88) hide show
  1. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/PKG-INFO +5 -4
  2. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/README.md +4 -3
  3. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/__init__.py +1 -1
  4. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/cache.py +6 -6
  5. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/PKG-INFO +5 -4
  6. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/SOURCES.txt +1 -0
  7. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/pyproject.toml +1 -1
  8. dominus_sdk_python-9.0.16/tests/test_cache_contracts.py +115 -0
  9. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/config/__init__.py +0 -0
  10. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/config/endpoints.py +0 -0
  11. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/contract/__init__.py +0 -0
  12. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/contract/envelope.py +0 -0
  13. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/contract/projections.py +0 -0
  14. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/errors.py +0 -0
  15. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/__init__.py +0 -0
  16. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/auth.py +0 -0
  17. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/console_capture.py +0 -0
  18. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/core.py +0 -0
  19. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/crypto.py +0 -0
  20. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/sse.py +0 -0
  21. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/helpers/trace.py +0 -0
  22. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/__init__.py +0 -0
  23. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/admin.py +0 -0
  24. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/ai.py +0 -0
  25. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/artifacts.py +0 -0
  26. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/auth.py +0 -0
  27. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/authority.py +0 -0
  28. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/browser.py +0 -0
  29. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/coder.py +0 -0
  30. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/courier.py +0 -0
  31. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/db.py +0 -0
  32. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/ddl.py +0 -0
  33. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/deployer.py +0 -0
  34. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/fastapi.py +0 -0
  35. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/files.py +0 -0
  36. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/health.py +0 -0
  37. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/jobs.py +0 -0
  38. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/logs.py +0 -0
  39. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/platform.py +0 -0
  40. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/portal.py +0 -0
  41. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/processor.py +0 -0
  42. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/publisher.py +0 -0
  43. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/recipes.py +0 -0
  44. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/redis.py +0 -0
  45. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/secrets.py +0 -0
  46. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/secure.py +0 -0
  47. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/stash.py +0 -0
  48. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/sync.py +0 -0
  49. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/usage.py +0 -0
  50. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/warden.py +0 -0
  51. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/namespaces/workflow.py +0 -0
  52. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/py.typed +0 -0
  53. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/services/__init__.py +0 -0
  54. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus/start.py +0 -0
  55. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
  56. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/requires.txt +0 -0
  57. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/dominus_sdk_python.egg-info/top_level.txt +0 -0
  58. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/setup.cfg +0 -0
  59. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_ai_namespace.py +0 -0
  60. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_artifacts_namespace.py +0 -0
  61. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_auth.py +0 -0
  62. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_authority_public_vocabulary.py +0 -0
  63. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_browser_namespace.py +0 -0
  64. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_contract.py +0 -0
  65. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_control_plane_namespaces.py +0 -0
  66. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_error_recovery_action.py +0 -0
  67. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_errors.py +0 -0
  68. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_errors_aliases.py +0 -0
  69. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_flat_commands.py +0 -0
  70. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_health.py +0 -0
  71. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_logs.py +0 -0
  72. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_namespace_barrel_exports.py +0 -0
  73. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_platform_coder_namespaces.py +0 -0
  74. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_provisioning_parity.py +0 -0
  75. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_public_exports.py +0 -0
  76. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_publisher_namespace.py +0 -0
  77. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_readme_quickstart_catalog.py +0 -0
  78. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_recipes_namespace.py +0 -0
  79. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_recipes_stash_routing.py +0 -0
  80. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_secrets_presence_contract.py +0 -0
  81. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_stash_artifact_facade.py +0 -0
  82. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_stash_tables_namespace.py +0 -0
  83. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_token_precedence.py +0 -0
  84. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_transport_compat.py +0 -0
  85. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_usage_namespace.py +0 -0
  86. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_version_consistency.py +0 -0
  87. {dominus_sdk_python-9.0.15 → dominus_sdk_python-9.0.16}/tests/test_workflow_lifecycle.py +0 -0
  88. {dominus_sdk_python-9.0.15 → 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.15
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-09-19-1300-sdk-python/00-reading-order.md`; the latest
42
- cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
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.15`
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-09-19-1300-sdk-python/00-reading-order.md`; the latest
9
- cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
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.15`
19
+ - Current package version: `9.0.16`
19
20
 
20
21
  ## Install
21
22
 
@@ -191,7 +191,7 @@ from .errors import (
191
191
  TimeoutError as DominusTimeoutError,
192
192
  )
193
193
 
194
- __version__ = "9.0.15"
194
+ __version__ = "9.0.16"
195
195
  __all__ = [
196
196
  # Main SDK instance
197
197
  "dominus",
@@ -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() + self._default_ttl)
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."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominus-sdk-python
3
- Version: 9.0.15
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-09-19-1300-sdk-python/00-reading-order.md`; the latest
42
- cleanup audit is `docs/janitor/2026-09-19-1300-sdk-python-cleanup-audit.md`.
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.15`
52
+ - Current package version: `9.0.16`
52
53
 
53
54
  ## Install
54
55
 
@@ -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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dominus-sdk-python"
7
- version = "9.0.15"
7
+ version = "9.0.16"
8
8
  description = "Python SDK for the Dominus gateway-first platform"
9
9
  readme = "README.md"
10
10
  license = "LicenseRef-Proprietary"
@@ -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