@xtrape/capsule-contracts-node 0.1.0-public-review.0
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/LICENSE +48 -0
- package/NOTICE +4 -0
- package/README.md +295 -0
- package/dist/index.cjs +271 -0
- package/dist/index.d.cts +2741 -0
- package/dist/index.d.ts +2741 -0
- package/dist/index.js +179 -0
- package/package.json +63 -0
- package/spec/.source +1 -0
- package/spec/enums/audit-actions.json +213 -0
- package/spec/enums/id-prefixes.json +32 -0
- package/spec/enums/status-enums.json +128 -0
- package/spec/errors.json +128 -0
- package/spec/errors.md +166 -0
- package/spec/openapi/opstage-ce-v0.1.yaml +2085 -0
- package/spec/openapi/redocly.yaml +18 -0
|
@@ -0,0 +1,2085 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
info:
|
|
3
|
+
title: Opstage CE API
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
summary: CE v0.1 API contract for Opstage Capsule Service governance.
|
|
6
|
+
license:
|
|
7
|
+
name: Apache-2.0
|
|
8
|
+
identifier: Apache-2.0
|
|
9
|
+
contact:
|
|
10
|
+
name: Opstage CE maintainers
|
|
11
|
+
url: https://github.com/xtrape/xtrape-capsule-ce
|
|
12
|
+
description: |
|
|
13
|
+
This contract defines the CE v0.1 Admin API, Agent API, and System API.
|
|
14
|
+
Admin API uses /api/admin/*, Agent API uses /api/agents/*, and System API uses /api/system/*.
|
|
15
|
+
|
|
16
|
+
## Standard Error Responses
|
|
17
|
+
|
|
18
|
+
Any endpoint MAY return one of the following standard error responses. The
|
|
19
|
+
canonical list of `error.code` values lives in `09-contracts/errors.md`.
|
|
20
|
+
|
|
21
|
+
400 Bad Request - malformed request (#/components/responses/BadRequest)
|
|
22
|
+
401 Unauthorized - missing or invalid auth (#/components/responses/Unauthorized)
|
|
23
|
+
403 Forbidden - allowed-but-blocked, CSRF mismatch (#/components/responses/Forbidden)
|
|
24
|
+
404 Not Found - resource missing (#/components/responses/NotFound)
|
|
25
|
+
409 Conflict - duplicate / terminal state (#/components/responses/Conflict)
|
|
26
|
+
410 Gone - expired Command (#/components/responses/Gone)
|
|
27
|
+
422 Unprocessable Entity - validation failed (#/components/responses/UnprocessableEntity)
|
|
28
|
+
500 Internal Server Error- unexpected error (#/components/responses/InternalError)
|
|
29
|
+
|
|
30
|
+
Endpoint-specific entries below add or override these where useful, but every
|
|
31
|
+
endpoint should be assumed to be capable of returning the relevant subset of
|
|
32
|
+
the above. Backend MUST always wrap error bodies in `ErrorEnvelope`.
|
|
33
|
+
|
|
34
|
+
## Authentication and CSRF
|
|
35
|
+
|
|
36
|
+
Admin API: cookie-based session (`opstage_session`, HttpOnly, Secure,
|
|
37
|
+
SameSite=Lax). Every state-changing call (POST/PUT/PATCH/DELETE) MUST
|
|
38
|
+
include the `X-CSRF-Token` header carrying the value returned by
|
|
39
|
+
`POST /api/admin/auth/login`, `GET /api/admin/auth/me`, or
|
|
40
|
+
`GET /api/admin/auth/csrf`. Mismatch returns `403 CSRF_INVALID`.
|
|
41
|
+
|
|
42
|
+
Agent API: `Authorization: Bearer <opstage_agent_token>` only. Agents
|
|
43
|
+
MUST NOT send cookies, and CSRF tokens do not apply.
|
|
44
|
+
|
|
45
|
+
System API: unauthenticated; safe to expose to liveness/readiness probes.
|
|
46
|
+
|
|
47
|
+
## Pagination, Sorting, and Filtering Conventions
|
|
48
|
+
|
|
49
|
+
All list endpoints follow these conventions unless an endpoint explicitly
|
|
50
|
+
states otherwise:
|
|
51
|
+
|
|
52
|
+
- `page` (>= 1, default 1)
|
|
53
|
+
- `pageSize` (1..100, default 20)
|
|
54
|
+
- `sort` (e.g. `-createdAt,name` for descending then ascending). Allowed
|
|
55
|
+
fields are documented per endpoint; unknown fields return
|
|
56
|
+
`422 VALIDATION_FAILED`.
|
|
57
|
+
- Filters are individual query params named after the filtered field
|
|
58
|
+
(e.g. `status=HEALTHY`, `agentId=agt_...`). Multiple values for the
|
|
59
|
+
same key are OR'ed; multiple keys are AND'ed.
|
|
60
|
+
- Response body is `{ data: T[], pagination: { page, pageSize, total } }`
|
|
61
|
+
wrapped by `SuccessEnvelope`.
|
|
62
|
+
|
|
63
|
+
The Backend MUST validate every query param with the matching Zod schema
|
|
64
|
+
in `packages/contracts` before reaching the data layer.
|
|
65
|
+
servers:
|
|
66
|
+
- url: http://localhost:8080
|
|
67
|
+
description: Local CE development server
|
|
68
|
+
security: []
|
|
69
|
+
tags:
|
|
70
|
+
- name: AdminAuth
|
|
71
|
+
description: Admin login, logout, session inspection, and CSRF refresh.
|
|
72
|
+
- name: AdminDashboard
|
|
73
|
+
description: Aggregate counters for the CE governance loop.
|
|
74
|
+
- name: AdminAgents
|
|
75
|
+
description: List, inspect, and manage Agents bound to Capsule Services.
|
|
76
|
+
- name: AdminRegistrationTokens
|
|
77
|
+
description: Create, list, and revoke single-use registration tokens.
|
|
78
|
+
- name: AdminCapsuleServices
|
|
79
|
+
description: Inspect Capsule Services and request predefined actions.
|
|
80
|
+
- name: AdminCommands
|
|
81
|
+
description: Inspect Commands created via Capsule Service actions.
|
|
82
|
+
- name: AdminAuditEvents
|
|
83
|
+
description: Read the immutable audit trail.
|
|
84
|
+
- name: Agent
|
|
85
|
+
description: Agent-side bearer-token API used by the Node Embedded Agent SDK.
|
|
86
|
+
- name: System
|
|
87
|
+
description: Unauthenticated probes for liveness and version metadata.
|
|
88
|
+
paths:
|
|
89
|
+
/api/admin/auth/login:
|
|
90
|
+
post:
|
|
91
|
+
tags: [AdminAuth]
|
|
92
|
+
summary: Log in an admin user.
|
|
93
|
+
description: |
|
|
94
|
+
Validates credentials and starts an admin session. On success the
|
|
95
|
+
Backend MUST set the `opstage_session` cookie (HttpOnly, Secure,
|
|
96
|
+
SameSite=Lax, Path=/, Max-Age per ADR 0004) and return a fresh
|
|
97
|
+
`csrfToken` in the response body. All subsequent state-changing
|
|
98
|
+
Admin API calls (POST/PUT/PATCH/DELETE) MUST include the same value
|
|
99
|
+
in the `X-CSRF-Token` header (double-submit token pattern).
|
|
100
|
+
operationId: adminLogin
|
|
101
|
+
requestBody:
|
|
102
|
+
required: true
|
|
103
|
+
content:
|
|
104
|
+
application/json:
|
|
105
|
+
schema:
|
|
106
|
+
$ref: '#/components/schemas/AdminLoginRequest'
|
|
107
|
+
example:
|
|
108
|
+
username: admin
|
|
109
|
+
password: change-on-first-login
|
|
110
|
+
responses:
|
|
111
|
+
'200':
|
|
112
|
+
description: Login succeeded. Session cookie is set and CSRF token returned.
|
|
113
|
+
headers:
|
|
114
|
+
Set-Cookie:
|
|
115
|
+
description: |
|
|
116
|
+
Sets the admin session cookie. Format:
|
|
117
|
+
`opstage_session=<opaque>; Path=/; HttpOnly; Secure;
|
|
118
|
+
SameSite=Lax; Max-Age=<sessionTtlSeconds>`.
|
|
119
|
+
schema:
|
|
120
|
+
type: string
|
|
121
|
+
content:
|
|
122
|
+
application/json:
|
|
123
|
+
schema:
|
|
124
|
+
allOf:
|
|
125
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
126
|
+
- type: object
|
|
127
|
+
properties:
|
|
128
|
+
data:
|
|
129
|
+
$ref: '#/components/schemas/AdminSession'
|
|
130
|
+
example:
|
|
131
|
+
success: true
|
|
132
|
+
data:
|
|
133
|
+
user:
|
|
134
|
+
id: usr_01HXYZABC1234567
|
|
135
|
+
username: admin
|
|
136
|
+
displayName: Admin
|
|
137
|
+
role: owner
|
|
138
|
+
status: ACTIVE
|
|
139
|
+
csrfToken: 7f3c1e8e9b2c4a8c91a0a7c2e1d3b5f6
|
|
140
|
+
expiresAt: '2026-05-01T13:30:00.000Z'
|
|
141
|
+
'401':
|
|
142
|
+
$ref: '#/components/responses/Unauthorized'
|
|
143
|
+
'422':
|
|
144
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
145
|
+
/api/admin/auth/logout:
|
|
146
|
+
post:
|
|
147
|
+
tags: [AdminAuth]
|
|
148
|
+
summary: Log out current admin session.
|
|
149
|
+
description: |
|
|
150
|
+
Invalidates the current admin session and clears the
|
|
151
|
+
`opstage_session` cookie. Requires a valid CSRF header.
|
|
152
|
+
operationId: adminLogout
|
|
153
|
+
security:
|
|
154
|
+
- AdminSessionCookie: []
|
|
155
|
+
parameters:
|
|
156
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
157
|
+
responses:
|
|
158
|
+
'200':
|
|
159
|
+
description: Logout succeeded. Session cookie is cleared.
|
|
160
|
+
headers:
|
|
161
|
+
Set-Cookie:
|
|
162
|
+
description: |
|
|
163
|
+
Clears the admin session cookie. Format:
|
|
164
|
+
`opstage_session=; Path=/; HttpOnly; Secure;
|
|
165
|
+
SameSite=Lax; Max-Age=0`.
|
|
166
|
+
schema:
|
|
167
|
+
type: string
|
|
168
|
+
content:
|
|
169
|
+
application/json:
|
|
170
|
+
schema:
|
|
171
|
+
$ref: '#/components/schemas/SuccessEnvelope'
|
|
172
|
+
'401':
|
|
173
|
+
$ref: '#/components/responses/Unauthorized'
|
|
174
|
+
'403':
|
|
175
|
+
$ref: '#/components/responses/Forbidden'
|
|
176
|
+
/api/admin/auth/me:
|
|
177
|
+
get:
|
|
178
|
+
tags: [AdminAuth]
|
|
179
|
+
summary: Get current admin user.
|
|
180
|
+
description: |
|
|
181
|
+
Returns the current admin session. Useful for UI bootstrap to detect
|
|
182
|
+
whether the user is logged in and to refresh the CSRF token.
|
|
183
|
+
operationId: adminMe
|
|
184
|
+
security:
|
|
185
|
+
- AdminSessionCookie: []
|
|
186
|
+
responses:
|
|
187
|
+
'200':
|
|
188
|
+
description: Current admin user.
|
|
189
|
+
content:
|
|
190
|
+
application/json:
|
|
191
|
+
schema:
|
|
192
|
+
allOf:
|
|
193
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
194
|
+
- type: object
|
|
195
|
+
properties:
|
|
196
|
+
data:
|
|
197
|
+
$ref: '#/components/schemas/AdminSession'
|
|
198
|
+
example:
|
|
199
|
+
success: true
|
|
200
|
+
data:
|
|
201
|
+
user:
|
|
202
|
+
id: usr_01HXYZABC1234567
|
|
203
|
+
username: admin
|
|
204
|
+
displayName: Admin
|
|
205
|
+
role: owner
|
|
206
|
+
status: ACTIVE
|
|
207
|
+
csrfToken: 7f3c1e8e9b2c4a8c91a0a7c2e1d3b5f6
|
|
208
|
+
expiresAt: '2026-05-01T13:30:00.000Z'
|
|
209
|
+
'401':
|
|
210
|
+
$ref: '#/components/responses/Unauthorized'
|
|
211
|
+
/api/admin/auth/csrf:
|
|
212
|
+
get:
|
|
213
|
+
tags: [AdminAuth]
|
|
214
|
+
summary: Refresh the CSRF token for the current session.
|
|
215
|
+
description: |
|
|
216
|
+
Returns a new CSRF token bound to the current `opstage_session`
|
|
217
|
+
cookie. The Backend MUST rotate the stored token on every call so
|
|
218
|
+
old tokens stop validating. Used by the UI right before
|
|
219
|
+
long-form interactions, or after a 403 `CSRF_INVALID` response.
|
|
220
|
+
operationId: adminCsrf
|
|
221
|
+
security:
|
|
222
|
+
- AdminSessionCookie: []
|
|
223
|
+
responses:
|
|
224
|
+
'200':
|
|
225
|
+
description: New CSRF token for the active session.
|
|
226
|
+
content:
|
|
227
|
+
application/json:
|
|
228
|
+
schema:
|
|
229
|
+
allOf:
|
|
230
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
231
|
+
- type: object
|
|
232
|
+
properties:
|
|
233
|
+
data:
|
|
234
|
+
type: object
|
|
235
|
+
required: [csrfToken]
|
|
236
|
+
properties:
|
|
237
|
+
csrfToken:
|
|
238
|
+
type: string
|
|
239
|
+
example:
|
|
240
|
+
success: true
|
|
241
|
+
data:
|
|
242
|
+
csrfToken: 7f3c1e8e9b2c4a8c91a0a7c2e1d3b5f6
|
|
243
|
+
'401':
|
|
244
|
+
$ref: '#/components/responses/Unauthorized'
|
|
245
|
+
/api/admin/dashboard/summary:
|
|
246
|
+
get:
|
|
247
|
+
tags: [AdminDashboard]
|
|
248
|
+
summary: Get CE dashboard summary.
|
|
249
|
+
operationId: getDashboardSummary
|
|
250
|
+
security:
|
|
251
|
+
- AdminSessionCookie: []
|
|
252
|
+
responses:
|
|
253
|
+
'200':
|
|
254
|
+
description: Dashboard summary.
|
|
255
|
+
content:
|
|
256
|
+
application/json:
|
|
257
|
+
schema:
|
|
258
|
+
allOf:
|
|
259
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
260
|
+
- type: object
|
|
261
|
+
properties:
|
|
262
|
+
data:
|
|
263
|
+
$ref: '#/components/schemas/DashboardSummary'
|
|
264
|
+
/api/admin/agents:
|
|
265
|
+
get:
|
|
266
|
+
tags: [AdminAgents]
|
|
267
|
+
summary: List Agents.
|
|
268
|
+
description: |
|
|
269
|
+
Allowed `sort` fields: `createdAt`, `lastSeenAt`, `name`. Default
|
|
270
|
+
sort: `-createdAt`. Filter `status` accepts multiple values
|
|
271
|
+
(OR'ed).
|
|
272
|
+
operationId: listAgents
|
|
273
|
+
security:
|
|
274
|
+
- AdminSessionCookie: []
|
|
275
|
+
parameters:
|
|
276
|
+
- $ref: '#/components/parameters/Page'
|
|
277
|
+
- $ref: '#/components/parameters/PageSize'
|
|
278
|
+
- $ref: '#/components/parameters/Sort'
|
|
279
|
+
- name: status
|
|
280
|
+
in: query
|
|
281
|
+
explode: true
|
|
282
|
+
schema:
|
|
283
|
+
type: array
|
|
284
|
+
items:
|
|
285
|
+
$ref: '#/components/schemas/AgentStatus'
|
|
286
|
+
responses:
|
|
287
|
+
'200':
|
|
288
|
+
description: Agent list.
|
|
289
|
+
content:
|
|
290
|
+
application/json:
|
|
291
|
+
schema:
|
|
292
|
+
allOf:
|
|
293
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
294
|
+
- type: object
|
|
295
|
+
properties:
|
|
296
|
+
data:
|
|
297
|
+
type: array
|
|
298
|
+
items:
|
|
299
|
+
$ref: '#/components/schemas/Agent'
|
|
300
|
+
pagination:
|
|
301
|
+
$ref: '#/components/schemas/Pagination'
|
|
302
|
+
example:
|
|
303
|
+
success: true
|
|
304
|
+
data:
|
|
305
|
+
- id: agt_01HXYZAGT1234567
|
|
306
|
+
code: demo-prod-1
|
|
307
|
+
name: Demo Prod Agent 1
|
|
308
|
+
mode: embedded
|
|
309
|
+
runtime: nodejs
|
|
310
|
+
status: ONLINE
|
|
311
|
+
lastHeartbeatAt: '2026-05-01T12:00:00.000Z'
|
|
312
|
+
createdAt: '2026-04-30T10:00:00.000Z'
|
|
313
|
+
updatedAt: '2026-05-01T12:00:00.000Z'
|
|
314
|
+
pagination:
|
|
315
|
+
page: 1
|
|
316
|
+
pageSize: 20
|
|
317
|
+
total: 1
|
|
318
|
+
'401':
|
|
319
|
+
$ref: '#/components/responses/Unauthorized'
|
|
320
|
+
'422':
|
|
321
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
322
|
+
/api/admin/agents/{agentId}:
|
|
323
|
+
get:
|
|
324
|
+
tags: [AdminAgents]
|
|
325
|
+
summary: Get Agent detail.
|
|
326
|
+
operationId: getAgent
|
|
327
|
+
security:
|
|
328
|
+
- AdminSessionCookie: []
|
|
329
|
+
parameters:
|
|
330
|
+
- $ref: '#/components/parameters/AgentId'
|
|
331
|
+
responses:
|
|
332
|
+
'200':
|
|
333
|
+
description: Agent detail.
|
|
334
|
+
content:
|
|
335
|
+
application/json:
|
|
336
|
+
schema:
|
|
337
|
+
allOf:
|
|
338
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
339
|
+
- type: object
|
|
340
|
+
properties:
|
|
341
|
+
data:
|
|
342
|
+
$ref: '#/components/schemas/Agent'
|
|
343
|
+
'404':
|
|
344
|
+
$ref: '#/components/responses/NotFound'
|
|
345
|
+
/api/admin/agents/{agentId}/disable:
|
|
346
|
+
post:
|
|
347
|
+
tags: [AdminAgents]
|
|
348
|
+
summary: Disable an Agent.
|
|
349
|
+
operationId: disableAgent
|
|
350
|
+
security:
|
|
351
|
+
- AdminSessionCookie: []
|
|
352
|
+
parameters:
|
|
353
|
+
- $ref: '#/components/parameters/AgentId'
|
|
354
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
355
|
+
responses:
|
|
356
|
+
'200':
|
|
357
|
+
$ref: '#/components/responses/Ok'
|
|
358
|
+
'401':
|
|
359
|
+
$ref: '#/components/responses/Unauthorized'
|
|
360
|
+
'403':
|
|
361
|
+
$ref: '#/components/responses/Forbidden'
|
|
362
|
+
'404':
|
|
363
|
+
$ref: '#/components/responses/NotFound'
|
|
364
|
+
/api/admin/agents/{agentId}/enable:
|
|
365
|
+
post:
|
|
366
|
+
tags: [AdminAgents]
|
|
367
|
+
summary: Enable an Agent.
|
|
368
|
+
operationId: enableAgent
|
|
369
|
+
security:
|
|
370
|
+
- AdminSessionCookie: []
|
|
371
|
+
parameters:
|
|
372
|
+
- $ref: '#/components/parameters/AgentId'
|
|
373
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
374
|
+
responses:
|
|
375
|
+
'200':
|
|
376
|
+
$ref: '#/components/responses/Ok'
|
|
377
|
+
'401':
|
|
378
|
+
$ref: '#/components/responses/Unauthorized'
|
|
379
|
+
'403':
|
|
380
|
+
$ref: '#/components/responses/Forbidden'
|
|
381
|
+
'404':
|
|
382
|
+
$ref: '#/components/responses/NotFound'
|
|
383
|
+
/api/admin/agents/{agentId}/revoke:
|
|
384
|
+
post:
|
|
385
|
+
tags: [AdminAgents]
|
|
386
|
+
summary: Revoke an Agent.
|
|
387
|
+
operationId: revokeAgent
|
|
388
|
+
security:
|
|
389
|
+
- AdminSessionCookie: []
|
|
390
|
+
parameters:
|
|
391
|
+
- $ref: '#/components/parameters/AgentId'
|
|
392
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
393
|
+
responses:
|
|
394
|
+
'200':
|
|
395
|
+
$ref: '#/components/responses/Ok'
|
|
396
|
+
'401':
|
|
397
|
+
$ref: '#/components/responses/Unauthorized'
|
|
398
|
+
'403':
|
|
399
|
+
$ref: '#/components/responses/Forbidden'
|
|
400
|
+
'404':
|
|
401
|
+
$ref: '#/components/responses/NotFound'
|
|
402
|
+
/api/admin/registration-tokens:
|
|
403
|
+
post:
|
|
404
|
+
tags: [AdminRegistrationTokens]
|
|
405
|
+
summary: Create a registration token.
|
|
406
|
+
description: |
|
|
407
|
+
Creates a single-use registration token. The raw token is returned
|
|
408
|
+
ONCE in `data.rawToken`; only its SHA-256 hash is persisted. Subsequent
|
|
409
|
+
list calls do not include `rawToken`.
|
|
410
|
+
operationId: createRegistrationToken
|
|
411
|
+
security:
|
|
412
|
+
- AdminSessionCookie: []
|
|
413
|
+
parameters:
|
|
414
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
415
|
+
requestBody:
|
|
416
|
+
required: false
|
|
417
|
+
content:
|
|
418
|
+
application/json:
|
|
419
|
+
schema:
|
|
420
|
+
$ref: '#/components/schemas/CreateRegistrationTokenRequest'
|
|
421
|
+
example:
|
|
422
|
+
name: demo-host-1
|
|
423
|
+
expiresInSeconds: 3600
|
|
424
|
+
responses:
|
|
425
|
+
'200':
|
|
426
|
+
description: Registration token created. Raw token is shown only once.
|
|
427
|
+
content:
|
|
428
|
+
application/json:
|
|
429
|
+
schema:
|
|
430
|
+
allOf:
|
|
431
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
432
|
+
- type: object
|
|
433
|
+
properties:
|
|
434
|
+
data:
|
|
435
|
+
$ref: '#/components/schemas/CreateRegistrationTokenResponse'
|
|
436
|
+
example:
|
|
437
|
+
success: true
|
|
438
|
+
data:
|
|
439
|
+
id: tok_01HXYZTOK1234567
|
|
440
|
+
name: demo-host-1
|
|
441
|
+
status: ACTIVE
|
|
442
|
+
expiresAt: '2026-05-01T13:00:00.000Z'
|
|
443
|
+
createdAt: '2026-05-01T12:00:00.000Z'
|
|
444
|
+
rawToken: opstage_reg_4xKj8mNpQ2rT5v7yA9bC1dF3gH6iJ0kL
|
|
445
|
+
'401':
|
|
446
|
+
$ref: '#/components/responses/Unauthorized'
|
|
447
|
+
'403':
|
|
448
|
+
$ref: '#/components/responses/Forbidden'
|
|
449
|
+
'422':
|
|
450
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
451
|
+
get:
|
|
452
|
+
tags: [AdminRegistrationTokens]
|
|
453
|
+
summary: List registration tokens without raw token values.
|
|
454
|
+
description: |
|
|
455
|
+
Allowed `sort` fields: `createdAt`, `expiresAt`. Default: `-createdAt`.
|
|
456
|
+
Filter `status` accepts multiple values (OR'ed).
|
|
457
|
+
operationId: listRegistrationTokens
|
|
458
|
+
security:
|
|
459
|
+
- AdminSessionCookie: []
|
|
460
|
+
parameters:
|
|
461
|
+
- $ref: '#/components/parameters/Page'
|
|
462
|
+
- $ref: '#/components/parameters/PageSize'
|
|
463
|
+
- $ref: '#/components/parameters/Sort'
|
|
464
|
+
- name: status
|
|
465
|
+
in: query
|
|
466
|
+
explode: true
|
|
467
|
+
schema:
|
|
468
|
+
type: array
|
|
469
|
+
items:
|
|
470
|
+
$ref: '#/components/schemas/TokenStatus'
|
|
471
|
+
responses:
|
|
472
|
+
'200':
|
|
473
|
+
description: Registration token list.
|
|
474
|
+
content:
|
|
475
|
+
application/json:
|
|
476
|
+
schema:
|
|
477
|
+
allOf:
|
|
478
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
479
|
+
- type: object
|
|
480
|
+
properties:
|
|
481
|
+
data:
|
|
482
|
+
type: array
|
|
483
|
+
items:
|
|
484
|
+
$ref: '#/components/schemas/RegistrationToken'
|
|
485
|
+
pagination:
|
|
486
|
+
$ref: '#/components/schemas/Pagination'
|
|
487
|
+
'401':
|
|
488
|
+
$ref: '#/components/responses/Unauthorized'
|
|
489
|
+
'422':
|
|
490
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
491
|
+
/api/admin/registration-tokens/{tokenId}/revoke:
|
|
492
|
+
post:
|
|
493
|
+
tags: [AdminRegistrationTokens]
|
|
494
|
+
summary: Revoke a registration token.
|
|
495
|
+
operationId: revokeRegistrationToken
|
|
496
|
+
security:
|
|
497
|
+
- AdminSessionCookie: []
|
|
498
|
+
parameters:
|
|
499
|
+
- $ref: '#/components/parameters/TokenId'
|
|
500
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
501
|
+
responses:
|
|
502
|
+
'200':
|
|
503
|
+
$ref: '#/components/responses/Ok'
|
|
504
|
+
'401':
|
|
505
|
+
$ref: '#/components/responses/Unauthorized'
|
|
506
|
+
'403':
|
|
507
|
+
$ref: '#/components/responses/Forbidden'
|
|
508
|
+
'404':
|
|
509
|
+
$ref: '#/components/responses/NotFound'
|
|
510
|
+
/api/admin/capsule-services:
|
|
511
|
+
get:
|
|
512
|
+
tags: [AdminCapsuleServices]
|
|
513
|
+
summary: List Capsule Services.
|
|
514
|
+
description: |
|
|
515
|
+
Allowed `sort` fields: `createdAt`, `lastReportedAt`, `code`, `name`.
|
|
516
|
+
Default sort: `-createdAt`. Filter `status` accepts multiple values
|
|
517
|
+
(OR'ed); `agentId` filters services owned by a specific Agent.
|
|
518
|
+
operationId: listCapsuleServices
|
|
519
|
+
security:
|
|
520
|
+
- AdminSessionCookie: []
|
|
521
|
+
parameters:
|
|
522
|
+
- $ref: '#/components/parameters/Page'
|
|
523
|
+
- $ref: '#/components/parameters/PageSize'
|
|
524
|
+
- $ref: '#/components/parameters/Sort'
|
|
525
|
+
- name: status
|
|
526
|
+
in: query
|
|
527
|
+
explode: true
|
|
528
|
+
schema:
|
|
529
|
+
type: array
|
|
530
|
+
items:
|
|
531
|
+
$ref: '#/components/schemas/CapsuleServiceStatus'
|
|
532
|
+
- name: agentId
|
|
533
|
+
in: query
|
|
534
|
+
schema:
|
|
535
|
+
type: string
|
|
536
|
+
pattern: '^agt_'
|
|
537
|
+
responses:
|
|
538
|
+
'200':
|
|
539
|
+
description: Capsule Service list.
|
|
540
|
+
content:
|
|
541
|
+
application/json:
|
|
542
|
+
schema:
|
|
543
|
+
allOf:
|
|
544
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
545
|
+
- type: object
|
|
546
|
+
properties:
|
|
547
|
+
data:
|
|
548
|
+
type: array
|
|
549
|
+
items:
|
|
550
|
+
$ref: '#/components/schemas/CapsuleService'
|
|
551
|
+
pagination:
|
|
552
|
+
$ref: '#/components/schemas/Pagination'
|
|
553
|
+
example:
|
|
554
|
+
success: true
|
|
555
|
+
data:
|
|
556
|
+
- id: svc_01HXYZSVC1234567
|
|
557
|
+
agentId: agt_01HXYZAGT1234567
|
|
558
|
+
code: demo-billing
|
|
559
|
+
name: Demo Billing Service
|
|
560
|
+
runtime: nodejs
|
|
561
|
+
status: HEALTHY
|
|
562
|
+
healthStatus: UP
|
|
563
|
+
lastReportedAt: '2026-05-01T12:00:00.000Z'
|
|
564
|
+
lastHealthAt: '2026-05-01T12:00:00.000Z'
|
|
565
|
+
createdAt: '2026-04-30T10:00:00.000Z'
|
|
566
|
+
updatedAt: '2026-05-01T12:00:00.000Z'
|
|
567
|
+
pagination:
|
|
568
|
+
page: 1
|
|
569
|
+
pageSize: 20
|
|
570
|
+
total: 1
|
|
571
|
+
'401':
|
|
572
|
+
$ref: '#/components/responses/Unauthorized'
|
|
573
|
+
'422':
|
|
574
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
575
|
+
/api/admin/capsule-services/{serviceId}:
|
|
576
|
+
get:
|
|
577
|
+
tags: [AdminCapsuleServices]
|
|
578
|
+
summary: Get Capsule Service detail.
|
|
579
|
+
operationId: getCapsuleService
|
|
580
|
+
security:
|
|
581
|
+
- AdminSessionCookie: []
|
|
582
|
+
parameters:
|
|
583
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
584
|
+
responses:
|
|
585
|
+
'200':
|
|
586
|
+
description: Capsule Service detail.
|
|
587
|
+
content:
|
|
588
|
+
application/json:
|
|
589
|
+
schema:
|
|
590
|
+
allOf:
|
|
591
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
592
|
+
- type: object
|
|
593
|
+
properties:
|
|
594
|
+
data:
|
|
595
|
+
$ref: '#/components/schemas/CapsuleServiceDetail'
|
|
596
|
+
'404':
|
|
597
|
+
$ref: '#/components/responses/NotFound'
|
|
598
|
+
/api/admin/capsule-services/{serviceId}/manifest:
|
|
599
|
+
get:
|
|
600
|
+
tags: [AdminCapsuleServices]
|
|
601
|
+
summary: Get Capsule Service manifest JSON.
|
|
602
|
+
operationId: getCapsuleServiceManifest
|
|
603
|
+
security:
|
|
604
|
+
- AdminSessionCookie: []
|
|
605
|
+
parameters:
|
|
606
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
607
|
+
responses:
|
|
608
|
+
'200':
|
|
609
|
+
description: Manifest JSON.
|
|
610
|
+
content:
|
|
611
|
+
application/json:
|
|
612
|
+
schema:
|
|
613
|
+
allOf:
|
|
614
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
615
|
+
- type: object
|
|
616
|
+
properties:
|
|
617
|
+
data:
|
|
618
|
+
type: object
|
|
619
|
+
additionalProperties: true
|
|
620
|
+
/api/admin/capsule-services/{serviceId}/health:
|
|
621
|
+
get:
|
|
622
|
+
tags: [AdminCapsuleServices]
|
|
623
|
+
summary: Get latest health report.
|
|
624
|
+
operationId: getCapsuleServiceHealth
|
|
625
|
+
security:
|
|
626
|
+
- AdminSessionCookie: []
|
|
627
|
+
parameters:
|
|
628
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
629
|
+
responses:
|
|
630
|
+
'200':
|
|
631
|
+
description: Latest health report.
|
|
632
|
+
content:
|
|
633
|
+
application/json:
|
|
634
|
+
schema:
|
|
635
|
+
allOf:
|
|
636
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
637
|
+
- type: object
|
|
638
|
+
properties:
|
|
639
|
+
data:
|
|
640
|
+
$ref: '#/components/schemas/HealthReport'
|
|
641
|
+
/api/admin/capsule-services/{serviceId}/configs:
|
|
642
|
+
get:
|
|
643
|
+
tags: [AdminCapsuleServices]
|
|
644
|
+
summary: List config metadata.
|
|
645
|
+
operationId: listCapsuleServiceConfigs
|
|
646
|
+
security:
|
|
647
|
+
- AdminSessionCookie: []
|
|
648
|
+
parameters:
|
|
649
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
650
|
+
responses:
|
|
651
|
+
'200':
|
|
652
|
+
description: Config metadata list.
|
|
653
|
+
content:
|
|
654
|
+
application/json:
|
|
655
|
+
schema:
|
|
656
|
+
allOf:
|
|
657
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
658
|
+
- type: object
|
|
659
|
+
properties:
|
|
660
|
+
data:
|
|
661
|
+
type: array
|
|
662
|
+
items:
|
|
663
|
+
$ref: '#/components/schemas/ConfigItem'
|
|
664
|
+
/api/admin/capsule-services/{serviceId}/actions:
|
|
665
|
+
get:
|
|
666
|
+
tags: [AdminCapsuleServices]
|
|
667
|
+
summary: List action definitions.
|
|
668
|
+
operationId: listCapsuleServiceActions
|
|
669
|
+
security:
|
|
670
|
+
- AdminSessionCookie: []
|
|
671
|
+
parameters:
|
|
672
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
673
|
+
responses:
|
|
674
|
+
'200':
|
|
675
|
+
description: Action definition list.
|
|
676
|
+
content:
|
|
677
|
+
application/json:
|
|
678
|
+
schema:
|
|
679
|
+
allOf:
|
|
680
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
681
|
+
- type: object
|
|
682
|
+
properties:
|
|
683
|
+
data:
|
|
684
|
+
type: array
|
|
685
|
+
items:
|
|
686
|
+
$ref: '#/components/schemas/ActionDefinition'
|
|
687
|
+
/api/admin/capsule-services/{serviceId}/actions/{actionName}:
|
|
688
|
+
post:
|
|
689
|
+
tags: [AdminCapsuleServices]
|
|
690
|
+
summary: Request predefined action execution.
|
|
691
|
+
description: |
|
|
692
|
+
Validates the action and creates a `Command` row in `PENDING` state.
|
|
693
|
+
Returns the freshly created Command. UI MAY then poll
|
|
694
|
+
`GET /api/admin/commands/{commandId}` for terminal status.
|
|
695
|
+
See `04-opstage/04-command-and-action-model.md` §23 for the
|
|
696
|
+
canonical sequence and validation rules.
|
|
697
|
+
operationId: createActionCommand
|
|
698
|
+
security:
|
|
699
|
+
- AdminSessionCookie: []
|
|
700
|
+
parameters:
|
|
701
|
+
- $ref: '#/components/parameters/ServiceId'
|
|
702
|
+
- $ref: '#/components/parameters/ActionName'
|
|
703
|
+
- $ref: '#/components/parameters/CsrfToken'
|
|
704
|
+
requestBody:
|
|
705
|
+
required: false
|
|
706
|
+
content:
|
|
707
|
+
application/json:
|
|
708
|
+
schema:
|
|
709
|
+
$ref: '#/components/schemas/CreateActionCommandRequest'
|
|
710
|
+
example:
|
|
711
|
+
payload:
|
|
712
|
+
graceful: true
|
|
713
|
+
confirmation: true
|
|
714
|
+
responses:
|
|
715
|
+
'200':
|
|
716
|
+
description: Command created.
|
|
717
|
+
content:
|
|
718
|
+
application/json:
|
|
719
|
+
schema:
|
|
720
|
+
allOf:
|
|
721
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
722
|
+
- type: object
|
|
723
|
+
properties:
|
|
724
|
+
data:
|
|
725
|
+
$ref: '#/components/schemas/Command'
|
|
726
|
+
example:
|
|
727
|
+
success: true
|
|
728
|
+
data:
|
|
729
|
+
id: cmd_01HXYZCMD1234567
|
|
730
|
+
agentId: agt_01HXYZAGT1234567
|
|
731
|
+
serviceId: svc_01HXYZSVC1234567
|
|
732
|
+
type: ACTION_EXECUTE
|
|
733
|
+
actionName: restart
|
|
734
|
+
payload:
|
|
735
|
+
graceful: true
|
|
736
|
+
status: PENDING
|
|
737
|
+
createdAt: '2026-05-01T12:00:00.000Z'
|
|
738
|
+
expiresAt: '2026-05-01T12:05:00.000Z'
|
|
739
|
+
createdByUserId: usr_01HXYZABC1234567
|
|
740
|
+
'401':
|
|
741
|
+
$ref: '#/components/responses/Unauthorized'
|
|
742
|
+
'403':
|
|
743
|
+
$ref: '#/components/responses/Forbidden'
|
|
744
|
+
'404':
|
|
745
|
+
$ref: '#/components/responses/NotFound'
|
|
746
|
+
'422':
|
|
747
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
748
|
+
default:
|
|
749
|
+
$ref: '#/components/responses/InternalError'
|
|
750
|
+
/api/admin/commands:
|
|
751
|
+
get:
|
|
752
|
+
tags: [AdminCommands]
|
|
753
|
+
summary: List Commands.
|
|
754
|
+
description: |
|
|
755
|
+
Allowed `sort` fields: `createdAt`, `finishedAt`. Default: `-createdAt`.
|
|
756
|
+
Filter `status` accepts multiple values (OR'ed). `serviceId` and
|
|
757
|
+
`agentId` filter by Capsule Service / Agent ownership.
|
|
758
|
+
operationId: listCommands
|
|
759
|
+
security:
|
|
760
|
+
- AdminSessionCookie: []
|
|
761
|
+
parameters:
|
|
762
|
+
- $ref: '#/components/parameters/Page'
|
|
763
|
+
- $ref: '#/components/parameters/PageSize'
|
|
764
|
+
- $ref: '#/components/parameters/Sort'
|
|
765
|
+
- name: status
|
|
766
|
+
in: query
|
|
767
|
+
explode: true
|
|
768
|
+
schema:
|
|
769
|
+
type: array
|
|
770
|
+
items:
|
|
771
|
+
$ref: '#/components/schemas/CommandStatus'
|
|
772
|
+
- name: serviceId
|
|
773
|
+
in: query
|
|
774
|
+
schema:
|
|
775
|
+
type: string
|
|
776
|
+
pattern: '^svc_'
|
|
777
|
+
- name: agentId
|
|
778
|
+
in: query
|
|
779
|
+
schema:
|
|
780
|
+
type: string
|
|
781
|
+
pattern: '^agt_'
|
|
782
|
+
responses:
|
|
783
|
+
'200':
|
|
784
|
+
description: Command list.
|
|
785
|
+
content:
|
|
786
|
+
application/json:
|
|
787
|
+
schema:
|
|
788
|
+
allOf:
|
|
789
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
790
|
+
- type: object
|
|
791
|
+
properties:
|
|
792
|
+
data:
|
|
793
|
+
type: array
|
|
794
|
+
items:
|
|
795
|
+
$ref: '#/components/schemas/Command'
|
|
796
|
+
pagination:
|
|
797
|
+
$ref: '#/components/schemas/Pagination'
|
|
798
|
+
example:
|
|
799
|
+
success: true
|
|
800
|
+
data:
|
|
801
|
+
- id: cmd_01HXYZCMD1234567
|
|
802
|
+
agentId: agt_01HXYZAGT1234567
|
|
803
|
+
serviceId: svc_01HXYZSVC1234567
|
|
804
|
+
type: ACTION_EXECUTE
|
|
805
|
+
actionName: restart
|
|
806
|
+
status: SUCCEEDED
|
|
807
|
+
createdAt: '2026-05-01T12:00:00.000Z'
|
|
808
|
+
startedAt: '2026-05-01T12:00:00.500Z'
|
|
809
|
+
completedAt: '2026-05-01T12:00:03.500Z'
|
|
810
|
+
pagination:
|
|
811
|
+
page: 1
|
|
812
|
+
pageSize: 20
|
|
813
|
+
total: 1
|
|
814
|
+
'401':
|
|
815
|
+
$ref: '#/components/responses/Unauthorized'
|
|
816
|
+
'422':
|
|
817
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
818
|
+
/api/admin/commands/{commandId}:
|
|
819
|
+
get:
|
|
820
|
+
tags: [AdminCommands]
|
|
821
|
+
summary: Get Command detail.
|
|
822
|
+
operationId: getCommand
|
|
823
|
+
security:
|
|
824
|
+
- AdminSessionCookie: []
|
|
825
|
+
parameters:
|
|
826
|
+
- $ref: '#/components/parameters/CommandId'
|
|
827
|
+
responses:
|
|
828
|
+
'200':
|
|
829
|
+
description: Command detail.
|
|
830
|
+
content:
|
|
831
|
+
application/json:
|
|
832
|
+
schema:
|
|
833
|
+
allOf:
|
|
834
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
835
|
+
- type: object
|
|
836
|
+
properties:
|
|
837
|
+
data:
|
|
838
|
+
$ref: '#/components/schemas/CommandDetail'
|
|
839
|
+
/api/admin/audit-events:
|
|
840
|
+
get:
|
|
841
|
+
tags: [AdminAuditEvents]
|
|
842
|
+
summary: List AuditEvents.
|
|
843
|
+
description: |
|
|
844
|
+
Allowed `sort` fields: `createdAt`. Default: `-createdAt`.
|
|
845
|
+
Filters: `actorType`, `targetType`, `targetId`, `result`, `from`/`to`
|
|
846
|
+
(ISO-8601, applied to `createdAt`).
|
|
847
|
+
operationId: listAuditEvents
|
|
848
|
+
security:
|
|
849
|
+
- AdminSessionCookie: []
|
|
850
|
+
parameters:
|
|
851
|
+
- $ref: '#/components/parameters/Page'
|
|
852
|
+
- $ref: '#/components/parameters/PageSize'
|
|
853
|
+
- $ref: '#/components/parameters/Sort'
|
|
854
|
+
- name: actorType
|
|
855
|
+
in: query
|
|
856
|
+
schema:
|
|
857
|
+
$ref: '#/components/schemas/AuditActorType'
|
|
858
|
+
- name: targetType
|
|
859
|
+
in: query
|
|
860
|
+
schema:
|
|
861
|
+
type: string
|
|
862
|
+
- name: targetId
|
|
863
|
+
in: query
|
|
864
|
+
schema:
|
|
865
|
+
type: string
|
|
866
|
+
- name: result
|
|
867
|
+
in: query
|
|
868
|
+
schema:
|
|
869
|
+
$ref: '#/components/schemas/AuditResult'
|
|
870
|
+
- name: from
|
|
871
|
+
in: query
|
|
872
|
+
description: Inclusive lower bound applied to `createdAt`.
|
|
873
|
+
schema:
|
|
874
|
+
type: string
|
|
875
|
+
format: date-time
|
|
876
|
+
- name: to
|
|
877
|
+
in: query
|
|
878
|
+
description: Inclusive upper bound applied to `createdAt`.
|
|
879
|
+
schema:
|
|
880
|
+
type: string
|
|
881
|
+
format: date-time
|
|
882
|
+
responses:
|
|
883
|
+
'200':
|
|
884
|
+
description: AuditEvent list.
|
|
885
|
+
content:
|
|
886
|
+
application/json:
|
|
887
|
+
schema:
|
|
888
|
+
allOf:
|
|
889
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
890
|
+
- type: object
|
|
891
|
+
properties:
|
|
892
|
+
data:
|
|
893
|
+
type: array
|
|
894
|
+
items:
|
|
895
|
+
$ref: '#/components/schemas/AuditEvent'
|
|
896
|
+
pagination:
|
|
897
|
+
$ref: '#/components/schemas/Pagination'
|
|
898
|
+
example:
|
|
899
|
+
success: true
|
|
900
|
+
data:
|
|
901
|
+
- id: aud_01HXYZAUD1234567
|
|
902
|
+
createdAt: '2026-05-01T12:00:00.000Z'
|
|
903
|
+
actorType: USER
|
|
904
|
+
actorId: usr_01HXYZABC1234567
|
|
905
|
+
action: agent.disabled
|
|
906
|
+
targetType: Agent
|
|
907
|
+
targetId: agt_01HXYZAGT1234567
|
|
908
|
+
result: SUCCESS
|
|
909
|
+
message: Disabled by admin.
|
|
910
|
+
pagination:
|
|
911
|
+
page: 1
|
|
912
|
+
pageSize: 20
|
|
913
|
+
total: 1
|
|
914
|
+
'401':
|
|
915
|
+
$ref: '#/components/responses/Unauthorized'
|
|
916
|
+
'422':
|
|
917
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
918
|
+
/api/admin/audit-events/{auditEventId}:
|
|
919
|
+
get:
|
|
920
|
+
tags: [AdminAuditEvents]
|
|
921
|
+
summary: Get AuditEvent detail.
|
|
922
|
+
operationId: getAuditEvent
|
|
923
|
+
security:
|
|
924
|
+
- AdminSessionCookie: []
|
|
925
|
+
parameters:
|
|
926
|
+
- $ref: '#/components/parameters/AuditEventId'
|
|
927
|
+
responses:
|
|
928
|
+
'200':
|
|
929
|
+
description: AuditEvent detail.
|
|
930
|
+
content:
|
|
931
|
+
application/json:
|
|
932
|
+
schema:
|
|
933
|
+
allOf:
|
|
934
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
935
|
+
- type: object
|
|
936
|
+
properties:
|
|
937
|
+
data:
|
|
938
|
+
$ref: '#/components/schemas/AuditEvent'
|
|
939
|
+
/api/agents/register:
|
|
940
|
+
post:
|
|
941
|
+
tags: [Agent]
|
|
942
|
+
summary: Register an Agent with a registration token.
|
|
943
|
+
description: |
|
|
944
|
+
Consumes a single-use registration token and creates an Agent row.
|
|
945
|
+
The Backend returns a fresh Agent bearer token in `data.agentToken`
|
|
946
|
+
ONCE — only its hash is persisted. Agent SDK MUST persist the token
|
|
947
|
+
in a write-once secure file or in-memory and supply it in
|
|
948
|
+
`Authorization: Bearer <token>` for all subsequent calls.
|
|
949
|
+
operationId: registerAgent
|
|
950
|
+
requestBody:
|
|
951
|
+
required: true
|
|
952
|
+
content:
|
|
953
|
+
application/json:
|
|
954
|
+
schema:
|
|
955
|
+
$ref: '#/components/schemas/RegisterAgentRequest'
|
|
956
|
+
example:
|
|
957
|
+
registrationToken: opstage_reg_4xKj8mNpQ2rT5v7yA9bC1dF3gH6iJ0kL
|
|
958
|
+
agent:
|
|
959
|
+
code: demo-prod-1
|
|
960
|
+
name: Demo Prod Agent 1
|
|
961
|
+
mode: embedded
|
|
962
|
+
runtime: nodejs
|
|
963
|
+
responses:
|
|
964
|
+
'200':
|
|
965
|
+
description: Agent registered. Agent token is returned once.
|
|
966
|
+
content:
|
|
967
|
+
application/json:
|
|
968
|
+
schema:
|
|
969
|
+
allOf:
|
|
970
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
971
|
+
- type: object
|
|
972
|
+
properties:
|
|
973
|
+
data:
|
|
974
|
+
$ref: '#/components/schemas/RegisterAgentResponse'
|
|
975
|
+
example:
|
|
976
|
+
success: true
|
|
977
|
+
data:
|
|
978
|
+
agentId: agt_01HXYZAGT1234567
|
|
979
|
+
agentToken: opstage_agent_3v7yA9bC1dF3gH6iJ0kL4xKj8mNpQ2rT
|
|
980
|
+
heartbeatIntervalSeconds: 30
|
|
981
|
+
commandPollIntervalSeconds: 5
|
|
982
|
+
'401':
|
|
983
|
+
$ref: '#/components/responses/Unauthorized'
|
|
984
|
+
'409':
|
|
985
|
+
$ref: '#/components/responses/Conflict'
|
|
986
|
+
'422':
|
|
987
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
988
|
+
default:
|
|
989
|
+
$ref: '#/components/responses/InternalError'
|
|
990
|
+
/api/agents/{agentId}/heartbeat:
|
|
991
|
+
post:
|
|
992
|
+
tags: [Agent]
|
|
993
|
+
summary: Send Agent heartbeat and optional health report.
|
|
994
|
+
description: |
|
|
995
|
+
Updates `Agent.lastSeenAt`. Optional body fields allow the Agent to
|
|
996
|
+
report its overall health and any transient diagnostic info. The
|
|
997
|
+
response echoes the current authoritative timing defaults so an Agent
|
|
998
|
+
can converge on Backend-side changes without a redeploy.
|
|
999
|
+
operationId: agentHeartbeat
|
|
1000
|
+
security:
|
|
1001
|
+
- AgentBearerToken: []
|
|
1002
|
+
parameters:
|
|
1003
|
+
- $ref: '#/components/parameters/AgentId'
|
|
1004
|
+
requestBody:
|
|
1005
|
+
required: false
|
|
1006
|
+
content:
|
|
1007
|
+
application/json:
|
|
1008
|
+
schema:
|
|
1009
|
+
$ref: '#/components/schemas/AgentHeartbeatRequest'
|
|
1010
|
+
example:
|
|
1011
|
+
health:
|
|
1012
|
+
status: UP
|
|
1013
|
+
message: ok
|
|
1014
|
+
responses:
|
|
1015
|
+
'200':
|
|
1016
|
+
description: Heartbeat accepted.
|
|
1017
|
+
content:
|
|
1018
|
+
application/json:
|
|
1019
|
+
schema:
|
|
1020
|
+
allOf:
|
|
1021
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
1022
|
+
- type: object
|
|
1023
|
+
properties:
|
|
1024
|
+
data:
|
|
1025
|
+
$ref: '#/components/schemas/AgentHeartbeatResponse'
|
|
1026
|
+
example:
|
|
1027
|
+
success: true
|
|
1028
|
+
data:
|
|
1029
|
+
heartbeatIntervalSeconds: 30
|
|
1030
|
+
commandPollIntervalSeconds: 5
|
|
1031
|
+
'401':
|
|
1032
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1033
|
+
'403':
|
|
1034
|
+
$ref: '#/components/responses/Forbidden'
|
|
1035
|
+
'404':
|
|
1036
|
+
$ref: '#/components/responses/NotFound'
|
|
1037
|
+
'422':
|
|
1038
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1039
|
+
default:
|
|
1040
|
+
$ref: '#/components/responses/InternalError'
|
|
1041
|
+
/api/agents/{agentId}/services/report:
|
|
1042
|
+
post:
|
|
1043
|
+
tags: [Agent]
|
|
1044
|
+
summary: Report Capsule Service manifest, configs, actions, and health.
|
|
1045
|
+
description: |
|
|
1046
|
+
Idempotent upsert keyed by `(workspaceId, code)`. The Agent SHOULD
|
|
1047
|
+
report once at startup and again when its manifest changes, NOT on
|
|
1048
|
+
every heartbeat. Backend persists `manifest`, `configs`, `actions`,
|
|
1049
|
+
and the latest `health` snapshot.
|
|
1050
|
+
operationId: reportAgentServices
|
|
1051
|
+
security:
|
|
1052
|
+
- AgentBearerToken: []
|
|
1053
|
+
parameters:
|
|
1054
|
+
- $ref: '#/components/parameters/AgentId'
|
|
1055
|
+
requestBody:
|
|
1056
|
+
required: true
|
|
1057
|
+
content:
|
|
1058
|
+
application/json:
|
|
1059
|
+
schema:
|
|
1060
|
+
$ref: '#/components/schemas/ServiceReportRequest'
|
|
1061
|
+
example:
|
|
1062
|
+
services:
|
|
1063
|
+
- code: demo-billing
|
|
1064
|
+
name: Demo Billing Service
|
|
1065
|
+
runtime: nodejs
|
|
1066
|
+
manifest:
|
|
1067
|
+
kind: CapsuleService
|
|
1068
|
+
schemaVersion: '1.0'
|
|
1069
|
+
code: demo-billing
|
|
1070
|
+
name: Demo Billing Service
|
|
1071
|
+
version: 0.1.0
|
|
1072
|
+
runtime: nodejs
|
|
1073
|
+
agentMode: embedded
|
|
1074
|
+
configs:
|
|
1075
|
+
- key: BILLING_API_URL
|
|
1076
|
+
type: string
|
|
1077
|
+
valuePreview: https://billing.example.com
|
|
1078
|
+
sensitive: false
|
|
1079
|
+
actions:
|
|
1080
|
+
- name: restart
|
|
1081
|
+
label: Restart service
|
|
1082
|
+
dangerLevel: MEDIUM
|
|
1083
|
+
requiresConfirmation: true
|
|
1084
|
+
health:
|
|
1085
|
+
status: UP
|
|
1086
|
+
message: 5 dependencies up
|
|
1087
|
+
responses:
|
|
1088
|
+
'200':
|
|
1089
|
+
$ref: '#/components/responses/Ok'
|
|
1090
|
+
'401':
|
|
1091
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1092
|
+
'403':
|
|
1093
|
+
$ref: '#/components/responses/Forbidden'
|
|
1094
|
+
'422':
|
|
1095
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1096
|
+
default:
|
|
1097
|
+
$ref: '#/components/responses/InternalError'
|
|
1098
|
+
/api/agents/{agentId}/commands:
|
|
1099
|
+
get:
|
|
1100
|
+
tags: [Agent]
|
|
1101
|
+
summary: Poll Commands assigned to the Agent.
|
|
1102
|
+
description: |
|
|
1103
|
+
Returns at most `limit` commands in `PENDING` status, ordered by
|
|
1104
|
+
`createdAt ASC`, atomically transitioning each to `RUNNING` before
|
|
1105
|
+
returning. Idempotent at the protocol level (a poll that returns no
|
|
1106
|
+
commands is identical to a missed poll).
|
|
1107
|
+
operationId: pollAgentCommands
|
|
1108
|
+
security:
|
|
1109
|
+
- AgentBearerToken: []
|
|
1110
|
+
parameters:
|
|
1111
|
+
- $ref: '#/components/parameters/AgentId'
|
|
1112
|
+
- name: limit
|
|
1113
|
+
in: query
|
|
1114
|
+
description: Maximum number of commands to return per poll. Default 10, max 50.
|
|
1115
|
+
schema:
|
|
1116
|
+
type: integer
|
|
1117
|
+
minimum: 1
|
|
1118
|
+
maximum: 50
|
|
1119
|
+
default: 10
|
|
1120
|
+
responses:
|
|
1121
|
+
'200':
|
|
1122
|
+
description: Commands assigned to this Agent.
|
|
1123
|
+
content:
|
|
1124
|
+
application/json:
|
|
1125
|
+
schema:
|
|
1126
|
+
allOf:
|
|
1127
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
1128
|
+
- type: object
|
|
1129
|
+
properties:
|
|
1130
|
+
data:
|
|
1131
|
+
type: array
|
|
1132
|
+
items:
|
|
1133
|
+
$ref: '#/components/schemas/Command'
|
|
1134
|
+
example:
|
|
1135
|
+
success: true
|
|
1136
|
+
data:
|
|
1137
|
+
- id: cmd_01HXYZCMD1234567
|
|
1138
|
+
agentId: agt_01HXYZAGT1234567
|
|
1139
|
+
serviceId: svc_01HXYZSVC1234567
|
|
1140
|
+
type: ACTION_EXECUTE
|
|
1141
|
+
actionName: restart
|
|
1142
|
+
payload: {}
|
|
1143
|
+
status: RUNNING
|
|
1144
|
+
createdAt: '2026-05-01T12:00:00.000Z'
|
|
1145
|
+
startedAt: '2026-05-01T12:00:00.500Z'
|
|
1146
|
+
expiresAt: '2026-05-01T12:05:00.000Z'
|
|
1147
|
+
'401':
|
|
1148
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1149
|
+
'403':
|
|
1150
|
+
$ref: '#/components/responses/Forbidden'
|
|
1151
|
+
'404':
|
|
1152
|
+
$ref: '#/components/responses/NotFound'
|
|
1153
|
+
default:
|
|
1154
|
+
$ref: '#/components/responses/InternalError'
|
|
1155
|
+
/api/agents/{agentId}/commands/{commandId}/result:
|
|
1156
|
+
post:
|
|
1157
|
+
tags: [Agent]
|
|
1158
|
+
summary: Report CommandResult.
|
|
1159
|
+
description: |
|
|
1160
|
+
Reports terminal CommandResult. Backend transitions the Command to
|
|
1161
|
+
`SUCCEEDED` (when `success: true`) or `FAILED`. A second result for
|
|
1162
|
+
the same Command is a `409 COMMAND_TERMINAL`. A result reported after
|
|
1163
|
+
the TTL has expired is a `410 COMMAND_EXPIRED` and is ignored.
|
|
1164
|
+
operationId: reportCommandResult
|
|
1165
|
+
security:
|
|
1166
|
+
- AgentBearerToken: []
|
|
1167
|
+
parameters:
|
|
1168
|
+
- $ref: '#/components/parameters/AgentId'
|
|
1169
|
+
- $ref: '#/components/parameters/CommandId'
|
|
1170
|
+
requestBody:
|
|
1171
|
+
required: true
|
|
1172
|
+
content:
|
|
1173
|
+
application/json:
|
|
1174
|
+
schema:
|
|
1175
|
+
$ref: '#/components/schemas/ReportCommandResultRequest'
|
|
1176
|
+
example:
|
|
1177
|
+
success: true
|
|
1178
|
+
message: Service restarted in 3.2s
|
|
1179
|
+
data:
|
|
1180
|
+
pidBefore: 1024
|
|
1181
|
+
pidAfter: 1097
|
|
1182
|
+
startedAt: '2026-05-01T12:00:00.500Z'
|
|
1183
|
+
finishedAt: '2026-05-01T12:00:03.700Z'
|
|
1184
|
+
responses:
|
|
1185
|
+
'200':
|
|
1186
|
+
$ref: '#/components/responses/Ok'
|
|
1187
|
+
'401':
|
|
1188
|
+
$ref: '#/components/responses/Unauthorized'
|
|
1189
|
+
'403':
|
|
1190
|
+
$ref: '#/components/responses/Forbidden'
|
|
1191
|
+
'404':
|
|
1192
|
+
$ref: '#/components/responses/NotFound'
|
|
1193
|
+
'409':
|
|
1194
|
+
$ref: '#/components/responses/Conflict'
|
|
1195
|
+
'410':
|
|
1196
|
+
$ref: '#/components/responses/Gone'
|
|
1197
|
+
'422':
|
|
1198
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
1199
|
+
default:
|
|
1200
|
+
$ref: '#/components/responses/InternalError'
|
|
1201
|
+
/api/system/health:
|
|
1202
|
+
get:
|
|
1203
|
+
tags: [System]
|
|
1204
|
+
summary: Get system health.
|
|
1205
|
+
operationId: getSystemHealth
|
|
1206
|
+
responses:
|
|
1207
|
+
'200':
|
|
1208
|
+
description: System health.
|
|
1209
|
+
content:
|
|
1210
|
+
application/json:
|
|
1211
|
+
schema:
|
|
1212
|
+
allOf:
|
|
1213
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
1214
|
+
- type: object
|
|
1215
|
+
properties:
|
|
1216
|
+
data:
|
|
1217
|
+
$ref: '#/components/schemas/SystemHealth'
|
|
1218
|
+
/api/system/version:
|
|
1219
|
+
get:
|
|
1220
|
+
tags: [System]
|
|
1221
|
+
summary: Get system version.
|
|
1222
|
+
operationId: getSystemVersion
|
|
1223
|
+
responses:
|
|
1224
|
+
'200':
|
|
1225
|
+
description: System version.
|
|
1226
|
+
content:
|
|
1227
|
+
application/json:
|
|
1228
|
+
schema:
|
|
1229
|
+
allOf:
|
|
1230
|
+
- $ref: '#/components/schemas/SuccessEnvelope'
|
|
1231
|
+
- type: object
|
|
1232
|
+
properties:
|
|
1233
|
+
data:
|
|
1234
|
+
$ref: '#/components/schemas/SystemVersion'
|
|
1235
|
+
components:
|
|
1236
|
+
securitySchemes:
|
|
1237
|
+
AdminSessionCookie:
|
|
1238
|
+
type: apiKey
|
|
1239
|
+
in: cookie
|
|
1240
|
+
name: opstage_session
|
|
1241
|
+
AgentBearerToken:
|
|
1242
|
+
type: http
|
|
1243
|
+
scheme: bearer
|
|
1244
|
+
bearerFormat: opstage_agent token
|
|
1245
|
+
parameters:
|
|
1246
|
+
Page:
|
|
1247
|
+
name: page
|
|
1248
|
+
in: query
|
|
1249
|
+
schema:
|
|
1250
|
+
type: integer
|
|
1251
|
+
minimum: 1
|
|
1252
|
+
default: 1
|
|
1253
|
+
PageSize:
|
|
1254
|
+
name: pageSize
|
|
1255
|
+
in: query
|
|
1256
|
+
schema:
|
|
1257
|
+
type: integer
|
|
1258
|
+
minimum: 1
|
|
1259
|
+
maximum: 100
|
|
1260
|
+
default: 20
|
|
1261
|
+
AgentId:
|
|
1262
|
+
name: agentId
|
|
1263
|
+
in: path
|
|
1264
|
+
required: true
|
|
1265
|
+
schema:
|
|
1266
|
+
type: string
|
|
1267
|
+
pattern: '^agt_'
|
|
1268
|
+
ServiceId:
|
|
1269
|
+
name: serviceId
|
|
1270
|
+
in: path
|
|
1271
|
+
required: true
|
|
1272
|
+
schema:
|
|
1273
|
+
type: string
|
|
1274
|
+
pattern: '^svc_'
|
|
1275
|
+
CommandId:
|
|
1276
|
+
name: commandId
|
|
1277
|
+
in: path
|
|
1278
|
+
required: true
|
|
1279
|
+
schema:
|
|
1280
|
+
type: string
|
|
1281
|
+
pattern: '^cmd_'
|
|
1282
|
+
TokenId:
|
|
1283
|
+
name: tokenId
|
|
1284
|
+
in: path
|
|
1285
|
+
required: true
|
|
1286
|
+
schema:
|
|
1287
|
+
type: string
|
|
1288
|
+
pattern: '^tok_'
|
|
1289
|
+
AuditEventId:
|
|
1290
|
+
name: auditEventId
|
|
1291
|
+
in: path
|
|
1292
|
+
required: true
|
|
1293
|
+
schema:
|
|
1294
|
+
type: string
|
|
1295
|
+
pattern: '^aud_'
|
|
1296
|
+
ActionName:
|
|
1297
|
+
name: actionName
|
|
1298
|
+
in: path
|
|
1299
|
+
required: true
|
|
1300
|
+
schema:
|
|
1301
|
+
type: string
|
|
1302
|
+
CsrfToken:
|
|
1303
|
+
name: X-CSRF-Token
|
|
1304
|
+
in: header
|
|
1305
|
+
required: true
|
|
1306
|
+
description: |
|
|
1307
|
+
Double-submit CSRF token bound to the active `opstage_session`
|
|
1308
|
+
cookie. Required for all state-changing Admin API calls
|
|
1309
|
+
(POST/PUT/PATCH/DELETE). Obtain it from `POST /api/admin/auth/login`,
|
|
1310
|
+
`GET /api/admin/auth/me`, or `GET /api/admin/auth/csrf`.
|
|
1311
|
+
schema:
|
|
1312
|
+
type: string
|
|
1313
|
+
Sort:
|
|
1314
|
+
name: sort
|
|
1315
|
+
in: query
|
|
1316
|
+
description: |
|
|
1317
|
+
Sort expression. Format: `field` (ascending) or `-field` (descending).
|
|
1318
|
+
Multiple fields are comma-separated and applied left-to-right. The
|
|
1319
|
+
set of allowed fields is documented per endpoint; unknown fields
|
|
1320
|
+
return 422 `VALIDATION_FAILED`.
|
|
1321
|
+
schema:
|
|
1322
|
+
type: string
|
|
1323
|
+
responses:
|
|
1324
|
+
Ok:
|
|
1325
|
+
description: Operation succeeded.
|
|
1326
|
+
content:
|
|
1327
|
+
application/json:
|
|
1328
|
+
schema:
|
|
1329
|
+
$ref: '#/components/schemas/SuccessEnvelope'
|
|
1330
|
+
BadRequest:
|
|
1331
|
+
description: Invalid request.
|
|
1332
|
+
content:
|
|
1333
|
+
application/json:
|
|
1334
|
+
schema:
|
|
1335
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1336
|
+
Unauthorized:
|
|
1337
|
+
description: Authentication failed (missing or invalid session/token).
|
|
1338
|
+
content:
|
|
1339
|
+
application/json:
|
|
1340
|
+
schema:
|
|
1341
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1342
|
+
Forbidden:
|
|
1343
|
+
description: Authenticated but not allowed (includes CSRF token mismatch and disabled/revoked Agents).
|
|
1344
|
+
content:
|
|
1345
|
+
application/json:
|
|
1346
|
+
schema:
|
|
1347
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1348
|
+
NotFound:
|
|
1349
|
+
description: Resource not found.
|
|
1350
|
+
content:
|
|
1351
|
+
application/json:
|
|
1352
|
+
schema:
|
|
1353
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1354
|
+
Conflict:
|
|
1355
|
+
description: State conflict (duplicate resource, terminal Command, etc.).
|
|
1356
|
+
content:
|
|
1357
|
+
application/json:
|
|
1358
|
+
schema:
|
|
1359
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1360
|
+
Gone:
|
|
1361
|
+
description: Resource is no longer available (expired Command).
|
|
1362
|
+
content:
|
|
1363
|
+
application/json:
|
|
1364
|
+
schema:
|
|
1365
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1366
|
+
UnprocessableEntity:
|
|
1367
|
+
description: Validation failed.
|
|
1368
|
+
content:
|
|
1369
|
+
application/json:
|
|
1370
|
+
schema:
|
|
1371
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1372
|
+
InternalError:
|
|
1373
|
+
description: Unexpected server error.
|
|
1374
|
+
content:
|
|
1375
|
+
application/json:
|
|
1376
|
+
schema:
|
|
1377
|
+
$ref: '#/components/schemas/ErrorEnvelope'
|
|
1378
|
+
schemas:
|
|
1379
|
+
SuccessEnvelope:
|
|
1380
|
+
type: object
|
|
1381
|
+
required: [success]
|
|
1382
|
+
properties:
|
|
1383
|
+
success:
|
|
1384
|
+
type: boolean
|
|
1385
|
+
const: true
|
|
1386
|
+
ErrorEnvelope:
|
|
1387
|
+
type: object
|
|
1388
|
+
required: [success, error]
|
|
1389
|
+
properties:
|
|
1390
|
+
success:
|
|
1391
|
+
type: boolean
|
|
1392
|
+
const: false
|
|
1393
|
+
error:
|
|
1394
|
+
$ref: '#/components/schemas/ErrorInfo'
|
|
1395
|
+
ErrorInfo:
|
|
1396
|
+
type: object
|
|
1397
|
+
required: [code, message]
|
|
1398
|
+
properties:
|
|
1399
|
+
code:
|
|
1400
|
+
type: string
|
|
1401
|
+
message:
|
|
1402
|
+
type: string
|
|
1403
|
+
details:
|
|
1404
|
+
type: object
|
|
1405
|
+
additionalProperties: true
|
|
1406
|
+
Pagination:
|
|
1407
|
+
type: object
|
|
1408
|
+
required: [page, pageSize, total]
|
|
1409
|
+
properties:
|
|
1410
|
+
page:
|
|
1411
|
+
type: integer
|
|
1412
|
+
pageSize:
|
|
1413
|
+
type: integer
|
|
1414
|
+
total:
|
|
1415
|
+
type: integer
|
|
1416
|
+
AdminLoginRequest:
|
|
1417
|
+
type: object
|
|
1418
|
+
required: [username, password]
|
|
1419
|
+
properties:
|
|
1420
|
+
username:
|
|
1421
|
+
type: string
|
|
1422
|
+
password:
|
|
1423
|
+
type: string
|
|
1424
|
+
format: password
|
|
1425
|
+
AdminSession:
|
|
1426
|
+
type: object
|
|
1427
|
+
required: [user, csrfToken, expiresAt]
|
|
1428
|
+
properties:
|
|
1429
|
+
user:
|
|
1430
|
+
$ref: '#/components/schemas/User'
|
|
1431
|
+
csrfToken:
|
|
1432
|
+
type: string
|
|
1433
|
+
description: |
|
|
1434
|
+
Token to be echoed in the `X-CSRF-Token` header for any
|
|
1435
|
+
state-changing Admin API call. Rotated on `/api/admin/auth/csrf`.
|
|
1436
|
+
expiresAt:
|
|
1437
|
+
type: string
|
|
1438
|
+
format: date-time
|
|
1439
|
+
description: |
|
|
1440
|
+
Absolute expiry of the current session cookie. UI may use this
|
|
1441
|
+
to schedule a silent refresh or warn the user before logout.
|
|
1442
|
+
User:
|
|
1443
|
+
type: object
|
|
1444
|
+
required: [id, username, role, status]
|
|
1445
|
+
properties:
|
|
1446
|
+
id:
|
|
1447
|
+
type: string
|
|
1448
|
+
pattern: '^usr_'
|
|
1449
|
+
username:
|
|
1450
|
+
type: string
|
|
1451
|
+
displayName:
|
|
1452
|
+
type: [string, 'null']
|
|
1453
|
+
role:
|
|
1454
|
+
type: string
|
|
1455
|
+
enum: [owner]
|
|
1456
|
+
status:
|
|
1457
|
+
type: string
|
|
1458
|
+
enum: [ACTIVE, DISABLED]
|
|
1459
|
+
DashboardSummary:
|
|
1460
|
+
type: object
|
|
1461
|
+
required: [agentCounts, serviceCounts, commandCounts]
|
|
1462
|
+
properties:
|
|
1463
|
+
agentCounts:
|
|
1464
|
+
type: object
|
|
1465
|
+
additionalProperties:
|
|
1466
|
+
type: integer
|
|
1467
|
+
serviceCounts:
|
|
1468
|
+
type: object
|
|
1469
|
+
additionalProperties:
|
|
1470
|
+
type: integer
|
|
1471
|
+
commandCounts:
|
|
1472
|
+
type: object
|
|
1473
|
+
additionalProperties:
|
|
1474
|
+
type: integer
|
|
1475
|
+
recentCommands:
|
|
1476
|
+
type: array
|
|
1477
|
+
items:
|
|
1478
|
+
$ref: '#/components/schemas/Command'
|
|
1479
|
+
recentAuditEvents:
|
|
1480
|
+
type: array
|
|
1481
|
+
items:
|
|
1482
|
+
$ref: '#/components/schemas/AuditEvent'
|
|
1483
|
+
AgentStatus:
|
|
1484
|
+
type: string
|
|
1485
|
+
enum: [PENDING, ONLINE, OFFLINE, DISABLED, REVOKED]
|
|
1486
|
+
CapsuleServiceStatus:
|
|
1487
|
+
type: string
|
|
1488
|
+
enum: [UNKNOWN, HEALTHY, UNHEALTHY, STALE, OFFLINE]
|
|
1489
|
+
HealthStatus:
|
|
1490
|
+
type: string
|
|
1491
|
+
enum: [UP, DEGRADED, DOWN, UNKNOWN]
|
|
1492
|
+
CommandStatus:
|
|
1493
|
+
type: string
|
|
1494
|
+
enum: [PENDING, RUNNING, SUCCEEDED, FAILED, EXPIRED, CANCELLED]
|
|
1495
|
+
DangerLevel:
|
|
1496
|
+
type: string
|
|
1497
|
+
enum: [LOW, MEDIUM, HIGH]
|
|
1498
|
+
AuditActorType:
|
|
1499
|
+
type: string
|
|
1500
|
+
enum: [USER, AGENT, SYSTEM]
|
|
1501
|
+
AuditResult:
|
|
1502
|
+
type: string
|
|
1503
|
+
enum: [SUCCESS, FAILURE]
|
|
1504
|
+
Agent:
|
|
1505
|
+
type: object
|
|
1506
|
+
required: [id, code, mode, status, createdAt, updatedAt]
|
|
1507
|
+
properties:
|
|
1508
|
+
id:
|
|
1509
|
+
type: string
|
|
1510
|
+
pattern: '^agt_'
|
|
1511
|
+
code:
|
|
1512
|
+
type: string
|
|
1513
|
+
name:
|
|
1514
|
+
type: [string, 'null']
|
|
1515
|
+
mode:
|
|
1516
|
+
type: string
|
|
1517
|
+
enum: [embedded, sidecar, external]
|
|
1518
|
+
runtime:
|
|
1519
|
+
type: [string, 'null']
|
|
1520
|
+
status:
|
|
1521
|
+
$ref: '#/components/schemas/AgentStatus'
|
|
1522
|
+
lastHeartbeatAt:
|
|
1523
|
+
type: [string, 'null']
|
|
1524
|
+
format: date-time
|
|
1525
|
+
createdAt:
|
|
1526
|
+
type: string
|
|
1527
|
+
format: date-time
|
|
1528
|
+
updatedAt:
|
|
1529
|
+
type: string
|
|
1530
|
+
format: date-time
|
|
1531
|
+
TokenStatus:
|
|
1532
|
+
type: string
|
|
1533
|
+
description: |
|
|
1534
|
+
Lifecycle of a registration or agent token. CE v0.1 enum.
|
|
1535
|
+
enum: [ACTIVE, USED, REVOKED, EXPIRED]
|
|
1536
|
+
RegistrationToken:
|
|
1537
|
+
type: object
|
|
1538
|
+
required: [id, name, status, createdAt]
|
|
1539
|
+
properties:
|
|
1540
|
+
id:
|
|
1541
|
+
type: string
|
|
1542
|
+
pattern: '^tok_'
|
|
1543
|
+
name:
|
|
1544
|
+
type: string
|
|
1545
|
+
status:
|
|
1546
|
+
$ref: '#/components/schemas/TokenStatus'
|
|
1547
|
+
expiresAt:
|
|
1548
|
+
type: [string, 'null']
|
|
1549
|
+
format: date-time
|
|
1550
|
+
usedAt:
|
|
1551
|
+
type: [string, 'null']
|
|
1552
|
+
format: date-time
|
|
1553
|
+
createdAt:
|
|
1554
|
+
type: string
|
|
1555
|
+
format: date-time
|
|
1556
|
+
CreateRegistrationTokenRequest:
|
|
1557
|
+
type: object
|
|
1558
|
+
properties:
|
|
1559
|
+
name:
|
|
1560
|
+
type: string
|
|
1561
|
+
default: Default registration token
|
|
1562
|
+
expiresInSeconds:
|
|
1563
|
+
type: integer
|
|
1564
|
+
minimum: 60
|
|
1565
|
+
CreateRegistrationTokenResponse:
|
|
1566
|
+
allOf:
|
|
1567
|
+
- $ref: '#/components/schemas/RegistrationToken'
|
|
1568
|
+
- type: object
|
|
1569
|
+
required: [rawToken]
|
|
1570
|
+
properties:
|
|
1571
|
+
rawToken:
|
|
1572
|
+
type: string
|
|
1573
|
+
description: Raw token shown only once. Persisted only as a SHA-256 hash.
|
|
1574
|
+
pattern: '^opstage_reg_'
|
|
1575
|
+
CapsuleService:
|
|
1576
|
+
type: object
|
|
1577
|
+
required: [id, code, name, status, createdAt, updatedAt]
|
|
1578
|
+
properties:
|
|
1579
|
+
id:
|
|
1580
|
+
type: string
|
|
1581
|
+
pattern: '^svc_'
|
|
1582
|
+
agentId:
|
|
1583
|
+
type: string
|
|
1584
|
+
pattern: '^agt_'
|
|
1585
|
+
code:
|
|
1586
|
+
type: string
|
|
1587
|
+
name:
|
|
1588
|
+
type: string
|
|
1589
|
+
description:
|
|
1590
|
+
type: [string, 'null']
|
|
1591
|
+
version:
|
|
1592
|
+
type: [string, 'null']
|
|
1593
|
+
runtime:
|
|
1594
|
+
type: [string, 'null']
|
|
1595
|
+
status:
|
|
1596
|
+
$ref: '#/components/schemas/CapsuleServiceStatus'
|
|
1597
|
+
healthStatus:
|
|
1598
|
+
$ref: '#/components/schemas/HealthStatus'
|
|
1599
|
+
lastReportedAt:
|
|
1600
|
+
type: [string, 'null']
|
|
1601
|
+
format: date-time
|
|
1602
|
+
lastHealthAt:
|
|
1603
|
+
type: [string, 'null']
|
|
1604
|
+
format: date-time
|
|
1605
|
+
createdAt:
|
|
1606
|
+
type: string
|
|
1607
|
+
format: date-time
|
|
1608
|
+
updatedAt:
|
|
1609
|
+
type: string
|
|
1610
|
+
format: date-time
|
|
1611
|
+
CapsuleServiceDetail:
|
|
1612
|
+
allOf:
|
|
1613
|
+
- $ref: '#/components/schemas/CapsuleService'
|
|
1614
|
+
- type: object
|
|
1615
|
+
properties:
|
|
1616
|
+
manifest:
|
|
1617
|
+
type: object
|
|
1618
|
+
additionalProperties: true
|
|
1619
|
+
health:
|
|
1620
|
+
$ref: '#/components/schemas/HealthReport'
|
|
1621
|
+
configs:
|
|
1622
|
+
type: array
|
|
1623
|
+
items:
|
|
1624
|
+
$ref: '#/components/schemas/ConfigItem'
|
|
1625
|
+
actions:
|
|
1626
|
+
type: array
|
|
1627
|
+
items:
|
|
1628
|
+
$ref: '#/components/schemas/ActionDefinition'
|
|
1629
|
+
HealthReport:
|
|
1630
|
+
type: object
|
|
1631
|
+
required: [id, serviceId, status, reportedAt]
|
|
1632
|
+
properties:
|
|
1633
|
+
id:
|
|
1634
|
+
type: string
|
|
1635
|
+
pattern: '^hlr_'
|
|
1636
|
+
serviceId:
|
|
1637
|
+
type: string
|
|
1638
|
+
pattern: '^svc_'
|
|
1639
|
+
agentId:
|
|
1640
|
+
type: string
|
|
1641
|
+
pattern: '^agt_'
|
|
1642
|
+
status:
|
|
1643
|
+
$ref: '#/components/schemas/HealthStatus'
|
|
1644
|
+
message:
|
|
1645
|
+
type: [string, 'null']
|
|
1646
|
+
details:
|
|
1647
|
+
type: object
|
|
1648
|
+
additionalProperties: true
|
|
1649
|
+
reportedAt:
|
|
1650
|
+
type: string
|
|
1651
|
+
format: date-time
|
|
1652
|
+
ConfigItem:
|
|
1653
|
+
type: object
|
|
1654
|
+
required: [id, serviceId, key, type, sensitive]
|
|
1655
|
+
properties:
|
|
1656
|
+
id:
|
|
1657
|
+
type: string
|
|
1658
|
+
pattern: '^cfg_'
|
|
1659
|
+
serviceId:
|
|
1660
|
+
type: string
|
|
1661
|
+
pattern: '^svc_'
|
|
1662
|
+
key:
|
|
1663
|
+
type: string
|
|
1664
|
+
label:
|
|
1665
|
+
type: [string, 'null']
|
|
1666
|
+
type:
|
|
1667
|
+
type: string
|
|
1668
|
+
source:
|
|
1669
|
+
type: [string, 'null']
|
|
1670
|
+
editable:
|
|
1671
|
+
type: boolean
|
|
1672
|
+
sensitive:
|
|
1673
|
+
type: boolean
|
|
1674
|
+
valuePreview:
|
|
1675
|
+
type: [string, 'null']
|
|
1676
|
+
defaultValue:
|
|
1677
|
+
type: [string, 'null']
|
|
1678
|
+
secretRef:
|
|
1679
|
+
type: [string, 'null']
|
|
1680
|
+
ActionDefinition:
|
|
1681
|
+
type: object
|
|
1682
|
+
required: [id, serviceId, name, label, dangerLevel, requiresConfirmation]
|
|
1683
|
+
properties:
|
|
1684
|
+
id:
|
|
1685
|
+
type: string
|
|
1686
|
+
pattern: '^act_'
|
|
1687
|
+
serviceId:
|
|
1688
|
+
type: string
|
|
1689
|
+
pattern: '^svc_'
|
|
1690
|
+
name:
|
|
1691
|
+
type: string
|
|
1692
|
+
label:
|
|
1693
|
+
type: string
|
|
1694
|
+
description:
|
|
1695
|
+
type: [string, 'null']
|
|
1696
|
+
dangerLevel:
|
|
1697
|
+
$ref: '#/components/schemas/DangerLevel'
|
|
1698
|
+
requiresConfirmation:
|
|
1699
|
+
type: boolean
|
|
1700
|
+
inputSchema:
|
|
1701
|
+
type: object
|
|
1702
|
+
additionalProperties: true
|
|
1703
|
+
timeoutSeconds:
|
|
1704
|
+
type: integer
|
|
1705
|
+
CreateActionCommandRequest:
|
|
1706
|
+
type: object
|
|
1707
|
+
properties:
|
|
1708
|
+
payload:
|
|
1709
|
+
type: object
|
|
1710
|
+
additionalProperties: true
|
|
1711
|
+
confirmation:
|
|
1712
|
+
type: boolean
|
|
1713
|
+
description: |
|
|
1714
|
+
Required to be `true` when `ActionDefinition.requiresConfirmation`
|
|
1715
|
+
is true. Backend rejects with `409 ACTION_REQUIRES_CONFIRMATION`
|
|
1716
|
+
otherwise. UI MUST show an explicit confirmation dialog before
|
|
1717
|
+
sending.
|
|
1718
|
+
Command:
|
|
1719
|
+
type: object
|
|
1720
|
+
required: [id, agentId, serviceId, type, actionName, status, createdAt]
|
|
1721
|
+
properties:
|
|
1722
|
+
id:
|
|
1723
|
+
type: string
|
|
1724
|
+
pattern: '^cmd_'
|
|
1725
|
+
agentId:
|
|
1726
|
+
type: string
|
|
1727
|
+
pattern: '^agt_'
|
|
1728
|
+
serviceId:
|
|
1729
|
+
type: string
|
|
1730
|
+
pattern: '^svc_'
|
|
1731
|
+
type:
|
|
1732
|
+
type: string
|
|
1733
|
+
enum: [ACTION_PREPARE, ACTION_EXECUTE, ACTION]
|
|
1734
|
+
actionName:
|
|
1735
|
+
type: string
|
|
1736
|
+
status:
|
|
1737
|
+
$ref: '#/components/schemas/CommandStatus'
|
|
1738
|
+
payload:
|
|
1739
|
+
type: object
|
|
1740
|
+
additionalProperties: true
|
|
1741
|
+
createdByUserId:
|
|
1742
|
+
type: [string, 'null']
|
|
1743
|
+
pattern: '^usr_'
|
|
1744
|
+
createdAt:
|
|
1745
|
+
type: string
|
|
1746
|
+
format: date-time
|
|
1747
|
+
startedAt:
|
|
1748
|
+
type: [string, 'null']
|
|
1749
|
+
format: date-time
|
|
1750
|
+
completedAt:
|
|
1751
|
+
type: [string, 'null']
|
|
1752
|
+
format: date-time
|
|
1753
|
+
expiresAt:
|
|
1754
|
+
type: [string, 'null']
|
|
1755
|
+
format: date-time
|
|
1756
|
+
CommandDetail:
|
|
1757
|
+
allOf:
|
|
1758
|
+
- $ref: '#/components/schemas/Command'
|
|
1759
|
+
- type: object
|
|
1760
|
+
properties:
|
|
1761
|
+
result:
|
|
1762
|
+
$ref: '#/components/schemas/CommandResult'
|
|
1763
|
+
CommandResult:
|
|
1764
|
+
type: object
|
|
1765
|
+
required: [id, commandId, success, reportedAt]
|
|
1766
|
+
properties:
|
|
1767
|
+
id:
|
|
1768
|
+
type: string
|
|
1769
|
+
pattern: '^crs_'
|
|
1770
|
+
commandId:
|
|
1771
|
+
type: string
|
|
1772
|
+
pattern: '^cmd_'
|
|
1773
|
+
success:
|
|
1774
|
+
type: boolean
|
|
1775
|
+
message:
|
|
1776
|
+
type: [string, 'null']
|
|
1777
|
+
data:
|
|
1778
|
+
type: object
|
|
1779
|
+
additionalProperties: true
|
|
1780
|
+
error:
|
|
1781
|
+
type: object
|
|
1782
|
+
additionalProperties: true
|
|
1783
|
+
reportedAt:
|
|
1784
|
+
type: string
|
|
1785
|
+
format: date-time
|
|
1786
|
+
ReportCommandResultRequest:
|
|
1787
|
+
type: object
|
|
1788
|
+
required: [success]
|
|
1789
|
+
properties:
|
|
1790
|
+
success:
|
|
1791
|
+
type: boolean
|
|
1792
|
+
message:
|
|
1793
|
+
type: string
|
|
1794
|
+
data:
|
|
1795
|
+
type: object
|
|
1796
|
+
additionalProperties: true
|
|
1797
|
+
error:
|
|
1798
|
+
type: object
|
|
1799
|
+
additionalProperties: true
|
|
1800
|
+
description: |
|
|
1801
|
+
Structured error payload. SHOULD include at minimum
|
|
1802
|
+
`{ code: string, message: string }`. Backend stores it as JSON.
|
|
1803
|
+
startedAt:
|
|
1804
|
+
type: string
|
|
1805
|
+
format: date-time
|
|
1806
|
+
description: When the Agent began executing the action handler.
|
|
1807
|
+
finishedAt:
|
|
1808
|
+
type: string
|
|
1809
|
+
format: date-time
|
|
1810
|
+
description: When the Agent finished executing. Defaults to receipt time.
|
|
1811
|
+
RegisterAgentRequest:
|
|
1812
|
+
type: object
|
|
1813
|
+
required: [registrationToken, agent]
|
|
1814
|
+
properties:
|
|
1815
|
+
registrationToken:
|
|
1816
|
+
type: string
|
|
1817
|
+
pattern: '^opstage_reg_'
|
|
1818
|
+
agent:
|
|
1819
|
+
type: object
|
|
1820
|
+
required: [code, mode]
|
|
1821
|
+
properties:
|
|
1822
|
+
code:
|
|
1823
|
+
type: string
|
|
1824
|
+
name:
|
|
1825
|
+
type: string
|
|
1826
|
+
mode:
|
|
1827
|
+
type: string
|
|
1828
|
+
enum: [embedded]
|
|
1829
|
+
runtime:
|
|
1830
|
+
type: string
|
|
1831
|
+
service:
|
|
1832
|
+
$ref: '#/components/schemas/ReportedService'
|
|
1833
|
+
RegisterAgentResponse:
|
|
1834
|
+
type: object
|
|
1835
|
+
required: [agentId, agentToken, heartbeatIntervalSeconds, commandPollIntervalSeconds]
|
|
1836
|
+
properties:
|
|
1837
|
+
agentId:
|
|
1838
|
+
type: string
|
|
1839
|
+
pattern: '^agt_'
|
|
1840
|
+
agentToken:
|
|
1841
|
+
type: string
|
|
1842
|
+
pattern: '^opstage_agent_'
|
|
1843
|
+
description: Raw Agent token shown only once to the Agent.
|
|
1844
|
+
heartbeatIntervalSeconds:
|
|
1845
|
+
type: integer
|
|
1846
|
+
commandPollIntervalSeconds:
|
|
1847
|
+
type: integer
|
|
1848
|
+
AgentHeartbeatRequest:
|
|
1849
|
+
type: object
|
|
1850
|
+
properties:
|
|
1851
|
+
serviceId:
|
|
1852
|
+
type: string
|
|
1853
|
+
pattern: '^svc_'
|
|
1854
|
+
health:
|
|
1855
|
+
$ref: '#/components/schemas/HealthReportInput'
|
|
1856
|
+
AgentHeartbeatResponse:
|
|
1857
|
+
type: object
|
|
1858
|
+
required: [heartbeatIntervalSeconds, commandPollIntervalSeconds]
|
|
1859
|
+
properties:
|
|
1860
|
+
heartbeatIntervalSeconds:
|
|
1861
|
+
type: integer
|
|
1862
|
+
commandPollIntervalSeconds:
|
|
1863
|
+
type: integer
|
|
1864
|
+
ServiceReportRequest:
|
|
1865
|
+
type: object
|
|
1866
|
+
required: [services]
|
|
1867
|
+
properties:
|
|
1868
|
+
services:
|
|
1869
|
+
type: array
|
|
1870
|
+
items:
|
|
1871
|
+
$ref: '#/components/schemas/ReportedService'
|
|
1872
|
+
ReportedService:
|
|
1873
|
+
type: object
|
|
1874
|
+
required: [code, name, manifest]
|
|
1875
|
+
properties:
|
|
1876
|
+
code:
|
|
1877
|
+
type: string
|
|
1878
|
+
minLength: 1
|
|
1879
|
+
maxLength: 80
|
|
1880
|
+
pattern: '^[a-z0-9][a-z0-9_-]*$'
|
|
1881
|
+
name:
|
|
1882
|
+
type: string
|
|
1883
|
+
minLength: 1
|
|
1884
|
+
maxLength: 200
|
|
1885
|
+
description:
|
|
1886
|
+
type: string
|
|
1887
|
+
maxLength: 2000
|
|
1888
|
+
version:
|
|
1889
|
+
type: string
|
|
1890
|
+
maxLength: 80
|
|
1891
|
+
runtime:
|
|
1892
|
+
type: string
|
|
1893
|
+
enum: [nodejs, java, python, go, other]
|
|
1894
|
+
manifest:
|
|
1895
|
+
$ref: '#/components/schemas/CapsuleManifest'
|
|
1896
|
+
health:
|
|
1897
|
+
$ref: '#/components/schemas/HealthReportInput'
|
|
1898
|
+
configs:
|
|
1899
|
+
type: array
|
|
1900
|
+
items:
|
|
1901
|
+
$ref: '#/components/schemas/ConfigItemInput'
|
|
1902
|
+
actions:
|
|
1903
|
+
type: array
|
|
1904
|
+
items:
|
|
1905
|
+
$ref: '#/components/schemas/ActionDefinitionInput'
|
|
1906
|
+
CapsuleManifest:
|
|
1907
|
+
type: object
|
|
1908
|
+
description: |
|
|
1909
|
+
Authoritative shape of a Capsule Service manifest reported by the Agent.
|
|
1910
|
+
Backend stores the full object as `CapsuleService.manifestJson` and validates
|
|
1911
|
+
the listed required fields. Unknown fields are preserved (forward-compat).
|
|
1912
|
+
required: [kind, code, name, version, runtime, agentMode]
|
|
1913
|
+
properties:
|
|
1914
|
+
kind:
|
|
1915
|
+
type: string
|
|
1916
|
+
const: CapsuleService
|
|
1917
|
+
schemaVersion:
|
|
1918
|
+
type: string
|
|
1919
|
+
description: Manifest schema version. Defaults to "1.0" if omitted.
|
|
1920
|
+
default: "1.0"
|
|
1921
|
+
code:
|
|
1922
|
+
type: string
|
|
1923
|
+
minLength: 1
|
|
1924
|
+
maxLength: 80
|
|
1925
|
+
pattern: '^[a-z0-9][a-z0-9_-]*$'
|
|
1926
|
+
name:
|
|
1927
|
+
type: string
|
|
1928
|
+
minLength: 1
|
|
1929
|
+
maxLength: 200
|
|
1930
|
+
description:
|
|
1931
|
+
type: string
|
|
1932
|
+
maxLength: 2000
|
|
1933
|
+
version:
|
|
1934
|
+
type: string
|
|
1935
|
+
minLength: 1
|
|
1936
|
+
maxLength: 80
|
|
1937
|
+
runtime:
|
|
1938
|
+
type: string
|
|
1939
|
+
enum: [nodejs, java, python, go, other]
|
|
1940
|
+
agentMode:
|
|
1941
|
+
type: string
|
|
1942
|
+
enum: [embedded, sidecar, external]
|
|
1943
|
+
capabilities:
|
|
1944
|
+
type: array
|
|
1945
|
+
items:
|
|
1946
|
+
type: string
|
|
1947
|
+
labels:
|
|
1948
|
+
type: object
|
|
1949
|
+
additionalProperties:
|
|
1950
|
+
type: string
|
|
1951
|
+
additionalProperties: true
|
|
1952
|
+
HealthReportInput:
|
|
1953
|
+
type: object
|
|
1954
|
+
required: [status]
|
|
1955
|
+
properties:
|
|
1956
|
+
status:
|
|
1957
|
+
$ref: '#/components/schemas/HealthStatus'
|
|
1958
|
+
message:
|
|
1959
|
+
type: string
|
|
1960
|
+
details:
|
|
1961
|
+
type: object
|
|
1962
|
+
additionalProperties: true
|
|
1963
|
+
ConfigItemInput:
|
|
1964
|
+
type: object
|
|
1965
|
+
required: [key, type]
|
|
1966
|
+
properties:
|
|
1967
|
+
key:
|
|
1968
|
+
type: string
|
|
1969
|
+
label:
|
|
1970
|
+
type: string
|
|
1971
|
+
type:
|
|
1972
|
+
type: string
|
|
1973
|
+
source:
|
|
1974
|
+
type: string
|
|
1975
|
+
editable:
|
|
1976
|
+
type: boolean
|
|
1977
|
+
sensitive:
|
|
1978
|
+
type: boolean
|
|
1979
|
+
valuePreview:
|
|
1980
|
+
type: string
|
|
1981
|
+
defaultValue:
|
|
1982
|
+
type: string
|
|
1983
|
+
secretRef:
|
|
1984
|
+
type: string
|
|
1985
|
+
ActionDefinitionInput:
|
|
1986
|
+
type: object
|
|
1987
|
+
required: [name, label]
|
|
1988
|
+
properties:
|
|
1989
|
+
name:
|
|
1990
|
+
type: string
|
|
1991
|
+
label:
|
|
1992
|
+
type: string
|
|
1993
|
+
description:
|
|
1994
|
+
type: string
|
|
1995
|
+
dangerLevel:
|
|
1996
|
+
$ref: '#/components/schemas/DangerLevel'
|
|
1997
|
+
requiresConfirmation:
|
|
1998
|
+
type: boolean
|
|
1999
|
+
inputSchema:
|
|
2000
|
+
type: object
|
|
2001
|
+
additionalProperties: true
|
|
2002
|
+
timeoutSeconds:
|
|
2003
|
+
type: integer
|
|
2004
|
+
AuditEvent:
|
|
2005
|
+
type: object
|
|
2006
|
+
required: [id, actorType, action, result, createdAt]
|
|
2007
|
+
properties:
|
|
2008
|
+
id:
|
|
2009
|
+
type: string
|
|
2010
|
+
pattern: '^aud_'
|
|
2011
|
+
actorType:
|
|
2012
|
+
$ref: '#/components/schemas/AuditActorType'
|
|
2013
|
+
actorId:
|
|
2014
|
+
type: [string, 'null']
|
|
2015
|
+
action:
|
|
2016
|
+
type: string
|
|
2017
|
+
targetType:
|
|
2018
|
+
type: [string, 'null']
|
|
2019
|
+
targetId:
|
|
2020
|
+
type: [string, 'null']
|
|
2021
|
+
result:
|
|
2022
|
+
$ref: '#/components/schemas/AuditResult'
|
|
2023
|
+
message:
|
|
2024
|
+
type: [string, 'null']
|
|
2025
|
+
metadata:
|
|
2026
|
+
type: object
|
|
2027
|
+
additionalProperties: true
|
|
2028
|
+
createdAt:
|
|
2029
|
+
type: string
|
|
2030
|
+
format: date-time
|
|
2031
|
+
SystemHealth:
|
|
2032
|
+
type: object
|
|
2033
|
+
required: [status, timestamp, version, edition, database]
|
|
2034
|
+
properties:
|
|
2035
|
+
status:
|
|
2036
|
+
type: string
|
|
2037
|
+
description: Overall Backend status. DOWN when any critical dependency is unreachable.
|
|
2038
|
+
enum: [UP, DEGRADED, DOWN]
|
|
2039
|
+
timestamp:
|
|
2040
|
+
type: string
|
|
2041
|
+
format: date-time
|
|
2042
|
+
description: Backend server clock at the time of the response.
|
|
2043
|
+
version:
|
|
2044
|
+
type: string
|
|
2045
|
+
description: Backend semantic version (matches package.json version).
|
|
2046
|
+
edition:
|
|
2047
|
+
type: string
|
|
2048
|
+
description: Build edition. Always "ce" for CE v0.1.
|
|
2049
|
+
enum: [ce]
|
|
2050
|
+
database:
|
|
2051
|
+
type: object
|
|
2052
|
+
required: [status]
|
|
2053
|
+
properties:
|
|
2054
|
+
status:
|
|
2055
|
+
type: string
|
|
2056
|
+
enum: [UP, DEGRADED, DOWN]
|
|
2057
|
+
kind:
|
|
2058
|
+
type: string
|
|
2059
|
+
enum: [sqlite, postgres, mysql]
|
|
2060
|
+
description: Database driver in use. Always "sqlite" in CE v0.1.
|
|
2061
|
+
latencyMs:
|
|
2062
|
+
type: integer
|
|
2063
|
+
minimum: 0
|
|
2064
|
+
description: Round-trip time of the health probe query (e.g. SELECT 1).
|
|
2065
|
+
uptimeSeconds:
|
|
2066
|
+
type: integer
|
|
2067
|
+
minimum: 0
|
|
2068
|
+
description: Seconds since the Backend process started.
|
|
2069
|
+
SystemVersion:
|
|
2070
|
+
type: object
|
|
2071
|
+
required: [version, edition]
|
|
2072
|
+
properties:
|
|
2073
|
+
version:
|
|
2074
|
+
type: string
|
|
2075
|
+
edition:
|
|
2076
|
+
type: string
|
|
2077
|
+
enum: [ce]
|
|
2078
|
+
commit:
|
|
2079
|
+
type: string
|
|
2080
|
+
description: Optional git commit short SHA when available at build time.
|
|
2081
|
+
buildTime:
|
|
2082
|
+
type: string
|
|
2083
|
+
format: date-time
|
|
2084
|
+
description: Optional ISO-8601 timestamp captured at build time.
|
|
2085
|
+
enum: [CE]
|