@sema-agent/sdk 0.0.126 → 0.0.127
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/package.json +7 -5
- package/registry-openapi.yaml +250 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.127",
|
|
4
4
|
"description": "Typed, zero-runtime-dependency SDK for the Sema agent fleet usage plane. The shared substrate for all doors (CC/Codex MCP façade + web). Server-side only — tokens never enter the browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -27,21 +27,23 @@
|
|
|
27
27
|
"./registry": {
|
|
28
28
|
"types": "./dist/registry/index.d.ts",
|
|
29
29
|
"import": "./dist/registry/index.js"
|
|
30
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"./registry-openapi.yaml": "./registry-openapi.yaml"
|
|
31
32
|
},
|
|
32
33
|
"files": [
|
|
33
34
|
"dist",
|
|
34
35
|
"openapi.yaml",
|
|
35
36
|
"README.md",
|
|
36
|
-
"LICENSE"
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"registry-openapi.yaml"
|
|
37
39
|
],
|
|
38
40
|
"engines": {
|
|
39
41
|
"node": ">=20"
|
|
40
42
|
},
|
|
41
43
|
"scripts": {
|
|
42
44
|
"build": "tsc -b",
|
|
43
|
-
"clean": "rm -rf dist openapi.yaml LICENSE tsconfig.tsbuildinfo",
|
|
44
|
-
"prepack": "node -e \"require('fs').copyFileSync('../../spec/openapi.yaml','openapi.yaml');require('fs').copyFileSync('../../LICENSE','LICENSE')\"",
|
|
45
|
+
"clean": "rm -rf dist openapi.yaml registry-openapi.yaml LICENSE tsconfig.tsbuildinfo",
|
|
46
|
+
"prepack": "node -e \"require('fs').copyFileSync('../../spec/openapi.yaml','openapi.yaml');require('fs').copyFileSync('../../spec/registry-openapi.yaml','registry-openapi.yaml');require('fs').copyFileSync('../../LICENSE','LICENSE')\"",
|
|
45
47
|
"publish:npm": "npm publish --access public --@sema-agent:registry=https://registry.npmjs.org/ --\"//registry.npmjs.org/:_authToken=${NPM_TOKEN}\"",
|
|
46
48
|
"prepublishOnly": "rm -f tsconfig.tsbuildinfo && npm run build"
|
|
47
49
|
},
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Sema Registry — the wire the SDK's `@sema-agent/sdk/registry` subpath consumes
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
description: >
|
|
6
|
+
⚠️ AUTHORITY POSTURE (read first): the registry SERVER lives in the sema-registry repo (web AI);
|
|
7
|
+
the machine contract single-source is `@sema-agent/registry-core` (zod schemas + path constants —
|
|
8
|
+
AUTH_V1_PATHS/SCOPES_V1_PATHS etc.; the SDK keeps value-copies with same-source anchor tests).
|
|
9
|
+
THIS file documents the surface the SDK's registry subpath actually calls, so a consumer generating
|
|
10
|
+
a client from spec sees the full face — it mirrors, it does not rule. Backfilled 2026-07-28 from
|
|
11
|
+
the [1895] retirement map (cli's hand-rolled HTTP → SDK verbs, G17 R1-R4 + G22 era); guarded by
|
|
12
|
+
`registry-spec-path-gate.test.ts` (reflective: every /api path the SDK hits must be here, zero baseline).
|
|
13
|
+
USER-PLANE paths carry real request/response shapes; the ADMIN family (RegistryAdmin, user-JWT
|
|
14
|
+
role-gated — "admin" is a registry-side ROLE, not a separate credential) is documented loose
|
|
15
|
+
(operator tooling; shapes live in registry-core/zod and the registry server).
|
|
16
|
+
x-sdk-subpath: "@sema-agent/sdk/registry"
|
|
17
|
+
paths:
|
|
18
|
+
/api/healthz:
|
|
19
|
+
get:
|
|
20
|
+
operationId: registryHealthz
|
|
21
|
+
summary: Registry liveness probe (probeRegistryHealth).
|
|
22
|
+
responses:
|
|
23
|
+
'200': { description: 'Alive. Open shape.' }
|
|
24
|
+
|
|
25
|
+
# ── auth (device flow RFC 8628 + refresh rotation + scope switch) ─────────────────────────────
|
|
26
|
+
/api/v1/auth/device/code:
|
|
27
|
+
post:
|
|
28
|
+
operationId: registryDeviceCode
|
|
29
|
+
summary: Start the device-authorization flow (requestDeviceCode).
|
|
30
|
+
responses:
|
|
31
|
+
'200':
|
|
32
|
+
description: '{device_code, user_code, verification_uri(_complete)?, interval, expires_in}.'
|
|
33
|
+
content: { application/json: { schema: { type: object, additionalProperties: true } } }
|
|
34
|
+
/api/v1/auth/device/token:
|
|
35
|
+
post:
|
|
36
|
+
operationId: registryDeviceToken
|
|
37
|
+
summary: Poll the device flow (pollUntilApproved's leg).
|
|
38
|
+
description: >
|
|
39
|
+
OAuth device-token semantics: `authorization_pending` keeps the interval, `slow_down` adds +5s,
|
|
40
|
+
`access_denied`/`expired_token` are terminal (typed errors in the SDK). Success = the token pair.
|
|
41
|
+
responses:
|
|
42
|
+
'200': { description: '{access_token, refresh_token, …} on approval.', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
43
|
+
'400': { description: 'OAuth error envelope {error: authorization_pending|slow_down|access_denied|expired_token|…}.' }
|
|
44
|
+
/api/v1/auth/device/approve:
|
|
45
|
+
post:
|
|
46
|
+
operationId: registryDeviceApprove
|
|
47
|
+
summary: Approve a pending device code (the signed-in side of the flow).
|
|
48
|
+
responses:
|
|
49
|
+
'200': { description: 'Approved.' }
|
|
50
|
+
/api/v1/auth/token/refresh:
|
|
51
|
+
post:
|
|
52
|
+
operationId: registryTokenRefresh
|
|
53
|
+
summary: Refresh-token rotation (STRICT single-use).
|
|
54
|
+
description: >
|
|
55
|
+
Rotation is single-use: the presented refresh_token is consumed; `invalid_grant` ⇒ the SDK
|
|
56
|
+
clears the token pair and surfaces a typed re-login error. The RegistryClient wraps this in a
|
|
57
|
+
single-flight 401-refresh-retry-once.
|
|
58
|
+
responses:
|
|
59
|
+
'200': { description: 'The NEW token pair (both tokens rotate).', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
60
|
+
'400': { description: '`invalid_grant` = consumed/expired refresh token → re-login.' }
|
|
61
|
+
/api/v1/auth/logout:
|
|
62
|
+
post:
|
|
63
|
+
operationId: registryLogout
|
|
64
|
+
summary: Revoke the session (logoutRegistry).
|
|
65
|
+
responses:
|
|
66
|
+
'200': { description: 'Revoked (SDK clears the TokenProvider either way).' }
|
|
67
|
+
/api/v1/auth/scope:
|
|
68
|
+
post:
|
|
69
|
+
operationId: registryScopeSwitch
|
|
70
|
+
summary: Switch the active scope (switchScope).
|
|
71
|
+
description: >
|
|
72
|
+
🔴 The response carries a NEW access_token but NO refresh_token (the refresh grant is untouched)
|
|
73
|
+
— the SDK PRESERVES the old refreshToken when persisting (copying the grant-shaped write here
|
|
74
|
+
would wipe it ⇒ next refresh = surprise logout; pinned by test).
|
|
75
|
+
responses:
|
|
76
|
+
'200': { description: '{access_token, scope, …} — NO refresh_token by design.', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
77
|
+
|
|
78
|
+
# ── scopes / effective config (user plane) ────────────────────────────────────────────────────
|
|
79
|
+
/api/v1/scopes:
|
|
80
|
+
get:
|
|
81
|
+
operationId: registryScopesList
|
|
82
|
+
summary: List the caller's scopes (listScopes; `?counts=` optional).
|
|
83
|
+
responses:
|
|
84
|
+
'200': { description: 'ScopesListResponse (registry-core schema).', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
85
|
+
post:
|
|
86
|
+
operationId: registryScopesCreate
|
|
87
|
+
summary: 'ADMIN: create a scope/space.'
|
|
88
|
+
responses: { '200': { description: Created. } }
|
|
89
|
+
/api/v1/effective:
|
|
90
|
+
get:
|
|
91
|
+
operationId: registryEffective
|
|
92
|
+
summary: The effective (merged) config for the caller (getEffective; ETag/304 engine).
|
|
93
|
+
description: >
|
|
94
|
+
Conditional-GET face: the SDK sends `If-None-Match` from the last ETag; 304 = unchanged (no
|
|
95
|
+
body). `?principal=` lets a service-credential caller read another principal's effective view.
|
|
96
|
+
Body is open-domain (domains are registry-defined; the consumer treats it as data).
|
|
97
|
+
parameters:
|
|
98
|
+
- { in: query, name: principal, required: false, schema: { type: string } }
|
|
99
|
+
- { in: header, name: If-None-Match, required: false, schema: { type: string } }
|
|
100
|
+
responses:
|
|
101
|
+
'200': { description: 'The effective view (ETag header rides).', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
102
|
+
'304': { description: 'Unchanged since the presented ETag.' }
|
|
103
|
+
|
|
104
|
+
# ── me / per-user config (CAS on the updatedAt STRING axis) ───────────────────────────────────
|
|
105
|
+
/api/v1/me:
|
|
106
|
+
get:
|
|
107
|
+
operationId: registryMe
|
|
108
|
+
summary: Who am I (claims + role).
|
|
109
|
+
responses:
|
|
110
|
+
'200': { description: 'The caller profile.', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
111
|
+
/api/v1/me/config/{domain}:
|
|
112
|
+
parameters:
|
|
113
|
+
- { in: path, name: domain, required: true, schema: { type: string } }
|
|
114
|
+
get:
|
|
115
|
+
operationId: registryMeConfigGet
|
|
116
|
+
summary: Read one config domain of the caller (getMeConfig).
|
|
117
|
+
responses:
|
|
118
|
+
'200': { description: '{value, updatedAt, …}.', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
119
|
+
put:
|
|
120
|
+
operationId: registryMeConfigPut
|
|
121
|
+
summary: CAS-write one config domain (putMeConfig; baseUpdatedAt = the compare axis).
|
|
122
|
+
description: >
|
|
123
|
+
🔴 CAS axis = the `updatedAt` STRING (verbatim echo), NOT a version number — the scopes/config
|
|
124
|
+
face below uses a NUMBER `version` axis; the two axes must never be mixed (pinned). 409 carries
|
|
125
|
+
`currentUpdatedAt` (typed ConfigCasConflictError; retryOn409 merge-callback retries ONCE).
|
|
126
|
+
responses:
|
|
127
|
+
'200': { description: Written. }
|
|
128
|
+
'409': { description: '{currentUpdatedAt} — concurrent write; refetch+merge+retry once.' }
|
|
129
|
+
/api/v1/users/{u}/config/{domain}:
|
|
130
|
+
parameters:
|
|
131
|
+
- { in: path, name: u, required: true, schema: { type: string } }
|
|
132
|
+
- { in: path, name: domain, required: true, schema: { type: string } }
|
|
133
|
+
get:
|
|
134
|
+
operationId: registryUserConfigGet
|
|
135
|
+
summary: 'Managed variant of me/config (--user; operator writes another user''s domain).'
|
|
136
|
+
responses: { '200': { description: 'Same shape as me/config.' } }
|
|
137
|
+
put:
|
|
138
|
+
operationId: registryUserConfigPut
|
|
139
|
+
summary: Managed CAS-write (same updatedAt axis + 409 semantics as me/config).
|
|
140
|
+
responses:
|
|
141
|
+
'200': { description: Written. }
|
|
142
|
+
'409': { description: '{currentUpdatedAt}.' }
|
|
143
|
+
|
|
144
|
+
# ── scope config draft / publish (CAS on the version NUMBER axis) ─────────────────────────────
|
|
145
|
+
/api/v1/scopes/{s}/config/{domain}:
|
|
146
|
+
parameters:
|
|
147
|
+
- { in: path, name: s, required: true, schema: { type: string } }
|
|
148
|
+
- { in: path, name: domain, required: true, schema: { type: string } }
|
|
149
|
+
get:
|
|
150
|
+
operationId: registryScopeConfigDraftGet
|
|
151
|
+
summary: Read a scope's config DRAFT (getScopeConfigDraft).
|
|
152
|
+
responses: { '200': { description: '{value, version, …}.' } }
|
|
153
|
+
put:
|
|
154
|
+
operationId: registryScopeConfigDraftPut
|
|
155
|
+
summary: CAS-write the draft (putScopeConfigDraft; version NUMBER axis — not updatedAt).
|
|
156
|
+
responses:
|
|
157
|
+
'200': { description: Written. }
|
|
158
|
+
'409': { description: 'Version conflict.' }
|
|
159
|
+
/api/v1/scopes/{s}/publish:
|
|
160
|
+
parameters:
|
|
161
|
+
- { in: path, name: s, required: true, schema: { type: string } }
|
|
162
|
+
post:
|
|
163
|
+
operationId: registryScopePublishRequest
|
|
164
|
+
summary: Request publish of the draft (requestPublish; goes through the approval gate).
|
|
165
|
+
responses: { '200': { description: 'Publish requested/pending.' } }
|
|
166
|
+
|
|
167
|
+
# ── feedback ──────────────────────────────────────────────────────────────────────────────────
|
|
168
|
+
/api/v1/feedback:
|
|
169
|
+
post:
|
|
170
|
+
operationId: registryFeedback
|
|
171
|
+
summary: Post product feedback (postFeedback; the privacy gate stays client-side).
|
|
172
|
+
responses: { '200': { description: Accepted. } }
|
|
173
|
+
|
|
174
|
+
# ── ADMIN family (RegistryAdmin; user JWT, registry-side role gate; loose shapes by design) ───
|
|
175
|
+
/api/v1/instance/features:
|
|
176
|
+
get: { operationId: adminInstanceFeatures, summary: 'ADMIN: instance feature flags.', responses: { '200': { description: OK } } }
|
|
177
|
+
/api/v1/users:
|
|
178
|
+
get: { operationId: adminUsersList, summary: 'ADMIN: list users.', responses: { '200': { description: OK } } }
|
|
179
|
+
post: { operationId: adminUsersCreate, summary: 'ADMIN: create user.', responses: { '200': { description: OK } } }
|
|
180
|
+
/api/v1/users/{u}:
|
|
181
|
+
parameters: [{ in: path, name: u, required: true, schema: { type: string } }]
|
|
182
|
+
get: { operationId: adminUsersShow, summary: 'ADMIN: show user.', responses: { '200': { description: OK } } }
|
|
183
|
+
delete: { operationId: adminUsersDelete, summary: 'ADMIN: delete user.', responses: { '200': { description: OK } } }
|
|
184
|
+
/api/v1/access-requests:
|
|
185
|
+
get: { operationId: adminAccessRequestsList, summary: 'ADMIN: list access requests (filters via query).', responses: { '200': { description: OK } } }
|
|
186
|
+
/api/v1/access-requests/{id}/decision:
|
|
187
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
188
|
+
post: { operationId: adminAccessRequestDecide, summary: 'ADMIN: decide an access request.', responses: { '200': { description: OK } } }
|
|
189
|
+
/api/v1/scopes/{id}:
|
|
190
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
191
|
+
patch: { operationId: adminSpacesPatch, summary: 'ADMIN: patch scope/space.', responses: { '200': { description: OK } } }
|
|
192
|
+
delete: { operationId: adminSpacesDelete, summary: 'ADMIN: delete scope/space.', responses: { '200': { description: OK } } }
|
|
193
|
+
/api/v1/scopes/{id}/members:
|
|
194
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
195
|
+
get: { operationId: adminSpaceMembersList, summary: 'ADMIN: list scope members.', responses: { '200': { description: OK } } }
|
|
196
|
+
put: { operationId: adminSpaceMembersPut, summary: 'ADMIN: upsert scope member.', responses: { '200': { description: OK } } }
|
|
197
|
+
delete: { operationId: adminSpaceMembersDelete, summary: 'ADMIN: remove scope member.', responses: { '200': { description: OK } } }
|
|
198
|
+
/api/v1/groups:
|
|
199
|
+
get: { operationId: adminGroupsList, summary: 'ADMIN: list groups.', responses: { '200': { description: OK } } }
|
|
200
|
+
post: { operationId: adminGroupsCreate, summary: 'ADMIN: create group.', responses: { '200': { description: OK } } }
|
|
201
|
+
/api/v1/groups/{id}:
|
|
202
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
203
|
+
get: { operationId: adminGroupsShow, summary: 'ADMIN: show group.', responses: { '200': { description: OK } } }
|
|
204
|
+
put: { operationId: adminGroupsRename, summary: 'ADMIN: rename group.', responses: { '200': { description: OK } } }
|
|
205
|
+
delete: { operationId: adminGroupsDelete, summary: 'ADMIN: delete group.', responses: { '200': { description: OK } } }
|
|
206
|
+
/api/v1/groups/{g}/members:
|
|
207
|
+
parameters: [{ in: path, name: g, required: true, schema: { type: string } }]
|
|
208
|
+
get: { operationId: adminGroupMembersList, summary: 'ADMIN: list group members.', responses: { '200': { description: OK } } }
|
|
209
|
+
put: { operationId: adminGroupMembersAdd, summary: 'ADMIN: add group member.', responses: { '200': { description: OK } } }
|
|
210
|
+
delete: { operationId: adminGroupMembersRemove, summary: 'ADMIN: remove group member.', responses: { '200': { description: OK } } }
|
|
211
|
+
/api/v1/audit:
|
|
212
|
+
get: { operationId: adminAuditList, summary: 'ADMIN: global audit log.', responses: { '200': { description: OK } } }
|
|
213
|
+
/api/v1/audit/{id}/diff:
|
|
214
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
215
|
+
get: { operationId: adminAuditDiff, summary: 'ADMIN: one audit entry''s diff.', responses: { '200': { description: OK } } }
|
|
216
|
+
/api/v1/scopes/{s}/audit:
|
|
217
|
+
parameters: [{ in: path, name: s, required: true, schema: { type: string } }]
|
|
218
|
+
get: { operationId: adminAuditListScoped, summary: 'ADMIN: scope-scoped audit log.', responses: { '200': { description: OK } } }
|
|
219
|
+
/api/v1/scopes/{s}/audit/{id}/diff:
|
|
220
|
+
parameters:
|
|
221
|
+
- { in: path, name: s, required: true, schema: { type: string } }
|
|
222
|
+
- { in: path, name: id, required: true, schema: { type: string } }
|
|
223
|
+
get: { operationId: adminAuditDiffScoped, summary: 'ADMIN: scope-scoped audit diff.', responses: { '200': { description: OK } } }
|
|
224
|
+
/api/v1/images:
|
|
225
|
+
get: { operationId: adminImagesList, summary: 'ADMIN: sandbox image profiles.', responses: { '200': { description: OK } } }
|
|
226
|
+
/api/v1/images/{profile}:
|
|
227
|
+
parameters: [{ in: path, name: profile, required: true, schema: { type: string } }]
|
|
228
|
+
get: { operationId: adminImagesShow, summary: 'ADMIN: one image profile.', responses: { '200': { description: OK } } }
|
|
229
|
+
/api/v1/secrets:
|
|
230
|
+
get: { operationId: adminSecretsList, summary: 'ADMIN: secrets metadata (values never returned).', responses: { '200': { description: OK } } }
|
|
231
|
+
/api/v1/secrets/refs:
|
|
232
|
+
get: { operationId: adminSecretsRefs, summary: 'ADMIN: secret reference names.', responses: { '200': { description: OK } } }
|
|
233
|
+
/api/v1/auth-providers:
|
|
234
|
+
get: { operationId: adminAuthProvidersList, summary: 'ADMIN: auth providers.', responses: { '200': { description: OK } } }
|
|
235
|
+
/api/v1/auth-providers/{id}:
|
|
236
|
+
parameters: [{ in: path, name: id, required: true, schema: { type: string } }]
|
|
237
|
+
get: { operationId: adminAuthProvidersShow, summary: 'ADMIN: one auth provider.', responses: { '200': { description: OK } } }
|
|
238
|
+
/api/v1/scopes/{s}/rollback:
|
|
239
|
+
parameters: [{ in: path, name: s, required: true, schema: { type: string } }]
|
|
240
|
+
post: { operationId: adminScopeRollback, summary: 'ADMIN: rollback a scope''s published config.', responses: { '200': { description: OK } } }
|
|
241
|
+
/api/v1/usage/me:
|
|
242
|
+
get: { operationId: adminUsageMe, summary: 'Usage of the caller.', responses: { '200': { description: OK } } }
|
|
243
|
+
/api/v1/usage/summary:
|
|
244
|
+
get: { operationId: adminUsageSummary, summary: 'ADMIN: usage summary.', responses: { '200': { description: OK } } }
|
|
245
|
+
/api/v1/scopes/{s}/publish/approve:
|
|
246
|
+
parameters: [{ in: path, name: s, required: true, schema: { type: string } }]
|
|
247
|
+
post: { operationId: adminPublishApprove, summary: 'ADMIN: approve a pending publish.', responses: { '200': { description: OK } } }
|
|
248
|
+
/api/v1/scopes/{s}/publish/pending:
|
|
249
|
+
parameters: [{ in: path, name: s, required: true, schema: { type: string } }]
|
|
250
|
+
delete: { operationId: adminPublishWithdraw, summary: 'ADMIN: withdraw a pending publish.', responses: { '200': { description: OK } } }
|