@sema-agent/sdk 0.0.75 → 0.0.77
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.
- package/dist/client.d.ts +48 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +55 -2
- package/dist/client.js.map +1 -1
- package/dist/control-client.d.ts +21 -0
- package/dist/control-client.d.ts.map +1 -1
- package/dist/control-client.js +42 -1
- package/dist/control-client.js.map +1 -1
- package/dist/control-types.d.ts +108 -0
- package/dist/control-types.d.ts.map +1 -1
- package/dist/control-types.js +15 -0
- package/dist/control-types.js.map +1 -1
- package/dist/errors.d.ts +88 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +105 -8
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +214 -20
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +5 -0
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +44 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +32 -0
- package/dist/health.js.map +1 -1
- package/dist/idempotency.d.ts +8 -0
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +8 -0
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/approvals.d.ts +43 -0
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +23 -3
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +23 -0
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +22 -0
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/control/auth-providers.d.ts +17 -0
- package/dist/resources/control/auth-providers.d.ts.map +1 -1
- package/dist/resources/control/auth-providers.js +6 -0
- package/dist/resources/control/auth-providers.js.map +1 -1
- package/dist/resources/control/config.d.ts +22 -0
- package/dist/resources/control/config.d.ts.map +1 -1
- package/dist/resources/control/config.js +12 -0
- package/dist/resources/control/config.js.map +1 -1
- package/dist/resources/control/fleet.d.ts +15 -0
- package/dist/resources/control/fleet.d.ts.map +1 -1
- package/dist/resources/control/fleet.js +8 -0
- package/dist/resources/control/fleet.js.map +1 -1
- package/dist/resources/control/images.d.ts +20 -0
- package/dist/resources/control/images.d.ts.map +1 -1
- package/dist/resources/control/images.js +10 -0
- package/dist/resources/control/images.js.map +1 -1
- package/dist/resources/control/lifecycle.d.ts +8 -0
- package/dist/resources/control/lifecycle.d.ts.map +1 -1
- package/dist/resources/control/lifecycle.js +3 -0
- package/dist/resources/control/lifecycle.js.map +1 -1
- package/dist/resources/control/publish.d.ts +12 -0
- package/dist/resources/control/publish.d.ts.map +1 -1
- package/dist/resources/control/publish.js +6 -0
- package/dist/resources/control/publish.js.map +1 -1
- package/dist/resources/control/secrets.d.ts +28 -0
- package/dist/resources/control/secrets.d.ts.map +1 -1
- package/dist/resources/control/secrets.js +16 -0
- package/dist/resources/control/secrets.js.map +1 -1
- package/dist/resources/control/users.d.ts +22 -0
- package/dist/resources/control/users.d.ts.map +1 -1
- package/dist/resources/control/users.js +12 -0
- package/dist/resources/control/users.js.map +1 -1
- package/dist/resources/control/versioning.d.ts +12 -0
- package/dist/resources/control/versioning.d.ts.map +1 -1
- package/dist/resources/control/versioning.js +6 -0
- package/dist/resources/control/versioning.js.map +1 -1
- package/dist/resources/control/workers.d.ts +14 -0
- package/dist/resources/control/workers.d.ts.map +1 -1
- package/dist/resources/control/workers.js +7 -0
- package/dist/resources/control/workers.js.map +1 -1
- package/dist/resources/elicitations.d.ts +43 -0
- package/dist/resources/elicitations.d.ts.map +1 -1
- package/dist/resources/elicitations.js +8 -0
- package/dist/resources/elicitations.js.map +1 -1
- package/dist/resources/fleet.d.ts +101 -0
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js +27 -4
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/images.d.ts +34 -0
- package/dist/resources/images.d.ts.map +1 -1
- package/dist/resources/images.js +29 -3
- package/dist/resources/images.js.map +1 -1
- package/dist/resources/leader.d.ts +10 -0
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +4 -0
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/memory.d.ts +37 -0
- package/dist/resources/memory.d.ts.map +1 -1
- package/dist/resources/memory.js +28 -0
- package/dist/resources/memory.js.map +1 -1
- package/dist/resources/models.d.ts +12 -0
- package/dist/resources/models.d.ts.map +1 -1
- package/dist/resources/models.js +4 -0
- package/dist/resources/models.js.map +1 -1
- package/dist/resources/ops.d.ts +16 -0
- package/dist/resources/ops.d.ts.map +1 -1
- package/dist/resources/ops.js +6 -0
- package/dist/resources/ops.js.map +1 -1
- package/dist/resources/policy.d.ts +8 -0
- package/dist/resources/policy.d.ts.map +1 -1
- package/dist/resources/policy.js +1 -0
- package/dist/resources/policy.js.map +1 -1
- package/dist/resources/questions.d.ts +57 -0
- package/dist/resources/questions.d.ts.map +1 -1
- package/dist/resources/questions.js +9 -0
- package/dist/resources/questions.js.map +1 -1
- package/dist/resources/runs.d.ts +147 -0
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +129 -2
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +61 -0
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +54 -1
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +74 -0
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +64 -2
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/side-query.d.ts +18 -0
- package/dist/resources/side-query.d.ts.map +1 -1
- package/dist/resources/side-query.js +1 -0
- package/dist/resources/side-query.js.map +1 -1
- package/dist/resources/tasks.d.ts +19 -0
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +21 -2
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +60 -0
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +10 -0
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/trace.d.ts +23 -0
- package/dist/resources/trace.d.ts.map +1 -1
- package/dist/resources/trace.js +27 -2
- package/dist/resources/trace.js.map +1 -1
- package/dist/resources/usage.d.ts +21 -0
- package/dist/resources/usage.d.ts.map +1 -1
- package/dist/resources/usage.js +8 -0
- package/dist/resources/usage.js.map +1 -1
- package/dist/resources/workflows.d.ts +48 -0
- package/dist/resources/workflows.d.ts.map +1 -1
- package/dist/resources/workflows.js +40 -3
- package/dist/resources/workflows.js.map +1 -1
- package/dist/settings.d.ts +90 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +24 -0
- package/dist/settings.js.map +1 -1
- package/dist/sse.d.ts +36 -0
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +53 -8
- package/dist/sse.js.map +1 -1
- package/dist/sync.d.ts +56 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +48 -4
- package/dist/sync.js.map +1 -1
- package/dist/transport.d.ts +32 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +40 -8
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +709 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** 折 null → OMIT(条件 spread,绝不写显式 undefined;exactOptionalPropertyTypes)。 */
|
|
1
2
|
function normalizeGate(g) {
|
|
2
3
|
return {
|
|
3
4
|
kind: g.kind,
|
|
@@ -14,6 +15,9 @@ export class AssistantResource {
|
|
|
14
15
|
constructor(t) {
|
|
15
16
|
this.t = t;
|
|
16
17
|
}
|
|
18
|
+
/** §2 GET /v1/assistant/inbox —— 单一 severity-sorted inbox(每用户视图)。operator 可用 `?owner=` 看某 owner,
|
|
19
|
+
* 否则看自己。返回行已由 core listPending 按 severity 排序 —— 消费方**不要再排**(且须容 undefined severity)。
|
|
20
|
+
* 解包 envelope `{inbox:[...]}`。owner query 在此手拼(transport.request 的 path 是裸串直拼, 无 query helper)。 */
|
|
17
21
|
async inbox(opts) {
|
|
18
22
|
const q = opts?.owner ? `?owner=${encodeURIComponent(opts.owner)}` : "";
|
|
19
23
|
const r = await this.t.request({
|
|
@@ -21,11 +25,19 @@ export class AssistantResource {
|
|
|
21
25
|
path: `/v1/assistant/inbox${q}`,
|
|
22
26
|
signal: opts?.signal,
|
|
23
27
|
});
|
|
28
|
+
// 🔴 severity 归一:部署的 worker 把 severity 放 riskDescriptor.severity(非顶层标量,违文档;
|
|
29
|
+
// server.ts:1414 inbox handler 直接 spread listPending() 未走 summarizeCheckpoint)。优先顶层标量(文档/未来态),
|
|
30
|
+
// 缺则回退 riskDescriptor.severity(当前 live 态)。service 修 handler 后顶层自动接管,前向兼容。
|
|
24
31
|
return r.inbox.map((row) => row.severity == null && row.riskDescriptor?.severity != null
|
|
25
32
|
? { ...row, severity: row.riskDescriptor.severity }
|
|
26
33
|
: row);
|
|
27
34
|
}
|
|
35
|
+
/** §3 GET /v1/assistant/tasks —— N-task 调度总览(每用户跨任务视图)。Triage 序由 core 给定(needsAttention 优先,
|
|
36
|
+
* 再 severity DESC, 再 spend DESC)—— **不要再排**。需 TiDB run store, 否则 worker 回 `{tasks:[]}`(原样透传)。 */
|
|
28
37
|
async tasks(opts) {
|
|
38
|
+
// wire gate 的 severity/spentMicroUsd/deadline 形如 `4 | null`(§3),但 AssistantGate 把它们规约为 `?:number`
|
|
39
|
+
// (缺/null 都容忍, OMIT 优先)。这里把 null 折成 OMIT —— 否则 raw 透传会把 wire 的 null 漏进 `?:number` 字段,
|
|
40
|
+
// 违反 exactOptionalPropertyTypes 的契约(消费方按 `number | undefined` 用,绝不该见 null)。
|
|
29
41
|
const r = await this.t.request({
|
|
30
42
|
method: "GET",
|
|
31
43
|
path: "/v1/assistant/tasks",
|
|
@@ -33,6 +45,9 @@ export class AssistantResource {
|
|
|
33
45
|
});
|
|
34
46
|
return r.tasks.map((t) => normalizeTask(t));
|
|
35
47
|
}
|
|
48
|
+
/** §4b POST /v1/assistant/tasks/:id/resume(:id = taskId)—— resource_limit CONTINUE。**无 body**。
|
|
49
|
+
* 非 submit → 不重试(一次决策不重放)。🔴 GATE-KIND GUARD: human/policy_ask 门 → 409 gate_not_resumable
|
|
50
|
+
* ("continue" 绝不绕过人审, 那条路是 /decide)。owner 非属 → 404。 */
|
|
36
51
|
async resume(taskId, opts) {
|
|
37
52
|
return this.t.request({
|
|
38
53
|
method: "POST",
|
|
@@ -40,6 +55,10 @@ export class AssistantResource {
|
|
|
40
55
|
signal: opts?.signal,
|
|
41
56
|
});
|
|
42
57
|
}
|
|
58
|
+
/** §4c POST /v1/assistant/tasks/:id/plan_review(:id = taskId)—— PRE-ACTION plan_review 门的 3-state 决策。
|
|
59
|
+
* body = {decision, editedPlan?, reason?}。approve/edit/reject 全跑模型 → 计费。非 submit → 不重试。
|
|
60
|
+
* 🔴 GATE-KIND GUARD: 非 plan_review 门 → 409 gate_not_plan_review。400: 坏/缺 decision; edit 缺非空 editedPlan;
|
|
61
|
+
* approve/reject 带 editedPlan; reason 非串。owner 非属 → 404。 */
|
|
43
62
|
async planReview(taskId, req, opts) {
|
|
44
63
|
return this.t.request({
|
|
45
64
|
method: "POST",
|
|
@@ -48,6 +67,9 @@ export class AssistantResource {
|
|
|
48
67
|
signal: opts?.signal,
|
|
49
68
|
});
|
|
50
69
|
}
|
|
70
|
+
/** §4d POST /v1/assistant/tasks/:id/preempt(:id = taskId)—— 优雅 YIELD(跨副本让位, 与 runs.cancel 的 kill 相反)。
|
|
71
|
+
* **无 body**。202 {status}(terminal → 202 no-op)。非 submit → 不重试。NOT billable。
|
|
72
|
+
* suspended → 409; RESOURCE_SUSPEND off → 501; owner 非属 → 404。 */
|
|
51
73
|
async preempt(taskId, opts) {
|
|
52
74
|
return this.t.request({
|
|
53
75
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,31 @@
|
|
|
1
|
+
/** control.authProviders — login auth-provider config (Gitea / OAuth2 quick-login). Backend: sema-registry
|
|
2
|
+
* GET/POST/DELETE /api/config/auth/providers. admin-only.
|
|
3
|
+
*
|
|
4
|
+
* 🔴 SECRET BOUNDARY (iron law, registry-enforced AND mirrored here): the client_secret VALUE is never stored,
|
|
5
|
+
* returned, or logged — only its env-NAME (`clientSecretEnv`). upsert() takes a `clientSecretEnv` NAME (the
|
|
6
|
+
* registry rejects a value-shaped string with the env-NAME regex); the result echoes the NON-secret record
|
|
7
|
+
* plus the registry-derived `secretPresent` boolean (is the env in place?) — never the value.
|
|
8
|
+
*
|
|
9
|
+
* Local accounts remain a permanent fallback independent of these rows, so a misconfigured provider can't lock
|
|
10
|
+
* the admin out. `type: "oidc"` is rejected by the registry today (discovery not yet implemented) → 400
|
|
11
|
+
* ControlValidationError; this SDK's upsert type admits only the supported "gitea"|"oauth2". */
|
|
1
12
|
import type { Transport } from "../../transport.js";
|
|
2
13
|
import type { AuthProvidersResult, AuthProviderUpsert, AuthProviderUpsertResult } from "../../control-types.js";
|
|
3
14
|
export declare class ControlAuthProvidersResource {
|
|
4
15
|
private readonly t;
|
|
5
16
|
constructor(t: Transport);
|
|
17
|
+
/** GET /api/config/auth/providers → all providers (each NON-secret config + the derived `secretPresent`).
|
|
18
|
+
* admin. */
|
|
6
19
|
list(opts?: {
|
|
7
20
|
signal?: AbortSignal;
|
|
8
21
|
}): Promise<AuthProvidersResult>;
|
|
22
|
+
/** POST /api/config/auth/providers → upsert one provider. 🔴 `clientSecretEnv` is an ENV-NAME (never a value);
|
|
23
|
+
* the registry validates it lives in the provider-secret namespace and rejects a platform secret (anti-exfil)
|
|
24
|
+
* → 400 ControlValidationError. A bad field → 400. admin. NOT submit-class (an upsert is idempotent on `id`). */
|
|
9
25
|
upsert(provider: AuthProviderUpsert, opts?: {
|
|
10
26
|
signal?: AbortSignal;
|
|
11
27
|
}): Promise<AuthProviderUpsertResult>;
|
|
28
|
+
/** DELETE /api/config/auth/providers?id=<id> → remove a provider. admin. */
|
|
12
29
|
delete(id: string, opts?: {
|
|
13
30
|
signal?: AbortSignal;
|
|
14
31
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-providers.d.ts","sourceRoot":"","sources":["../../../src/resources/control/auth-providers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-providers.d.ts","sourceRoot":"","sources":["../../../src/resources/control/auth-providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;iGAUiG;AACjG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEhH,qBAAa,4BAA4B;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;iBACa;IACP,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIzE;;sHAEkH;IAC5G,MAAM,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAI9G,4EAA4E;IACtE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;CAGjF"}
|
|
@@ -3,12 +3,18 @@ export class ControlAuthProvidersResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/auth/providers → all providers (each NON-secret config + the derived `secretPresent`).
|
|
7
|
+
* admin. */
|
|
6
8
|
async list(opts) {
|
|
7
9
|
return this.t.request({ method: "GET", path: "/api/config/auth/providers", signal: opts?.signal });
|
|
8
10
|
}
|
|
11
|
+
/** POST /api/config/auth/providers → upsert one provider. 🔴 `clientSecretEnv` is an ENV-NAME (never a value);
|
|
12
|
+
* the registry validates it lives in the provider-secret namespace and rejects a platform secret (anti-exfil)
|
|
13
|
+
* → 400 ControlValidationError. A bad field → 400. admin. NOT submit-class (an upsert is idempotent on `id`). */
|
|
9
14
|
async upsert(provider, opts) {
|
|
10
15
|
return this.t.request({ method: "POST", path: "/api/config/auth/providers", body: provider, signal: opts?.signal });
|
|
11
16
|
}
|
|
17
|
+
/** DELETE /api/config/auth/providers?id=<id> → remove a provider. admin. */
|
|
12
18
|
async delete(id, opts) {
|
|
13
19
|
return this.t.request({ method: "DELETE", path: `/api/config/auth/providers?id=${encodeURIComponent(id)}`, signal: opts?.signal });
|
|
14
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-providers.js","sourceRoot":"","sources":["../../../src/resources/control/auth-providers.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,4BAA4B;IACV;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-providers.js","sourceRoot":"","sources":["../../../src/resources/control/auth-providers.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,4BAA4B;IACV;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;iBACa;IACb,KAAK,CAAC,IAAI,CAAC,IAA+B;QACxC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,4BAA4B,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrG,CAAC;IAED;;sHAEkH;IAClH,KAAK,CAAC,MAAM,CAAC,QAA4B,EAAE,IAA+B;QACxE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,4BAA4B,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtH,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAA+B;QACtD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,iCAAiC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrI,CAAC;CACF"}
|
|
@@ -1,28 +1,50 @@
|
|
|
1
|
+
/** control.config — config DOMAIN CRUD + atomic batch + schema introspection + portable export.
|
|
2
|
+
* Backend: sema-registry GET/PUT /api/config/[domain], POST /api/config/batch, GET /api/config/schema,
|
|
3
|
+
* GET /api/config/export. This is where the CLI's裸-HTTP fleet.ts (export/batch/PUT) lands inside the SDK.
|
|
4
|
+
*
|
|
5
|
+
* 🔴 The SDK does NOT interpret per-domain values, NOR re-derive the per-domain write-role table
|
|
6
|
+
* (domainWriteRole drifts with the registry). It sends the write; a too-low role lands as a typed 403
|
|
7
|
+
* (ControlForbiddenError). Validation 400 / CAS 409 are surfaced typed (ControlValidationError /
|
|
8
|
+
* ControlConflictError), never auto-retried. */
|
|
1
9
|
import type { Transport } from "../../transport.js";
|
|
2
10
|
import type { ConfigDomain, DomainRead, PutResult, BatchChange, BatchResult, SchemaAll, SchemaOne, ExportResult } from "../../control-types.js";
|
|
3
11
|
export declare class ControlConfigResource {
|
|
4
12
|
private readonly t;
|
|
5
13
|
constructor(t: Transport);
|
|
14
|
+
/** GET /api/config/[domain] → the domain value + global version (echo `version` as a put() `baseVersion`
|
|
15
|
+
* for true optimistic locking). viewer+. */
|
|
6
16
|
get(domain: ConfigDomain, opts?: {
|
|
7
17
|
signal?: AbortSignal;
|
|
8
18
|
}): Promise<DomainRead>;
|
|
19
|
+
/** PUT /api/config/[domain] — write one domain. `baseVersion` (from a prior get()) makes the write a CAS:
|
|
20
|
+
* a write racing ANY config change since that read is rejected 409 (ControlConflictError). editor+ (some
|
|
21
|
+
* domains publisher+ → 403 ControlForbiddenError). NOT submit-class: a non-idempotent PUT is never retried.
|
|
22
|
+
* Returns droppedKeys/autoPlaced so a "success" that dropped fields isn't a silent false-success. */
|
|
9
23
|
put(domain: ConfigDomain, body: {
|
|
10
24
|
value: unknown;
|
|
11
25
|
summary?: string;
|
|
12
26
|
baseVersion?: number;
|
|
13
27
|
signal?: AbortSignal;
|
|
14
28
|
}): Promise<PutResult>;
|
|
29
|
+
/** POST /api/config/batch — atomic multi-domain write (validated whole, applied all-or-nothing, version
|
|
30
|
+
* bumps once). editor+ (publisher-only domains in the batch → 403). NOT submit-class (no idempotency key:
|
|
31
|
+
* a batch is a CAS write, re-running could clobber). A bad/forbidden domain → 400 ControlValidationError. */
|
|
15
32
|
batch(body: {
|
|
16
33
|
changes: BatchChange[];
|
|
17
34
|
summary?: string;
|
|
18
35
|
signal?: AbortSignal;
|
|
19
36
|
}): Promise<BatchResult>;
|
|
37
|
+
/** GET /api/config/schema → every domain's JSON Schema (Draft-07). viewer+. */
|
|
20
38
|
schema(opts?: {
|
|
21
39
|
signal?: AbortSignal;
|
|
22
40
|
}): Promise<SchemaAll>;
|
|
41
|
+
/** GET /api/config/schema?domain=<d> → one domain's JSON Schema. */
|
|
23
42
|
schema(domain: ConfigDomain, opts?: {
|
|
24
43
|
signal?: AbortSignal;
|
|
25
44
|
}): Promise<SchemaOne>;
|
|
45
|
+
/** GET /api/config/export → portable config bundle (env-NAME refs only, never secret VALUES). `?published`
|
|
46
|
+
* exports the last published snapshot (409 ControlConflictError if nothing was ever published) instead of
|
|
47
|
+
* the live draft. editor+. */
|
|
26
48
|
export(opts?: {
|
|
27
49
|
published?: boolean;
|
|
28
50
|
signal?: AbortSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/resources/control/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/resources/control/config.ts"],"names":[],"mappings":"AAAA;;;;;;;oDAOoD;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAClG,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;iDAC6C;IACvC,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrF;;;0GAGsG;IAChG,GAAG,CACP,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACrF,OAAO,CAAC,SAAS,CAAC;IAKrB;;kHAE8G;IACxG,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3G,+EAA+E;IACzE,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IACjE,oEAAoE;IAC9D,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAWvF;;mCAE+B;IACzB,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAI1F"}
|
|
@@ -3,13 +3,22 @@ export class ControlConfigResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/[domain] → the domain value + global version (echo `version` as a put() `baseVersion`
|
|
7
|
+
* for true optimistic locking). viewer+. */
|
|
6
8
|
async get(domain, opts) {
|
|
7
9
|
return this.t.request({ method: "GET", path: `/api/config/${encodeURIComponent(domain)}`, signal: opts?.signal });
|
|
8
10
|
}
|
|
11
|
+
/** PUT /api/config/[domain] — write one domain. `baseVersion` (from a prior get()) makes the write a CAS:
|
|
12
|
+
* a write racing ANY config change since that read is rejected 409 (ControlConflictError). editor+ (some
|
|
13
|
+
* domains publisher+ → 403 ControlForbiddenError). NOT submit-class: a non-idempotent PUT is never retried.
|
|
14
|
+
* Returns droppedKeys/autoPlaced so a "success" that dropped fields isn't a silent false-success. */
|
|
9
15
|
async put(domain, body) {
|
|
10
16
|
const { signal, ...rest } = body;
|
|
11
17
|
return this.t.request({ method: "PUT", path: `/api/config/${encodeURIComponent(domain)}`, body: rest, signal });
|
|
12
18
|
}
|
|
19
|
+
/** POST /api/config/batch — atomic multi-domain write (validated whole, applied all-or-nothing, version
|
|
20
|
+
* bumps once). editor+ (publisher-only domains in the batch → 403). NOT submit-class (no idempotency key:
|
|
21
|
+
* a batch is a CAS write, re-running could clobber). A bad/forbidden domain → 400 ControlValidationError. */
|
|
13
22
|
async batch(body) {
|
|
14
23
|
const { signal, ...rest } = body;
|
|
15
24
|
return this.t.request({ method: "POST", path: "/api/config/batch", body: rest, signal });
|
|
@@ -20,6 +29,9 @@ export class ControlConfigResource {
|
|
|
20
29
|
const qs = domain ? `?domain=${encodeURIComponent(domain)}` : "";
|
|
21
30
|
return this.t.request({ method: "GET", path: `/api/config/schema${qs}`, signal });
|
|
22
31
|
}
|
|
32
|
+
/** GET /api/config/export → portable config bundle (env-NAME refs only, never secret VALUES). `?published`
|
|
33
|
+
* exports the last published snapshot (409 ControlConflictError if nothing was ever published) instead of
|
|
34
|
+
* the live draft. editor+. */
|
|
23
35
|
async export(opts) {
|
|
24
36
|
const qs = opts?.published ? "?published" : "";
|
|
25
37
|
return this.t.request({ method: "GET", path: `/api/config/export${qs}`, signal: opts?.signal });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/resources/control/config.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/resources/control/config.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;iDAC6C;IAC7C,KAAK,CAAC,GAAG,CAAC,MAAoB,EAAE,IAA+B;QAC7D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpH,CAAC;IAED;;;0GAGsG;IACtG,KAAK,CAAC,GAAG,CACP,MAAoB,EACpB,IAAsF;QAEtF,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClH,CAAC;IAED;;kHAE8G;IAC9G,KAAK,CAAC,KAAK,CAAC,IAAwE;QAClF,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3F,CAAC;IAMD,KAAK,CAAC,MAAM,CACV,CAA2C,EAC3C,CAA4B;QAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrD,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QACvD,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,CAAC;IAED;;mCAE+B;IAC/B,KAAK,CAAC,MAAM,CAAC,IAAoD;QAC/D,MAAM,EAAE,GAAG,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClG,CAAC;CACF"}
|
|
@@ -1,29 +1,44 @@
|
|
|
1
|
+
/** control.fleet — the operations dashboard's read + scheduling actions (多主机调度).
|
|
2
|
+
* Backend: sema-registry GET /api/config/fleet, GET /api/config/fleet/metrics, GET/POST
|
|
3
|
+
* /api/config/placement, GET/POST /api/config/rebalance, GET/POST /api/config/reschedule.
|
|
4
|
+
*
|
|
5
|
+
* GET previews (snapshot/metrics/*Plan) are viewer+ and cheap-to-poll. The *apply POSTs are editor+ and are
|
|
6
|
+
* CAS writes over the workers domain: a concurrent workers edit → 409 ControlConflictError (the move set is
|
|
7
|
+
* never clobbered). The SDK previews/applies the registry's plans; it does NOT compute scheduling itself. */
|
|
1
8
|
import type { Transport } from "../../transport.js";
|
|
2
9
|
import type { FleetSnapshot, FleetMetrics, SchedulePlan, ScheduleApplyResult } from "../../control-types.js";
|
|
3
10
|
export declare class ControlFleetResource {
|
|
4
11
|
private readonly t;
|
|
5
12
|
constructor(t: Transport);
|
|
13
|
+
/** GET /api/config/fleet → live FleetSnapshot (desired ⊕ status ⊕ lifecycle + derived signals). viewer+. */
|
|
6
14
|
snapshot(opts?: {
|
|
7
15
|
signal?: AbortSignal;
|
|
8
16
|
}): Promise<FleetSnapshot>;
|
|
17
|
+
/** GET /api/config/fleet/metrics → { worker → MetricsSummary } + per-worker scrape errors. viewer+. */
|
|
9
18
|
metrics(opts?: {
|
|
10
19
|
signal?: AbortSignal;
|
|
11
20
|
}): Promise<FleetMetrics>;
|
|
21
|
+
/** GET /api/config/placement → placement plan preview (auto workers ↔ hosts). viewer+. */
|
|
12
22
|
placementPlan(opts?: {
|
|
13
23
|
signal?: AbortSignal;
|
|
14
24
|
}): Promise<SchedulePlan>;
|
|
25
|
+
/** POST /api/config/placement → apply the placement plan (rewrite auto workers' host, one CAS write). editor+. */
|
|
15
26
|
applyPlacement(opts?: {
|
|
16
27
|
signal?: AbortSignal;
|
|
17
28
|
}): Promise<ScheduleApplyResult>;
|
|
29
|
+
/** GET /api/config/rebalance → rebalance plan preview (even out load off over-loaded hosts). viewer+. */
|
|
18
30
|
rebalancePlan(opts?: {
|
|
19
31
|
signal?: AbortSignal;
|
|
20
32
|
}): Promise<SchedulePlan>;
|
|
33
|
+
/** POST /api/config/rebalance → apply the rebalance moves (CAS-safe). editor+. */
|
|
21
34
|
applyRebalance(opts?: {
|
|
22
35
|
signal?: AbortSignal;
|
|
23
36
|
}): Promise<ScheduleApplyResult>;
|
|
37
|
+
/** GET /api/config/reschedule → failover plan preview (evacuate auto workers off silent/dead hosts). viewer+. */
|
|
24
38
|
reschedulePlan(opts?: {
|
|
25
39
|
signal?: AbortSignal;
|
|
26
40
|
}): Promise<SchedulePlan>;
|
|
41
|
+
/** POST /api/config/reschedule → apply the evacuations (operator one-click; CAS-safe). editor+. */
|
|
27
42
|
applyReschedule(opts?: {
|
|
28
43
|
signal?: AbortSignal;
|
|
29
44
|
}): Promise<ScheduleApplyResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/resources/control/fleet.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/resources/control/fleet.ts"],"names":[],"mappings":"AAAA;;;;;;8GAM8G;AAC9G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7G,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC,4GAA4G;IACtG,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAIvE,uGAAuG;IACjG,OAAO,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAIrE,0FAA0F;IACpF,aAAa,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAI3E,kHAAkH;IAC5G,cAAc,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAInF,yGAAyG;IACnG,aAAa,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAI3E,kFAAkF;IAC5E,cAAc,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAInF,iHAAiH;IAC3G,cAAc,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAI5E,mGAAmG;IAC7F,eAAe,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAGrF"}
|
|
@@ -3,27 +3,35 @@ export class ControlFleetResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/fleet → live FleetSnapshot (desired ⊕ status ⊕ lifecycle + derived signals). viewer+. */
|
|
6
7
|
async snapshot(opts) {
|
|
7
8
|
return this.t.request({ method: "GET", path: "/api/config/fleet", signal: opts?.signal });
|
|
8
9
|
}
|
|
10
|
+
/** GET /api/config/fleet/metrics → { worker → MetricsSummary } + per-worker scrape errors. viewer+. */
|
|
9
11
|
async metrics(opts) {
|
|
10
12
|
return this.t.request({ method: "GET", path: "/api/config/fleet/metrics", signal: opts?.signal });
|
|
11
13
|
}
|
|
14
|
+
/** GET /api/config/placement → placement plan preview (auto workers ↔ hosts). viewer+. */
|
|
12
15
|
async placementPlan(opts) {
|
|
13
16
|
return this.t.request({ method: "GET", path: "/api/config/placement", signal: opts?.signal });
|
|
14
17
|
}
|
|
18
|
+
/** POST /api/config/placement → apply the placement plan (rewrite auto workers' host, one CAS write). editor+. */
|
|
15
19
|
async applyPlacement(opts) {
|
|
16
20
|
return this.t.request({ method: "POST", path: "/api/config/placement", body: {}, signal: opts?.signal });
|
|
17
21
|
}
|
|
22
|
+
/** GET /api/config/rebalance → rebalance plan preview (even out load off over-loaded hosts). viewer+. */
|
|
18
23
|
async rebalancePlan(opts) {
|
|
19
24
|
return this.t.request({ method: "GET", path: "/api/config/rebalance", signal: opts?.signal });
|
|
20
25
|
}
|
|
26
|
+
/** POST /api/config/rebalance → apply the rebalance moves (CAS-safe). editor+. */
|
|
21
27
|
async applyRebalance(opts) {
|
|
22
28
|
return this.t.request({ method: "POST", path: "/api/config/rebalance", body: {}, signal: opts?.signal });
|
|
23
29
|
}
|
|
30
|
+
/** GET /api/config/reschedule → failover plan preview (evacuate auto workers off silent/dead hosts). viewer+. */
|
|
24
31
|
async reschedulePlan(opts) {
|
|
25
32
|
return this.t.request({ method: "GET", path: "/api/config/reschedule", signal: opts?.signal });
|
|
26
33
|
}
|
|
34
|
+
/** POST /api/config/reschedule → apply the evacuations (operator one-click; CAS-safe). editor+. */
|
|
27
35
|
async applyReschedule(opts) {
|
|
28
36
|
return this.t.request({ method: "POST", path: "/api/config/reschedule", body: {}, signal: opts?.signal });
|
|
29
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../src/resources/control/fleet.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../src/resources/control/fleet.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C,4GAA4G;IAC5G,KAAK,CAAC,QAAQ,CAAC,IAA+B;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,uGAAuG;IACvG,KAAK,CAAC,OAAO,CAAC,IAA+B;QAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,0FAA0F;IAC1F,KAAK,CAAC,aAAa,CAAC,IAA+B;QACjD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,kHAAkH;IAClH,KAAK,CAAC,cAAc,CAAC,IAA+B;QAClD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3G,CAAC;IAED,yGAAyG;IACzG,KAAK,CAAC,aAAa,CAAC,IAA+B;QACjD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,kFAAkF;IAClF,KAAK,CAAC,cAAc,CAAC,IAA+B;QAClD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3G,CAAC;IAED,iHAAiH;IACjH,KAAK,CAAC,cAAc,CAAC,IAA+B;QAClD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,mGAAmG;IACnG,KAAK,CAAC,eAAe,CAAC,IAA+B;QACnD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5G,CAAC;CACF"}
|
|
@@ -1,17 +1,37 @@
|
|
|
1
|
+
/** control.images — the shared sandbox-image pool, read + resolve. Backend: sema-registry GET
|
|
2
|
+
* /api/config/images, GET /api/config/images/:profile, GET /api/config/images/digests/:digest,
|
|
3
|
+
* POST /api/config/images/select. The registry is a BFF RELAY in front of the worker's /v1/images: it reaches
|
|
4
|
+
* the worker with its OWN server-side IMAGE_API_TOKEN (never echoed) and zod-validates every relayed row.
|
|
5
|
+
*
|
|
6
|
+
* 🔴 All four are gated by the EDITOR Bearer (the SAME registry token) — NOT the service pull token. list/get/
|
|
7
|
+
* byDigest are read-only (viewer-shaped, editor+ here). select() is a PURE resolution PREVIEW: it resolves a
|
|
8
|
+
* profile/bands → a concrete `ref` (repo@digest) to bind onto a worker; it builds nothing. The registry
|
|
9
|
+
* 503s when the upstream image API is unconfigured (surfaced as a ControlError) and 409s when no image
|
|
10
|
+
* satisfies the selection (ControlConflictError). */
|
|
1
11
|
import type { Transport } from "../../transport.js";
|
|
2
12
|
import type { ControlImageList, ControlImageEntry, ImageListQuery, ImageSelectQuery, ImageSelectResolution } from "../../control-types.js";
|
|
3
13
|
export declare class ControlImagesResource {
|
|
4
14
|
private readonly t;
|
|
5
15
|
constructor(t: Transport);
|
|
16
|
+
/** GET /api/config/images[?status=&profile=&capability=&visibility=&latest=&limit=&cursor=] → a page of image
|
|
17
|
+
* rows. Only the documented list params are forwarded; `nextCursor` (when present) feeds the next call. editor+. */
|
|
6
18
|
list(query?: ImageListQuery, opts?: {
|
|
7
19
|
signal?: AbortSignal;
|
|
8
20
|
}): Promise<ControlImageList>;
|
|
21
|
+
/** GET /api/config/images/:profile → the latest published entry for a profile (404 → ControlNotFoundError).
|
|
22
|
+
* The registry unwraps the upstream `{ image }` envelope; this returns the bare entry. editor+. */
|
|
9
23
|
get(profile: string, opts?: {
|
|
10
24
|
signal?: AbortSignal;
|
|
11
25
|
}): Promise<ControlImageEntry>;
|
|
26
|
+
/** GET /api/config/images/digests/:digest → one entry by its immutable digest (`sha256:<64 hex>`; the drift
|
|
27
|
+
* lookup). 404 → ControlNotFoundError; a malformed digest → 400 ControlValidationError. editor+. */
|
|
12
28
|
byDigest(digest: string, opts?: {
|
|
13
29
|
signal?: AbortSignal;
|
|
14
30
|
}): Promise<ControlImageEntry>;
|
|
31
|
+
/** POST /api/config/images/select → resolve a profile/bands to a concrete pull `ref` (repo@digest) for binding
|
|
32
|
+
* onto a worker. PURE resolution + visibility/capability admission — builds NOTHING. One of `profile`/`bands`
|
|
33
|
+
* is required. No image satisfies the selection → 409 ControlConflictError. NOT submit-class (idempotent,
|
|
34
|
+
* read-shaped resolution — re-running just re-resolves; no client idempotency key). editor+. */
|
|
15
35
|
select(body: ImageSelectQuery & {
|
|
16
36
|
signal?: AbortSignal;
|
|
17
37
|
}): Promise<ImageSelectResolution>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../../src/resources/control/images.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../../src/resources/control/images.ts"],"names":[],"mappings":"AAAA;;;;;;;;;yDASyD;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAC7F,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;yHACqH;IAC/G,IAAI,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAW9F;wGACoG;IAC9F,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIvF;yGACqG;IAC/F,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAI3F;;;qGAGiG;IAC3F,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAIhG"}
|
|
@@ -3,6 +3,8 @@ export class ControlImagesResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/images[?status=&profile=&capability=&visibility=&latest=&limit=&cursor=] → a page of image
|
|
7
|
+
* rows. Only the documented list params are forwarded; `nextCursor` (when present) feeds the next call. editor+. */
|
|
6
8
|
async list(query, opts) {
|
|
7
9
|
const q = new URLSearchParams();
|
|
8
10
|
if (query) {
|
|
@@ -14,12 +16,20 @@ export class ControlImagesResource {
|
|
|
14
16
|
const qs = q.toString();
|
|
15
17
|
return this.t.request({ method: "GET", path: `/api/config/images${qs ? `?${qs}` : ""}`, signal: opts?.signal });
|
|
16
18
|
}
|
|
19
|
+
/** GET /api/config/images/:profile → the latest published entry for a profile (404 → ControlNotFoundError).
|
|
20
|
+
* The registry unwraps the upstream `{ image }` envelope; this returns the bare entry. editor+. */
|
|
17
21
|
async get(profile, opts) {
|
|
18
22
|
return this.t.request({ method: "GET", path: `/api/config/images/${encodeURIComponent(profile)}`, signal: opts?.signal });
|
|
19
23
|
}
|
|
24
|
+
/** GET /api/config/images/digests/:digest → one entry by its immutable digest (`sha256:<64 hex>`; the drift
|
|
25
|
+
* lookup). 404 → ControlNotFoundError; a malformed digest → 400 ControlValidationError. editor+. */
|
|
20
26
|
async byDigest(digest, opts) {
|
|
21
27
|
return this.t.request({ method: "GET", path: `/api/config/images/digests/${encodeURIComponent(digest)}`, signal: opts?.signal });
|
|
22
28
|
}
|
|
29
|
+
/** POST /api/config/images/select → resolve a profile/bands to a concrete pull `ref` (repo@digest) for binding
|
|
30
|
+
* onto a worker. PURE resolution + visibility/capability admission — builds NOTHING. One of `profile`/`bands`
|
|
31
|
+
* is required. No image satisfies the selection → 409 ControlConflictError. NOT submit-class (idempotent,
|
|
32
|
+
* read-shaped resolution — re-running just re-resolves; no client idempotency key). editor+. */
|
|
23
33
|
async select(body) {
|
|
24
34
|
const { signal, ...rest } = body;
|
|
25
35
|
return this.t.request({ method: "POST", path: "/api/config/images/select", body: rest, signal });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../../src/resources/control/images.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../../src/resources/control/images.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;yHACqH;IACrH,KAAK,CAAC,IAAI,CAAC,KAAsB,EAAE,IAA+B;QAChE,MAAM,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC;QAChC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;oBAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QACD,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClH,CAAC;IAED;wGACoG;IACpG,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,IAA+B;QACxD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5H,CAAC;IAED;yGACqG;IACrG,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,IAA+B;QAC5D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,8BAA8B,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnI,CAAC;IAED;;;qGAGiG;IACjG,KAAK,CAAC,MAAM,CAAC,IAAiD;QAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC;CACF"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
/** control.lifecycle — fleet lifecycle ops: cascade-delete an owner's workers, run one sweep pass.
|
|
2
|
+
* Backend: sema-registry POST /api/config/lifecycle/cascade-owner, POST /api/config/lifecycle/sweep.
|
|
3
|
+
*
|
|
4
|
+
* Both are editor+. cascadeOwner removes ALL workers owned by a decommissioned owner (atomic). sweep runs one
|
|
5
|
+
* lifecycle pass (TTL expiry / idle detection / failover / status GC); `?dryRun` previews (writes/logs nothing). */
|
|
1
6
|
import type { Transport } from "../../transport.js";
|
|
2
7
|
import type { CascadeOwnerResult, SweepResult } from "../../control-types.js";
|
|
3
8
|
export declare class ControlLifecycleResource {
|
|
4
9
|
private readonly t;
|
|
5
10
|
constructor(t: Transport);
|
|
11
|
+
/** POST /api/config/lifecycle/cascade-owner {owner} → remove all workers that owner owns. editor+. NOT
|
|
12
|
+
* submit-class (a CAS-guarded atomic removal; re-running just removes nothing more). */
|
|
6
13
|
cascadeOwner(body: {
|
|
7
14
|
owner: string;
|
|
8
15
|
signal?: AbortSignal;
|
|
9
16
|
}): Promise<CascadeOwnerResult>;
|
|
17
|
+
/** POST /api/config/lifecycle/sweep[?dryRun=1] → one sweep pass (or a preview). editor+. */
|
|
10
18
|
sweep(opts?: {
|
|
11
19
|
dryRun?: boolean;
|
|
12
20
|
signal?: AbortSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/resources/control/lifecycle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/resources/control/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;qHAIqH;AACrH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE9E,qBAAa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;6FACyF;IACnF,YAAY,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAK9F,4FAA4F;IACtF,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC;CAIrF"}
|
|
@@ -3,10 +3,13 @@ export class ControlLifecycleResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** POST /api/config/lifecycle/cascade-owner {owner} → remove all workers that owner owns. editor+. NOT
|
|
7
|
+
* submit-class (a CAS-guarded atomic removal; re-running just removes nothing more). */
|
|
6
8
|
async cascadeOwner(body) {
|
|
7
9
|
const { signal, ...rest } = body;
|
|
8
10
|
return this.t.request({ method: "POST", path: "/api/config/lifecycle/cascade-owner", body: rest, signal });
|
|
9
11
|
}
|
|
12
|
+
/** POST /api/config/lifecycle/sweep[?dryRun=1] → one sweep pass (or a preview). editor+. */
|
|
10
13
|
async sweep(opts) {
|
|
11
14
|
const qs = opts?.dryRun ? "?dryRun=1" : "";
|
|
12
15
|
return this.t.request({ method: "POST", path: `/api/config/lifecycle/sweep${qs}`, body: {}, signal: opts?.signal });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src/resources/control/lifecycle.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,wBAAwB;IACN;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src/resources/control/lifecycle.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,wBAAwB;IACN;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;6FACyF;IACzF,KAAK,CAAC,YAAY,CAAC,IAA6C;QAC9D,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qCAAqC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7G,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,KAAK,CAAC,IAAiD;QAC3D,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtH,CAAC;CACF"}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
|
+
/** control.publish — the draft→production publish gate + optional N-approver approval workflow.
|
|
2
|
+
* Backend: sema-registry POST/GET/DELETE /api/config/publish, POST /api/config/publish/approve.
|
|
3
|
+
*
|
|
4
|
+
* request()/approve()/cancel() are publisher+ (admin token ⊇ publisher); state() is viewer+. Separation of
|
|
5
|
+
* duties is enforced SERVER-SIDE: the requester may not approve their own request (403 ControlForbiddenError),
|
|
6
|
+
* and a draft that moved since the request invalidates pending approvals (409 ControlConflictError). */
|
|
1
7
|
import type { Transport } from "../../transport.js";
|
|
2
8
|
import type { PublishState, PublishResult, ApprovePublishResult, CancelPublishResult } from "../../control-types.js";
|
|
3
9
|
export declare class ControlPublishResource {
|
|
4
10
|
private readonly t;
|
|
5
11
|
constructor(t: Transport);
|
|
12
|
+
/** GET /api/config/publish → gate state { published, pending, approvalsRequired }. viewer+. */
|
|
6
13
|
state(opts?: {
|
|
7
14
|
signal?: AbortSignal;
|
|
8
15
|
}): Promise<PublishState>;
|
|
16
|
+
/** POST /api/config/publish {summary?} → publish immediately (approvals=0) OR open a pending request (N>0).
|
|
17
|
+
* publisher+. NOT submit-class (re-POSTing would open a duplicate request → the route 409s anyway). */
|
|
9
18
|
request(body?: {
|
|
10
19
|
summary?: string;
|
|
11
20
|
signal?: AbortSignal;
|
|
12
21
|
}): Promise<PublishResult>;
|
|
22
|
+
/** POST /api/config/publish/approve → record one approval; the Nth publishes. publisher+, NOT the requester
|
|
23
|
+
* (403 ControlForbiddenError). Atomic server-side. Draft moved since the request → 409 ControlConflictError. */
|
|
13
24
|
approve(opts?: {
|
|
14
25
|
signal?: AbortSignal;
|
|
15
26
|
}): Promise<ApprovePublishResult>;
|
|
27
|
+
/** DELETE /api/config/publish → cancel the pending request (requester or admin only). publisher+. */
|
|
16
28
|
cancel(opts?: {
|
|
17
29
|
signal?: AbortSignal;
|
|
18
30
|
}): Promise<CancelPublishResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/resources/control/publish.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/resources/control/publish.ts"],"names":[],"mappings":"AAAA;;;;;yGAKyG;AACzG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAErH,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC,+FAA+F;IACzF,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAInE;4GACwG;IAClG,OAAO,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAKxF;qHACiH;IAC3G,OAAO,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI7E,qGAAqG;IAC/F,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAG5E"}
|
|
@@ -3,16 +3,22 @@ export class ControlPublishResource {
|
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.t = t;
|
|
5
5
|
}
|
|
6
|
+
/** GET /api/config/publish → gate state { published, pending, approvalsRequired }. viewer+. */
|
|
6
7
|
async state(opts) {
|
|
7
8
|
return this.t.request({ method: "GET", path: "/api/config/publish", signal: opts?.signal });
|
|
8
9
|
}
|
|
10
|
+
/** POST /api/config/publish {summary?} → publish immediately (approvals=0) OR open a pending request (N>0).
|
|
11
|
+
* publisher+. NOT submit-class (re-POSTing would open a duplicate request → the route 409s anyway). */
|
|
9
12
|
async request(body) {
|
|
10
13
|
const { signal, ...rest } = body ?? {};
|
|
11
14
|
return this.t.request({ method: "POST", path: "/api/config/publish", body: rest, signal });
|
|
12
15
|
}
|
|
16
|
+
/** POST /api/config/publish/approve → record one approval; the Nth publishes. publisher+, NOT the requester
|
|
17
|
+
* (403 ControlForbiddenError). Atomic server-side. Draft moved since the request → 409 ControlConflictError. */
|
|
13
18
|
async approve(opts) {
|
|
14
19
|
return this.t.request({ method: "POST", path: "/api/config/publish/approve", body: {}, signal: opts?.signal });
|
|
15
20
|
}
|
|
21
|
+
/** DELETE /api/config/publish → cancel the pending request (requester or admin only). publisher+. */
|
|
16
22
|
async cancel(opts) {
|
|
17
23
|
return this.t.request({ method: "DELETE", path: "/api/config/publish", signal: opts?.signal });
|
|
18
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/resources/control/publish.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/resources/control/publish.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C,+FAA+F;IAC/F,KAAK,CAAC,KAAK,CAAC,IAA+B;QACzC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED;4GACwG;IACxG,KAAK,CAAC,OAAO,CAAC,IAAiD;QAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED;qHACiH;IACjH,KAAK,CAAC,OAAO,CAAC,IAA+B;QAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,6BAA6B,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjH,CAAC;IAED,qGAAqG;IACrG,KAAK,CAAC,MAAM,CAAC,IAA+B;QAC1C,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjG,CAAC;CACF"}
|