@terminus-ai/cli 0.0.1
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 +21 -0
- package/README.md +1055 -0
- package/bin/agent-discovery.mjs +71 -0
- package/bin/agent-icon.mjs +77 -0
- package/bin/agent-models.mjs +77 -0
- package/bin/agent-type.mjs +51 -0
- package/bin/agentdev.mjs +657 -0
- package/bin/app-route-script.mjs +59 -0
- package/bin/app-runtime-contract.mjs +2 -0
- package/bin/appdev-remote.mjs +346 -0
- package/bin/appdev.mjs +4446 -0
- package/bin/apps.mjs +5512 -0
- package/bin/capability-calls.mjs +437 -0
- package/bin/capsule-data.mjs +260 -0
- package/bin/client.mjs +189 -0
- package/bin/commands.mjs +1194 -0
- package/bin/dev-capsules.mjs +1599 -0
- package/bin/dev-contract.mjs +262 -0
- package/bin/dev-data.mjs +287 -0
- package/bin/dev-members.mjs +18 -0
- package/bin/dev-net.mjs +316 -0
- package/bin/dev-notification-popup.mjs +628 -0
- package/bin/dev-ports.mjs +567 -0
- package/bin/dev-server-binding.mjs +35 -0
- package/bin/dev-server-ops.mjs +1086 -0
- package/bin/dev-ui/IoskeleyMono-400.woff2 +0 -0
- package/bin/dev-ui/IoskeleyMono-600.woff2 +0 -0
- package/bin/dev-ui/OFL.txt +92 -0
- package/bin/dev-ui/agent-robot.webp +0 -0
- package/bin/dev-ui/app.js +5217 -0
- package/bin/dev-ui/highlight.js +195 -0
- package/bin/dev-ui/index.html +34 -0
- package/bin/dev-ui/style.css +3640 -0
- package/bin/devlint.mjs +112 -0
- package/bin/devserver.mjs +2127 -0
- package/bin/devtriggers.mjs +367 -0
- package/bin/endpoints.mjs +156 -0
- package/bin/errors.mjs +61 -0
- package/bin/files.mjs +169 -0
- package/bin/horizontal-capabilities/v1/contract.json +280 -0
- package/bin/http.mjs +500 -0
- package/bin/lint-manifests/justbash-commands.json +88 -0
- package/bin/lint-manifests/python-stdlib.json +295 -0
- package/bin/login-page.mjs +488 -0
- package/bin/schedules.mjs +664 -0
- package/bin/server-sandbox.mjs +204 -0
- package/bin/servicedev.mjs +425 -0
- package/bin/sync.mjs +357 -0
- package/bin/terminus.js +3666 -0
- package/bin/toolchain.mjs +125 -0
- package/bin/vendor/app-runtime-v1/app-host.json +124 -0
- package/bin/vendor/app-runtime-v1/capability-calls.json +412 -0
- package/bin/vendor/app-runtime-v1/doors.json +2867 -0
- package/bin/vendor/appd/node-harness.mjs +209 -0
- package/bin/vendor/appd/python-harness.py +12 -0
- package/bin/vendor/appd/server-protocol.json +84 -0
- package/bin/vendor/where.mjs +541 -0
- package/bin/versioning.mjs +72 -0
- package/bin/write-rules.mjs +398 -0
- package/package.json +41 -0
|
@@ -0,0 +1,2867 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"contract": "terminus.app-runtime.doors",
|
|
4
|
+
"runtime_api_version": 1,
|
|
5
|
+
"notation": {
|
|
6
|
+
"fields": "A field name ending in ? may be absent; $body stands for the whole JSON body when it is not an object of named fields.",
|
|
7
|
+
"types": "string, integer, number, boolean, object, json (any JSON value) and null; a PascalCase Name is a key of types; T[] is an array; a|b is a union; any other alternative is a literal value (direct, GET, 1).",
|
|
8
|
+
"paths": "path is the app-relative door under /_terminus (null when app code cannot reach it); upstream is the backend route the app host forwards to, in the route contract's notation.",
|
|
9
|
+
"response_kinds": "json, bytes (raw body), sse (see frames) or redirect (a Location answer the app host passes through)."
|
|
10
|
+
},
|
|
11
|
+
"conventions": {
|
|
12
|
+
"casing": "Every request and response field, query parameter and SSE frame field on /_terminus and /v1/app-runtime is snake_case (D1); the SDK speaks camelCase to apps, and grammar keywords inside app-authored definitions (where, permissions, validate, relations) keep the spelling their own vectors pin.",
|
|
13
|
+
"auth": "App doors authenticate with the session the app host attaches from its HttpOnly cookie; app code never holds a credential, and the app host refuses cross-origin mutations.",
|
|
14
|
+
"idempotency": "The Idempotency-Key header (1-200 visible characters) is required on record PUT/DELETE, deliver and transactions and optional on events, notifications, collect submit, jobs, connectors and services (D11); a replay is recognized before any other check (permission, write rules, version, quota) and repeats no effect, rings nobody and answers the first answer even where those checks would now refuse the request, a key reused for a different request is 409 idempotency_conflict, and a key still in flight is 409 still_pending. The platform keeps no copy of what a connector's provider or a developer-operated service answered, so those replays differ: a connector call under a resource grant answers a replayed key with the action it first staged or applied (never a second one); a plain connector call is not deduplicated; a developer-operated service receives the key in its own Idempotency-Key header, and a replayed key is 409 idempotency_conflict rather than its first answer — never a second charge (managed services replay the first answer).",
|
|
15
|
+
"space_id": "space_id rides the query string on GET and DELETE and on doors whose body is a raw value, is a JSON body field on POST/PUT/PATCH doors with JSON bodies, and is a path segment on /spaces/{space_id}/... (D12).",
|
|
16
|
+
"pagination": "Lists page with ?after=<opaque cursor>&limit=<n> and answer next_cursor (string or null); collections keep records, next_cursor, has_more and sync_cursor (D13); no page is larger than limits.page_size.",
|
|
17
|
+
"binary": "Binary never rides a JSON string field as text: JSON answers carry body (UTF-8 text or null) beside body_base64 (base64 bytes or null) (D14), and raw bytes travel as raw bodies.",
|
|
18
|
+
"echo": "An event is never delivered back to any session of the user who published it, and a presence change is not echoed to the member who made it; platform change signals reach every member who can read the change, the writer's own sessions included — a change to a member's own (personal) collection reaches only that member, even inside a space (D3).",
|
|
19
|
+
"errors": "Every non-2xx answer from any host - backend, terminus dev or the app host, extractor and body-limit rejections and admission refusals included - is JSON {error:{code, message, details?}} with a code from errors; clients branch on code and status, never on message (D16).",
|
|
20
|
+
"ids_and_times": "Ids are opaque strings (UUIDs on hosted runtimes) and times are RFC 3339 strings.",
|
|
21
|
+
"body_limits": "A door's body limit is checked before its body is parsed; doors without an explicit limit take limits.default_body_bytes (D17)."
|
|
22
|
+
},
|
|
23
|
+
"common_errors": ["method_not_allowed", "service_unavailable", "deadline_exceeded"],
|
|
24
|
+
"types": {
|
|
25
|
+
"PublicUser": {
|
|
26
|
+
"id": "string",
|
|
27
|
+
"handle": "string",
|
|
28
|
+
"display_name": "string",
|
|
29
|
+
"avatar_url": "string|null",
|
|
30
|
+
"public_profile_url": "string|null"
|
|
31
|
+
},
|
|
32
|
+
"SpaceMember": {
|
|
33
|
+
"id": "string",
|
|
34
|
+
"handle": "string",
|
|
35
|
+
"display_name": "string",
|
|
36
|
+
"avatar_url": "string|null",
|
|
37
|
+
"public_profile_url": "string|null",
|
|
38
|
+
"role": "owner|admin|editor|viewer",
|
|
39
|
+
"joined_at": "string"
|
|
40
|
+
},
|
|
41
|
+
"Space": {
|
|
42
|
+
"id": "string",
|
|
43
|
+
"name": "string",
|
|
44
|
+
"kind": "direct|group",
|
|
45
|
+
"peer": "PublicUser|null",
|
|
46
|
+
"parent_id": "string|null",
|
|
47
|
+
"meta": "object|null",
|
|
48
|
+
"my_role": "owner|admin|editor|viewer",
|
|
49
|
+
"blocked_by_me": "boolean",
|
|
50
|
+
"blocked_by_peer": "boolean",
|
|
51
|
+
"muted": "boolean",
|
|
52
|
+
"capabilities": "SpaceCapabilities"
|
|
53
|
+
},
|
|
54
|
+
"SpaceCapabilities": {
|
|
55
|
+
"can_send": "boolean",
|
|
56
|
+
"can_invite": "boolean",
|
|
57
|
+
"can_remove_members": "boolean",
|
|
58
|
+
"can_manage_roles": "boolean",
|
|
59
|
+
"can_update": "boolean",
|
|
60
|
+
"can_leave": "boolean",
|
|
61
|
+
"can_block_peer": "boolean",
|
|
62
|
+
"can_delete": "boolean"
|
|
63
|
+
},
|
|
64
|
+
"SpaceInviteReceipt": { "id": "string", "user_id": "string", "handle": "string", "created": "boolean" },
|
|
65
|
+
"SpaceInvitation": {
|
|
66
|
+
"id": "string",
|
|
67
|
+
"space_id": "string",
|
|
68
|
+
"invitee": "PublicUser",
|
|
69
|
+
"role": "admin|editor|viewer",
|
|
70
|
+
"status": "pending",
|
|
71
|
+
"created_at": "string",
|
|
72
|
+
"expires_at": "string"
|
|
73
|
+
},
|
|
74
|
+
"SpaceCursorMember": {
|
|
75
|
+
"user_id": "string",
|
|
76
|
+
"role": "owner|admin|editor|viewer|null",
|
|
77
|
+
"delivered_through": "integer",
|
|
78
|
+
"read_through": "integer"
|
|
79
|
+
},
|
|
80
|
+
"BootstrapApp": { "id": "string", "slug": "string", "name": "string", "icon_url": "string" },
|
|
81
|
+
"BootstrapInstallation": { "id": "string", "release_id": "string", "release_version": "integer" },
|
|
82
|
+
"BootstrapData": { "grants": "DataGrant[]", "resource_grants": "ResourceGrant[]" },
|
|
83
|
+
"DataGrant": {
|
|
84
|
+
"id": "string",
|
|
85
|
+
"path_prefix": "string",
|
|
86
|
+
"access": "read|read-write",
|
|
87
|
+
"expires_at": "string|null"
|
|
88
|
+
},
|
|
89
|
+
"ResourceGrant": {
|
|
90
|
+
"id": "string",
|
|
91
|
+
"connector": "string",
|
|
92
|
+
"label": "string",
|
|
93
|
+
"resource_type": "path|object|collection",
|
|
94
|
+
"resource": "string",
|
|
95
|
+
"operations": "string[]",
|
|
96
|
+
"field_rules": "object",
|
|
97
|
+
"rate_limit_per_minute": "integer",
|
|
98
|
+
"approval_mode": "manual|scoped_auto",
|
|
99
|
+
"space_id": "string|null",
|
|
100
|
+
"expires_at": "string|null",
|
|
101
|
+
"revoked_at": "string|null",
|
|
102
|
+
"created_at": "string",
|
|
103
|
+
"updated_at": "string"
|
|
104
|
+
},
|
|
105
|
+
"RuntimePolicy": {
|
|
106
|
+
"connect_src?": "string[]",
|
|
107
|
+
"font_src?": "string[]",
|
|
108
|
+
"frame_src?": "string[]",
|
|
109
|
+
"img_src?": "string[]",
|
|
110
|
+
"script_src?": "string[]",
|
|
111
|
+
"style_src?": "string[]"
|
|
112
|
+
},
|
|
113
|
+
"FileEntry": {
|
|
114
|
+
"path": "string",
|
|
115
|
+
"size_bytes": "integer",
|
|
116
|
+
"sha256": "string",
|
|
117
|
+
"media_type": "string",
|
|
118
|
+
"version": "integer",
|
|
119
|
+
"updated_at": "string"
|
|
120
|
+
},
|
|
121
|
+
"WriteReceipt": {
|
|
122
|
+
"path": "string",
|
|
123
|
+
"size_bytes": "integer",
|
|
124
|
+
"sha256": "string",
|
|
125
|
+
"media_type": "string",
|
|
126
|
+
"version": "integer",
|
|
127
|
+
"updated_at": "string"
|
|
128
|
+
},
|
|
129
|
+
"CollectionDefinition": {
|
|
130
|
+
"name?": "string",
|
|
131
|
+
"ownership?": "personal|space",
|
|
132
|
+
"search?": "string[]",
|
|
133
|
+
"indexes?": "string[]",
|
|
134
|
+
"unique?": "string[]",
|
|
135
|
+
"relations?": "object",
|
|
136
|
+
"permissions?": "object",
|
|
137
|
+
"schema?": "json",
|
|
138
|
+
"validate?": "json[]"
|
|
139
|
+
},
|
|
140
|
+
"ManagedRecord": {
|
|
141
|
+
"id": "string",
|
|
142
|
+
"value": "object",
|
|
143
|
+
"version": "integer",
|
|
144
|
+
"created_at": "string",
|
|
145
|
+
"updated_at": "string",
|
|
146
|
+
"created_by_user_id": "string|null",
|
|
147
|
+
"updated_by_user_id": "string|null",
|
|
148
|
+
"delivery_sequence": "integer|null",
|
|
149
|
+
"delivery_recipients": "string[]|null"
|
|
150
|
+
},
|
|
151
|
+
"ManagedPutReceipt": {
|
|
152
|
+
"id": "string",
|
|
153
|
+
"value": "object",
|
|
154
|
+
"version": "integer|null",
|
|
155
|
+
"created_at?": "string",
|
|
156
|
+
"updated_at?": "string",
|
|
157
|
+
"created_by_user_id?": "string|null",
|
|
158
|
+
"updated_by_user_id?": "string|null",
|
|
159
|
+
"mutation_id": "string",
|
|
160
|
+
"sync_cursor": "string",
|
|
161
|
+
"replayed?": "boolean"
|
|
162
|
+
},
|
|
163
|
+
"ManagedDeleteReceipt": {
|
|
164
|
+
"ok": "boolean",
|
|
165
|
+
"mutation_id": "string",
|
|
166
|
+
"sync_cursor": "string",
|
|
167
|
+
"cascaded?": "DeleteCascade[]",
|
|
168
|
+
"replayed?": "boolean"
|
|
169
|
+
},
|
|
170
|
+
"DeleteCascade": { "collection": "string", "record_id": "string", "sync_cursor": "string" },
|
|
171
|
+
"ManagedDelivery": {
|
|
172
|
+
"id": "string",
|
|
173
|
+
"value": "object",
|
|
174
|
+
"version?": "integer",
|
|
175
|
+
"sequence": "integer",
|
|
176
|
+
"recipients": "string[]",
|
|
177
|
+
"mutation_id": "string",
|
|
178
|
+
"sync_cursor?": "string|null",
|
|
179
|
+
"replayed?": "boolean"
|
|
180
|
+
},
|
|
181
|
+
"TransactionOperation": {
|
|
182
|
+
"action": "put|delete",
|
|
183
|
+
"collection": "string",
|
|
184
|
+
"id": "string",
|
|
185
|
+
"value?": "object",
|
|
186
|
+
"expected_version?": "integer"
|
|
187
|
+
},
|
|
188
|
+
"TransactionOperationResult": {
|
|
189
|
+
"action": "put|delete",
|
|
190
|
+
"collection": "string",
|
|
191
|
+
"id": "string",
|
|
192
|
+
"value?": "object",
|
|
193
|
+
"version?": "integer",
|
|
194
|
+
"created_at?": "string",
|
|
195
|
+
"updated_at?": "string",
|
|
196
|
+
"created_by_user_id?": "string|null",
|
|
197
|
+
"updated_by_user_id?": "string|null",
|
|
198
|
+
"ok?": "boolean",
|
|
199
|
+
"mutation_id": "string",
|
|
200
|
+
"sync_cursor": "string"
|
|
201
|
+
},
|
|
202
|
+
"TransactionCascade": {
|
|
203
|
+
"collection": "string",
|
|
204
|
+
"id": "string",
|
|
205
|
+
"mutation_id": "string",
|
|
206
|
+
"sync_cursor": "string"
|
|
207
|
+
},
|
|
208
|
+
"TransactionResult": {
|
|
209
|
+
"transaction_id": "string",
|
|
210
|
+
"replayed": "boolean",
|
|
211
|
+
"results": "TransactionOperationResult[]",
|
|
212
|
+
"cascaded": "TransactionCascade[]"
|
|
213
|
+
},
|
|
214
|
+
"ManagedRecordChange": {
|
|
215
|
+
"cursor": "string",
|
|
216
|
+
"operation": "put|delete|reset",
|
|
217
|
+
"record_id": "string",
|
|
218
|
+
"mutation_id": "string",
|
|
219
|
+
"committed_version": "integer|null",
|
|
220
|
+
"version": "integer|null",
|
|
221
|
+
"value": "object|null",
|
|
222
|
+
"actor_user_id": "string|null",
|
|
223
|
+
"created_by_user_id": "string|null",
|
|
224
|
+
"updated_by_user_id": "string|null",
|
|
225
|
+
"delivery_sequence": "integer|null",
|
|
226
|
+
"delivery_recipients": "string[]|null",
|
|
227
|
+
"changed_fields": "string[]",
|
|
228
|
+
"created_at": "string|null",
|
|
229
|
+
"committed_at": "string"
|
|
230
|
+
},
|
|
231
|
+
"CollaborationOperationInput": { "id": "string", "operation": "json" },
|
|
232
|
+
"CollaborationOperation": {
|
|
233
|
+
"cursor": "string",
|
|
234
|
+
"id": "string",
|
|
235
|
+
"operation": "json",
|
|
236
|
+
"actor_user_id": "string",
|
|
237
|
+
"actor_session_id": "string",
|
|
238
|
+
"committed_at": "string"
|
|
239
|
+
},
|
|
240
|
+
"EventNotify": { "title": "string", "body?": "string", "route?": "string|null" },
|
|
241
|
+
"WriteNotify": {
|
|
242
|
+
"title": "string",
|
|
243
|
+
"body?": "string",
|
|
244
|
+
"route?": "string|null",
|
|
245
|
+
"audience?": "absent|mentioned"
|
|
246
|
+
},
|
|
247
|
+
"EventPublishResult": {
|
|
248
|
+
"ok?": "boolean",
|
|
249
|
+
"transient?": "boolean",
|
|
250
|
+
"error?": "payload_too_large|rate_limited"
|
|
251
|
+
},
|
|
252
|
+
"EventOrigin": {
|
|
253
|
+
"kind": "member|platform|agent|server",
|
|
254
|
+
"user_id?": "string",
|
|
255
|
+
"role?": "owner|admin|editor|viewer",
|
|
256
|
+
"browser_session_id?": "string",
|
|
257
|
+
"task_id?": "string"
|
|
258
|
+
},
|
|
259
|
+
"AppNotice": {
|
|
260
|
+
"id": "string",
|
|
261
|
+
"kind": "invite|mention|message|notice",
|
|
262
|
+
"title": "string",
|
|
263
|
+
"body": "string",
|
|
264
|
+
"route": "string|null",
|
|
265
|
+
"data": "json",
|
|
266
|
+
"space_id": "string|null",
|
|
267
|
+
"read_at": "string|null",
|
|
268
|
+
"created_at": "string"
|
|
269
|
+
},
|
|
270
|
+
"AppJob": {
|
|
271
|
+
"id": "string",
|
|
272
|
+
"automation": "string",
|
|
273
|
+
"status": "queued|running|waiting|succeeded|failed|cancelled",
|
|
274
|
+
"input": "json",
|
|
275
|
+
"result": "json|null",
|
|
276
|
+
"error": "string|null",
|
|
277
|
+
"attempts": "integer",
|
|
278
|
+
"created_at": "string",
|
|
279
|
+
"finished_at": "string|null"
|
|
280
|
+
},
|
|
281
|
+
"AppSchedule": {
|
|
282
|
+
"name": "string",
|
|
283
|
+
"automation": "string",
|
|
284
|
+
"cron": "string",
|
|
285
|
+
"enabled": "boolean",
|
|
286
|
+
"next_run_at": "string",
|
|
287
|
+
"last_enqueued_at": "string|null",
|
|
288
|
+
"origin": "declared|agent"
|
|
289
|
+
},
|
|
290
|
+
"LifecycleMigration": {
|
|
291
|
+
"from": "integer",
|
|
292
|
+
"to": "integer",
|
|
293
|
+
"status": "pending|running|succeeded|failed|skipped",
|
|
294
|
+
"error": "string|null"
|
|
295
|
+
},
|
|
296
|
+
"ConnectorResponse": {
|
|
297
|
+
"connector": "string",
|
|
298
|
+
"status": "integer",
|
|
299
|
+
"ok": "boolean",
|
|
300
|
+
"content_type": "string",
|
|
301
|
+
"headers": "object",
|
|
302
|
+
"body": "string|null",
|
|
303
|
+
"body_base64": "string|null",
|
|
304
|
+
"observation_id?": "string",
|
|
305
|
+
"resource_grant_id?": "string"
|
|
306
|
+
},
|
|
307
|
+
"ConnectorAction": {
|
|
308
|
+
"status": "integer",
|
|
309
|
+
"ok": "boolean",
|
|
310
|
+
"staged": "boolean",
|
|
311
|
+
"action_id": "string",
|
|
312
|
+
"approval_status": "pending|approved|applying|applied|failed|rejected|needs_reconciliation|canceled",
|
|
313
|
+
"preview?": "object",
|
|
314
|
+
"result?": "json"
|
|
315
|
+
},
|
|
316
|
+
"ExternalServiceInvocation": {
|
|
317
|
+
"invocation_id": "string",
|
|
318
|
+
"status": "integer",
|
|
319
|
+
"content_type": "string",
|
|
320
|
+
"body": "string|null",
|
|
321
|
+
"body_base64": "string|null",
|
|
322
|
+
"billed_credits": "string",
|
|
323
|
+
"platform_fee_credits": "string",
|
|
324
|
+
"developer_earning_credits": "string",
|
|
325
|
+
"metadata?": "ServiceExecutionMetadata"
|
|
326
|
+
},
|
|
327
|
+
"ServiceExecutionMetadata": {
|
|
328
|
+
"contract": "string",
|
|
329
|
+
"provider_service_id": "string",
|
|
330
|
+
"route_revision": "integer",
|
|
331
|
+
"duration_ms": "integer",
|
|
332
|
+
"attempts": "integer",
|
|
333
|
+
"cache": "string"
|
|
334
|
+
},
|
|
335
|
+
"ServiceJob": {
|
|
336
|
+
"job_id": "string",
|
|
337
|
+
"service_id": "string",
|
|
338
|
+
"operation": "string",
|
|
339
|
+
"status": "queued|running|succeeded|failed|cancelled|reconciling",
|
|
340
|
+
"error_code": "string|null",
|
|
341
|
+
"delivery_status": "string|null",
|
|
342
|
+
"cancel_requested": "boolean",
|
|
343
|
+
"created_at": "string",
|
|
344
|
+
"completed_at": "string|null",
|
|
345
|
+
"result_expires_at": "string|null",
|
|
346
|
+
"billing_status": "string",
|
|
347
|
+
"billed_credits": "string",
|
|
348
|
+
"gateway_request_id": "string|null",
|
|
349
|
+
"result_expired": "boolean",
|
|
350
|
+
"result": "json|null",
|
|
351
|
+
"result_access_allowed": "boolean"
|
|
352
|
+
},
|
|
353
|
+
"CollectSubmission": { "id": "string", "deliver_after": "string", "delivered": "boolean" }
|
|
354
|
+
},
|
|
355
|
+
"errors": [
|
|
356
|
+
{
|
|
357
|
+
"code": "bad_request",
|
|
358
|
+
"status": 400,
|
|
359
|
+
"meaning": "The request is malformed: an invalid path, query, header or JSON body, an unknown field, or a value out of range."
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"code": "unauthorized",
|
|
363
|
+
"status": 401,
|
|
364
|
+
"meaning": "No valid app session: the cookie or token is missing or unknown — as in every window of an app whose own sign-out door removed the cookie — or a signed-out guest called a door that needs a person."
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"code": "session_ended",
|
|
368
|
+
"status": 401,
|
|
369
|
+
"meaning": "The app session presented was revoked or has ended — the person signed out of Terminus, or the session expired; the app should stop and say so (opening the app again signs in). The SDK also answers it itself, without a request, on the device that signed out."
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"code": "forbidden",
|
|
373
|
+
"status": 403,
|
|
374
|
+
"meaning": "Authenticated but not allowed: the release did not declare the capability, the member's role or a block forbids it, or a cross-origin mutation."
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"code": "grant_required",
|
|
378
|
+
"status": 403,
|
|
379
|
+
"meaning": "A per-person consent grant is missing (the collect plane's first use); raise the consent ask instead of a plain refusal."
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"code": "not_found",
|
|
383
|
+
"status": 404,
|
|
384
|
+
"meaning": "No such door, space, member, file, record, job, notification or declared resource visible to the caller."
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"code": "not_installed",
|
|
388
|
+
"status": 404,
|
|
389
|
+
"meaning": "The person has no installation of this app, so there is nothing to pause or mute."
|
|
390
|
+
},
|
|
391
|
+
{ "code": "method_not_allowed", "status": 405, "meaning": "The path exists but not with this method." },
|
|
392
|
+
{
|
|
393
|
+
"code": "conflict",
|
|
394
|
+
"status": 409,
|
|
395
|
+
"meaning": "The request conflicts with current state: the app was updated since the session began, a unique or relation constraint, a cursor frontier, a stale snapshot."
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"code": "version_conflict",
|
|
399
|
+
"status": 409,
|
|
400
|
+
"meaning": "A compare-and-set precondition failed: expected_version or expected_sha256 does not match."
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"code": "idempotency_conflict",
|
|
404
|
+
"status": 409,
|
|
405
|
+
"meaning": "The Idempotency-Key (or operation id) was already used for a different request."
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"code": "still_pending",
|
|
409
|
+
"status": 409,
|
|
410
|
+
"meaning": "A request with the same Idempotency-Key is still in flight; retry later with the same key."
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"code": "payload_too_large",
|
|
414
|
+
"status": 413,
|
|
415
|
+
"meaning": "A body, field or fetched resource exceeds its byte limit."
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"code": "unprocessable",
|
|
419
|
+
"status": 422,
|
|
420
|
+
"meaning": "A well-formed write violates a collection's declared validate rules; details carry the rule's message."
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"code": "rate_limited",
|
|
424
|
+
"status": 429,
|
|
425
|
+
"meaning": "A rate limit or daily budget is exhausted; Retry-After says when to try again when known."
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"code": "quota_exceeded",
|
|
429
|
+
"status": 402,
|
|
430
|
+
"meaning": "Credits or storage quota are exhausted for this operation."
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"code": "price_confirmation_required",
|
|
434
|
+
"status": 402,
|
|
435
|
+
"meaning": "A priced action needs the caller to confirm the current price; details.price_credits carries it and nothing was charged."
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"code": "url_not_allowed",
|
|
439
|
+
"status": 400,
|
|
440
|
+
"meaning": "The destination is refused: not a public http(s) URL on a standard port, or it resolves to a private address."
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"code": "upstream_failed",
|
|
444
|
+
"status": 502,
|
|
445
|
+
"meaning": "An upstream the door called (a web site, provider API, service or the app server tier) failed or answered badly."
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"code": "server_disabled",
|
|
449
|
+
"status": 503,
|
|
450
|
+
"meaning": "App server code is switched off on this deployment."
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"code": "server_unavailable",
|
|
454
|
+
"status": 503,
|
|
455
|
+
"meaning": "The app server tier is not configured or cannot be reached."
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"code": "service_unavailable",
|
|
459
|
+
"status": 503,
|
|
460
|
+
"meaning": "The platform is busy (admission refused, Retry-After set) or a dependency is unavailable."
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
"code": "deadline_exceeded",
|
|
464
|
+
"status": 504,
|
|
465
|
+
"meaning": "The door or its upstream did not finish within its deadline."
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"code": "not_implemented",
|
|
469
|
+
"status": 501,
|
|
470
|
+
"meaning": "The host cannot serve this capability (for example no object storage, or a connector without a generic API adapter)."
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"code": "unsupported_in_dev",
|
|
474
|
+
"status": 501,
|
|
475
|
+
"meaning": "terminus dev cannot serve this door; exercise it against a real host. Only terminus dev answers it."
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
"code": "internal_error",
|
|
479
|
+
"status": 500,
|
|
480
|
+
"meaning": "An unexpected server error. Safe to retry an idempotent request."
|
|
481
|
+
}
|
|
482
|
+
],
|
|
483
|
+
"limits": {
|
|
484
|
+
"default_body_bytes": 262144,
|
|
485
|
+
"transaction_operations": 64,
|
|
486
|
+
"transaction_body_bytes": 1048576,
|
|
487
|
+
"deliver_body_bytes": 262144,
|
|
488
|
+
"record_value_bytes": 131072,
|
|
489
|
+
"record_put_body_bytes": 262144,
|
|
490
|
+
"record_id_pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$",
|
|
491
|
+
"where_bytes": 16384,
|
|
492
|
+
"page_size": 200,
|
|
493
|
+
"event_batch": 16,
|
|
494
|
+
"mentions": 8,
|
|
495
|
+
"event_payload_bytes": 32768,
|
|
496
|
+
"presence_state_bytes": 4096,
|
|
497
|
+
"publish_durable_per_minute": 240,
|
|
498
|
+
"publish_transient_per_minute": 1200,
|
|
499
|
+
"collaboration_batch_operations": 64,
|
|
500
|
+
"collaboration_body_bytes": 262144,
|
|
501
|
+
"bucket_object_bytes": 8388608,
|
|
502
|
+
"data_object_bytes": 12582912,
|
|
503
|
+
"net_fetch_bytes": 524288,
|
|
504
|
+
"net_image_bytes": 5242880,
|
|
505
|
+
"notification_title_chars": 160,
|
|
506
|
+
"notification_body_chars": 2000,
|
|
507
|
+
"notification_route_chars": 500,
|
|
508
|
+
"log_message_chars": 2000,
|
|
509
|
+
"logs_per_minute": 60,
|
|
510
|
+
"notification_pause_days": 31,
|
|
511
|
+
"delivery_recipients": 50,
|
|
512
|
+
"space_meta_bytes": 4096,
|
|
513
|
+
"collections_per_release": 32,
|
|
514
|
+
"idempotency_key_chars": 200,
|
|
515
|
+
"collection_definition_bytes": 32768,
|
|
516
|
+
"space_name_chars": 120,
|
|
517
|
+
"notification_data_bytes": 32768,
|
|
518
|
+
"log_detail_bytes": 65536,
|
|
519
|
+
"job_input_bytes": 262144,
|
|
520
|
+
"collect_payload_bytes": 65536,
|
|
521
|
+
"collect_submissions_per_day": 100,
|
|
522
|
+
"connector_body_bytes": 2097152,
|
|
523
|
+
"connector_response_bytes": 2097152,
|
|
524
|
+
"service_body_bytes": 12582912,
|
|
525
|
+
"capability_operation_body_bytes": 1048576,
|
|
526
|
+
"egress_calls_per_day": 500,
|
|
527
|
+
"server_op_sync_ms": 10000,
|
|
528
|
+
"changes_batch": 500,
|
|
529
|
+
"user_search_results": 8
|
|
530
|
+
},
|
|
531
|
+
"doors": [
|
|
532
|
+
{
|
|
533
|
+
"id": "session.bootstrap",
|
|
534
|
+
"method": "GET",
|
|
535
|
+
"also_head": true,
|
|
536
|
+
"path": "/bootstrap",
|
|
537
|
+
"upstream": "/v1/app-runtime/session/current",
|
|
538
|
+
"summary": "The app's own view of this session, trimmed to what is read (D23): the runtime major, the guest flag, the app, the installation and release the session is pinned to, the signed-in person and their data grants. On an app open to guests the app host answers it for a signed-out visitor itself (guest true, installation and user null, no grants). The SDK refuses a platform_api_version other than its own.",
|
|
539
|
+
"auth": "app_session",
|
|
540
|
+
"guest_allowed": true,
|
|
541
|
+
"space_id": "none",
|
|
542
|
+
"idempotency": "none",
|
|
543
|
+
"body": "none",
|
|
544
|
+
"body_limit_bytes": null,
|
|
545
|
+
"lane": "interactive",
|
|
546
|
+
"query": {},
|
|
547
|
+
"request": {},
|
|
548
|
+
"response": {
|
|
549
|
+
"kind": "json",
|
|
550
|
+
"fields": {
|
|
551
|
+
"platform_api_version": "integer",
|
|
552
|
+
"guest": "boolean",
|
|
553
|
+
"app": "BootstrapApp",
|
|
554
|
+
"installation": "BootstrapInstallation|null",
|
|
555
|
+
"user": "PublicUser|null",
|
|
556
|
+
"data": "BootstrapData"
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
"response_headers": [],
|
|
560
|
+
"errors": ["session_ended", "unauthorized"],
|
|
561
|
+
"hosts": { "production": true, "dev": true },
|
|
562
|
+
"sdk": ["ready"]
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
"id": "session.identity",
|
|
566
|
+
"method": "GET",
|
|
567
|
+
"path": null,
|
|
568
|
+
"upstream": "/v1/app-runtime/session/identity",
|
|
569
|
+
"summary": "Worker only, never reachable from app code (D20): who a session is, answered from the session cache with no manifest, grant or avatar query. The app host calls it before serving a release asset (the identity keys the asset cache) and in /_terminus/open; network_domains and runtime_policy are the inputs of the HTML page's Content-Security-Policy, derived from the pinned release's capabilities.",
|
|
570
|
+
"auth": "worker",
|
|
571
|
+
"guest_allowed": false,
|
|
572
|
+
"space_id": "none",
|
|
573
|
+
"idempotency": "none",
|
|
574
|
+
"body": "none",
|
|
575
|
+
"body_limit_bytes": null,
|
|
576
|
+
"lane": "interactive",
|
|
577
|
+
"query": {},
|
|
578
|
+
"request": {},
|
|
579
|
+
"response": {
|
|
580
|
+
"kind": "json",
|
|
581
|
+
"fields": {
|
|
582
|
+
"app_id": "string",
|
|
583
|
+
"installation_id": "string",
|
|
584
|
+
"release_id": "string",
|
|
585
|
+
"user_id": "string|null",
|
|
586
|
+
"guest": "boolean",
|
|
587
|
+
"network_domains": "string[]",
|
|
588
|
+
"runtime_policy": "RuntimePolicy"
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
"response_headers": [],
|
|
592
|
+
"errors": ["session_ended", "unauthorized"],
|
|
593
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
594
|
+
"sdk": []
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
"id": "users.lookup",
|
|
598
|
+
"method": "GET",
|
|
599
|
+
"path": "/users/lookup",
|
|
600
|
+
"upstream": "/v1/app-runtime/users/lookup",
|
|
601
|
+
"summary": "Resolves one exact handle (1-64 characters, leading @ ignored) to a public identity.",
|
|
602
|
+
"auth": "app_session",
|
|
603
|
+
"guest_allowed": false,
|
|
604
|
+
"space_id": "none",
|
|
605
|
+
"idempotency": "none",
|
|
606
|
+
"body": "none",
|
|
607
|
+
"body_limit_bytes": null,
|
|
608
|
+
"lane": "interactive",
|
|
609
|
+
"query": { "handle": "string" },
|
|
610
|
+
"request": {},
|
|
611
|
+
"response": { "kind": "json", "fields": { "$body": "PublicUser" } },
|
|
612
|
+
"response_headers": [],
|
|
613
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
614
|
+
"hosts": { "production": true, "dev": true },
|
|
615
|
+
"sdk": ["users.lookup"]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
"id": "users.search",
|
|
619
|
+
"method": "GET",
|
|
620
|
+
"path": "/users/search",
|
|
621
|
+
"upstream": "/v1/app-runtime/users/search",
|
|
622
|
+
"summary": "Prefix typeahead over active people's handles and display names for recipient pickers: at most 8, never the caller; a query shorter than 2 or longer than 64 characters answers no users.",
|
|
623
|
+
"auth": "app_session",
|
|
624
|
+
"guest_allowed": false,
|
|
625
|
+
"space_id": "none",
|
|
626
|
+
"idempotency": "none",
|
|
627
|
+
"body": "none",
|
|
628
|
+
"body_limit_bytes": null,
|
|
629
|
+
"lane": "interactive",
|
|
630
|
+
"query": { "q": "string" },
|
|
631
|
+
"request": {},
|
|
632
|
+
"response": { "kind": "json", "fields": { "users": "PublicUser[]" } },
|
|
633
|
+
"response_headers": [],
|
|
634
|
+
"errors": ["session_ended", "unauthorized"],
|
|
635
|
+
"hosts": { "production": true, "dev": true },
|
|
636
|
+
"sdk": ["users.search"]
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"id": "users.avatar",
|
|
640
|
+
"method": "GET",
|
|
641
|
+
"path": "/users/{user_id}/avatar",
|
|
642
|
+
"upstream": "/v1/app-runtime/users/{user_id}/avatar",
|
|
643
|
+
"summary": "A person's avatar image: the target of PublicUser.avatar_url, which carries a version query, so the answer is cached as immutable.",
|
|
644
|
+
"auth": "app_session",
|
|
645
|
+
"guest_allowed": false,
|
|
646
|
+
"space_id": "none",
|
|
647
|
+
"idempotency": "none",
|
|
648
|
+
"body": "none",
|
|
649
|
+
"body_limit_bytes": null,
|
|
650
|
+
"lane": "interactive",
|
|
651
|
+
"query": {},
|
|
652
|
+
"request": {},
|
|
653
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
654
|
+
"response_headers": ["cache-control", "content-type"],
|
|
655
|
+
"errors": ["not_found", "session_ended", "unauthorized"],
|
|
656
|
+
"hosts": { "production": true, "dev": true },
|
|
657
|
+
"sdk": []
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
"id": "users.profile",
|
|
661
|
+
"method": "GET",
|
|
662
|
+
"path": "/users/{handle}/profile",
|
|
663
|
+
"upstream": "/v1/app-runtime/users/{handle}/profile",
|
|
664
|
+
"summary": "The target of PublicUser.public_profile_url: a temporary redirect to the person's public profile page on the platform (the app host passes the redirect through rather than following it).",
|
|
665
|
+
"auth": "app_session",
|
|
666
|
+
"guest_allowed": false,
|
|
667
|
+
"space_id": "none",
|
|
668
|
+
"idempotency": "none",
|
|
669
|
+
"body": "none",
|
|
670
|
+
"body_limit_bytes": null,
|
|
671
|
+
"lane": "interactive",
|
|
672
|
+
"query": {},
|
|
673
|
+
"request": {},
|
|
674
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
675
|
+
"response_headers": ["location"],
|
|
676
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
677
|
+
"hosts": { "production": true, "dev": true },
|
|
678
|
+
"sdk": []
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
"id": "spaces.list",
|
|
682
|
+
"method": "GET",
|
|
683
|
+
"path": "/spaces",
|
|
684
|
+
"upstream": "/v1/app-runtime/spaces",
|
|
685
|
+
"summary": "The spaces bound to this app that the caller is a member of, most recently updated first, at most 200 (D27; replaces /spaces/installations). A direct space's peer is its other member — or, until they answer, the person invited — and null for a group, or once nobody else is in it or invited.",
|
|
686
|
+
"auth": "app_session",
|
|
687
|
+
"guest_allowed": false,
|
|
688
|
+
"space_id": "none",
|
|
689
|
+
"idempotency": "none",
|
|
690
|
+
"body": "none",
|
|
691
|
+
"body_limit_bytes": null,
|
|
692
|
+
"lane": "interactive",
|
|
693
|
+
"query": {},
|
|
694
|
+
"request": {},
|
|
695
|
+
"response": { "kind": "json", "fields": { "spaces": "Space[]" } },
|
|
696
|
+
"response_headers": [],
|
|
697
|
+
"errors": ["session_ended", "unauthorized"],
|
|
698
|
+
"hosts": { "production": true, "dev": true },
|
|
699
|
+
"sdk": ["spaces.list", "spaces.live"]
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
"id": "spaces.create",
|
|
703
|
+
"method": "POST",
|
|
704
|
+
"path": "/spaces",
|
|
705
|
+
"upstream": "/v1/app-runtime/spaces",
|
|
706
|
+
"summary": "Opens a space bound to this app with the caller as owner and invites everyone named — membership is only ever the invitee's own answer. One transaction: space, app binding and invitations; a bad handle creates nothing. The caller hears space_membership_joined for the new space on their account stream, so every one of their windows lists it. kind defaults to group; a direct space names exactly one other person and neither may have blocked the other; a group may name nobody yet. name is 1-120 characters (\"New space\" when omitted). parent_id names a space bound to the same app that the caller is a member of. meta is an app-defined JSON object of at most 4096 serialized bytes that every member can read. 409 conflict while the session's release is not the app's published release.",
|
|
707
|
+
"auth": "app_session",
|
|
708
|
+
"guest_allowed": false,
|
|
709
|
+
"space_id": "none",
|
|
710
|
+
"idempotency": "none",
|
|
711
|
+
"body": "json",
|
|
712
|
+
"body_limit_bytes": 262144,
|
|
713
|
+
"lane": "interactive",
|
|
714
|
+
"query": {},
|
|
715
|
+
"request": {
|
|
716
|
+
"name?": "string",
|
|
717
|
+
"kind?": "direct|group",
|
|
718
|
+
"member_handles": "string[]",
|
|
719
|
+
"parent_id?": "string",
|
|
720
|
+
"meta?": "object"
|
|
721
|
+
},
|
|
722
|
+
"response": { "kind": "json", "fields": { "space": "Space", "invitations": "SpaceInviteReceipt[]" } },
|
|
723
|
+
"response_headers": [],
|
|
724
|
+
"errors": [
|
|
725
|
+
"bad_request",
|
|
726
|
+
"conflict",
|
|
727
|
+
"forbidden",
|
|
728
|
+
"not_found",
|
|
729
|
+
"payload_too_large",
|
|
730
|
+
"session_ended",
|
|
731
|
+
"unauthorized"
|
|
732
|
+
],
|
|
733
|
+
"hosts": { "production": true, "dev": true },
|
|
734
|
+
"sdk": ["spaces.create"]
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"id": "spaces.update",
|
|
738
|
+
"method": "PATCH",
|
|
739
|
+
"path": "/spaces/{space_id}",
|
|
740
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}",
|
|
741
|
+
"summary": "Renames a space or replaces its meta (D2): name is for groups only, by the owner or an admin; meta is changed by the owner or an admin in a group and by either member in a direct space; null clears meta. At least one field. Members hear space_conversation_updated.",
|
|
742
|
+
"auth": "app_session",
|
|
743
|
+
"guest_allowed": false,
|
|
744
|
+
"space_id": "path",
|
|
745
|
+
"idempotency": "none",
|
|
746
|
+
"body": "json",
|
|
747
|
+
"body_limit_bytes": 262144,
|
|
748
|
+
"lane": "interactive",
|
|
749
|
+
"query": {},
|
|
750
|
+
"request": { "name?": "string", "meta?": "object|null" },
|
|
751
|
+
"response": { "kind": "json", "fields": { "space": "Space" } },
|
|
752
|
+
"response_headers": [],
|
|
753
|
+
"errors": [
|
|
754
|
+
"bad_request",
|
|
755
|
+
"forbidden",
|
|
756
|
+
"not_found",
|
|
757
|
+
"payload_too_large",
|
|
758
|
+
"session_ended",
|
|
759
|
+
"unauthorized"
|
|
760
|
+
],
|
|
761
|
+
"hosts": { "production": true, "dev": true },
|
|
762
|
+
"sdk": ["spaces.update"]
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
"id": "spaces.delete",
|
|
766
|
+
"method": "DELETE",
|
|
767
|
+
"path": "/spaces/{space_id}",
|
|
768
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}",
|
|
769
|
+
"summary": "Owner only (D2): deletes the space and all of its app data for every member; each member hears space_deleted on their account stream. 409 conflict while child spaces (parent_id = this space) exist; 429 rate_limited when another write holds the space's lock past its wait.",
|
|
770
|
+
"auth": "app_session",
|
|
771
|
+
"guest_allowed": false,
|
|
772
|
+
"space_id": "path",
|
|
773
|
+
"idempotency": "none",
|
|
774
|
+
"body": "none",
|
|
775
|
+
"body_limit_bytes": null,
|
|
776
|
+
"lane": "interactive",
|
|
777
|
+
"query": {},
|
|
778
|
+
"request": {},
|
|
779
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
780
|
+
"response_headers": [],
|
|
781
|
+
"errors": ["conflict", "forbidden", "not_found", "rate_limited", "session_ended", "unauthorized"],
|
|
782
|
+
"hosts": { "production": true, "dev": true },
|
|
783
|
+
"sdk": ["spaces.delete"]
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
"id": "spaces.members",
|
|
787
|
+
"method": "GET",
|
|
788
|
+
"path": "/spaces/{space_id}/members",
|
|
789
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/members",
|
|
790
|
+
"summary": "The space's members: the owner, then admins, editors and viewers, each by handle.",
|
|
791
|
+
"auth": "app_session",
|
|
792
|
+
"guest_allowed": false,
|
|
793
|
+
"space_id": "path",
|
|
794
|
+
"idempotency": "none",
|
|
795
|
+
"body": "none",
|
|
796
|
+
"body_limit_bytes": null,
|
|
797
|
+
"lane": "interactive",
|
|
798
|
+
"query": {},
|
|
799
|
+
"request": {},
|
|
800
|
+
"response": { "kind": "json", "fields": { "members": "SpaceMember[]" } },
|
|
801
|
+
"response_headers": [],
|
|
802
|
+
"errors": ["not_found", "session_ended", "unauthorized"],
|
|
803
|
+
"hosts": { "production": true, "dev": true },
|
|
804
|
+
"sdk": ["spaces.members", "spaces.liveMembers"]
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"id": "spaces.invite",
|
|
808
|
+
"method": "POST",
|
|
809
|
+
"path": "/spaces/{space_id}/members",
|
|
810
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/members",
|
|
811
|
+
"summary": "Always an invitation, never direct membership: groups only, by the owner or an admin; only the owner invites an admin; a space holds at most 50 people. created is false when a pending invitation already existed; 409 conflict when the person is already a member. The invitee is told through the platform's invitation notice.",
|
|
812
|
+
"auth": "app_session",
|
|
813
|
+
"guest_allowed": false,
|
|
814
|
+
"space_id": "path",
|
|
815
|
+
"idempotency": "none",
|
|
816
|
+
"body": "json",
|
|
817
|
+
"body_limit_bytes": 262144,
|
|
818
|
+
"lane": "interactive",
|
|
819
|
+
"query": {},
|
|
820
|
+
"request": { "handle": "string", "role?": "admin|editor|viewer" },
|
|
821
|
+
"response": { "kind": "json", "fields": { "invitation": "SpaceInviteReceipt" } },
|
|
822
|
+
"response_headers": [],
|
|
823
|
+
"errors": [
|
|
824
|
+
"bad_request",
|
|
825
|
+
"conflict",
|
|
826
|
+
"forbidden",
|
|
827
|
+
"not_found",
|
|
828
|
+
"payload_too_large",
|
|
829
|
+
"session_ended",
|
|
830
|
+
"unauthorized"
|
|
831
|
+
],
|
|
832
|
+
"hosts": { "production": true, "dev": true },
|
|
833
|
+
"sdk": ["spaces.invite"]
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
"id": "spaces.update_member",
|
|
837
|
+
"method": "PATCH",
|
|
838
|
+
"path": "/spaces/{space_id}/members/{member_id}",
|
|
839
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/members/{member_id}",
|
|
840
|
+
"summary": "Changes a member's role in a group: by the owner or an admin; the owner's role never changes and only the owner manages admins.",
|
|
841
|
+
"auth": "app_session",
|
|
842
|
+
"guest_allowed": false,
|
|
843
|
+
"space_id": "path",
|
|
844
|
+
"idempotency": "none",
|
|
845
|
+
"body": "json",
|
|
846
|
+
"body_limit_bytes": 262144,
|
|
847
|
+
"lane": "interactive",
|
|
848
|
+
"query": {},
|
|
849
|
+
"request": { "role": "admin|editor|viewer" },
|
|
850
|
+
"response": { "kind": "json", "fields": { "member": "SpaceMember" } },
|
|
851
|
+
"response_headers": [],
|
|
852
|
+
"errors": [
|
|
853
|
+
"bad_request",
|
|
854
|
+
"forbidden",
|
|
855
|
+
"not_found",
|
|
856
|
+
"payload_too_large",
|
|
857
|
+
"session_ended",
|
|
858
|
+
"unauthorized"
|
|
859
|
+
],
|
|
860
|
+
"hosts": { "production": true, "dev": true },
|
|
861
|
+
"sdk": ["spaces.updateMember"]
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
"id": "spaces.remove_member",
|
|
865
|
+
"method": "DELETE",
|
|
866
|
+
"path": "/spaces/{space_id}/members/{member_id}",
|
|
867
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/members/{member_id}",
|
|
868
|
+
"summary": "Removes a member from a group: by the owner or an admin, never the owner, and only the owner removes an admin. Their access ends at once and they hear space_membership_left.",
|
|
869
|
+
"auth": "app_session",
|
|
870
|
+
"guest_allowed": false,
|
|
871
|
+
"space_id": "path",
|
|
872
|
+
"idempotency": "none",
|
|
873
|
+
"body": "none",
|
|
874
|
+
"body_limit_bytes": null,
|
|
875
|
+
"lane": "interactive",
|
|
876
|
+
"query": {},
|
|
877
|
+
"request": {},
|
|
878
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
879
|
+
"response_headers": [],
|
|
880
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
881
|
+
"hosts": { "production": true, "dev": true },
|
|
882
|
+
"sdk": ["spaces.removeMember"]
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
"id": "spaces.leave",
|
|
886
|
+
"method": "DELETE",
|
|
887
|
+
"path": "/spaces/{space_id}/membership",
|
|
888
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/membership",
|
|
889
|
+
"summary": "The caller leaves a group; anyone but the owner.",
|
|
890
|
+
"auth": "app_session",
|
|
891
|
+
"guest_allowed": false,
|
|
892
|
+
"space_id": "path",
|
|
893
|
+
"idempotency": "none",
|
|
894
|
+
"body": "none",
|
|
895
|
+
"body_limit_bytes": null,
|
|
896
|
+
"lane": "interactive",
|
|
897
|
+
"query": {},
|
|
898
|
+
"request": {},
|
|
899
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
900
|
+
"response_headers": [],
|
|
901
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
902
|
+
"hosts": { "production": true, "dev": true },
|
|
903
|
+
"sdk": ["spaces.leave"]
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
"id": "spaces.invitations",
|
|
907
|
+
"method": "GET",
|
|
908
|
+
"path": "/spaces/{space_id}/invitations",
|
|
909
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/invitations",
|
|
910
|
+
"summary": "The space's pending, unexpired invitations for a member's roster UI, oldest first, at most 200. Invitees are not members: they are never recipients, cursors or presence.",
|
|
911
|
+
"auth": "app_session",
|
|
912
|
+
"guest_allowed": false,
|
|
913
|
+
"space_id": "path",
|
|
914
|
+
"idempotency": "none",
|
|
915
|
+
"body": "none",
|
|
916
|
+
"body_limit_bytes": null,
|
|
917
|
+
"lane": "interactive",
|
|
918
|
+
"query": {},
|
|
919
|
+
"request": {},
|
|
920
|
+
"response": { "kind": "json", "fields": { "invitations": "SpaceInvitation[]" } },
|
|
921
|
+
"response_headers": [],
|
|
922
|
+
"errors": ["not_found", "session_ended", "unauthorized"],
|
|
923
|
+
"hosts": { "production": true, "dev": true },
|
|
924
|
+
"sdk": ["spaces.invitations"]
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
"id": "spaces.block_peer",
|
|
928
|
+
"method": "POST",
|
|
929
|
+
"path": "/spaces/{space_id}/block",
|
|
930
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/block",
|
|
931
|
+
"summary": "Blocks the other person of a direct space (direct spaces only; 409 conflict unless it has exactly one peer). While either person blocks the other the space takes no events, cursors or messages.",
|
|
932
|
+
"auth": "app_session",
|
|
933
|
+
"guest_allowed": false,
|
|
934
|
+
"space_id": "path",
|
|
935
|
+
"idempotency": "none",
|
|
936
|
+
"body": "none",
|
|
937
|
+
"body_limit_bytes": null,
|
|
938
|
+
"lane": "interactive",
|
|
939
|
+
"query": {},
|
|
940
|
+
"request": {},
|
|
941
|
+
"response": { "kind": "json", "fields": { "ok": "boolean", "peer_user_id": "string" } },
|
|
942
|
+
"response_headers": [],
|
|
943
|
+
"errors": ["bad_request", "conflict", "not_found", "session_ended", "unauthorized"],
|
|
944
|
+
"hosts": { "production": true, "dev": true },
|
|
945
|
+
"sdk": ["spaces.blockPeer"]
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
"id": "spaces.unblock_peer",
|
|
949
|
+
"method": "DELETE",
|
|
950
|
+
"path": "/spaces/{space_id}/block",
|
|
951
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/block",
|
|
952
|
+
"summary": "Lifts the caller's block of the other person of a direct space.",
|
|
953
|
+
"auth": "app_session",
|
|
954
|
+
"guest_allowed": false,
|
|
955
|
+
"space_id": "path",
|
|
956
|
+
"idempotency": "none",
|
|
957
|
+
"body": "none",
|
|
958
|
+
"body_limit_bytes": null,
|
|
959
|
+
"lane": "interactive",
|
|
960
|
+
"query": {},
|
|
961
|
+
"request": {},
|
|
962
|
+
"response": { "kind": "json", "fields": { "ok": "boolean", "peer_user_id": "string" } },
|
|
963
|
+
"response_headers": [],
|
|
964
|
+
"errors": ["bad_request", "conflict", "not_found", "session_ended", "unauthorized"],
|
|
965
|
+
"hosts": { "production": true, "dev": true },
|
|
966
|
+
"sdk": ["spaces.unblockPeer"]
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
"id": "spaces.cursors",
|
|
970
|
+
"method": "GET",
|
|
971
|
+
"path": "/spaces/{space_id}/cursor",
|
|
972
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/cursor",
|
|
973
|
+
"summary": "Delivery and read high-water marks per member against the space's delivery sequence head (former members keep their row with role null).",
|
|
974
|
+
"auth": "app_session",
|
|
975
|
+
"guest_allowed": false,
|
|
976
|
+
"space_id": "path",
|
|
977
|
+
"idempotency": "none",
|
|
978
|
+
"body": "none",
|
|
979
|
+
"body_limit_bytes": null,
|
|
980
|
+
"lane": "interactive",
|
|
981
|
+
"query": {},
|
|
982
|
+
"request": {},
|
|
983
|
+
"response": {
|
|
984
|
+
"kind": "json",
|
|
985
|
+
"fields": { "head_sequence": "integer", "members": "SpaceCursorMember[]" }
|
|
986
|
+
},
|
|
987
|
+
"response_headers": [],
|
|
988
|
+
"errors": ["not_found", "session_ended", "unauthorized"],
|
|
989
|
+
"hosts": { "production": true, "dev": true },
|
|
990
|
+
"sdk": ["spaces.cursors", "spaces.liveCursors"]
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
"id": "spaces.update_cursor",
|
|
994
|
+
"method": "PUT",
|
|
995
|
+
"path": "/spaces/{space_id}/cursor",
|
|
996
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/cursor",
|
|
997
|
+
"summary": "Advances the caller's delivered/read marks; marks never move back and read <= delivered <= head (409 conflict otherwise). At least one field. Members hear space_cursor_updated only when a mark actually advanced.",
|
|
998
|
+
"auth": "app_session",
|
|
999
|
+
"guest_allowed": false,
|
|
1000
|
+
"space_id": "path",
|
|
1001
|
+
"idempotency": "none",
|
|
1002
|
+
"body": "json",
|
|
1003
|
+
"body_limit_bytes": 262144,
|
|
1004
|
+
"lane": "interactive",
|
|
1005
|
+
"query": {},
|
|
1006
|
+
"request": { "delivered_through?": "integer", "read_through?": "integer" },
|
|
1007
|
+
"response": {
|
|
1008
|
+
"kind": "json",
|
|
1009
|
+
"fields": { "delivered_through": "integer", "read_through": "integer", "head_sequence": "integer" }
|
|
1010
|
+
},
|
|
1011
|
+
"response_headers": [],
|
|
1012
|
+
"errors": [
|
|
1013
|
+
"bad_request",
|
|
1014
|
+
"conflict",
|
|
1015
|
+
"forbidden",
|
|
1016
|
+
"not_found",
|
|
1017
|
+
"payload_too_large",
|
|
1018
|
+
"session_ended",
|
|
1019
|
+
"unauthorized"
|
|
1020
|
+
],
|
|
1021
|
+
"hosts": { "production": true, "dev": true },
|
|
1022
|
+
"sdk": ["spaces.updateCursor"]
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
"id": "spaces.mute",
|
|
1026
|
+
"method": "PUT",
|
|
1027
|
+
"path": "/spaces/{space_id}/mute",
|
|
1028
|
+
"upstream": "/v1/app-runtime/spaces/{space_id}/mute",
|
|
1029
|
+
"summary": "Mutes a space's message rings for the caller (true), lets it ring (false) or follows their default for the app (null); mentions, invitations and the app's own notices ring either way; nobody else can see it. Answers whether it is now muted; the caller's other windows hear space_notifications_updated.",
|
|
1030
|
+
"auth": "app_session",
|
|
1031
|
+
"guest_allowed": false,
|
|
1032
|
+
"space_id": "path",
|
|
1033
|
+
"idempotency": "none",
|
|
1034
|
+
"body": "json",
|
|
1035
|
+
"body_limit_bytes": 262144,
|
|
1036
|
+
"lane": "interactive",
|
|
1037
|
+
"query": {},
|
|
1038
|
+
"request": { "muted": "boolean|null" },
|
|
1039
|
+
"response": { "kind": "json", "fields": { "muted": "boolean" } },
|
|
1040
|
+
"response_headers": [],
|
|
1041
|
+
"errors": ["bad_request", "not_found", "payload_too_large", "session_ended", "unauthorized"],
|
|
1042
|
+
"hosts": { "production": true, "dev": true },
|
|
1043
|
+
"sdk": ["notifications.mute"]
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
"id": "data.list",
|
|
1047
|
+
"method": "GET",
|
|
1048
|
+
"path": "/data",
|
|
1049
|
+
"upstream": "/v1/app-runtime/data",
|
|
1050
|
+
"summary": "The caller's files under prefix, paths relative to the zone root, ordered by path: zone private (the default) is the app's own area, output is the person's deliverables. With space_id the door addresses the caller's own member shard in that space (D4; zone must be private). limit defaults to 100, at most 200.",
|
|
1051
|
+
"auth": "app_session",
|
|
1052
|
+
"guest_allowed": false,
|
|
1053
|
+
"space_id": "query",
|
|
1054
|
+
"idempotency": "none",
|
|
1055
|
+
"body": "none",
|
|
1056
|
+
"body_limit_bytes": null,
|
|
1057
|
+
"lane": "interactive",
|
|
1058
|
+
"query": {
|
|
1059
|
+
"zone?": "private|output",
|
|
1060
|
+
"prefix?": "string",
|
|
1061
|
+
"space_id?": "string",
|
|
1062
|
+
"after?": "string",
|
|
1063
|
+
"limit?": "integer"
|
|
1064
|
+
},
|
|
1065
|
+
"request": {},
|
|
1066
|
+
"response": { "kind": "json", "fields": { "files": "FileEntry[]", "next_cursor": "string|null" } },
|
|
1067
|
+
"response_headers": [],
|
|
1068
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1069
|
+
"hosts": { "production": true, "dev": true },
|
|
1070
|
+
"sdk": ["files.list"]
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
"id": "data.read",
|
|
1074
|
+
"method": "GET",
|
|
1075
|
+
"also_head": true,
|
|
1076
|
+
"path": "/data/object",
|
|
1077
|
+
"upstream": "/v1/app-runtime/data/object",
|
|
1078
|
+
"summary": "One file's bytes under its stored media type; the ETag is its quoted sha256, x-terminus-data-version its version, and a file derived from a connector observation names it with its provenance (restricted or declassified). HEAD answers the headers alone.",
|
|
1079
|
+
"auth": "app_session",
|
|
1080
|
+
"guest_allowed": false,
|
|
1081
|
+
"space_id": "query",
|
|
1082
|
+
"idempotency": "none",
|
|
1083
|
+
"body": "none",
|
|
1084
|
+
"body_limit_bytes": null,
|
|
1085
|
+
"lane": "interactive",
|
|
1086
|
+
"query": { "path": "string", "zone?": "private|output", "space_id?": "string" },
|
|
1087
|
+
"request": {},
|
|
1088
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
1089
|
+
"response_headers": [
|
|
1090
|
+
"content-type",
|
|
1091
|
+
"etag",
|
|
1092
|
+
"x-terminus-data-version",
|
|
1093
|
+
"x-terminus-schema-id",
|
|
1094
|
+
"x-terminus-schema-version",
|
|
1095
|
+
"x-terminus-observation-id",
|
|
1096
|
+
"x-terminus-provenance"
|
|
1097
|
+
],
|
|
1098
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1099
|
+
"hosts": { "production": true, "dev": true },
|
|
1100
|
+
"sdk": ["files.read", "files.readBlob", "files.stat"]
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
"id": "data.write",
|
|
1104
|
+
"method": "PUT",
|
|
1105
|
+
"path": "/data/object",
|
|
1106
|
+
"upstream": "/v1/app-runtime/data/object",
|
|
1107
|
+
"summary": "Writes one file from the raw body, storing the request Content-Type as its media type (D15). expected_sha256=missing requires that the path does not exist; any other value must equal its current sha256 (409 version_conflict otherwise). observation_id attaches verified connector provenance. Paths under buckets/ are refused in the private zone with 400 bad_request (they belong to storage buckets). 402 quota_exceeded when the person's storage is full.",
|
|
1108
|
+
"auth": "app_session",
|
|
1109
|
+
"guest_allowed": false,
|
|
1110
|
+
"space_id": "query",
|
|
1111
|
+
"idempotency": "none",
|
|
1112
|
+
"body": "bytes",
|
|
1113
|
+
"body_limit_bytes": 12582912,
|
|
1114
|
+
"lane": "interactive",
|
|
1115
|
+
"query": {
|
|
1116
|
+
"path": "string",
|
|
1117
|
+
"zone?": "private|output",
|
|
1118
|
+
"space_id?": "string",
|
|
1119
|
+
"expected_sha256?": "string",
|
|
1120
|
+
"schema_id?": "string",
|
|
1121
|
+
"schema_version?": "integer",
|
|
1122
|
+
"observation_id?": "string"
|
|
1123
|
+
},
|
|
1124
|
+
"request": {},
|
|
1125
|
+
"response": { "kind": "json", "fields": { "$body": "WriteReceipt" } },
|
|
1126
|
+
"response_headers": [],
|
|
1127
|
+
"errors": [
|
|
1128
|
+
"bad_request",
|
|
1129
|
+
"forbidden",
|
|
1130
|
+
"not_found",
|
|
1131
|
+
"payload_too_large",
|
|
1132
|
+
"quota_exceeded",
|
|
1133
|
+
"session_ended",
|
|
1134
|
+
"unauthorized",
|
|
1135
|
+
"version_conflict"
|
|
1136
|
+
],
|
|
1137
|
+
"hosts": { "production": true, "dev": true },
|
|
1138
|
+
"sdk": ["files.write"]
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
"id": "data.delete",
|
|
1142
|
+
"method": "DELETE",
|
|
1143
|
+
"path": "/data/object",
|
|
1144
|
+
"upstream": "/v1/app-runtime/data/object",
|
|
1145
|
+
"summary": "Removes one file; expected_sha256, when given, must equal its current sha256 (409 version_conflict otherwise); expected_sha256=missing is 400 bad_request, since a delete needs something to delete.",
|
|
1146
|
+
"auth": "app_session",
|
|
1147
|
+
"guest_allowed": false,
|
|
1148
|
+
"space_id": "query",
|
|
1149
|
+
"idempotency": "none",
|
|
1150
|
+
"body": "none",
|
|
1151
|
+
"body_limit_bytes": null,
|
|
1152
|
+
"lane": "interactive",
|
|
1153
|
+
"query": {
|
|
1154
|
+
"path": "string",
|
|
1155
|
+
"zone?": "private|output",
|
|
1156
|
+
"space_id?": "string",
|
|
1157
|
+
"expected_sha256?": "string"
|
|
1158
|
+
},
|
|
1159
|
+
"request": {},
|
|
1160
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
1161
|
+
"response_headers": [],
|
|
1162
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized", "version_conflict"],
|
|
1163
|
+
"hosts": { "production": true, "dev": true },
|
|
1164
|
+
"sdk": ["files.remove"]
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
"id": "storage.list",
|
|
1168
|
+
"method": "GET",
|
|
1169
|
+
"path": "/storage/{bucket}",
|
|
1170
|
+
"upstream": "/v1/app-runtime/storage/{bucket}",
|
|
1171
|
+
"summary": "A bucket's files under prefix. Nothing declares a bucket: opened with space_id it is that space's (every member reads it and a file outlives its writer's membership), otherwise it is the caller's own. Bucket names are 1-64 letters, digits, '.', '-' or '_' not starting with '.'. limit defaults to 100, at most 200.",
|
|
1172
|
+
"auth": "app_session",
|
|
1173
|
+
"guest_allowed": false,
|
|
1174
|
+
"space_id": "query",
|
|
1175
|
+
"idempotency": "none",
|
|
1176
|
+
"body": "none",
|
|
1177
|
+
"body_limit_bytes": null,
|
|
1178
|
+
"lane": "interactive",
|
|
1179
|
+
"query": { "space_id?": "string", "prefix?": "string", "after?": "string", "limit?": "integer" },
|
|
1180
|
+
"request": {},
|
|
1181
|
+
"response": { "kind": "json", "fields": { "files": "FileEntry[]", "next_cursor": "string|null" } },
|
|
1182
|
+
"response_headers": [],
|
|
1183
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
1184
|
+
"hosts": { "production": true, "dev": true },
|
|
1185
|
+
"sdk": ["storage.bucket().list"]
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
"id": "storage.read",
|
|
1189
|
+
"method": "GET",
|
|
1190
|
+
"also_head": true,
|
|
1191
|
+
"path": "/storage/{bucket}/object",
|
|
1192
|
+
"upstream": "/v1/app-runtime/storage/{bucket}/object",
|
|
1193
|
+
"summary": "One bucket object's bytes under the content type it was written with (D15); the ETag is its quoted sha256.",
|
|
1194
|
+
"auth": "app_session",
|
|
1195
|
+
"guest_allowed": false,
|
|
1196
|
+
"space_id": "query",
|
|
1197
|
+
"idempotency": "none",
|
|
1198
|
+
"body": "none",
|
|
1199
|
+
"body_limit_bytes": null,
|
|
1200
|
+
"lane": "interactive",
|
|
1201
|
+
"query": { "path": "string", "space_id?": "string" },
|
|
1202
|
+
"request": {},
|
|
1203
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
1204
|
+
"response_headers": ["content-type", "etag"],
|
|
1205
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
1206
|
+
"hosts": { "production": true, "dev": true },
|
|
1207
|
+
"sdk": ["storage.bucket().read"]
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
"id": "storage.write",
|
|
1211
|
+
"method": "PUT",
|
|
1212
|
+
"path": "/storage/{bucket}/object",
|
|
1213
|
+
"upstream": "/v1/app-runtime/storage/{bucket}/object",
|
|
1214
|
+
"summary": "Writes one bucket object (at most 8 MiB, D31) from the raw body and stores the request Content-Type (D15). Writing a space's bucket needs space write access. expected_sha256=missing requires that the object does not exist (create-only); any other value must equal its current sha256 (409 version_conflict otherwise), so members of a space do not overwrite each other's files.",
|
|
1215
|
+
"auth": "app_session",
|
|
1216
|
+
"guest_allowed": false,
|
|
1217
|
+
"space_id": "query",
|
|
1218
|
+
"idempotency": "none",
|
|
1219
|
+
"body": "bytes",
|
|
1220
|
+
"body_limit_bytes": 8388608,
|
|
1221
|
+
"lane": "interactive",
|
|
1222
|
+
"query": { "path": "string", "space_id?": "string", "expected_sha256?": "string" },
|
|
1223
|
+
"request": {},
|
|
1224
|
+
"response": { "kind": "json", "fields": { "$body": "WriteReceipt" } },
|
|
1225
|
+
"response_headers": [],
|
|
1226
|
+
"errors": [
|
|
1227
|
+
"bad_request",
|
|
1228
|
+
"forbidden",
|
|
1229
|
+
"not_found",
|
|
1230
|
+
"payload_too_large",
|
|
1231
|
+
"quota_exceeded",
|
|
1232
|
+
"session_ended",
|
|
1233
|
+
"unauthorized",
|
|
1234
|
+
"version_conflict"
|
|
1235
|
+
],
|
|
1236
|
+
"hosts": { "production": true, "dev": true },
|
|
1237
|
+
"sdk": ["storage.bucket().write"]
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
"id": "storage.delete",
|
|
1241
|
+
"method": "DELETE",
|
|
1242
|
+
"path": "/storage/{bucket}/object",
|
|
1243
|
+
"upstream": "/v1/app-runtime/storage/{bucket}/object",
|
|
1244
|
+
"summary": "Removes one bucket object; expected_sha256, when given, must equal its current sha256 (409 version_conflict otherwise); expected_sha256=missing is 400 bad_request, since a delete needs something to delete.",
|
|
1245
|
+
"auth": "app_session",
|
|
1246
|
+
"guest_allowed": false,
|
|
1247
|
+
"space_id": "query",
|
|
1248
|
+
"idempotency": "none",
|
|
1249
|
+
"body": "none",
|
|
1250
|
+
"body_limit_bytes": null,
|
|
1251
|
+
"lane": "interactive",
|
|
1252
|
+
"query": { "path": "string", "space_id?": "string", "expected_sha256?": "string" },
|
|
1253
|
+
"request": {},
|
|
1254
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
1255
|
+
"response_headers": [],
|
|
1256
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized", "version_conflict"],
|
|
1257
|
+
"hosts": { "production": true, "dev": true },
|
|
1258
|
+
"sdk": ["storage.bucket().delete"]
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
"id": "collections.define",
|
|
1262
|
+
"method": "PUT",
|
|
1263
|
+
"path": "/collections/{collection}/definition",
|
|
1264
|
+
"upstream": "/v1/app-runtime/collections/{collection}/definition",
|
|
1265
|
+
"summary": "Lazily pins the SDK's collection definition to this installation and release; the grammar is collection-definitions.json and write-rules.json. The same definition again answers the stored one; a different one is 409 conflict (a changed definition ships in a new release). At most 32 collections per release installation. Collection names are 1-64 lowercase letters, digits, '-' or '_' starting with a letter.",
|
|
1266
|
+
"auth": "app_session",
|
|
1267
|
+
"guest_allowed": false,
|
|
1268
|
+
"space_id": "none",
|
|
1269
|
+
"idempotency": "none",
|
|
1270
|
+
"body": "json",
|
|
1271
|
+
"body_limit_bytes": 32768,
|
|
1272
|
+
"lane": "interactive",
|
|
1273
|
+
"query": {},
|
|
1274
|
+
"request": { "$body": "CollectionDefinition" },
|
|
1275
|
+
"response": { "kind": "json", "fields": { "$body": "CollectionDefinition" } },
|
|
1276
|
+
"response_headers": [],
|
|
1277
|
+
"errors": ["bad_request", "conflict", "payload_too_large", "session_ended", "unauthorized"],
|
|
1278
|
+
"hosts": { "production": true, "dev": true },
|
|
1279
|
+
"sdk": ["db.collection"]
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
"id": "collections.list",
|
|
1283
|
+
"method": "GET",
|
|
1284
|
+
"path": "/collections/{collection}",
|
|
1285
|
+
"upstream": "/v1/app-runtime/collections/{collection}",
|
|
1286
|
+
"summary": "A page of records the caller may read (fields redacted by the read policy). sync_cursor is captured before the rows are read. The default order is by id and pages with after; sort (field, or -field for descending) pages by limit only and refuses after. where is the §2.6 grammar as JSON (where-grammar.json, at most 16 KiB); search is websearch syntax over the declared search fields; a blank search (empty or only spaces) is no search. limit defaults to 100, at most 200. A space-owned collection needs space_id.",
|
|
1287
|
+
"auth": "app_session",
|
|
1288
|
+
"guest_allowed": false,
|
|
1289
|
+
"space_id": "query",
|
|
1290
|
+
"idempotency": "none",
|
|
1291
|
+
"body": "none",
|
|
1292
|
+
"body_limit_bytes": null,
|
|
1293
|
+
"lane": "interactive",
|
|
1294
|
+
"query": {
|
|
1295
|
+
"space_id?": "string",
|
|
1296
|
+
"where?": "string",
|
|
1297
|
+
"after?": "string",
|
|
1298
|
+
"limit?": "integer",
|
|
1299
|
+
"sort?": "string",
|
|
1300
|
+
"search?": "string"
|
|
1301
|
+
},
|
|
1302
|
+
"request": {},
|
|
1303
|
+
"response": {
|
|
1304
|
+
"kind": "json",
|
|
1305
|
+
"fields": {
|
|
1306
|
+
"records": "ManagedRecord[]",
|
|
1307
|
+
"next_cursor": "string|null",
|
|
1308
|
+
"has_more": "boolean",
|
|
1309
|
+
"sync_cursor": "string"
|
|
1310
|
+
}
|
|
1311
|
+
},
|
|
1312
|
+
"response_headers": [],
|
|
1313
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1314
|
+
"hosts": { "production": true, "dev": true },
|
|
1315
|
+
"sdk": [
|
|
1316
|
+
"db.collection().list",
|
|
1317
|
+
"db.collection().find",
|
|
1318
|
+
"db.collection().findPage",
|
|
1319
|
+
"db.collection().search",
|
|
1320
|
+
"db.collection().live"
|
|
1321
|
+
]
|
|
1322
|
+
},
|
|
1323
|
+
{
|
|
1324
|
+
"id": "collections.get",
|
|
1325
|
+
"method": "GET",
|
|
1326
|
+
"path": "/collections/{collection}/{record_id}",
|
|
1327
|
+
"upstream": "/v1/app-runtime/collections/{collection}/{record_id}",
|
|
1328
|
+
"summary": "One record by id (limits.record_id_pattern), redacted by the read policy.",
|
|
1329
|
+
"auth": "app_session",
|
|
1330
|
+
"guest_allowed": false,
|
|
1331
|
+
"space_id": "query",
|
|
1332
|
+
"idempotency": "none",
|
|
1333
|
+
"body": "none",
|
|
1334
|
+
"body_limit_bytes": null,
|
|
1335
|
+
"lane": "interactive",
|
|
1336
|
+
"query": { "space_id?": "string" },
|
|
1337
|
+
"request": {},
|
|
1338
|
+
"response": { "kind": "json", "fields": { "$body": "ManagedRecord" } },
|
|
1339
|
+
"response_headers": [],
|
|
1340
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1341
|
+
"hosts": { "production": true, "dev": true },
|
|
1342
|
+
"sdk": ["db.collection().get", "db.collection().getRecord"]
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
"id": "collections.put",
|
|
1346
|
+
"method": "PUT",
|
|
1347
|
+
"path": "/collections/{collection}/{record_id}",
|
|
1348
|
+
"upstream": "/v1/app-runtime/collections/{collection}/{record_id}",
|
|
1349
|
+
"summary": "Creates or replaces one record from the body (a JSON object of at most 128 KiB). expected_version 0 requires that the record is absent and a positive value must equal its version (409 version_conflict). The write, its receipt and the change cursor commit together; a replayed Idempotency-Key answers the committed result with replayed true. Declared unique fields and relations answer 409 conflict, validate rules 422 unprocessable.",
|
|
1350
|
+
"auth": "app_session",
|
|
1351
|
+
"guest_allowed": false,
|
|
1352
|
+
"space_id": "query",
|
|
1353
|
+
"idempotency": "required",
|
|
1354
|
+
"body": "json",
|
|
1355
|
+
"body_limit_bytes": 262144,
|
|
1356
|
+
"lane": "interactive",
|
|
1357
|
+
"query": { "space_id?": "string", "expected_version?": "integer" },
|
|
1358
|
+
"request": { "$body": "object" },
|
|
1359
|
+
"response": { "kind": "json", "fields": { "$body": "ManagedPutReceipt" } },
|
|
1360
|
+
"response_headers": [],
|
|
1361
|
+
"errors": [
|
|
1362
|
+
"bad_request",
|
|
1363
|
+
"conflict",
|
|
1364
|
+
"forbidden",
|
|
1365
|
+
"idempotency_conflict",
|
|
1366
|
+
"not_found",
|
|
1367
|
+
"payload_too_large",
|
|
1368
|
+
"session_ended",
|
|
1369
|
+
"still_pending",
|
|
1370
|
+
"unauthorized",
|
|
1371
|
+
"unprocessable",
|
|
1372
|
+
"version_conflict"
|
|
1373
|
+
],
|
|
1374
|
+
"hosts": { "production": true, "dev": true },
|
|
1375
|
+
"sdk": ["db.collection().put", "db.collection().update", "db.collection().putMany"]
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
"id": "collections.delete",
|
|
1379
|
+
"method": "DELETE",
|
|
1380
|
+
"path": "/collections/{collection}/{record_id}",
|
|
1381
|
+
"upstream": "/v1/app-runtime/collections/{collection}/{record_id}",
|
|
1382
|
+
"summary": "Deletes one record (expected_version as for put); relations declared onDelete cascade remove their dependents in the same commit and are listed in cascaded.",
|
|
1383
|
+
"auth": "app_session",
|
|
1384
|
+
"guest_allowed": false,
|
|
1385
|
+
"space_id": "query",
|
|
1386
|
+
"idempotency": "required",
|
|
1387
|
+
"body": "none",
|
|
1388
|
+
"body_limit_bytes": null,
|
|
1389
|
+
"lane": "interactive",
|
|
1390
|
+
"query": { "space_id?": "string", "expected_version?": "integer" },
|
|
1391
|
+
"request": {},
|
|
1392
|
+
"response": { "kind": "json", "fields": { "$body": "ManagedDeleteReceipt" } },
|
|
1393
|
+
"response_headers": [],
|
|
1394
|
+
"errors": [
|
|
1395
|
+
"bad_request",
|
|
1396
|
+
"conflict",
|
|
1397
|
+
"forbidden",
|
|
1398
|
+
"idempotency_conflict",
|
|
1399
|
+
"not_found",
|
|
1400
|
+
"session_ended",
|
|
1401
|
+
"still_pending",
|
|
1402
|
+
"unauthorized",
|
|
1403
|
+
"version_conflict"
|
|
1404
|
+
],
|
|
1405
|
+
"hosts": { "production": true, "dev": true },
|
|
1406
|
+
"sdk": ["db.collection().delete"]
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
"id": "collections.deliver",
|
|
1410
|
+
"method": "POST",
|
|
1411
|
+
"path": "/collections/{collection}/deliver",
|
|
1412
|
+
"upstream": "/v1/app-runtime/collections/{collection}/deliver",
|
|
1413
|
+
"summary": "Delivers one record to a space: freezes the current membership as the recipient set and writes a replica into each recipient's personal collection under one app-space delivery sequence (space-delivery.json). Personal collections only. notify and mentions ring with the commit through the one ring core (D8); a replay rings nobody and answers the original sequence and recipients. A replica that would break a declared unique field or relation in a recipient's collection refuses the whole delivery with 409 conflict; validate rules answer 422 unprocessable.",
|
|
1414
|
+
"auth": "app_session",
|
|
1415
|
+
"guest_allowed": false,
|
|
1416
|
+
"space_id": "body",
|
|
1417
|
+
"idempotency": "required",
|
|
1418
|
+
"body": "json",
|
|
1419
|
+
"body_limit_bytes": 262144,
|
|
1420
|
+
"lane": "interactive",
|
|
1421
|
+
"query": {},
|
|
1422
|
+
"request": {
|
|
1423
|
+
"space_id": "string",
|
|
1424
|
+
"record_id": "string",
|
|
1425
|
+
"value": "object",
|
|
1426
|
+
"notify?": "WriteNotify",
|
|
1427
|
+
"mentions?": "string[]"
|
|
1428
|
+
},
|
|
1429
|
+
"response": { "kind": "json", "fields": { "$body": "ManagedDelivery" } },
|
|
1430
|
+
"response_headers": [],
|
|
1431
|
+
"errors": [
|
|
1432
|
+
"bad_request",
|
|
1433
|
+
"conflict",
|
|
1434
|
+
"forbidden",
|
|
1435
|
+
"idempotency_conflict",
|
|
1436
|
+
"not_found",
|
|
1437
|
+
"payload_too_large",
|
|
1438
|
+
"session_ended",
|
|
1439
|
+
"still_pending",
|
|
1440
|
+
"unauthorized",
|
|
1441
|
+
"unprocessable"
|
|
1442
|
+
],
|
|
1443
|
+
"hosts": { "production": true, "dev": true },
|
|
1444
|
+
"sdk": ["db.collection().deliver"]
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
"id": "collections.changes",
|
|
1448
|
+
"method": "GET",
|
|
1449
|
+
"path": "/collections/{collection}/changes",
|
|
1450
|
+
"upstream": "/v1/app-runtime/collections/{collection}/changes",
|
|
1451
|
+
"summary": "Ordered committed changes after a collection cursor (at most 500 per answer), filtered and redacted by the read policy. reset_required means retention no longer bridges after: read a fresh snapshot.",
|
|
1452
|
+
"auth": "app_session",
|
|
1453
|
+
"guest_allowed": false,
|
|
1454
|
+
"space_id": "query",
|
|
1455
|
+
"idempotency": "none",
|
|
1456
|
+
"body": "none",
|
|
1457
|
+
"body_limit_bytes": null,
|
|
1458
|
+
"lane": "interactive",
|
|
1459
|
+
"query": { "space_id?": "string", "after?": "string" },
|
|
1460
|
+
"request": {},
|
|
1461
|
+
"response": {
|
|
1462
|
+
"kind": "json",
|
|
1463
|
+
"fields": {
|
|
1464
|
+
"reset_required": "boolean",
|
|
1465
|
+
"reason?": "cursor_expired",
|
|
1466
|
+
"cursor": "string",
|
|
1467
|
+
"retained_after": "string",
|
|
1468
|
+
"has_more": "boolean",
|
|
1469
|
+
"changes": "ManagedRecordChange[]"
|
|
1470
|
+
}
|
|
1471
|
+
},
|
|
1472
|
+
"response_headers": [],
|
|
1473
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1474
|
+
"hosts": { "production": true, "dev": true },
|
|
1475
|
+
"sdk": ["db.collection().live"]
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
"id": "collections.rebuild",
|
|
1479
|
+
"method": "POST",
|
|
1480
|
+
"path": "/collections/{collection}/rebuild",
|
|
1481
|
+
"upstream": "/v1/app-runtime/collections/{collection}/rebuild",
|
|
1482
|
+
"summary": "One call (D25): counts the canonical records and commits a reset change, so every live projection of the collection re-reads a fresh snapshot.",
|
|
1483
|
+
"auth": "app_session",
|
|
1484
|
+
"guest_allowed": false,
|
|
1485
|
+
"space_id": "query",
|
|
1486
|
+
"idempotency": "none",
|
|
1487
|
+
"body": "none",
|
|
1488
|
+
"body_limit_bytes": null,
|
|
1489
|
+
"lane": "interactive",
|
|
1490
|
+
"query": { "space_id?": "string" },
|
|
1491
|
+
"request": {},
|
|
1492
|
+
"response": { "kind": "json", "fields": { "rebuilt": "integer", "sync_cursor": "string" } },
|
|
1493
|
+
"response_headers": [],
|
|
1494
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1495
|
+
"hosts": { "production": true, "dev": true },
|
|
1496
|
+
"sdk": ["db.collection().rebuild"]
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
"id": "transactions.commit",
|
|
1500
|
+
"method": "POST",
|
|
1501
|
+
"path": "/transactions",
|
|
1502
|
+
"upstream": "/v1/app-runtime/transactions",
|
|
1503
|
+
"summary": "Commits 1-64 record puts and deletes in one database transaction within one capsule scope, each address at most once; preconditions, declared constraints, cascades, cursors and the replay receipt commit or roll back together. notify and mentions need space_id and ring with the commit (D8); a replay rings nobody and answers the first result with replayed true.",
|
|
1504
|
+
"auth": "app_session",
|
|
1505
|
+
"guest_allowed": false,
|
|
1506
|
+
"space_id": "body",
|
|
1507
|
+
"idempotency": "required",
|
|
1508
|
+
"body": "json",
|
|
1509
|
+
"body_limit_bytes": 1048576,
|
|
1510
|
+
"lane": "interactive",
|
|
1511
|
+
"query": {},
|
|
1512
|
+
"request": {
|
|
1513
|
+
"space_id?": "string",
|
|
1514
|
+
"notify?": "WriteNotify",
|
|
1515
|
+
"mentions?": "string[]",
|
|
1516
|
+
"operations": "TransactionOperation[]"
|
|
1517
|
+
},
|
|
1518
|
+
"response": { "kind": "json", "fields": { "$body": "TransactionResult" } },
|
|
1519
|
+
"response_headers": [],
|
|
1520
|
+
"errors": [
|
|
1521
|
+
"bad_request",
|
|
1522
|
+
"conflict",
|
|
1523
|
+
"forbidden",
|
|
1524
|
+
"idempotency_conflict",
|
|
1525
|
+
"not_found",
|
|
1526
|
+
"payload_too_large",
|
|
1527
|
+
"session_ended",
|
|
1528
|
+
"still_pending",
|
|
1529
|
+
"unauthorized",
|
|
1530
|
+
"unprocessable",
|
|
1531
|
+
"version_conflict"
|
|
1532
|
+
],
|
|
1533
|
+
"hosts": { "production": true, "dev": true },
|
|
1534
|
+
"sdk": ["db.transact"]
|
|
1535
|
+
},
|
|
1536
|
+
{
|
|
1537
|
+
"id": "collaboration.append",
|
|
1538
|
+
"method": "POST",
|
|
1539
|
+
"path": "/collaboration/{document_id}/operations",
|
|
1540
|
+
"upstream": "/v1/app-runtime/collaboration/{document_id}/operations",
|
|
1541
|
+
"summary": "Appends 1-64 operations to a document's ordered journal, the only durable-journal family (D21). An operation id is idempotent per author: a retried id answers its committed position, and the same id with different content is 409 idempotency_conflict. The journal commits before collaboration_changed is published. Document ids are 1-128 safe characters; the SDK names a durable stream's journal stream.<id>. Opened with space_id the journal is the space's (writing needs space write access), otherwise the caller's own.",
|
|
1542
|
+
"auth": "app_session",
|
|
1543
|
+
"guest_allowed": false,
|
|
1544
|
+
"space_id": "body",
|
|
1545
|
+
"idempotency": "none",
|
|
1546
|
+
"body": "json",
|
|
1547
|
+
"body_limit_bytes": 262144,
|
|
1548
|
+
"lane": "interactive",
|
|
1549
|
+
"query": {},
|
|
1550
|
+
"request": { "operations": "CollaborationOperationInput[]", "space_id?": "string" },
|
|
1551
|
+
"response": {
|
|
1552
|
+
"kind": "json",
|
|
1553
|
+
"fields": { "cursor": "string", "operations": "CollaborationOperation[]" }
|
|
1554
|
+
},
|
|
1555
|
+
"response_headers": [],
|
|
1556
|
+
"errors": [
|
|
1557
|
+
"bad_request",
|
|
1558
|
+
"conflict",
|
|
1559
|
+
"forbidden",
|
|
1560
|
+
"idempotency_conflict",
|
|
1561
|
+
"not_found",
|
|
1562
|
+
"payload_too_large",
|
|
1563
|
+
"session_ended",
|
|
1564
|
+
"unauthorized"
|
|
1565
|
+
],
|
|
1566
|
+
"hosts": { "production": true, "dev": true },
|
|
1567
|
+
"sdk": ["streams.open"]
|
|
1568
|
+
},
|
|
1569
|
+
{
|
|
1570
|
+
"id": "collaboration.read",
|
|
1571
|
+
"method": "GET",
|
|
1572
|
+
"path": "/collaboration/{document_id}/operations",
|
|
1573
|
+
"upstream": "/v1/app-runtime/collaboration/{document_id}/operations",
|
|
1574
|
+
"summary": "Journal operations after a cursor (limit defaults to 200, at most 200). A read from the start carries the latest snapshot; a reader behind the compaction frontier gets reset_required with the snapshot and resumes at snapshot_cursor.",
|
|
1575
|
+
"auth": "app_session",
|
|
1576
|
+
"guest_allowed": false,
|
|
1577
|
+
"space_id": "query",
|
|
1578
|
+
"idempotency": "none",
|
|
1579
|
+
"body": "none",
|
|
1580
|
+
"body_limit_bytes": null,
|
|
1581
|
+
"lane": "interactive",
|
|
1582
|
+
"query": { "space_id?": "string", "after?": "string", "limit?": "integer" },
|
|
1583
|
+
"request": {},
|
|
1584
|
+
"response": {
|
|
1585
|
+
"kind": "json",
|
|
1586
|
+
"fields": {
|
|
1587
|
+
"cursor": "string",
|
|
1588
|
+
"operations": "CollaborationOperation[]",
|
|
1589
|
+
"has_more": "boolean",
|
|
1590
|
+
"reset_required": "boolean",
|
|
1591
|
+
"reason?": "cursor_expired",
|
|
1592
|
+
"snapshot_cursor?": "string",
|
|
1593
|
+
"snapshot?": "json"
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
"response_headers": [],
|
|
1597
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
1598
|
+
"hosts": { "production": true, "dev": true },
|
|
1599
|
+
"sdk": ["streams.open"]
|
|
1600
|
+
},
|
|
1601
|
+
{
|
|
1602
|
+
"id": "collaboration.snapshot",
|
|
1603
|
+
"method": "PUT",
|
|
1604
|
+
"path": "/collaboration/{document_id}/snapshot",
|
|
1605
|
+
"upstream": "/v1/app-runtime/collaboration/{document_id}/snapshot",
|
|
1606
|
+
"summary": "Compare-and-set checkpoint of the document's projected state through a journal cursor: through may not be behind the current snapshot or ahead of the head (409 conflict). Operations covered by a committed snapshot may then be compacted.",
|
|
1607
|
+
"auth": "app_session",
|
|
1608
|
+
"guest_allowed": false,
|
|
1609
|
+
"space_id": "body",
|
|
1610
|
+
"idempotency": "none",
|
|
1611
|
+
"body": "json",
|
|
1612
|
+
"body_limit_bytes": 262144,
|
|
1613
|
+
"lane": "interactive",
|
|
1614
|
+
"query": {},
|
|
1615
|
+
"request": { "snapshot": "json", "through": "string", "space_id?": "string" },
|
|
1616
|
+
"response": {
|
|
1617
|
+
"kind": "json",
|
|
1618
|
+
"fields": { "ok": "boolean", "cursor": "string", "snapshot_cursor": "string" }
|
|
1619
|
+
},
|
|
1620
|
+
"response_headers": [],
|
|
1621
|
+
"errors": [
|
|
1622
|
+
"bad_request",
|
|
1623
|
+
"conflict",
|
|
1624
|
+
"forbidden",
|
|
1625
|
+
"not_found",
|
|
1626
|
+
"payload_too_large",
|
|
1627
|
+
"session_ended",
|
|
1628
|
+
"unauthorized"
|
|
1629
|
+
],
|
|
1630
|
+
"hosts": { "production": true, "dev": true },
|
|
1631
|
+
"sdk": ["streams.open"]
|
|
1632
|
+
},
|
|
1633
|
+
{
|
|
1634
|
+
"id": "events.publish",
|
|
1635
|
+
"method": "POST",
|
|
1636
|
+
"path": "/events",
|
|
1637
|
+
"upstream": "/v1/app-runtime/events",
|
|
1638
|
+
"summary": "Publishes an app event (or a batch of 1-16) to a space: each payload is at most 32 KiB and reaches every other member's account stream, never any session of the publisher (D3). transient events are live-only and carry no mentions or notify; batches carry neither. mentions (at most 8 handles) ring the members named; notify rings the members not looking at the space, through the one ring core (D8). Budget: 240 durable and 1200 transient publishes per minute per publisher and topic. A replayed Idempotency-Key rings nobody and answers the first answer (D8).",
|
|
1639
|
+
"auth": "app_session",
|
|
1640
|
+
"guest_allowed": false,
|
|
1641
|
+
"space_id": "body",
|
|
1642
|
+
"idempotency": "optional",
|
|
1643
|
+
"body": "json",
|
|
1644
|
+
"body_limit_bytes": 262144,
|
|
1645
|
+
"lane": "interactive",
|
|
1646
|
+
"query": {},
|
|
1647
|
+
"request": {
|
|
1648
|
+
"event?": "json",
|
|
1649
|
+
"events?": "json[]",
|
|
1650
|
+
"space_id": "string",
|
|
1651
|
+
"mentions?": "string[]",
|
|
1652
|
+
"transient?": "boolean",
|
|
1653
|
+
"notify?": "EventNotify"
|
|
1654
|
+
},
|
|
1655
|
+
"response": {
|
|
1656
|
+
"kind": "json",
|
|
1657
|
+
"fields": { "ok": "boolean", "transient": "boolean" },
|
|
1658
|
+
"variants": [
|
|
1659
|
+
{
|
|
1660
|
+
"when": "the request carried events[] (a batch)",
|
|
1661
|
+
"fields": { "results": "EventPublishResult[]" }
|
|
1662
|
+
}
|
|
1663
|
+
]
|
|
1664
|
+
},
|
|
1665
|
+
"response_headers": [],
|
|
1666
|
+
"errors": [
|
|
1667
|
+
"bad_request",
|
|
1668
|
+
"forbidden",
|
|
1669
|
+
"idempotency_conflict",
|
|
1670
|
+
"not_found",
|
|
1671
|
+
"payload_too_large",
|
|
1672
|
+
"rate_limited",
|
|
1673
|
+
"session_ended",
|
|
1674
|
+
"still_pending",
|
|
1675
|
+
"unauthorized"
|
|
1676
|
+
],
|
|
1677
|
+
"hosts": { "production": true, "dev": true },
|
|
1678
|
+
"sdk": ["rooms.open"]
|
|
1679
|
+
},
|
|
1680
|
+
{
|
|
1681
|
+
"id": "events.stream",
|
|
1682
|
+
"method": "GET",
|
|
1683
|
+
"path": "/events",
|
|
1684
|
+
"upstream": "/v1/app-runtime/events",
|
|
1685
|
+
"summary": "The session's one live stream (SSE; frames in `frames`): the caller's account stream for this app, which hears every space-scoped frame of the app in every space they share plus account frames. rooms narrows room_event frames to the listed rooms (comma-separated); every other frame flows.",
|
|
1686
|
+
"auth": "app_session",
|
|
1687
|
+
"guest_allowed": false,
|
|
1688
|
+
"space_id": "none",
|
|
1689
|
+
"idempotency": "none",
|
|
1690
|
+
"body": "none",
|
|
1691
|
+
"body_limit_bytes": null,
|
|
1692
|
+
"lane": "interactive",
|
|
1693
|
+
"query": { "rooms?": "string" },
|
|
1694
|
+
"request": {},
|
|
1695
|
+
"response": { "kind": "sse", "fields": {} },
|
|
1696
|
+
"response_headers": ["cache-control", "content-type"],
|
|
1697
|
+
"errors": ["session_ended", "unauthorized"],
|
|
1698
|
+
"hosts": { "production": true, "dev": true },
|
|
1699
|
+
"sdk": [
|
|
1700
|
+
"rooms.open",
|
|
1701
|
+
"spaces.live",
|
|
1702
|
+
"spaces.liveMembers",
|
|
1703
|
+
"spaces.liveCursors",
|
|
1704
|
+
"db.collection().live",
|
|
1705
|
+
"streams.open",
|
|
1706
|
+
"jobs.wait"
|
|
1707
|
+
]
|
|
1708
|
+
},
|
|
1709
|
+
{
|
|
1710
|
+
"id": "events.presence",
|
|
1711
|
+
"method": "GET",
|
|
1712
|
+
"path": "/events/presence",
|
|
1713
|
+
"upstream": "/v1/app-runtime/events/presence",
|
|
1714
|
+
"summary": "The space's members holding a live stream for this app right now, with each one's presence state (states maps user id to state).",
|
|
1715
|
+
"auth": "app_session",
|
|
1716
|
+
"guest_allowed": false,
|
|
1717
|
+
"space_id": "query",
|
|
1718
|
+
"idempotency": "none",
|
|
1719
|
+
"body": "none",
|
|
1720
|
+
"body_limit_bytes": null,
|
|
1721
|
+
"lane": "interactive",
|
|
1722
|
+
"query": { "space_id": "string" },
|
|
1723
|
+
"request": {},
|
|
1724
|
+
"response": { "kind": "json", "fields": { "online": "string[]", "states": "object" } },
|
|
1725
|
+
"response_headers": [],
|
|
1726
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
1727
|
+
"hosts": { "production": true, "dev": true },
|
|
1728
|
+
"sdk": ["rooms.open"]
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
"id": "events.set_presence",
|
|
1732
|
+
"method": "POST",
|
|
1733
|
+
"path": "/events/presence",
|
|
1734
|
+
"upstream": "/v1/app-runtime/events/presence",
|
|
1735
|
+
"summary": "Sets (or with null clears) the caller's presence state, at most 4 KiB: with space_id it parks on that space, without one on the caller's account topic. window (1-64 letters, digits, '-' or '_') and visible say whether that window is showing the space; a hidden window or a cleared state is not looking. An unchanged re-assert is a silent heartbeat, and a change is never echoed to the caller (D3). Co-members hear a cleared state, and the member's last stream closing, as online false; a heartbeat that lapses without either is not announced.",
|
|
1736
|
+
"auth": "app_session",
|
|
1737
|
+
"guest_allowed": false,
|
|
1738
|
+
"space_id": "body",
|
|
1739
|
+
"idempotency": "none",
|
|
1740
|
+
"body": "json",
|
|
1741
|
+
"body_limit_bytes": 262144,
|
|
1742
|
+
"lane": "interactive",
|
|
1743
|
+
"query": {},
|
|
1744
|
+
"request": { "state?": "json|null", "space_id?": "string", "window?": "string", "visible?": "boolean" },
|
|
1745
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
1746
|
+
"response_headers": [],
|
|
1747
|
+
"errors": [
|
|
1748
|
+
"bad_request",
|
|
1749
|
+
"forbidden",
|
|
1750
|
+
"not_found",
|
|
1751
|
+
"payload_too_large",
|
|
1752
|
+
"rate_limited",
|
|
1753
|
+
"session_ended",
|
|
1754
|
+
"unauthorized"
|
|
1755
|
+
],
|
|
1756
|
+
"hosts": { "production": true, "dev": true },
|
|
1757
|
+
"sdk": ["rooms.open"]
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
"id": "notifications.create",
|
|
1761
|
+
"method": "POST",
|
|
1762
|
+
"path": "/notifications",
|
|
1763
|
+
"upstream": "/v1/app-runtime/notifications",
|
|
1764
|
+
"summary": "The app's own notice to the signed-in person, never to anyone else; needs the release's shell.notifications. title 1-160 characters, body at most 2000, route at most 500, data at most 32 KiB. While the person paused the app's notifications nothing is written and the answer says so.",
|
|
1765
|
+
"auth": "app_session",
|
|
1766
|
+
"guest_allowed": false,
|
|
1767
|
+
"space_id": "none",
|
|
1768
|
+
"idempotency": "optional",
|
|
1769
|
+
"body": "json",
|
|
1770
|
+
"body_limit_bytes": 262144,
|
|
1771
|
+
"lane": "interactive",
|
|
1772
|
+
"query": {},
|
|
1773
|
+
"request": { "title": "string", "body?": "string", "route?": "string|null", "data?": "json" },
|
|
1774
|
+
"response": {
|
|
1775
|
+
"kind": "json",
|
|
1776
|
+
"fields": { "id": "string", "created": "boolean" },
|
|
1777
|
+
"variants": [
|
|
1778
|
+
{
|
|
1779
|
+
"when": "the person paused this app's notifications",
|
|
1780
|
+
"fields": { "created": "boolean", "paused": "boolean" }
|
|
1781
|
+
}
|
|
1782
|
+
]
|
|
1783
|
+
},
|
|
1784
|
+
"response_headers": [],
|
|
1785
|
+
"errors": [
|
|
1786
|
+
"bad_request",
|
|
1787
|
+
"forbidden",
|
|
1788
|
+
"idempotency_conflict",
|
|
1789
|
+
"payload_too_large",
|
|
1790
|
+
"session_ended",
|
|
1791
|
+
"still_pending",
|
|
1792
|
+
"unauthorized"
|
|
1793
|
+
],
|
|
1794
|
+
"hosts": { "production": true, "dev": true },
|
|
1795
|
+
"sdk": ["notifications.create"]
|
|
1796
|
+
},
|
|
1797
|
+
{
|
|
1798
|
+
"id": "notifications.list",
|
|
1799
|
+
"method": "GET",
|
|
1800
|
+
"path": "/notifications",
|
|
1801
|
+
"upstream": "/v1/app-runtime/notifications",
|
|
1802
|
+
"summary": "The app's notifications for the signed-in person, newest first; limit defaults to 50, at most 200.",
|
|
1803
|
+
"auth": "app_session",
|
|
1804
|
+
"guest_allowed": false,
|
|
1805
|
+
"space_id": "none",
|
|
1806
|
+
"idempotency": "none",
|
|
1807
|
+
"body": "none",
|
|
1808
|
+
"body_limit_bytes": null,
|
|
1809
|
+
"lane": "interactive",
|
|
1810
|
+
"query": { "after?": "string", "limit?": "integer" },
|
|
1811
|
+
"request": {},
|
|
1812
|
+
"response": {
|
|
1813
|
+
"kind": "json",
|
|
1814
|
+
"fields": { "notifications": "AppNotice[]", "next_cursor": "string|null" }
|
|
1815
|
+
},
|
|
1816
|
+
"response_headers": [],
|
|
1817
|
+
"errors": ["bad_request", "session_ended", "unauthorized"],
|
|
1818
|
+
"hosts": { "production": true, "dev": true },
|
|
1819
|
+
"sdk": ["notifications.list"]
|
|
1820
|
+
},
|
|
1821
|
+
{
|
|
1822
|
+
"id": "notifications.read",
|
|
1823
|
+
"method": "POST",
|
|
1824
|
+
"path": "/notifications/{notification_id}/read",
|
|
1825
|
+
"upstream": "/v1/app-runtime/notifications/{notification_id}/read",
|
|
1826
|
+
"summary": "Marks one of the app's notifications read, idempotently, through the one core it shares with the platform bell (D22); an unknown id is 404 not_found.",
|
|
1827
|
+
"auth": "app_session",
|
|
1828
|
+
"guest_allowed": false,
|
|
1829
|
+
"space_id": "none",
|
|
1830
|
+
"idempotency": "none",
|
|
1831
|
+
"body": "none",
|
|
1832
|
+
"body_limit_bytes": null,
|
|
1833
|
+
"lane": "interactive",
|
|
1834
|
+
"query": {},
|
|
1835
|
+
"request": {},
|
|
1836
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
1837
|
+
"response_headers": [],
|
|
1838
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
1839
|
+
"hosts": { "production": true, "dev": true },
|
|
1840
|
+
"sdk": ["notifications.markRead"]
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
"id": "notifications.pause_status",
|
|
1844
|
+
"method": "GET",
|
|
1845
|
+
"path": "/notifications/pause",
|
|
1846
|
+
"upstream": "/v1/app-runtime/notifications/pause",
|
|
1847
|
+
"summary": "Until when the signed-in person paused this app's notifications, or null.",
|
|
1848
|
+
"auth": "app_session",
|
|
1849
|
+
"guest_allowed": false,
|
|
1850
|
+
"space_id": "none",
|
|
1851
|
+
"idempotency": "none",
|
|
1852
|
+
"body": "none",
|
|
1853
|
+
"body_limit_bytes": null,
|
|
1854
|
+
"lane": "interactive",
|
|
1855
|
+
"query": {},
|
|
1856
|
+
"request": {},
|
|
1857
|
+
"response": { "kind": "json", "fields": { "paused_until": "string|null" } },
|
|
1858
|
+
"response_headers": [],
|
|
1859
|
+
"errors": ["session_ended", "unauthorized"],
|
|
1860
|
+
"hosts": { "production": true, "dev": true },
|
|
1861
|
+
"sdk": ["notifications.pausedUntil"]
|
|
1862
|
+
},
|
|
1863
|
+
{
|
|
1864
|
+
"id": "notifications.pause",
|
|
1865
|
+
"method": "PUT",
|
|
1866
|
+
"path": "/notifications/pause",
|
|
1867
|
+
"upstream": "/v1/app-runtime/notifications/pause",
|
|
1868
|
+
"summary": "Pauses the signed-in person's notifications from this app until a moment at most 31 days ahead; null or a past moment resumes. While paused nothing but invitations rings, and nothing is saved up.",
|
|
1869
|
+
"auth": "app_session",
|
|
1870
|
+
"guest_allowed": false,
|
|
1871
|
+
"space_id": "none",
|
|
1872
|
+
"idempotency": "none",
|
|
1873
|
+
"body": "json",
|
|
1874
|
+
"body_limit_bytes": 262144,
|
|
1875
|
+
"lane": "interactive",
|
|
1876
|
+
"query": {},
|
|
1877
|
+
"request": { "until": "string|null" },
|
|
1878
|
+
"response": { "kind": "json", "fields": { "paused_until": "string|null" } },
|
|
1879
|
+
"response_headers": [],
|
|
1880
|
+
"errors": ["bad_request", "not_installed", "payload_too_large", "session_ended", "unauthorized"],
|
|
1881
|
+
"hosts": { "production": true, "dev": true },
|
|
1882
|
+
"sdk": ["notifications.pause"]
|
|
1883
|
+
},
|
|
1884
|
+
{
|
|
1885
|
+
"id": "notifications.default_mute_status",
|
|
1886
|
+
"method": "GET",
|
|
1887
|
+
"path": "/notifications/default-mute",
|
|
1888
|
+
"upstream": "/v1/app-runtime/notifications/default-mute",
|
|
1889
|
+
"summary": "Whether the spaces the signed-in person has not decided for are muted for them.",
|
|
1890
|
+
"auth": "app_session",
|
|
1891
|
+
"guest_allowed": false,
|
|
1892
|
+
"space_id": "none",
|
|
1893
|
+
"idempotency": "none",
|
|
1894
|
+
"body": "none",
|
|
1895
|
+
"body_limit_bytes": null,
|
|
1896
|
+
"lane": "interactive",
|
|
1897
|
+
"query": {},
|
|
1898
|
+
"request": {},
|
|
1899
|
+
"response": { "kind": "json", "fields": { "muted": "boolean" } },
|
|
1900
|
+
"response_headers": [],
|
|
1901
|
+
"errors": ["session_ended", "unauthorized"],
|
|
1902
|
+
"hosts": { "production": true, "dev": true },
|
|
1903
|
+
"sdk": ["notifications.mutedByDefault"]
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
"id": "notifications.default_mute",
|
|
1907
|
+
"method": "PUT",
|
|
1908
|
+
"path": "/notifications/default-mute",
|
|
1909
|
+
"upstream": "/v1/app-runtime/notifications/default-mute",
|
|
1910
|
+
"summary": "Mutes (or stops muting) every space the signed-in person has not decided for, including future ones; a space they muted or unmuted themselves keeps its answer.",
|
|
1911
|
+
"auth": "app_session",
|
|
1912
|
+
"guest_allowed": false,
|
|
1913
|
+
"space_id": "none",
|
|
1914
|
+
"idempotency": "none",
|
|
1915
|
+
"body": "json",
|
|
1916
|
+
"body_limit_bytes": 262144,
|
|
1917
|
+
"lane": "interactive",
|
|
1918
|
+
"query": {},
|
|
1919
|
+
"request": { "muted": "boolean" },
|
|
1920
|
+
"response": { "kind": "json", "fields": { "muted": "boolean" } },
|
|
1921
|
+
"response_headers": [],
|
|
1922
|
+
"errors": ["bad_request", "not_installed", "payload_too_large", "session_ended", "unauthorized"],
|
|
1923
|
+
"hosts": { "production": true, "dev": true },
|
|
1924
|
+
"sdk": ["notifications.muteByDefault"]
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
"id": "jobs.run",
|
|
1928
|
+
"method": "POST",
|
|
1929
|
+
"path": "/jobs",
|
|
1930
|
+
"upstream": "/v1/app-runtime/jobs",
|
|
1931
|
+
"summary": "Enqueues one automation the release declared, with a JSON object input of at most 256 KiB; the platform interprets its declarative steps. A replayed Idempotency-Key answers the job it already made (D11). A job's terminal state is pushed as job.updated on the installation owner's account stream (D29). 429 rate_limited when a daily job budget is spent (a draft's Test window world has one).",
|
|
1932
|
+
"auth": "app_session",
|
|
1933
|
+
"guest_allowed": false,
|
|
1934
|
+
"space_id": "body",
|
|
1935
|
+
"idempotency": "optional",
|
|
1936
|
+
"body": "json",
|
|
1937
|
+
"body_limit_bytes": 262144,
|
|
1938
|
+
"lane": "interactive",
|
|
1939
|
+
"query": {},
|
|
1940
|
+
"request": { "automation": "string", "input": "object", "space_id?": "string" },
|
|
1941
|
+
"response": { "kind": "json", "fields": { "id": "string", "automation": "string", "status": "queued" } },
|
|
1942
|
+
"response_headers": [],
|
|
1943
|
+
"errors": [
|
|
1944
|
+
"bad_request",
|
|
1945
|
+
"forbidden",
|
|
1946
|
+
"idempotency_conflict",
|
|
1947
|
+
"not_found",
|
|
1948
|
+
"payload_too_large",
|
|
1949
|
+
"rate_limited",
|
|
1950
|
+
"session_ended",
|
|
1951
|
+
"still_pending",
|
|
1952
|
+
"unauthorized"
|
|
1953
|
+
],
|
|
1954
|
+
"hosts": { "production": true, "dev": true },
|
|
1955
|
+
"sdk": ["jobs.run"]
|
|
1956
|
+
},
|
|
1957
|
+
{
|
|
1958
|
+
"id": "jobs.get",
|
|
1959
|
+
"method": "GET",
|
|
1960
|
+
"path": "/jobs/{job_id}",
|
|
1961
|
+
"upstream": "/v1/app-runtime/jobs/{job_id}",
|
|
1962
|
+
"summary": "One of this installation's jobs.",
|
|
1963
|
+
"auth": "app_session",
|
|
1964
|
+
"guest_allowed": false,
|
|
1965
|
+
"space_id": "none",
|
|
1966
|
+
"idempotency": "none",
|
|
1967
|
+
"body": "none",
|
|
1968
|
+
"body_limit_bytes": null,
|
|
1969
|
+
"lane": "interactive",
|
|
1970
|
+
"query": {},
|
|
1971
|
+
"request": {},
|
|
1972
|
+
"response": { "kind": "json", "fields": { "$body": "AppJob" } },
|
|
1973
|
+
"response_headers": [],
|
|
1974
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
1975
|
+
"hosts": { "production": true, "dev": true },
|
|
1976
|
+
"sdk": ["jobs.get", "jobs.wait"]
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
"id": "jobs.cancel",
|
|
1980
|
+
"method": "DELETE",
|
|
1981
|
+
"path": "/jobs/{job_id}",
|
|
1982
|
+
"upstream": "/v1/app-runtime/jobs/{job_id}",
|
|
1983
|
+
"summary": "Cancels a queued job; only queued, non-migration jobs can be cancelled (409 conflict otherwise).",
|
|
1984
|
+
"auth": "app_session",
|
|
1985
|
+
"guest_allowed": false,
|
|
1986
|
+
"space_id": "none",
|
|
1987
|
+
"idempotency": "none",
|
|
1988
|
+
"body": "none",
|
|
1989
|
+
"body_limit_bytes": null,
|
|
1990
|
+
"lane": "interactive",
|
|
1991
|
+
"query": {},
|
|
1992
|
+
"request": {},
|
|
1993
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
1994
|
+
"response_headers": [],
|
|
1995
|
+
"errors": ["bad_request", "conflict", "session_ended", "unauthorized"],
|
|
1996
|
+
"hosts": { "production": true, "dev": true },
|
|
1997
|
+
"sdk": ["jobs.cancel"]
|
|
1998
|
+
},
|
|
1999
|
+
{
|
|
2000
|
+
"id": "schedules.list",
|
|
2001
|
+
"method": "GET",
|
|
2002
|
+
"path": "/schedules",
|
|
2003
|
+
"upstream": "/v1/app-runtime/schedules",
|
|
2004
|
+
"summary": "This installation's schedules, by name.",
|
|
2005
|
+
"auth": "app_session",
|
|
2006
|
+
"guest_allowed": false,
|
|
2007
|
+
"space_id": "none",
|
|
2008
|
+
"idempotency": "none",
|
|
2009
|
+
"body": "none",
|
|
2010
|
+
"body_limit_bytes": null,
|
|
2011
|
+
"lane": "interactive",
|
|
2012
|
+
"query": {},
|
|
2013
|
+
"request": {},
|
|
2014
|
+
"response": { "kind": "json", "fields": { "schedules": "AppSchedule[]" } },
|
|
2015
|
+
"response_headers": [],
|
|
2016
|
+
"errors": ["session_ended", "unauthorized"],
|
|
2017
|
+
"hosts": { "production": true, "dev": true },
|
|
2018
|
+
"sdk": ["schedules.list"]
|
|
2019
|
+
},
|
|
2020
|
+
{
|
|
2021
|
+
"id": "schedules.set_enabled",
|
|
2022
|
+
"method": "PATCH",
|
|
2023
|
+
"path": "/schedules/{schedule_name}",
|
|
2024
|
+
"upstream": "/v1/app-runtime/schedules/{schedule_name}",
|
|
2025
|
+
"summary": "Switches a schedule on or off; the person's decision sticks against provisioning, and switching on also clears a fatigue pause and the failure streak.",
|
|
2026
|
+
"auth": "app_session",
|
|
2027
|
+
"guest_allowed": false,
|
|
2028
|
+
"space_id": "none",
|
|
2029
|
+
"idempotency": "none",
|
|
2030
|
+
"body": "json",
|
|
2031
|
+
"body_limit_bytes": 262144,
|
|
2032
|
+
"lane": "interactive",
|
|
2033
|
+
"query": {},
|
|
2034
|
+
"request": { "enabled": "boolean" },
|
|
2035
|
+
"response": { "kind": "json", "fields": { "name": "string", "enabled": "boolean" } },
|
|
2036
|
+
"response_headers": [],
|
|
2037
|
+
"errors": ["bad_request", "not_found", "payload_too_large", "session_ended", "unauthorized"],
|
|
2038
|
+
"hosts": { "production": true, "dev": true },
|
|
2039
|
+
"sdk": ["schedules.setEnabled"]
|
|
2040
|
+
},
|
|
2041
|
+
{
|
|
2042
|
+
"id": "lifecycle.status",
|
|
2043
|
+
"method": "GET",
|
|
2044
|
+
"path": "/lifecycle",
|
|
2045
|
+
"upstream": "/v1/app-runtime/lifecycle",
|
|
2046
|
+
"summary": "The installation's data version, the release's target version, and its lifecycle migrations.",
|
|
2047
|
+
"auth": "app_session",
|
|
2048
|
+
"guest_allowed": false,
|
|
2049
|
+
"space_id": "none",
|
|
2050
|
+
"idempotency": "none",
|
|
2051
|
+
"body": "none",
|
|
2052
|
+
"body_limit_bytes": null,
|
|
2053
|
+
"lane": "interactive",
|
|
2054
|
+
"query": {},
|
|
2055
|
+
"request": {},
|
|
2056
|
+
"response": {
|
|
2057
|
+
"kind": "json",
|
|
2058
|
+
"fields": {
|
|
2059
|
+
"installed_data_version": "integer",
|
|
2060
|
+
"target_data_version": "integer",
|
|
2061
|
+
"migrations": "LifecycleMigration[]"
|
|
2062
|
+
}
|
|
2063
|
+
},
|
|
2064
|
+
"response_headers": [],
|
|
2065
|
+
"errors": ["session_ended", "unauthorized"],
|
|
2066
|
+
"hosts": { "production": true, "dev": true },
|
|
2067
|
+
"sdk": ["lifecycle.status"]
|
|
2068
|
+
},
|
|
2069
|
+
{
|
|
2070
|
+
"id": "logs.write",
|
|
2071
|
+
"method": "POST",
|
|
2072
|
+
"path": "/logs",
|
|
2073
|
+
"upstream": "/v1/app-runtime/logs",
|
|
2074
|
+
"summary": "One browser log line for the app's maintainers: message 1-2000 characters, detail at most 64 KiB, level defaults to info; at most 60 per installation per minute.",
|
|
2075
|
+
"auth": "app_session",
|
|
2076
|
+
"guest_allowed": false,
|
|
2077
|
+
"space_id": "none",
|
|
2078
|
+
"idempotency": "none",
|
|
2079
|
+
"body": "json",
|
|
2080
|
+
"body_limit_bytes": 262144,
|
|
2081
|
+
"lane": "interactive",
|
|
2082
|
+
"query": {},
|
|
2083
|
+
"request": { "level?": "debug|info|warn|error", "message": "string", "detail?": "json" },
|
|
2084
|
+
"response": { "kind": "json", "fields": { "ok": "boolean" } },
|
|
2085
|
+
"response_headers": [],
|
|
2086
|
+
"errors": ["bad_request", "payload_too_large", "rate_limited", "session_ended", "unauthorized"],
|
|
2087
|
+
"hosts": { "production": true, "dev": true },
|
|
2088
|
+
"sdk": ["log.debug", "log.info", "log.warn", "log.error"]
|
|
2089
|
+
},
|
|
2090
|
+
{
|
|
2091
|
+
"id": "net.fetch",
|
|
2092
|
+
"method": "GET",
|
|
2093
|
+
"path": "/net/fetch",
|
|
2094
|
+
"upstream": "/v1/app-runtime/net/fetch",
|
|
2095
|
+
"summary": "SSRF-guarded fetch of a public text resource for a release with network_proxy public-text: http(s) on default ports, every resolved address and every redirect hop public, at most 3 redirects, text, XML, JSON or calendar content only. A body over 512 KiB is refused with 413 unless partial=1, which answers its first 512 KiB with truncated true (D28). Spends the caller's per-user daily fetch budget and rate limit and writes an activity receipt (D28). A private or disallowed address or scheme is 400 url_not_allowed; content the door does not serve (not text), a DNS failure or an unreachable upstream is 502 upstream_failed; an upstream slower than the door's own timeout is 504 deadline_exceeded.",
|
|
2096
|
+
"auth": "app_session",
|
|
2097
|
+
"guest_allowed": false,
|
|
2098
|
+
"space_id": "none",
|
|
2099
|
+
"idempotency": "none",
|
|
2100
|
+
"body": "none",
|
|
2101
|
+
"body_limit_bytes": null,
|
|
2102
|
+
"lane": "heavy",
|
|
2103
|
+
"query": { "url": "string", "partial?": "1|true" },
|
|
2104
|
+
"request": {},
|
|
2105
|
+
"response": {
|
|
2106
|
+
"kind": "json",
|
|
2107
|
+
"fields": {
|
|
2108
|
+
"url": "string",
|
|
2109
|
+
"status": "integer",
|
|
2110
|
+
"content_type": "string",
|
|
2111
|
+
"body": "string",
|
|
2112
|
+
"truncated": "boolean"
|
|
2113
|
+
}
|
|
2114
|
+
},
|
|
2115
|
+
"response_headers": [],
|
|
2116
|
+
"errors": [
|
|
2117
|
+
"bad_request",
|
|
2118
|
+
"deadline_exceeded",
|
|
2119
|
+
"forbidden",
|
|
2120
|
+
"payload_too_large",
|
|
2121
|
+
"rate_limited",
|
|
2122
|
+
"session_ended",
|
|
2123
|
+
"unauthorized",
|
|
2124
|
+
"upstream_failed",
|
|
2125
|
+
"url_not_allowed"
|
|
2126
|
+
],
|
|
2127
|
+
"hosts": { "production": true, "dev": true },
|
|
2128
|
+
"sdk": ["net.fetch"]
|
|
2129
|
+
},
|
|
2130
|
+
{
|
|
2131
|
+
"id": "net.image",
|
|
2132
|
+
"method": "GET",
|
|
2133
|
+
"path": "/net/image",
|
|
2134
|
+
"upstream": "/v1/app-runtime/net/image",
|
|
2135
|
+
"summary": "A public raster image (PNG, JPEG, GIF, WebP or AVIF by its own bytes, at most 5 MiB) for a release with network_proxy public-image, through the same guarded path as net.fetch (D28); served under the sniffed type, never cached, x-terminus-url naming the final URL. A private or disallowed address is 400 url_not_allowed; bytes that are not a supported raster image, a DNS failure or an unreachable upstream are 502 upstream_failed; over 5 MiB is 413 payload_too_large.",
|
|
2136
|
+
"auth": "app_session",
|
|
2137
|
+
"guest_allowed": false,
|
|
2138
|
+
"space_id": "none",
|
|
2139
|
+
"idempotency": "none",
|
|
2140
|
+
"body": "none",
|
|
2141
|
+
"body_limit_bytes": null,
|
|
2142
|
+
"lane": "heavy",
|
|
2143
|
+
"query": { "url": "string" },
|
|
2144
|
+
"request": {},
|
|
2145
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
2146
|
+
"response_headers": ["cache-control", "content-type", "x-terminus-url"],
|
|
2147
|
+
"errors": [
|
|
2148
|
+
"bad_request",
|
|
2149
|
+
"deadline_exceeded",
|
|
2150
|
+
"forbidden",
|
|
2151
|
+
"payload_too_large",
|
|
2152
|
+
"session_ended",
|
|
2153
|
+
"unauthorized",
|
|
2154
|
+
"upstream_failed",
|
|
2155
|
+
"url_not_allowed"
|
|
2156
|
+
],
|
|
2157
|
+
"hosts": { "production": true, "dev": true },
|
|
2158
|
+
"sdk": ["net.image"]
|
|
2159
|
+
},
|
|
2160
|
+
{
|
|
2161
|
+
"id": "connectors.request",
|
|
2162
|
+
"method": "POST",
|
|
2163
|
+
"path": "/connectors/{slug}/request",
|
|
2164
|
+
"upstream": "/v1/app-runtime/connectors/{slug}/request",
|
|
2165
|
+
"summary": "Calls a declared connector's provider API with the person's own credential, which never reaches the app. path is an absolute provider path under the connector's configured base (base_url may only restate that base); platform-controlled headers (authorization, cookie, host, content-length, content-type, proxy-*, x-forwarded-*, x-terminus-*) are refused; the body is sent as JSON and both it and the response are at most 2 MiB. Without resource_grant_id only GET, or a declared tool profile, is allowed. With a resource grant a read is recorded as an observation and a write is staged for approval or applied under scoped_auto. The body comes back as UTF-8 text, or as body_base64 when it is not UTF-8 (D14).",
|
|
2166
|
+
"auth": "app_session",
|
|
2167
|
+
"guest_allowed": false,
|
|
2168
|
+
"space_id": "body",
|
|
2169
|
+
"idempotency": "optional",
|
|
2170
|
+
"body": "json",
|
|
2171
|
+
"body_limit_bytes": 2097152,
|
|
2172
|
+
"lane": "heavy",
|
|
2173
|
+
"query": {},
|
|
2174
|
+
"request": {
|
|
2175
|
+
"method?": "GET|POST|PUT|PATCH|DELETE",
|
|
2176
|
+
"path": "string",
|
|
2177
|
+
"base_url?": "string",
|
|
2178
|
+
"query?": "object",
|
|
2179
|
+
"headers?": "object",
|
|
2180
|
+
"body?": "json",
|
|
2181
|
+
"resource_grant_id?": "string",
|
|
2182
|
+
"space_id?": "string"
|
|
2183
|
+
},
|
|
2184
|
+
"response": {
|
|
2185
|
+
"kind": "json",
|
|
2186
|
+
"fields": { "$body": "ConnectorResponse" },
|
|
2187
|
+
"variants": [
|
|
2188
|
+
{
|
|
2189
|
+
"when": "a write under a resource grant (staged or applied)",
|
|
2190
|
+
"fields": { "$body": "ConnectorAction" }
|
|
2191
|
+
}
|
|
2192
|
+
]
|
|
2193
|
+
},
|
|
2194
|
+
"response_headers": [],
|
|
2195
|
+
"errors": [
|
|
2196
|
+
"bad_request",
|
|
2197
|
+
"deadline_exceeded",
|
|
2198
|
+
"forbidden",
|
|
2199
|
+
"idempotency_conflict",
|
|
2200
|
+
"not_found",
|
|
2201
|
+
"not_implemented",
|
|
2202
|
+
"payload_too_large",
|
|
2203
|
+
"rate_limited",
|
|
2204
|
+
"session_ended",
|
|
2205
|
+
"still_pending",
|
|
2206
|
+
"unauthorized",
|
|
2207
|
+
"unsupported_in_dev",
|
|
2208
|
+
"upstream_failed"
|
|
2209
|
+
],
|
|
2210
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2211
|
+
"sdk": ["connectors.request"]
|
|
2212
|
+
},
|
|
2213
|
+
{
|
|
2214
|
+
"id": "services.invoke",
|
|
2215
|
+
"method": "POST",
|
|
2216
|
+
"path": "/services/{publisher}/{slug}/{operation}",
|
|
2217
|
+
"upstream": "/v1/app-runtime/services/{publisher}/{slug}/{operation}",
|
|
2218
|
+
"summary": "Invokes one exact operation of a service the release declared (capabilities.services address and operation; publisher is the handle without '@'). The provider receives a short-lived Terminus invocation token, never the person's or the app's credential. input and body_base64 are mutually exclusive. Bills the caller's credits (402 quota_exceeded when short); a job-contract operation answers status 202 with the ServiceJob as JSON text in body.",
|
|
2219
|
+
"auth": "app_session",
|
|
2220
|
+
"guest_allowed": false,
|
|
2221
|
+
"space_id": "none",
|
|
2222
|
+
"idempotency": "optional",
|
|
2223
|
+
"body": "json",
|
|
2224
|
+
"body_limit_bytes": 12582912,
|
|
2225
|
+
"lane": "heavy",
|
|
2226
|
+
"query": {},
|
|
2227
|
+
"request": { "input?": "json", "body_base64?": "string", "query?": "object" },
|
|
2228
|
+
"response": { "kind": "json", "fields": { "$body": "ExternalServiceInvocation" } },
|
|
2229
|
+
"response_headers": [],
|
|
2230
|
+
"errors": [
|
|
2231
|
+
"bad_request",
|
|
2232
|
+
"deadline_exceeded",
|
|
2233
|
+
"forbidden",
|
|
2234
|
+
"idempotency_conflict",
|
|
2235
|
+
"not_found",
|
|
2236
|
+
"payload_too_large",
|
|
2237
|
+
"quota_exceeded",
|
|
2238
|
+
"session_ended",
|
|
2239
|
+
"still_pending",
|
|
2240
|
+
"unauthorized",
|
|
2241
|
+
"unsupported_in_dev",
|
|
2242
|
+
"upstream_failed"
|
|
2243
|
+
],
|
|
2244
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2245
|
+
"sdk": [
|
|
2246
|
+
"services.invoke",
|
|
2247
|
+
"services.json",
|
|
2248
|
+
"services.search",
|
|
2249
|
+
"services.fetch",
|
|
2250
|
+
"services.generateImage",
|
|
2251
|
+
"services.convertDocument",
|
|
2252
|
+
"services.executeCode",
|
|
2253
|
+
"services.sendEmail"
|
|
2254
|
+
]
|
|
2255
|
+
},
|
|
2256
|
+
{
|
|
2257
|
+
"id": "service_jobs.get",
|
|
2258
|
+
"method": "GET",
|
|
2259
|
+
"path": "/service-jobs/{id}",
|
|
2260
|
+
"upstream": "/v1/app-runtime/service-jobs/{id}",
|
|
2261
|
+
"summary": "A service job this installation submitted; result is null unless the caller may read it.",
|
|
2262
|
+
"auth": "app_session",
|
|
2263
|
+
"guest_allowed": false,
|
|
2264
|
+
"space_id": "none",
|
|
2265
|
+
"idempotency": "none",
|
|
2266
|
+
"body": "none",
|
|
2267
|
+
"body_limit_bytes": null,
|
|
2268
|
+
"lane": "interactive",
|
|
2269
|
+
"query": {},
|
|
2270
|
+
"request": {},
|
|
2271
|
+
"response": { "kind": "json", "fields": { "$body": "ServiceJob" } },
|
|
2272
|
+
"response_headers": ["cache-control"],
|
|
2273
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized", "unsupported_in_dev"],
|
|
2274
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2275
|
+
"sdk": ["services.jobs.get", "services.jobs.wait"]
|
|
2276
|
+
},
|
|
2277
|
+
{
|
|
2278
|
+
"id": "service_jobs.cancel",
|
|
2279
|
+
"method": "POST",
|
|
2280
|
+
"path": "/service-jobs/{id}/cancel",
|
|
2281
|
+
"upstream": "/v1/app-runtime/service-jobs/{id}/cancel",
|
|
2282
|
+
"summary": "Requests cancellation of a queued or running service job and answers the job.",
|
|
2283
|
+
"auth": "app_session",
|
|
2284
|
+
"guest_allowed": false,
|
|
2285
|
+
"space_id": "none",
|
|
2286
|
+
"idempotency": "none",
|
|
2287
|
+
"body": "none",
|
|
2288
|
+
"body_limit_bytes": null,
|
|
2289
|
+
"lane": "interactive",
|
|
2290
|
+
"query": {},
|
|
2291
|
+
"request": {},
|
|
2292
|
+
"response": { "kind": "json", "fields": { "$body": "ServiceJob" } },
|
|
2293
|
+
"response_headers": ["cache-control"],
|
|
2294
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized", "unsupported_in_dev"],
|
|
2295
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2296
|
+
"sdk": ["services.jobs.cancel"]
|
|
2297
|
+
},
|
|
2298
|
+
{
|
|
2299
|
+
"id": "service_jobs.file",
|
|
2300
|
+
"method": "GET",
|
|
2301
|
+
"path": "/service-jobs/{id}/files/{file}",
|
|
2302
|
+
"upstream": "/v1/app-runtime/service-jobs/{id}/files/{file}",
|
|
2303
|
+
"summary": "One result file of a service job, as an attachment, never cached.",
|
|
2304
|
+
"auth": "app_session",
|
|
2305
|
+
"guest_allowed": false,
|
|
2306
|
+
"space_id": "none",
|
|
2307
|
+
"idempotency": "none",
|
|
2308
|
+
"body": "none",
|
|
2309
|
+
"body_limit_bytes": null,
|
|
2310
|
+
"lane": "heavy",
|
|
2311
|
+
"query": {},
|
|
2312
|
+
"request": {},
|
|
2313
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
2314
|
+
"response_headers": ["cache-control", "content-disposition", "content-type"],
|
|
2315
|
+
"errors": [
|
|
2316
|
+
"bad_request",
|
|
2317
|
+
"forbidden",
|
|
2318
|
+
"not_found",
|
|
2319
|
+
"session_ended",
|
|
2320
|
+
"unauthorized",
|
|
2321
|
+
"unsupported_in_dev"
|
|
2322
|
+
],
|
|
2323
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2324
|
+
"sdk": ["services.jobs.file"]
|
|
2325
|
+
},
|
|
2326
|
+
{
|
|
2327
|
+
"id": "service_jobs.save",
|
|
2328
|
+
"method": "POST",
|
|
2329
|
+
"path": "/service-jobs/{id}/files/{file}/save",
|
|
2330
|
+
"upstream": "/v1/app-runtime/service-jobs/{id}/files/{file}/save",
|
|
2331
|
+
"summary": "Saves a result file into the person's home/, which needs a write grant covering the destination; without expected_sha256 the destination must not exist, with it the value must equal the current sha256.",
|
|
2332
|
+
"auth": "app_session",
|
|
2333
|
+
"guest_allowed": false,
|
|
2334
|
+
"space_id": "none",
|
|
2335
|
+
"idempotency": "none",
|
|
2336
|
+
"body": "json",
|
|
2337
|
+
"body_limit_bytes": 262144,
|
|
2338
|
+
"lane": "heavy",
|
|
2339
|
+
"query": {},
|
|
2340
|
+
"request": { "path": "string", "expected_sha256?": "string" },
|
|
2341
|
+
"response": { "kind": "json", "fields": { "path": "string" } },
|
|
2342
|
+
"response_headers": [],
|
|
2343
|
+
"errors": [
|
|
2344
|
+
"bad_request",
|
|
2345
|
+
"forbidden",
|
|
2346
|
+
"not_found",
|
|
2347
|
+
"payload_too_large",
|
|
2348
|
+
"quota_exceeded",
|
|
2349
|
+
"session_ended",
|
|
2350
|
+
"unauthorized",
|
|
2351
|
+
"unsupported_in_dev",
|
|
2352
|
+
"version_conflict"
|
|
2353
|
+
],
|
|
2354
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2355
|
+
"sdk": ["services.jobs.save"]
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
"id": "capabilities.list",
|
|
2359
|
+
"method": "GET",
|
|
2360
|
+
"path": "/capabilities",
|
|
2361
|
+
"upstream": "/v1/capabilities",
|
|
2362
|
+
"summary": "The horizontal capability registry, narrowed to the capabilities this release declared.",
|
|
2363
|
+
"auth": "app_session",
|
|
2364
|
+
"guest_allowed": false,
|
|
2365
|
+
"space_id": "none",
|
|
2366
|
+
"idempotency": "none",
|
|
2367
|
+
"body": "none",
|
|
2368
|
+
"body_limit_bytes": null,
|
|
2369
|
+
"lane": "interactive",
|
|
2370
|
+
"query": {},
|
|
2371
|
+
"request": {},
|
|
2372
|
+
"response": { "kind": "json", "fields": { "$body": "json" } },
|
|
2373
|
+
"response_headers": [],
|
|
2374
|
+
"errors": ["session_ended", "unauthorized"],
|
|
2375
|
+
"hosts": { "production": true, "dev": true },
|
|
2376
|
+
"sdk": ["horizontal.list"]
|
|
2377
|
+
},
|
|
2378
|
+
{
|
|
2379
|
+
"id": "capabilities.describe",
|
|
2380
|
+
"method": "GET",
|
|
2381
|
+
"path": "/capabilities/{id}/{major}",
|
|
2382
|
+
"upstream": "/v1/capabilities/{id}/{major}",
|
|
2383
|
+
"summary": "One declared capability's descriptor; major is 'v' and the integer major version (v1).",
|
|
2384
|
+
"auth": "app_session",
|
|
2385
|
+
"guest_allowed": false,
|
|
2386
|
+
"space_id": "none",
|
|
2387
|
+
"idempotency": "none",
|
|
2388
|
+
"body": "none",
|
|
2389
|
+
"body_limit_bytes": null,
|
|
2390
|
+
"lane": "interactive",
|
|
2391
|
+
"query": {},
|
|
2392
|
+
"request": {},
|
|
2393
|
+
"response": { "kind": "json", "fields": { "$body": "json" } },
|
|
2394
|
+
"response_headers": [],
|
|
2395
|
+
"errors": ["bad_request", "forbidden", "not_found", "session_ended", "unauthorized"],
|
|
2396
|
+
"hosts": { "production": true, "dev": true },
|
|
2397
|
+
"sdk": ["horizontal.describe", "horizontal.require"]
|
|
2398
|
+
},
|
|
2399
|
+
{
|
|
2400
|
+
"id": "capabilities.invoke",
|
|
2401
|
+
"method": "POST",
|
|
2402
|
+
"path": "/capabilities/{id}/{major}/operations/{operation_id}",
|
|
2403
|
+
"upstream": "/v1/capabilities/{id}/{major}/operations/{operation_id}",
|
|
2404
|
+
"summary": "Runs one declared operation of a declared capability with a JSON input of at most 1 MiB and answers its JSON result. Brokered operations (web-search, maps geocode and provider-session) spend platform-held provider credentials, the per-user budget and any registry price in credits.",
|
|
2405
|
+
"auth": "app_session",
|
|
2406
|
+
"guest_allowed": false,
|
|
2407
|
+
"space_id": "none",
|
|
2408
|
+
"idempotency": "none",
|
|
2409
|
+
"body": "json",
|
|
2410
|
+
"body_limit_bytes": 1048576,
|
|
2411
|
+
"lane": "interactive",
|
|
2412
|
+
"query": {},
|
|
2413
|
+
"request": { "$body": "json" },
|
|
2414
|
+
"response": { "kind": "json", "fields": { "$body": "json" } },
|
|
2415
|
+
"response_headers": [],
|
|
2416
|
+
"errors": [
|
|
2417
|
+
"bad_request",
|
|
2418
|
+
"forbidden",
|
|
2419
|
+
"not_found",
|
|
2420
|
+
"payload_too_large",
|
|
2421
|
+
"quota_exceeded",
|
|
2422
|
+
"rate_limited",
|
|
2423
|
+
"session_ended",
|
|
2424
|
+
"unauthorized",
|
|
2425
|
+
"upstream_failed"
|
|
2426
|
+
],
|
|
2427
|
+
"hosts": { "production": true, "dev": true },
|
|
2428
|
+
"sdk": ["horizontal.invoke"]
|
|
2429
|
+
},
|
|
2430
|
+
{
|
|
2431
|
+
"id": "capabilities.asset",
|
|
2432
|
+
"method": "GET",
|
|
2433
|
+
"path": "/capabilities/{id}/{major}/assets/{*path}",
|
|
2434
|
+
"upstream": "/v1/capabilities/{id}/{major}/assets/{*path}",
|
|
2435
|
+
"summary": "A platform-served capability asset (module, stylesheet, font). It answers an ETag with Cache-Control no-cache and 304 to a matching If-None-Match, so an updated capability is never served stale (D30); only content-named files are immutable. A guest of an app open to guests reaches it too, for a capability the app's current release declares.",
|
|
2436
|
+
"auth": "app_session",
|
|
2437
|
+
"guest_allowed": true,
|
|
2438
|
+
"space_id": "none",
|
|
2439
|
+
"idempotency": "none",
|
|
2440
|
+
"body": "none",
|
|
2441
|
+
"body_limit_bytes": null,
|
|
2442
|
+
"lane": "interactive",
|
|
2443
|
+
"query": {},
|
|
2444
|
+
"request": {},
|
|
2445
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
2446
|
+
"response_headers": ["cache-control", "content-type", "etag"],
|
|
2447
|
+
"errors": ["forbidden", "not_found", "session_ended", "unauthorized"],
|
|
2448
|
+
"hosts": { "production": true, "dev": true },
|
|
2449
|
+
"sdk": [
|
|
2450
|
+
"horizontal.assetUrl",
|
|
2451
|
+
"horizontal.moduleUrl",
|
|
2452
|
+
"horizontal.loadModule",
|
|
2453
|
+
"horizontal.loadStyle",
|
|
2454
|
+
"horizontal.require"
|
|
2455
|
+
]
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
"id": "egress.request",
|
|
2459
|
+
"method": "POST",
|
|
2460
|
+
"path": "/egress/{template}",
|
|
2461
|
+
"upstream": "/v1/app-runtime/egress/{template}",
|
|
2462
|
+
"summary": "Runs one egress template the release declared: the platform renders its URL, query, headers (sealed secrets included) and body from params, pins the connection to a public address of the template's literal host (same-host redirects only, at most 3) and answers the upstream response, at most the template's max_response_bytes (2 MiB by default). At most 500 calls per app and person per day. 403 forbidden when the caller may not use the release's sealed secrets (a draft's Test window whose maker cannot publish the app).",
|
|
2463
|
+
"auth": "app_session",
|
|
2464
|
+
"guest_allowed": false,
|
|
2465
|
+
"space_id": "none",
|
|
2466
|
+
"idempotency": "none",
|
|
2467
|
+
"body": "json",
|
|
2468
|
+
"body_limit_bytes": 262144,
|
|
2469
|
+
"lane": "heavy",
|
|
2470
|
+
"query": {},
|
|
2471
|
+
"request": { "params?": "object" },
|
|
2472
|
+
"response": {
|
|
2473
|
+
"kind": "json",
|
|
2474
|
+
"fields": {
|
|
2475
|
+
"status": "integer",
|
|
2476
|
+
"content_type": "string",
|
|
2477
|
+
"body": "string|null",
|
|
2478
|
+
"body_base64": "string|null"
|
|
2479
|
+
}
|
|
2480
|
+
},
|
|
2481
|
+
"response_headers": [],
|
|
2482
|
+
"errors": [
|
|
2483
|
+
"bad_request",
|
|
2484
|
+
"deadline_exceeded",
|
|
2485
|
+
"forbidden",
|
|
2486
|
+
"not_found",
|
|
2487
|
+
"payload_too_large",
|
|
2488
|
+
"rate_limited",
|
|
2489
|
+
"session_ended",
|
|
2490
|
+
"unauthorized",
|
|
2491
|
+
"unsupported_in_dev",
|
|
2492
|
+
"upstream_failed",
|
|
2493
|
+
"url_not_allowed"
|
|
2494
|
+
],
|
|
2495
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2496
|
+
"sdk": ["egress.request"]
|
|
2497
|
+
},
|
|
2498
|
+
{
|
|
2499
|
+
"id": "server.call",
|
|
2500
|
+
"method": "POST",
|
|
2501
|
+
"path": "/server/{op}",
|
|
2502
|
+
"upstream": "/v1/app-runtime/server/{op}",
|
|
2503
|
+
"summary": "Runs one of the app's own server ops (compiled from its server/ code) on the app server tier under the interactive cap (at most 10 s); a background-only op is refused. 503 server_disabled while app server code is switched off, 503 server_unavailable when the tier is not configured or unreachable.",
|
|
2504
|
+
"auth": "app_session",
|
|
2505
|
+
"guest_allowed": false,
|
|
2506
|
+
"space_id": "none",
|
|
2507
|
+
"idempotency": "none",
|
|
2508
|
+
"body": "json",
|
|
2509
|
+
"body_limit_bytes": 262144,
|
|
2510
|
+
"lane": "heavy",
|
|
2511
|
+
"query": {},
|
|
2512
|
+
"request": { "input?": "json" },
|
|
2513
|
+
"response": { "kind": "json", "fields": { "result": "json" } },
|
|
2514
|
+
"response_headers": [],
|
|
2515
|
+
"errors": [
|
|
2516
|
+
"bad_request",
|
|
2517
|
+
"deadline_exceeded",
|
|
2518
|
+
"not_found",
|
|
2519
|
+
"payload_too_large",
|
|
2520
|
+
"server_disabled",
|
|
2521
|
+
"server_unavailable",
|
|
2522
|
+
"session_ended",
|
|
2523
|
+
"unauthorized",
|
|
2524
|
+
"upstream_failed"
|
|
2525
|
+
],
|
|
2526
|
+
"hosts": { "production": true, "dev": true },
|
|
2527
|
+
"sdk": ["server.call"]
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
"id": "collect.submit",
|
|
2531
|
+
"method": "POST",
|
|
2532
|
+
"path": "/collect/{channel}",
|
|
2533
|
+
"upstream": "/v1/app-runtime/collect/{channel}",
|
|
2534
|
+
"summary": "Sends what the person submits to the app's maintainers over a declared documents channel. The first use needs the person's one-time consent (403 grant_required); the payload is at most 64 KiB; 100 submissions per installation, channel and day. Delivery waits out a 120-second undo window.",
|
|
2535
|
+
"auth": "app_session",
|
|
2536
|
+
"guest_allowed": false,
|
|
2537
|
+
"space_id": "none",
|
|
2538
|
+
"idempotency": "optional",
|
|
2539
|
+
"body": "json",
|
|
2540
|
+
"body_limit_bytes": 262144,
|
|
2541
|
+
"lane": "interactive",
|
|
2542
|
+
"query": {},
|
|
2543
|
+
"request": { "payload": "json" },
|
|
2544
|
+
"response": { "kind": "json", "fields": { "$body": "CollectSubmission" } },
|
|
2545
|
+
"response_headers": [],
|
|
2546
|
+
"errors": [
|
|
2547
|
+
"bad_request",
|
|
2548
|
+
"forbidden",
|
|
2549
|
+
"grant_required",
|
|
2550
|
+
"idempotency_conflict",
|
|
2551
|
+
"payload_too_large",
|
|
2552
|
+
"rate_limited",
|
|
2553
|
+
"session_ended",
|
|
2554
|
+
"still_pending",
|
|
2555
|
+
"unauthorized"
|
|
2556
|
+
],
|
|
2557
|
+
"hosts": { "production": true, "dev": true },
|
|
2558
|
+
"sdk": ["collect.submit"]
|
|
2559
|
+
},
|
|
2560
|
+
{
|
|
2561
|
+
"id": "collect.retract",
|
|
2562
|
+
"method": "POST",
|
|
2563
|
+
"path": "/collect/{channel}/{document_id}/retract",
|
|
2564
|
+
"upstream": "/v1/app-runtime/collect/{channel}/{document_id}/retract",
|
|
2565
|
+
"summary": "The author takes a submission back: inside the undo window it is deleted outright (undone), afterwards its payload is shed and a tombstone stays (retracted).",
|
|
2566
|
+
"auth": "app_session",
|
|
2567
|
+
"guest_allowed": false,
|
|
2568
|
+
"space_id": "none",
|
|
2569
|
+
"idempotency": "none",
|
|
2570
|
+
"body": "none",
|
|
2571
|
+
"body_limit_bytes": null,
|
|
2572
|
+
"lane": "interactive",
|
|
2573
|
+
"query": {},
|
|
2574
|
+
"request": {},
|
|
2575
|
+
"response": {
|
|
2576
|
+
"kind": "json",
|
|
2577
|
+
"fields": { "id": "string", "undone?": "boolean", "retracted?": "boolean" }
|
|
2578
|
+
},
|
|
2579
|
+
"response_headers": [],
|
|
2580
|
+
"errors": ["bad_request", "not_found", "session_ended", "unauthorized"],
|
|
2581
|
+
"hosts": { "production": true, "dev": true },
|
|
2582
|
+
"sdk": ["collect.retract"]
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
"id": "host.icon",
|
|
2586
|
+
"method": "GET",
|
|
2587
|
+
"also_head": true,
|
|
2588
|
+
"path": "/icon",
|
|
2589
|
+
"upstream": "/v1/app-runtime/icon",
|
|
2590
|
+
"upstream_method": "GET",
|
|
2591
|
+
"worker_handled": true,
|
|
2592
|
+
"summary": "The platform-owned app icon (bootstrap app.icon_url), sessionless so it works on consent screens and for guests; the app host asks the backend by its own host name and passes If-None-Match through.",
|
|
2593
|
+
"auth": "none",
|
|
2594
|
+
"guest_allowed": true,
|
|
2595
|
+
"space_id": "none",
|
|
2596
|
+
"idempotency": "none",
|
|
2597
|
+
"body": "none",
|
|
2598
|
+
"body_limit_bytes": null,
|
|
2599
|
+
"lane": "interactive",
|
|
2600
|
+
"query": {},
|
|
2601
|
+
"request": {},
|
|
2602
|
+
"response": { "kind": "bytes", "fields": {} },
|
|
2603
|
+
"response_headers": ["cache-control", "content-type", "etag"],
|
|
2604
|
+
"errors": ["not_found"],
|
|
2605
|
+
"hosts": { "production": true, "dev": true },
|
|
2606
|
+
"sdk": []
|
|
2607
|
+
},
|
|
2608
|
+
{
|
|
2609
|
+
"id": "host.logout",
|
|
2610
|
+
"method": "POST",
|
|
2611
|
+
"path": "/logout",
|
|
2612
|
+
"upstream": "/v1/app-runtime/session/current",
|
|
2613
|
+
"upstream_method": "DELETE",
|
|
2614
|
+
"worker_handled": true,
|
|
2615
|
+
"summary": "Signs the person out of this app on this device: the app host revokes the session (DELETE upstream), clears its cookie and redirects to the platform's sign-in page for the app; on an app open to guests it also marks the browser a guest (guest.marker_cookie), so the app opens as a guest next time instead of signing straight back in. Same-origin only. terminus dev forgets the member's sign-in instead (a guest seat becomes a guest again).",
|
|
2616
|
+
"auth": "none",
|
|
2617
|
+
"guest_allowed": true,
|
|
2618
|
+
"space_id": "none",
|
|
2619
|
+
"idempotency": "none",
|
|
2620
|
+
"body": "none",
|
|
2621
|
+
"body_limit_bytes": null,
|
|
2622
|
+
"lane": "interactive",
|
|
2623
|
+
"query": {},
|
|
2624
|
+
"request": {},
|
|
2625
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
2626
|
+
"response_headers": ["location"],
|
|
2627
|
+
"errors": ["forbidden"],
|
|
2628
|
+
"hosts": { "production": true, "dev": true },
|
|
2629
|
+
"sdk": ["session.signOut"]
|
|
2630
|
+
},
|
|
2631
|
+
{
|
|
2632
|
+
"id": "host.callback",
|
|
2633
|
+
"method": "GET",
|
|
2634
|
+
"path": "/callback",
|
|
2635
|
+
"upstream": "/v1/app-runtime/session",
|
|
2636
|
+
"upstream_method": "POST",
|
|
2637
|
+
"worker_handled": true,
|
|
2638
|
+
"summary": "Sign-in landing: the app host exchanges the one-time code (POST upstream), sets its HttpOnly session cookie and redirects to return_to or the path a signed-out visit asked for (same-origin paths only). A navigation: failures render an HTML page.",
|
|
2639
|
+
"auth": "none",
|
|
2640
|
+
"guest_allowed": true,
|
|
2641
|
+
"space_id": "none",
|
|
2642
|
+
"idempotency": "none",
|
|
2643
|
+
"body": "none",
|
|
2644
|
+
"body_limit_bytes": null,
|
|
2645
|
+
"lane": "interactive",
|
|
2646
|
+
"query": { "code": "string", "return_to?": "string" },
|
|
2647
|
+
"request": {},
|
|
2648
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
2649
|
+
"response_headers": ["location"],
|
|
2650
|
+
"errors": ["bad_request", "unauthorized", "unsupported_in_dev"],
|
|
2651
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2652
|
+
"sdk": []
|
|
2653
|
+
},
|
|
2654
|
+
{
|
|
2655
|
+
"id": "host.open",
|
|
2656
|
+
"method": "GET",
|
|
2657
|
+
"path": "/open",
|
|
2658
|
+
"upstream": "/v1/app-runtime/session/identity",
|
|
2659
|
+
"upstream_method": "GET",
|
|
2660
|
+
"worker_handled": true,
|
|
2661
|
+
"summary": "How a place reaches an app that may already be open: with a live session (checked against the identity door) it redirects to /, otherwise it clears the cookie and redirects to the platform's authorization page for the app. A navigation.",
|
|
2662
|
+
"auth": "none",
|
|
2663
|
+
"guest_allowed": true,
|
|
2664
|
+
"space_id": "none",
|
|
2665
|
+
"idempotency": "none",
|
|
2666
|
+
"body": "none",
|
|
2667
|
+
"body_limit_bytes": null,
|
|
2668
|
+
"lane": "interactive",
|
|
2669
|
+
"query": {},
|
|
2670
|
+
"request": {},
|
|
2671
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
2672
|
+
"response_headers": ["location"],
|
|
2673
|
+
"errors": ["not_found", "unsupported_in_dev"],
|
|
2674
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2675
|
+
"sdk": []
|
|
2676
|
+
},
|
|
2677
|
+
{
|
|
2678
|
+
"id": "host.signin",
|
|
2679
|
+
"method": "GET",
|
|
2680
|
+
"path": "/signin",
|
|
2681
|
+
"upstream": "/v1/app-runtime/session/identity",
|
|
2682
|
+
"upstream_method": "GET",
|
|
2683
|
+
"worker_handled": true,
|
|
2684
|
+
"summary": "Sign in, then come back: the app host keeps return_to (a path on the app's own origin; anything else is /) and sends the navigation to the platform's authorization page with sign-in required, where a guest signs in or makes an account and comes back to return_to signed in. A live session (checked against the identity door) goes straight to return_to. terminus dev answers a guest seat with a page that picks the member to sign in as, and a member's port straight to return_to. A navigation.",
|
|
2685
|
+
"auth": "none",
|
|
2686
|
+
"guest_allowed": true,
|
|
2687
|
+
"space_id": "none",
|
|
2688
|
+
"idempotency": "none",
|
|
2689
|
+
"body": "none",
|
|
2690
|
+
"body_limit_bytes": null,
|
|
2691
|
+
"lane": "interactive",
|
|
2692
|
+
"query": { "return_to?": "string" },
|
|
2693
|
+
"request": {},
|
|
2694
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
2695
|
+
"response_headers": ["location"],
|
|
2696
|
+
"errors": ["not_found"],
|
|
2697
|
+
"hosts": { "production": true, "dev": true },
|
|
2698
|
+
"sdk": ["session.signIn"]
|
|
2699
|
+
},
|
|
2700
|
+
{
|
|
2701
|
+
"id": "host.guest",
|
|
2702
|
+
"method": "GET",
|
|
2703
|
+
"path": "/guest",
|
|
2704
|
+
"upstream": "/v1/app-runtime/resolve",
|
|
2705
|
+
"upstream_method": "GET",
|
|
2706
|
+
"worker_handled": true,
|
|
2707
|
+
"summary": "Where the platform's authorization page sends a signed-out visitor of an app open to guests: the app host marks the browser a guest (guest.marker_cookie, for guest.marker_max_age_seconds) so its page navigations are not sent to ask again, and redirects to the path the visit asked for. An app not open to guests goes to the authorization page instead. A navigation.",
|
|
2708
|
+
"auth": "none",
|
|
2709
|
+
"guest_allowed": true,
|
|
2710
|
+
"space_id": "none",
|
|
2711
|
+
"idempotency": "none",
|
|
2712
|
+
"body": "none",
|
|
2713
|
+
"body_limit_bytes": null,
|
|
2714
|
+
"lane": "interactive",
|
|
2715
|
+
"query": {},
|
|
2716
|
+
"request": {},
|
|
2717
|
+
"response": { "kind": "redirect", "fields": {} },
|
|
2718
|
+
"response_headers": ["location"],
|
|
2719
|
+
"errors": ["not_found", "unsupported_in_dev"],
|
|
2720
|
+
"hosts": { "production": true, "dev": "unsupported" },
|
|
2721
|
+
"sdk": []
|
|
2722
|
+
}
|
|
2723
|
+
],
|
|
2724
|
+
"frames": {
|
|
2725
|
+
"door": "events.stream",
|
|
2726
|
+
"encoding": "Each SSE message is one data line holding one JSON object; keep-alive comments carry no data.",
|
|
2727
|
+
"control": { "stream_open": { "type": "stream_open" }, "stream_gap": { "type": "stream_gap" } },
|
|
2728
|
+
"envelope": {
|
|
2729
|
+
"type": "space_event|account_event|presence",
|
|
2730
|
+
"transient": "boolean",
|
|
2731
|
+
"space_id": "string|null",
|
|
2732
|
+
"app_id": "string",
|
|
2733
|
+
"from": "EventOrigin",
|
|
2734
|
+
"event": "object",
|
|
2735
|
+
"published_at": "string"
|
|
2736
|
+
},
|
|
2737
|
+
"rules": [
|
|
2738
|
+
"The first frame is stream_open. On buffer lag or a dropped platform signal the server sends stream_gap and every durable reader (collections, collaboration journals, spaces, members, cursors) drains through its JSON door.",
|
|
2739
|
+
"No sequence number, no epoch and no replay: a (re)connect starts at stream_open and recovers state from the durable doors.",
|
|
2740
|
+
"Echo rule (D3): an event published through events.publish is never delivered to any session of its publisher, and a presence change is not echoed to the member who made it. Platform change signals (record_changed, record_delivered, collaboration_changed, object_changed, space_cursor_updated and the platform space updates) reach every member who can read the change, the writer's own sessions included: a change to a member's own (personal) collection reaches only that member even when opened in a space, a delivery sends each recipient the record_delivered frame of their own replica, and space-owned records and space updates reach every member.",
|
|
2741
|
+
"Every space-scoped frame of the app fans out to each member's account stream, so one stream per session hears every space it shares; account_event frames carry space_id null and name the space inside the event when they concern one.",
|
|
2742
|
+
"A durable record_changed frame carries the ledger's cursor and prev_cursor (a recovered wake — re-sent, with recovered true, for a commit whose live frame was never acknowledged as sent — carries the ledger's prev_cursor too, or none once retention has pruned it; a reader skips any frame at or below its cursor); it carries value (with created_by_user_id, updated_by_user_id, created_at and committed_at) only when the frame fits the 32 KiB payload limit and the collection's read policy grants the full record to every member. A frame without prev_cursor, or whose prev_cursor is not the reader's cursor, means drain the changes door.",
|
|
2743
|
+
"Transient frames (transient true: typing, object_changed, presence) are live-only and never retained.",
|
|
2744
|
+
"rooms=a,b narrows room_event frames to the listed rooms; every other frame flows."
|
|
2745
|
+
],
|
|
2746
|
+
"space_events": {
|
|
2747
|
+
"record_changed": {
|
|
2748
|
+
"type": "record_changed",
|
|
2749
|
+
"operation": "put|delete|reset",
|
|
2750
|
+
"collection": "string",
|
|
2751
|
+
"record_id?": "string",
|
|
2752
|
+
"version?": "integer|null",
|
|
2753
|
+
"mutation_id": "string",
|
|
2754
|
+
"cursor": "string",
|
|
2755
|
+
"prev_cursor?": "string",
|
|
2756
|
+
"transaction_id?": "string",
|
|
2757
|
+
"recovered?": "boolean",
|
|
2758
|
+
"value?": "object",
|
|
2759
|
+
"created_by_user_id?": "string|null",
|
|
2760
|
+
"updated_by_user_id?": "string|null",
|
|
2761
|
+
"created_at?": "string",
|
|
2762
|
+
"committed_at?": "string"
|
|
2763
|
+
},
|
|
2764
|
+
"record_delivered": {
|
|
2765
|
+
"type": "record_delivered",
|
|
2766
|
+
"collection": "string",
|
|
2767
|
+
"record_id": "string",
|
|
2768
|
+
"sequence": "integer",
|
|
2769
|
+
"mutation_id": "string"
|
|
2770
|
+
},
|
|
2771
|
+
"collaboration_changed": {
|
|
2772
|
+
"type": "collaboration_changed",
|
|
2773
|
+
"document_id": "string",
|
|
2774
|
+
"cursor": "string"
|
|
2775
|
+
},
|
|
2776
|
+
"object_changed": {
|
|
2777
|
+
"type": "object_changed",
|
|
2778
|
+
"plane": "data|storage",
|
|
2779
|
+
"zone?": "private|output",
|
|
2780
|
+
"bucket?": "string",
|
|
2781
|
+
"path": "string",
|
|
2782
|
+
"operation": "put|delete"
|
|
2783
|
+
},
|
|
2784
|
+
"space_cursor_updated": {
|
|
2785
|
+
"type": "space_cursor_updated",
|
|
2786
|
+
"user_id": "string",
|
|
2787
|
+
"delivered_through": "integer",
|
|
2788
|
+
"read_through": "integer"
|
|
2789
|
+
},
|
|
2790
|
+
"space_members_updated": { "type": "space_members_updated" },
|
|
2791
|
+
"space_invitations_updated": { "type": "space_invitations_updated" },
|
|
2792
|
+
"space_conversation_updated": { "type": "space_conversation_updated" },
|
|
2793
|
+
"space_relationship_updated": { "type": "space_relationship_updated" },
|
|
2794
|
+
"room_event": { "type": "room_event", "room_id": "string", "payload": "json" }
|
|
2795
|
+
},
|
|
2796
|
+
"account_events": {
|
|
2797
|
+
"notification.created": {
|
|
2798
|
+
"type": "notification.created",
|
|
2799
|
+
"notification_id": "string",
|
|
2800
|
+
"title": "string",
|
|
2801
|
+
"body": "string",
|
|
2802
|
+
"data": "json"
|
|
2803
|
+
},
|
|
2804
|
+
"space_membership_joined": { "type": "space_membership_joined", "space_id": "string" },
|
|
2805
|
+
"space_membership_left": { "type": "space_membership_left", "space_id": "string" },
|
|
2806
|
+
"space_invitation_resolved": { "type": "space_invitation_resolved", "space_id": "string" },
|
|
2807
|
+
"space_notifications_updated": { "type": "space_notifications_updated", "space_id": "string|null" },
|
|
2808
|
+
"space_deleted": { "type": "space_deleted", "space_id": "string" },
|
|
2809
|
+
"job.updated": {
|
|
2810
|
+
"type": "job.updated",
|
|
2811
|
+
"job_id": "string",
|
|
2812
|
+
"status": "queued|running|waiting|succeeded|failed|cancelled"
|
|
2813
|
+
}
|
|
2814
|
+
},
|
|
2815
|
+
"presence_event": { "online": "boolean", "state?": "json" }
|
|
2816
|
+
},
|
|
2817
|
+
"plumbing": [
|
|
2818
|
+
{
|
|
2819
|
+
"method": "GET",
|
|
2820
|
+
"upstream": "/v1/app-runtime/resolve",
|
|
2821
|
+
"caller": "worker",
|
|
2822
|
+
"summary": "Public discovery of an app by host (or by id, for the platform's authorization page): identity, whether it is open to guests and the release their files come from, and whether it has a browser interface."
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
"method": "GET",
|
|
2826
|
+
"upstream": "/v1/app-runtime/icon",
|
|
2827
|
+
"caller": "worker",
|
|
2828
|
+
"summary": "The platform-owned app icon by host, behind /_terminus/icon."
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
"method": "POST",
|
|
2832
|
+
"upstream": "/v1/app-runtime/session",
|
|
2833
|
+
"caller": "worker",
|
|
2834
|
+
"summary": "One-time authorization-code exchange for an app session token, behind /_terminus/callback."
|
|
2835
|
+
},
|
|
2836
|
+
{
|
|
2837
|
+
"method": "DELETE",
|
|
2838
|
+
"upstream": "/v1/app-runtime/session/current",
|
|
2839
|
+
"caller": "worker",
|
|
2840
|
+
"summary": "Revokes the app session, behind /_terminus/logout."
|
|
2841
|
+
},
|
|
2842
|
+
{
|
|
2843
|
+
"method": "GET",
|
|
2844
|
+
"upstream": "/v1/app-runtime/assets/{*path}",
|
|
2845
|
+
"caller": "worker",
|
|
2846
|
+
"summary": "Release assets of the session's pinned release."
|
|
2847
|
+
},
|
|
2848
|
+
{
|
|
2849
|
+
"method": "GET",
|
|
2850
|
+
"upstream": "/v1/app-runtime/guest-assets/{release_id}/{*path}",
|
|
2851
|
+
"caller": "worker",
|
|
2852
|
+
"summary": "Release files for guests, while the app is open to them: the release resolve names, and any other published, free release of the app, so a page a guest is loading stays whole in the minute after a publish. Never a draft's Test build."
|
|
2853
|
+
},
|
|
2854
|
+
{
|
|
2855
|
+
"method": "POST",
|
|
2856
|
+
"upstream": "/v1/app-runtime/authorizations",
|
|
2857
|
+
"caller": "web",
|
|
2858
|
+
"summary": "The product (and terminus dev --remote) mints a one-time authorization code to open an installed app."
|
|
2859
|
+
},
|
|
2860
|
+
{
|
|
2861
|
+
"method": "POST",
|
|
2862
|
+
"upstream": "/v1/app-runtime/dev-sessions",
|
|
2863
|
+
"caller": "cli",
|
|
2864
|
+
"summary": "terminus dev mints a capability dev session for the /v1/capabilities plane."
|
|
2865
|
+
}
|
|
2866
|
+
]
|
|
2867
|
+
}
|