dominus-sdk-python 6.1.1__tar.gz → 6.1.3__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-6.1.1 → dominus_sdk_python-6.1.3}/PKG-INFO +2 -1
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/README.md +1 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/__init__.py +3 -1
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/coder.py +2 -0
- dominus_sdk_python-6.1.3/dominus/namespaces/publisher.py +300 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/start.py +3 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/PKG-INFO +2 -1
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/SOURCES.txt +2 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/pyproject.toml +1 -1
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_platform_coder_namespaces.py +2 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_public_exports.py +3 -0
- dominus_sdk_python-6.1.3/tests/test_publisher_namespace.py +82 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/config/__init__.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/config/endpoints.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/errors.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/__init__.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/auth.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/cache.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/console_capture.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/core.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/crypto.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/sse.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/helpers/trace.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/__init__.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/admin.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/ai.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/artifacts.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/auth.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/authority.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/browser.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/courier.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/db.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/ddl.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/deployer.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/fastapi.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/files.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/health.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/jobs.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/logs.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/platform.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/portal.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/processor.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/recipes.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/redis.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/secrets.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/secure.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/stash.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/sync.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/warden.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/namespaces/workflow.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus/services/__init__.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/top_level.txt +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/setup.cfg +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_auth.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_authority_public_vocabulary.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_browser_namespace.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_control_plane_namespaces.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_errors.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_flat_commands.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_health.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_logs.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_provisioning_parity.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_recipes_namespace.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_transport_compat.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_workflow_lifecycle.py +0 -0
- {dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/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: 6.1.
|
|
3
|
+
Version: 6.1.3
|
|
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
|
|
@@ -105,6 +105,7 @@ coder_run = await dominus.coder.ensure_run(
|
|
|
105
105
|
policy_decision_id=policy["data"]["policy_decision"]["decision_id"],
|
|
106
106
|
workflow_recipe_ref="recipe://workflow-recipe-v1/coder-feature@head",
|
|
107
107
|
repository="carebridgesystems/dominus-platform-worker",
|
|
108
|
+
executor="managed_anthropic",
|
|
108
109
|
instructions="Fix failing tests",
|
|
109
110
|
actor_context={"type": "user", "id": "operator-1"},
|
|
110
111
|
)
|
|
@@ -72,6 +72,7 @@ coder_run = await dominus.coder.ensure_run(
|
|
|
72
72
|
policy_decision_id=policy["data"]["policy_decision"]["decision_id"],
|
|
73
73
|
workflow_recipe_ref="recipe://workflow-recipe-v1/coder-feature@head",
|
|
74
74
|
repository="carebridgesystems/dominus-platform-worker",
|
|
75
|
+
executor="managed_anthropic",
|
|
75
76
|
instructions="Fix failing tests",
|
|
76
77
|
actor_context={"type": "user", "id": "operator-1"},
|
|
77
78
|
)
|
|
@@ -114,6 +114,7 @@ from .namespaces.deployer import DeployerNamespace
|
|
|
114
114
|
from .namespaces.warden import WardenNamespace
|
|
115
115
|
from .namespaces.platform import PlatformNamespace
|
|
116
116
|
from .namespaces.coder import CoderNamespace
|
|
117
|
+
from .namespaces.publisher import PublisherNamespace
|
|
117
118
|
|
|
118
119
|
# Export AI namespace for agent-runtime operations
|
|
119
120
|
from .namespaces.ai import (
|
|
@@ -164,7 +165,7 @@ from .errors import (
|
|
|
164
165
|
TimeoutError as DominusTimeoutError,
|
|
165
166
|
)
|
|
166
167
|
|
|
167
|
-
__version__ = "6.1.
|
|
168
|
+
__version__ = "6.1.3"
|
|
168
169
|
__all__ = [
|
|
169
170
|
# Main SDK instance
|
|
170
171
|
"dominus",
|
|
@@ -217,6 +218,7 @@ __all__ = [
|
|
|
217
218
|
"WardenNamespace",
|
|
218
219
|
"PlatformNamespace",
|
|
219
220
|
"CoderNamespace",
|
|
221
|
+
"PublisherNamespace",
|
|
220
222
|
# AI namespace for agent-runtime operations
|
|
221
223
|
"AiNamespace",
|
|
222
224
|
"RagSubNamespace",
|
|
@@ -117,6 +117,7 @@ class CoderNamespace:
|
|
|
117
117
|
branch: Optional[str] = None,
|
|
118
118
|
base_branch: Optional[str] = None,
|
|
119
119
|
working_branch: Optional[str] = None,
|
|
120
|
+
executor: Optional[str] = None,
|
|
120
121
|
title: Optional[str] = None,
|
|
121
122
|
instructions: Optional[str] = None,
|
|
122
123
|
inputs: Optional[Dict[str, Any]] = None,
|
|
@@ -140,6 +141,7 @@ class CoderNamespace:
|
|
|
140
141
|
"branch": branch,
|
|
141
142
|
"base_branch": base_branch,
|
|
142
143
|
"working_branch": working_branch,
|
|
144
|
+
"executor": executor,
|
|
143
145
|
"title": title,
|
|
144
146
|
"instructions": instructions,
|
|
145
147
|
"inputs": inputs,
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Publisher namespace.
|
|
2
|
+
|
|
3
|
+
Build-artifact lifecycle, signing, release records, channel pins, and resolver
|
|
4
|
+
reads for dominus-publisher. This surface intentionally does not expose raw
|
|
5
|
+
runner credentials or direct byte upload shortcuts.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
10
|
+
from urllib.parse import quote, urlencode
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..start import Dominus
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _compact(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
17
|
+
out: Dict[str, Any] = {}
|
|
18
|
+
for key, value in payload.items():
|
|
19
|
+
if value is None:
|
|
20
|
+
continue
|
|
21
|
+
if isinstance(value, str) and value.strip() == "":
|
|
22
|
+
continue
|
|
23
|
+
out[key] = value
|
|
24
|
+
return out
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _query_string(params: Dict[str, Any]) -> str:
|
|
28
|
+
cleaned = _compact(params)
|
|
29
|
+
return f"?{urlencode(cleaned)}" if cleaned else ""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _normalize_publisher_path(path: str) -> str:
|
|
33
|
+
trimmed = path.strip()
|
|
34
|
+
normalized = trimmed if trimmed.startswith("/") else f"/{trimmed}"
|
|
35
|
+
if normalized == "/svc/publisher" or normalized.startswith("/svc/publisher/"):
|
|
36
|
+
return normalized
|
|
37
|
+
if normalized == "/api/publisher" or normalized.startswith("/api/publisher/"):
|
|
38
|
+
return normalized.replace("/api/", "/svc/", 1)
|
|
39
|
+
return f"/svc/publisher{normalized}"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _actor_headers(actor_context: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]:
|
|
43
|
+
if not actor_context:
|
|
44
|
+
return None
|
|
45
|
+
actor_type = str(actor_context.get("type") or actor_context.get("actor_type") or "").strip()
|
|
46
|
+
actor_id = str(actor_context.get("id") or actor_context.get("actor_id") or "").strip()
|
|
47
|
+
if not actor_type or not actor_id:
|
|
48
|
+
return None
|
|
49
|
+
return {"X-Actor-Type": actor_type, "X-Actor-Id": actor_id}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _mutation_body(
|
|
53
|
+
*,
|
|
54
|
+
reason: Optional[str] = None,
|
|
55
|
+
idempotency_key: Optional[str] = None,
|
|
56
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
57
|
+
) -> Dict[str, Any]:
|
|
58
|
+
return _compact(
|
|
59
|
+
{
|
|
60
|
+
"reason": reason,
|
|
61
|
+
"idempotency_key": idempotency_key,
|
|
62
|
+
"metadata": metadata,
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class PublisherNamespace:
|
|
68
|
+
"""Publisher build-artifact lifecycle helpers."""
|
|
69
|
+
|
|
70
|
+
def __init__(self, client: "Dominus"):
|
|
71
|
+
self._client = client
|
|
72
|
+
|
|
73
|
+
async def request(
|
|
74
|
+
self,
|
|
75
|
+
path: str,
|
|
76
|
+
*,
|
|
77
|
+
method: str = "GET",
|
|
78
|
+
body: Optional[Dict[str, Any]] = None,
|
|
79
|
+
headers: Optional[Dict[str, str]] = None,
|
|
80
|
+
timeout: float = 30.0,
|
|
81
|
+
) -> Any:
|
|
82
|
+
return await self._client.gateway_fetch(
|
|
83
|
+
_normalize_publisher_path(path),
|
|
84
|
+
method=method,
|
|
85
|
+
body=body,
|
|
86
|
+
headers=headers,
|
|
87
|
+
timeout=timeout,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
async def health(self) -> Dict[str, Any]:
|
|
91
|
+
return await self.request("/health", method="GET")
|
|
92
|
+
|
|
93
|
+
async def ready(self) -> Dict[str, Any]:
|
|
94
|
+
return await self.request("/ready", method="GET")
|
|
95
|
+
|
|
96
|
+
async def list_builds(
|
|
97
|
+
self,
|
|
98
|
+
*,
|
|
99
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
100
|
+
) -> Dict[str, Any]:
|
|
101
|
+
return await self.request("/builds", method="GET", headers=_actor_headers(actor_context))
|
|
102
|
+
|
|
103
|
+
async def ensure_build(
|
|
104
|
+
self,
|
|
105
|
+
payload: Dict[str, Any],
|
|
106
|
+
*,
|
|
107
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
108
|
+
) -> Dict[str, Any]:
|
|
109
|
+
return await self.request(
|
|
110
|
+
"/builds/ensure",
|
|
111
|
+
method="POST",
|
|
112
|
+
body=payload,
|
|
113
|
+
headers=_actor_headers(actor_context),
|
|
114
|
+
timeout=600.0,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
async def get_build(
|
|
118
|
+
self,
|
|
119
|
+
build_id: str,
|
|
120
|
+
*,
|
|
121
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
122
|
+
) -> Dict[str, Any]:
|
|
123
|
+
return await self.request(
|
|
124
|
+
f"/builds/{quote(build_id, safe='')}",
|
|
125
|
+
method="GET",
|
|
126
|
+
headers=_actor_headers(actor_context),
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
async def retry_build(
|
|
130
|
+
self,
|
|
131
|
+
build_id: str,
|
|
132
|
+
*,
|
|
133
|
+
reason: Optional[str] = None,
|
|
134
|
+
idempotency_key: Optional[str] = None,
|
|
135
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
136
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
137
|
+
) -> Dict[str, Any]:
|
|
138
|
+
return await self.request(
|
|
139
|
+
f"/builds/{quote(build_id, safe='')}/retry",
|
|
140
|
+
method="POST",
|
|
141
|
+
body=_mutation_body(reason=reason, idempotency_key=idempotency_key, metadata=metadata),
|
|
142
|
+
headers=_actor_headers(actor_context),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
async def cancel_build(
|
|
146
|
+
self,
|
|
147
|
+
build_id: str,
|
|
148
|
+
*,
|
|
149
|
+
reason: Optional[str] = None,
|
|
150
|
+
idempotency_key: Optional[str] = None,
|
|
151
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
152
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
153
|
+
) -> Dict[str, Any]:
|
|
154
|
+
return await self.request(
|
|
155
|
+
f"/builds/{quote(build_id, safe='')}/cancel",
|
|
156
|
+
method="POST",
|
|
157
|
+
body=_mutation_body(reason=reason, idempotency_key=idempotency_key, metadata=metadata),
|
|
158
|
+
headers=_actor_headers(actor_context),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
async def evaluate_signing(
|
|
162
|
+
self,
|
|
163
|
+
payload: Dict[str, Any],
|
|
164
|
+
*,
|
|
165
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
166
|
+
) -> Dict[str, Any]:
|
|
167
|
+
return await self.request(
|
|
168
|
+
"/builds/signing/evaluate",
|
|
169
|
+
method="POST",
|
|
170
|
+
body=payload,
|
|
171
|
+
headers=_actor_headers(actor_context),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
async def record_signing_evidence(
|
|
175
|
+
self,
|
|
176
|
+
payload: Dict[str, Any],
|
|
177
|
+
*,
|
|
178
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
179
|
+
) -> Dict[str, Any]:
|
|
180
|
+
return await self.request(
|
|
181
|
+
"/builds/signing/evidence",
|
|
182
|
+
method="POST",
|
|
183
|
+
body=payload,
|
|
184
|
+
headers=_actor_headers(actor_context),
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
async def list_artifacts(
|
|
188
|
+
self,
|
|
189
|
+
*,
|
|
190
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
191
|
+
) -> Dict[str, Any]:
|
|
192
|
+
return await self.request("/artifacts", method="GET", headers=_actor_headers(actor_context))
|
|
193
|
+
|
|
194
|
+
async def record_release(
|
|
195
|
+
self,
|
|
196
|
+
payload: Dict[str, Any],
|
|
197
|
+
*,
|
|
198
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
199
|
+
) -> Dict[str, Any]:
|
|
200
|
+
return await self.request(
|
|
201
|
+
"/artifacts/releases/record",
|
|
202
|
+
method="POST",
|
|
203
|
+
body=payload,
|
|
204
|
+
headers=_actor_headers(actor_context),
|
|
205
|
+
timeout=600.0,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
async def resolve_artifact(
|
|
209
|
+
self,
|
|
210
|
+
artifact_key: str,
|
|
211
|
+
*,
|
|
212
|
+
selector: Optional[str] = None,
|
|
213
|
+
environment: Optional[str] = None,
|
|
214
|
+
target_app: Optional[str] = None,
|
|
215
|
+
architecture: Optional[str] = None,
|
|
216
|
+
runtime_family: Optional[str] = None,
|
|
217
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
218
|
+
) -> Dict[str, Any]:
|
|
219
|
+
qs = _query_string(
|
|
220
|
+
{
|
|
221
|
+
"selector": selector,
|
|
222
|
+
"environment": environment,
|
|
223
|
+
"target_app": target_app,
|
|
224
|
+
"architecture": architecture,
|
|
225
|
+
"runtime_family": runtime_family,
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
return await self.request(
|
|
229
|
+
f"/artifacts/{quote(artifact_key, safe='')}{qs}",
|
|
230
|
+
method="GET",
|
|
231
|
+
headers=_actor_headers(actor_context),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
async def list_channels(
|
|
235
|
+
self,
|
|
236
|
+
*,
|
|
237
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
238
|
+
) -> Dict[str, Any]:
|
|
239
|
+
return await self.request("/channels", method="GET", headers=_actor_headers(actor_context))
|
|
240
|
+
|
|
241
|
+
async def get_channel(
|
|
242
|
+
self,
|
|
243
|
+
artifact_key: str,
|
|
244
|
+
selector: str,
|
|
245
|
+
*,
|
|
246
|
+
environment: Optional[str] = None,
|
|
247
|
+
target_app: Optional[str] = None,
|
|
248
|
+
architecture: Optional[str] = None,
|
|
249
|
+
runtime_family: Optional[str] = None,
|
|
250
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
251
|
+
) -> Dict[str, Any]:
|
|
252
|
+
qs = _query_string(
|
|
253
|
+
{
|
|
254
|
+
"environment": environment,
|
|
255
|
+
"target_app": target_app,
|
|
256
|
+
"architecture": architecture,
|
|
257
|
+
"runtime_family": runtime_family,
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
return await self.request(
|
|
261
|
+
f"/channels/{quote(artifact_key, safe='')}/{quote(selector, safe='')}{qs}",
|
|
262
|
+
method="GET",
|
|
263
|
+
headers=_actor_headers(actor_context),
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
async def pin_channel(
|
|
267
|
+
self,
|
|
268
|
+
artifact_key: str,
|
|
269
|
+
selector: str,
|
|
270
|
+
payload: Dict[str, Any],
|
|
271
|
+
*,
|
|
272
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
273
|
+
) -> Dict[str, Any]:
|
|
274
|
+
return await self.request(
|
|
275
|
+
f"/channels/{quote(artifact_key, safe='')}/{quote(selector, safe='')}/pin",
|
|
276
|
+
method="POST",
|
|
277
|
+
body=payload,
|
|
278
|
+
headers=_actor_headers(actor_context),
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
async def list_prestage(
|
|
282
|
+
self,
|
|
283
|
+
*,
|
|
284
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
285
|
+
) -> Dict[str, Any]:
|
|
286
|
+
return await self.request("/prestage", method="GET", headers=_actor_headers(actor_context))
|
|
287
|
+
|
|
288
|
+
async def ensure_prestage(
|
|
289
|
+
self,
|
|
290
|
+
payload: Dict[str, Any],
|
|
291
|
+
*,
|
|
292
|
+
actor_context: Optional[Dict[str, str]] = None,
|
|
293
|
+
) -> Dict[str, Any]:
|
|
294
|
+
return await self.request(
|
|
295
|
+
"/prestage/ensure",
|
|
296
|
+
method="POST",
|
|
297
|
+
body=payload,
|
|
298
|
+
headers=_actor_headers(actor_context),
|
|
299
|
+
timeout=600.0,
|
|
300
|
+
)
|
|
@@ -181,10 +181,12 @@ class Dominus:
|
|
|
181
181
|
from .namespaces.warden import WardenNamespace
|
|
182
182
|
from .namespaces.platform import PlatformNamespace
|
|
183
183
|
from .namespaces.coder import CoderNamespace
|
|
184
|
+
from .namespaces.publisher import PublisherNamespace
|
|
184
185
|
self.deployer = DeployerNamespace(self)
|
|
185
186
|
self.warden = WardenNamespace(self)
|
|
186
187
|
self.platform = PlatformNamespace(self)
|
|
187
188
|
self.coder = CoderNamespace(self)
|
|
189
|
+
self.publisher = PublisherNamespace(self)
|
|
188
190
|
|
|
189
191
|
# Stash worker (per-scope durable items: credentials + configs)
|
|
190
192
|
from .namespaces.stash import StashNamespace
|
|
@@ -539,6 +541,7 @@ class Dominus:
|
|
|
539
541
|
or "/svc/admin/" in path
|
|
540
542
|
or "/svc/platform/" in path
|
|
541
543
|
or "/svc/coder/" in path
|
|
544
|
+
or "/svc/publisher/" in path
|
|
542
545
|
)
|
|
543
546
|
decode_base64 = (
|
|
544
547
|
"/svc/warden/secrets" in path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python
|
|
3
|
-
Version: 6.1.
|
|
3
|
+
Version: 6.1.3
|
|
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
|
|
@@ -105,6 +105,7 @@ coder_run = await dominus.coder.ensure_run(
|
|
|
105
105
|
policy_decision_id=policy["data"]["policy_decision"]["decision_id"],
|
|
106
106
|
workflow_recipe_ref="recipe://workflow-recipe-v1/coder-feature@head",
|
|
107
107
|
repository="carebridgesystems/dominus-platform-worker",
|
|
108
|
+
executor="managed_anthropic",
|
|
108
109
|
instructions="Fix failing tests",
|
|
109
110
|
actor_context={"type": "user", "id": "operator-1"},
|
|
110
111
|
)
|
{dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/SOURCES.txt
RENAMED
|
@@ -33,6 +33,7 @@ dominus/namespaces/logs.py
|
|
|
33
33
|
dominus/namespaces/platform.py
|
|
34
34
|
dominus/namespaces/portal.py
|
|
35
35
|
dominus/namespaces/processor.py
|
|
36
|
+
dominus/namespaces/publisher.py
|
|
36
37
|
dominus/namespaces/recipes.py
|
|
37
38
|
dominus/namespaces/redis.py
|
|
38
39
|
dominus/namespaces/secrets.py
|
|
@@ -58,6 +59,7 @@ tests/test_logs.py
|
|
|
58
59
|
tests/test_platform_coder_namespaces.py
|
|
59
60
|
tests/test_provisioning_parity.py
|
|
60
61
|
tests/test_public_exports.py
|
|
62
|
+
tests/test_publisher_namespace.py
|
|
61
63
|
tests/test_recipes_namespace.py
|
|
62
64
|
tests/test_transport_compat.py
|
|
63
65
|
tests/test_workflow_lifecycle.py
|
{dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_platform_coder_namespaces.py
RENAMED
|
@@ -80,6 +80,7 @@ async def test_coder_namespace_exposes_lifecycle_helpers_but_no_raw_shell():
|
|
|
80
80
|
task_recipe_ref="recipe://coder-task-recipe-v1/fix-tests@head",
|
|
81
81
|
workflow_recipe_ref="recipe://workflow-recipe-v1/coder-feature@head",
|
|
82
82
|
repository="carebridgesystems/dominus-platform-worker",
|
|
83
|
+
executor="managed_anthropic",
|
|
83
84
|
instructions="Fix failing tests",
|
|
84
85
|
actor_context={"type": "user", "id": "user-1"},
|
|
85
86
|
)
|
|
@@ -105,6 +106,7 @@ async def test_coder_namespace_exposes_lifecycle_helpers_but_no_raw_shell():
|
|
|
105
106
|
"task_recipe_ref": "recipe://coder-task-recipe-v1/fix-tests@head",
|
|
106
107
|
"workflow_recipe_ref": "recipe://workflow-recipe-v1/coder-feature@head",
|
|
107
108
|
"repository": "carebridgesystems/dominus-platform-worker",
|
|
109
|
+
"executor": "managed_anthropic",
|
|
108
110
|
"instructions": "Fix failing tests",
|
|
109
111
|
}
|
|
110
112
|
assert client.calls[0][1]["headers"] == {"X-Actor-Type": "user", "X-Actor-Id": "user-1"}
|
|
@@ -3,6 +3,7 @@ from dominus import (
|
|
|
3
3
|
CoderNamespace,
|
|
4
4
|
DeployerNamespace,
|
|
5
5
|
PlatformNamespace,
|
|
6
|
+
PublisherNamespace,
|
|
6
7
|
RecipesNamespace,
|
|
7
8
|
WardenNamespace,
|
|
8
9
|
gateway_circuit_breaker,
|
|
@@ -37,6 +38,7 @@ def test_top_level_exports_drop_delegate_alias():
|
|
|
37
38
|
assert RecipesNamespace is not None
|
|
38
39
|
assert PlatformNamespace is not None
|
|
39
40
|
assert CoderNamespace is not None
|
|
41
|
+
assert PublisherNamespace is not None
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
def test_singleton_exposes_browser_namespace():
|
|
@@ -46,3 +48,4 @@ def test_singleton_exposes_browser_namespace():
|
|
|
46
48
|
assert callable(dominus.recipes.list_types)
|
|
47
49
|
assert callable(dominus.platform.ensure_policy_decision)
|
|
48
50
|
assert callable(dominus.coder.ensure_run)
|
|
51
|
+
assert callable(dominus.publisher.resolve_artifact)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from dominus.namespaces.publisher import PublisherNamespace
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MockGatewayClient:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.calls = []
|
|
9
|
+
|
|
10
|
+
async def gateway_fetch(self, path, **kwargs):
|
|
11
|
+
self.calls.append((path, kwargs))
|
|
12
|
+
return {"ok": True}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.mark.asyncio
|
|
16
|
+
async def test_publisher_namespace_normalizes_lifecycle_and_resolver_helpers():
|
|
17
|
+
client = MockGatewayClient()
|
|
18
|
+
publisher = PublisherNamespace(client)
|
|
19
|
+
|
|
20
|
+
await publisher.health()
|
|
21
|
+
await publisher.ready()
|
|
22
|
+
await publisher.list_builds()
|
|
23
|
+
await publisher.ensure_build(
|
|
24
|
+
{"artifact_key": "envoy_binary"},
|
|
25
|
+
actor_context={"type": "service", "id": "dominus-deployer"},
|
|
26
|
+
)
|
|
27
|
+
await publisher.get_build("pub_123")
|
|
28
|
+
await publisher.retry_build("pub_123", reason="rerun", idempotency_key="retry-1")
|
|
29
|
+
await publisher.cancel_build("pub_123", metadata={"requested_by": "operator"})
|
|
30
|
+
await publisher.evaluate_signing({"environment": "production"})
|
|
31
|
+
await publisher.record_signing_evidence({"artifact_key": "envoy_binary"})
|
|
32
|
+
await publisher.list_artifacts()
|
|
33
|
+
await publisher.record_release({"artifact_key": "envoy_binary"})
|
|
34
|
+
await publisher.resolve_artifact(
|
|
35
|
+
"envoy_binary",
|
|
36
|
+
selector="stable",
|
|
37
|
+
environment="production",
|
|
38
|
+
target_app="powerscribe",
|
|
39
|
+
architecture="x64",
|
|
40
|
+
runtime_family="rust-tauri",
|
|
41
|
+
)
|
|
42
|
+
await publisher.list_channels()
|
|
43
|
+
await publisher.get_channel("envoy_binary", "stable", environment="production")
|
|
44
|
+
await publisher.pin_channel("envoy_binary", "stable", {"release_ref": "ar://..."})
|
|
45
|
+
await publisher.list_prestage()
|
|
46
|
+
|
|
47
|
+
assert [(path, kwargs["method"]) for path, kwargs in client.calls] == [
|
|
48
|
+
("/svc/publisher/health", "GET"),
|
|
49
|
+
("/svc/publisher/ready", "GET"),
|
|
50
|
+
("/svc/publisher/builds", "GET"),
|
|
51
|
+
("/svc/publisher/builds/ensure", "POST"),
|
|
52
|
+
("/svc/publisher/builds/pub_123", "GET"),
|
|
53
|
+
("/svc/publisher/builds/pub_123/retry", "POST"),
|
|
54
|
+
("/svc/publisher/builds/pub_123/cancel", "POST"),
|
|
55
|
+
("/svc/publisher/builds/signing/evaluate", "POST"),
|
|
56
|
+
("/svc/publisher/builds/signing/evidence", "POST"),
|
|
57
|
+
("/svc/publisher/artifacts", "GET"),
|
|
58
|
+
("/svc/publisher/artifacts/releases/record", "POST"),
|
|
59
|
+
("/svc/publisher/artifacts/envoy_binary?selector=stable&environment=production&target_app=powerscribe&architecture=x64&runtime_family=rust-tauri", "GET"),
|
|
60
|
+
("/svc/publisher/channels", "GET"),
|
|
61
|
+
("/svc/publisher/channels/envoy_binary/stable?environment=production", "GET"),
|
|
62
|
+
("/svc/publisher/channels/envoy_binary/stable/pin", "POST"),
|
|
63
|
+
("/svc/publisher/prestage", "GET"),
|
|
64
|
+
]
|
|
65
|
+
assert client.calls[3][1]["headers"] == {"X-Actor-Type": "service", "X-Actor-Id": "dominus-deployer"}
|
|
66
|
+
assert client.calls[5][1]["body"] == {"reason": "rerun", "idempotency_key": "retry-1"}
|
|
67
|
+
assert not hasattr(publisher, "shell")
|
|
68
|
+
assert not hasattr(publisher, "command")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.asyncio
|
|
72
|
+
async def test_publisher_request_rewrites_api_paths_to_svc_paths():
|
|
73
|
+
client = MockGatewayClient()
|
|
74
|
+
publisher = PublisherNamespace(client)
|
|
75
|
+
|
|
76
|
+
await publisher.request("/api/publisher/builds", method="GET")
|
|
77
|
+
await publisher.request("/svc/publisher/channels", method="GET")
|
|
78
|
+
|
|
79
|
+
assert [path for path, _ in client.calls] == [
|
|
80
|
+
"/svc/publisher/builds",
|
|
81
|
+
"/svc/publisher/channels",
|
|
82
|
+
]
|
|
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-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/dominus_sdk_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/tests/test_authority_public_vocabulary.py
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-6.1.1 → dominus_sdk_python-6.1.3}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|