dominus-sdk-python 9.0.12__tar.gz → 9.0.14__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.12 → dominus_sdk_python-9.0.14}/PKG-INFO +4 -4
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/README.md +3 -3
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/__init__.py +1 -1
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/authority.py +46 -2
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/start.py +3 -1
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/PKG-INFO +4 -4
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/pyproject.toml +1 -1
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_authority_public_vocabulary.py +85 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_transport_compat.py +92 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/config/__init__.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/config/endpoints.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/contract/__init__.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/contract/envelope.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/contract/projections.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/errors.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/__init__.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/auth.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/cache.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/console_capture.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/core.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/crypto.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/sse.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/helpers/trace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/__init__.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/admin.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/ai.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/artifacts.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/auth.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/browser.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/coder.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/courier.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/db.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/ddl.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/deployer.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/fastapi.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/files.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/health.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/jobs.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/logs.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/platform.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/portal.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/processor.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/publisher.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/recipes.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/redis.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/secrets.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/secure.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/stash.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/sync.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/usage.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/warden.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/namespaces/workflow.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/py.typed +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus/services/__init__.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/SOURCES.txt +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/top_level.txt +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/setup.cfg +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_ai_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_artifacts_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_auth.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_browser_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_contract.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_control_plane_namespaces.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_error_recovery_action.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_errors.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_errors_aliases.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_flat_commands.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_health.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_logs.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_namespace_barrel_exports.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_platform_coder_namespaces.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_provisioning_parity.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_public_exports.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_publisher_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_readme_quickstart_catalog.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_recipes_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_recipes_stash_routing.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_secrets_presence_contract.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_stash_artifact_facade.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_stash_tables_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_token_precedence.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_usage_namespace.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_version_consistency.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_workflow_lifecycle.py +0 -0
- {dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/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.14
|
|
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,8 @@ 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-
|
|
42
|
-
cleanup audit is `docs/janitor/2026-09-
|
|
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`.
|
|
43
43
|
|
|
44
44
|
## What This Repo Ships
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
|
|
|
48
48
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
49
49
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
50
50
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
51
|
-
- Current package version: `9.0.
|
|
51
|
+
- Current package version: `9.0.14`
|
|
52
52
|
|
|
53
53
|
## Install
|
|
54
54
|
|
|
@@ -5,8 +5,8 @@ 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-
|
|
9
|
-
cleanup audit is `docs/janitor/2026-09-
|
|
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`.
|
|
10
10
|
|
|
11
11
|
## What This Repo Ships
|
|
12
12
|
|
|
@@ -15,7 +15,7 @@ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
|
|
|
15
15
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
16
16
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
17
17
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
18
|
-
- Current package version: `9.0.
|
|
18
|
+
- Current package version: `9.0.14`
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
@@ -56,6 +56,11 @@ LIST_RUN_KIND = "workflow"
|
|
|
56
56
|
#: top-level projection on the wire; this SDK never relies on that default.
|
|
57
57
|
RESULT_VIEW_BOUND = "bound"
|
|
58
58
|
|
|
59
|
+
#: Canonical coherent deploy read view. Authority still serves the legacy
|
|
60
|
+
#: ``latest_deployment_*`` projection when ``view`` is omitted; this SDK never
|
|
61
|
+
#: relies on that default, and carries no legacy fallback.
|
|
62
|
+
DEPLOY_VIEW_COHERENT = "coherent"
|
|
63
|
+
|
|
59
64
|
|
|
60
65
|
def remote_command_outcome(payload: Mapping[str, Any]) -> Dict[str, Any]:
|
|
61
66
|
"""Unwrap a canonical ``RemoteCommandResult`` to the remote outcome it carries.
|
|
@@ -72,6 +77,35 @@ def remote_command_outcome(payload: Mapping[str, Any]) -> Dict[str, Any]:
|
|
|
72
77
|
return dict(payload)
|
|
73
78
|
|
|
74
79
|
|
|
80
|
+
def coherent_deploy_state(payload: Mapping[str, Any]) -> Dict[str, Any]:
|
|
81
|
+
"""Split a coherent deploy read into current state, labeled history, provenance.
|
|
82
|
+
|
|
83
|
+
A coherent read returns the deploy's one current rollout, its executor
|
|
84
|
+
history, and the provenance naming which rollout is current. This accessor
|
|
85
|
+
keeps that separation intact so history can never be read as current state:
|
|
86
|
+
``current_rollout`` stays ``None`` when Authority reports the read as
|
|
87
|
+
partial (an unset or unresolvable ``current_rollout_id``), and the newest
|
|
88
|
+
history entry is never substituted for it. ``partial`` restates the
|
|
89
|
+
provenance flag for callers that branch on it.
|
|
90
|
+
"""
|
|
91
|
+
envelope: Mapping[str, Any] = payload if isinstance(payload, Mapping) else {}
|
|
92
|
+
provenance = envelope.get("provenance")
|
|
93
|
+
provenance = dict(provenance) if isinstance(provenance, Mapping) else {}
|
|
94
|
+
current = envelope.get("current_rollout")
|
|
95
|
+
history = envelope.get("executor_history")
|
|
96
|
+
return {
|
|
97
|
+
"deploy": dict(envelope.get("deploy") or {}),
|
|
98
|
+
"current_rollout": dict(current) if isinstance(current, Mapping) else None,
|
|
99
|
+
"executor_history": (
|
|
100
|
+
[dict(row) for row in history if isinstance(row, Mapping)]
|
|
101
|
+
if isinstance(history, list)
|
|
102
|
+
else []
|
|
103
|
+
),
|
|
104
|
+
"provenance": provenance,
|
|
105
|
+
"partial": bool(provenance.get("partial")),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
75
109
|
def _is_workflow_recipe_ref(value: Optional[str]) -> bool:
|
|
76
110
|
return str(value or "").strip().startswith("recipe://workflow-recipe-v1/")
|
|
77
111
|
|
|
@@ -1077,11 +1111,21 @@ class AuthorityNamespace:
|
|
|
1077
1111
|
)
|
|
1078
1112
|
|
|
1079
1113
|
async def get_deploy(self, deploy_id: str, *, timeout: Optional[float] = None) -> Dict[str, Any]:
|
|
1080
|
-
"""Get deploy by id
|
|
1114
|
+
"""Get deploy by id in coherent current state.
|
|
1115
|
+
|
|
1116
|
+
``GET /api/authority/deploys/{deploy_id}?view=coherent`` returns
|
|
1117
|
+
``{deploy, current_rollout, executor_history, provenance}``: the single
|
|
1118
|
+
current rollout, the executor history labeled as history, and the
|
|
1119
|
+
provenance naming which rollout is current (``partial`` when Authority
|
|
1120
|
+
cannot resolve one). The view is requested explicitly so the read never
|
|
1121
|
+
rides the server's legacy default, and there is no legacy fallback.
|
|
1122
|
+
Use :func:`coherent_deploy_state` to read the sections apart.
|
|
1123
|
+
"""
|
|
1081
1124
|
if not deploy_id:
|
|
1082
1125
|
raise ValueError("deploy_id is required")
|
|
1126
|
+
qs = _query_string({"view": DEPLOY_VIEW_COHERENT})
|
|
1083
1127
|
return await self._get(
|
|
1084
|
-
f"/api/authority/deploys/{quote(deploy_id, safe='')}",
|
|
1128
|
+
f"/api/authority/deploys/{quote(deploy_id, safe='')}{qs}",
|
|
1085
1129
|
timeout=self._http_timeout(timeout, 30.0),
|
|
1086
1130
|
)
|
|
1087
1131
|
|
|
@@ -437,7 +437,9 @@ class Dominus:
|
|
|
437
437
|
response = await client.get(endpoint)
|
|
438
438
|
elif method == "DELETE":
|
|
439
439
|
# Kernel wire format: same base64 JSON body as POST (Node SDK parity).
|
|
440
|
-
|
|
440
|
+
# httpx.AsyncClient.delete() accepts no body kwarg (unlike
|
|
441
|
+
# post/put), so use the generic verb to keep the body on the wire.
|
|
442
|
+
response = await client.request("DELETE", endpoint, content=body_b64)
|
|
441
443
|
elif method == "PUT":
|
|
442
444
|
response = await client.put(endpoint, content=body_b64)
|
|
443
445
|
else:
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/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.14
|
|
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,8 @@ 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-
|
|
42
|
-
cleanup audit is `docs/janitor/2026-09-
|
|
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`.
|
|
43
43
|
|
|
44
44
|
## What This Repo Ships
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
|
|
|
48
48
|
- Gateway-scoped client mode for MCP and other user-JWT sessions
|
|
49
49
|
- Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
|
|
50
50
|
- Local helpers for JWT verification, trace propagation, retries, and console capture
|
|
51
|
-
- Current package version: `9.0.
|
|
51
|
+
- Current package version: `9.0.14`
|
|
52
52
|
|
|
53
53
|
## Install
|
|
54
54
|
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_authority_public_vocabulary.py
RENAMED
|
@@ -611,6 +611,91 @@ async def test_bootstrap_provisioning_target_carries_repo_template():
|
|
|
611
611
|
assert "repo_template" not in absent_client.calls[-1]["body"]
|
|
612
612
|
|
|
613
613
|
|
|
614
|
+
# --- Task 16: singular deploy reader reads coherent current state --
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
@pytest.mark.asyncio
|
|
618
|
+
async def test_get_deploy_requests_the_coherent_view_explicitly():
|
|
619
|
+
from dominus.namespaces.authority import DEPLOY_VIEW_COHERENT
|
|
620
|
+
|
|
621
|
+
client = FakeClient()
|
|
622
|
+
ns = AuthorityNamespace(client)
|
|
623
|
+
|
|
624
|
+
await ns.get_deploy("deploy::dominus-authority--production")
|
|
625
|
+
|
|
626
|
+
assert client.calls[0]["method"] == "GET"
|
|
627
|
+
assert client.calls[0]["endpoint"] == (
|
|
628
|
+
"/api/authority/deploys/deploy%3A%3Adominus-authority--production?view=coherent"
|
|
629
|
+
)
|
|
630
|
+
# The view is named on the wire, never inherited from the server default.
|
|
631
|
+
assert DEPLOY_VIEW_COHERENT == "coherent"
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
def test_coherent_deploy_state_keeps_current_and_history_labeled_apart():
|
|
635
|
+
from dominus.namespaces.authority import coherent_deploy_state
|
|
636
|
+
|
|
637
|
+
state = coherent_deploy_state(
|
|
638
|
+
{
|
|
639
|
+
"deploy": {"deploy_id": "deploy-1", "app_slug": "carebridge"},
|
|
640
|
+
"current_rollout": {"rollout_id": "rollout-2", "generation": 7},
|
|
641
|
+
"executor_history": [
|
|
642
|
+
{"rollout_id": "rollout-1", "generation": 6},
|
|
643
|
+
{"rollout_id": "rollout-2", "generation": 7, "is_current": True},
|
|
644
|
+
],
|
|
645
|
+
"provenance": {
|
|
646
|
+
"view": "coherent",
|
|
647
|
+
"source": "current_rollout",
|
|
648
|
+
"rollout_id": "rollout-2",
|
|
649
|
+
"generation": 7,
|
|
650
|
+
"is_current": True,
|
|
651
|
+
"partial": False,
|
|
652
|
+
},
|
|
653
|
+
}
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
assert state["current_rollout"]["rollout_id"] == "rollout-2"
|
|
657
|
+
assert [row["rollout_id"] for row in state["executor_history"]] == ["rollout-1", "rollout-2"]
|
|
658
|
+
assert state["provenance"]["generation"] == 7
|
|
659
|
+
assert state["partial"] is False
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
def test_coherent_deploy_state_never_substitutes_history_for_a_missing_current_rollout():
|
|
663
|
+
from dominus.namespaces.authority import coherent_deploy_state
|
|
664
|
+
|
|
665
|
+
state = coherent_deploy_state(
|
|
666
|
+
{
|
|
667
|
+
"deploy": {"deploy_id": "deploy-2"},
|
|
668
|
+
"current_rollout": None,
|
|
669
|
+
"executor_history": [{"rollout_id": "rollout-9", "generation": 3}],
|
|
670
|
+
"provenance": {
|
|
671
|
+
"view": "coherent",
|
|
672
|
+
"source": None,
|
|
673
|
+
"rollout_id": None,
|
|
674
|
+
"is_current": False,
|
|
675
|
+
"partial": True,
|
|
676
|
+
},
|
|
677
|
+
}
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
# An unresolved current rollout stays an explicit partial; the newest
|
|
681
|
+
# history entry is not promoted into its place.
|
|
682
|
+
assert state["current_rollout"] is None
|
|
683
|
+
assert state["partial"] is True
|
|
684
|
+
assert [row["rollout_id"] for row in state["executor_history"]] == ["rollout-9"]
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def test_coherent_deploy_state_tolerates_a_non_envelope_payload():
|
|
688
|
+
from dominus.namespaces.authority import coherent_deploy_state
|
|
689
|
+
|
|
690
|
+
state = coherent_deploy_state({"code": "authority.deploy_not_found"})
|
|
691
|
+
|
|
692
|
+
assert state["deploy"] == {}
|
|
693
|
+
assert state["current_rollout"] is None
|
|
694
|
+
assert state["executor_history"] == []
|
|
695
|
+
assert state["provenance"] == {}
|
|
696
|
+
assert state["partial"] is False
|
|
697
|
+
|
|
698
|
+
|
|
614
699
|
def test_bootstrap_signature_carries_standalone_and_root_role():
|
|
615
700
|
bootstrap_sig = inspect.signature(AuthorityNamespace.bootstrap_provisioning_target)
|
|
616
701
|
assert "standalone" in bootstrap_sig.parameters
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
import json
|
|
2
3
|
import sys
|
|
3
4
|
from pathlib import Path
|
|
@@ -56,6 +57,51 @@ class RequestClient:
|
|
|
56
57
|
return FakeResponse(json.dumps({"success": True, "data": {"ok": True}}))
|
|
57
58
|
|
|
58
59
|
|
|
60
|
+
class HttpxFaithfulDeleteClient:
|
|
61
|
+
"""Fake AsyncClient whose ``delete()`` mirrors httpx's real signature.
|
|
62
|
+
|
|
63
|
+
httpx.AsyncClient.delete() takes no body kwarg (unlike post/put), so a fake
|
|
64
|
+
that tolerated ``content=`` here would silently mask the very regression
|
|
65
|
+
these tests exist to catch. ``request()`` is the body-capable generic verb.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
calls = []
|
|
69
|
+
|
|
70
|
+
def __init__(self, *, base_url, headers, timeout):
|
|
71
|
+
self.base_url = base_url
|
|
72
|
+
self.headers = headers
|
|
73
|
+
self.timeout = timeout
|
|
74
|
+
|
|
75
|
+
async def __aenter__(self):
|
|
76
|
+
return self
|
|
77
|
+
|
|
78
|
+
async def __aexit__(self, exc_type, exc, tb):
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
async def delete(self, endpoint, *, params=None, headers=None, cookies=None):
|
|
82
|
+
# Exact httpx 0.28 surface: no content/json/data parameter.
|
|
83
|
+
raise AssertionError(
|
|
84
|
+
"_request() must not send a body through httpx's body-less delete(); "
|
|
85
|
+
"use client.request('DELETE', ...) instead"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
async def get(self, endpoint):
|
|
89
|
+
self.calls.append({"method": "GET", "endpoint": endpoint, "content": None})
|
|
90
|
+
return FakeResponse(json.dumps({"success": True, "data": {"ok": True}}))
|
|
91
|
+
|
|
92
|
+
async def post(self, endpoint, content=None):
|
|
93
|
+
self.calls.append({"method": "POST", "endpoint": endpoint, "content": content})
|
|
94
|
+
return FakeResponse(json.dumps({"success": True, "data": {"ok": True}}))
|
|
95
|
+
|
|
96
|
+
async def put(self, endpoint, content=None):
|
|
97
|
+
self.calls.append({"method": "PUT", "endpoint": endpoint, "content": content})
|
|
98
|
+
return FakeResponse(json.dumps({"success": True, "data": {"ok": True}}))
|
|
99
|
+
|
|
100
|
+
async def request(self, method, endpoint, *, content=None, **kwargs):
|
|
101
|
+
self.calls.append({"method": method, "endpoint": endpoint, "content": content})
|
|
102
|
+
return FakeResponse(json.dumps({"success": True, "data": {"ok": True}}))
|
|
103
|
+
|
|
104
|
+
|
|
59
105
|
class UnwrappedRequestClient:
|
|
60
106
|
calls = []
|
|
61
107
|
|
|
@@ -199,6 +245,52 @@ async def test_request_accepts_raw_json_success_envelope(monkeypatch, sdk):
|
|
|
199
245
|
assert RequestClient.calls[0]["endpoint"] == "/svc/health"
|
|
200
246
|
|
|
201
247
|
|
|
248
|
+
@pytest.mark.asyncio
|
|
249
|
+
async def test_guardian_delete_reaches_transport_with_body(monkeypatch, sdk):
|
|
250
|
+
"""Regression: guardian_delete (no explicit body) hit httpx's delete() kwarg wall.
|
|
251
|
+
|
|
252
|
+
Live failure 2026-09-22: AsyncClient.delete() got an unexpected keyword
|
|
253
|
+
argument 'content' -- every DELETE through _request raised TypeError.
|
|
254
|
+
"""
|
|
255
|
+
HttpxFaithfulDeleteClient.calls = []
|
|
256
|
+
|
|
257
|
+
async def fake_ensure_valid_jwt(psk_token, base_url):
|
|
258
|
+
return "jwt-abc"
|
|
259
|
+
|
|
260
|
+
monkeypatch.setattr(core_module, "_ensure_valid_jwt", fake_ensure_valid_jwt)
|
|
261
|
+
monkeypatch.setattr(start_module.httpx, "AsyncClient", HttpxFaithfulDeleteClient)
|
|
262
|
+
|
|
263
|
+
result = await sdk.auth.guardian_delete("tenants", "5d05b96e-0aef-4dbf-a4dc-19354da9f58e")
|
|
264
|
+
|
|
265
|
+
assert result == {"ok": True}
|
|
266
|
+
call = HttpxFaithfulDeleteClient.calls[0]
|
|
267
|
+
assert call["method"] == "DELETE"
|
|
268
|
+
assert call["endpoint"] == "/svc/guardian/tenants/5d05b96e-0aef-4dbf-a4dc-19354da9f58e"
|
|
269
|
+
assert call["content"] == base64.b64encode(json.dumps({}).encode()).decode()
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@pytest.mark.asyncio
|
|
273
|
+
async def test_non_guardian_delete_reaches_transport_with_body(monkeypatch, sdk):
|
|
274
|
+
"""Same shared _request path, non-guardian namespace, real body on the wire."""
|
|
275
|
+
HttpxFaithfulDeleteClient.calls = []
|
|
276
|
+
|
|
277
|
+
async def fake_ensure_valid_jwt(psk_token, base_url):
|
|
278
|
+
return "jwt-abc"
|
|
279
|
+
|
|
280
|
+
monkeypatch.setattr(core_module, "_ensure_valid_jwt", fake_ensure_valid_jwt)
|
|
281
|
+
monkeypatch.setattr(start_module.httpx, "AsyncClient", HttpxFaithfulDeleteClient)
|
|
282
|
+
|
|
283
|
+
result = await sdk.ddl.drop_table("public", "widgets")
|
|
284
|
+
|
|
285
|
+
assert result == {"ok": True}
|
|
286
|
+
call = HttpxFaithfulDeleteClient.calls[0]
|
|
287
|
+
assert call["method"] == "DELETE"
|
|
288
|
+
assert call["endpoint"] == "/svc/smith/schema/drop-table"
|
|
289
|
+
assert call["content"] == base64.b64encode(
|
|
290
|
+
json.dumps({"schema": "public", "table": "widgets"}).encode()
|
|
291
|
+
).decode()
|
|
292
|
+
|
|
293
|
+
|
|
202
294
|
@pytest.mark.asyncio
|
|
203
295
|
async def test_request_accepts_unwrapped_control_plane_success(monkeypatch, sdk):
|
|
204
296
|
UnwrappedRequestClient.calls = []
|
|
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.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/dominus_sdk_python.egg-info/top_level.txt
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.12 → dominus_sdk_python-9.0.14}/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.12 → dominus_sdk_python-9.0.14}/tests/test_namespace_barrel_exports.py
RENAMED
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_platform_coder_namespaces.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_readme_quickstart_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/tests/test_secrets_presence_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-9.0.12 → dominus_sdk_python-9.0.14}/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
|