@runlot/api 0.1.0-rc.78 → 0.1.0-rc.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.d.ts CHANGED
@@ -75,6 +75,35 @@ export interface paths {
75
75
  patch?: never;
76
76
  trace?: never;
77
77
  };
78
+ "/v1/auth/totp": {
79
+ parameters: {
80
+ query?: never;
81
+ header?: never;
82
+ path?: never;
83
+ cookie?: never;
84
+ };
85
+ get?: never;
86
+ put?: never;
87
+ /**
88
+ * Finish a sign-in with the second factor
89
+ * @description Takes the `pending` token a first factor handed back, plus either the six-digit
90
+ * code from the authenticator app or one recovery code. Success mints the real
91
+ * session.
92
+ *
93
+ * The pending token carries the account's session revision, so a password reset
94
+ * landing between the two steps kills the half-finished login too.
95
+ *
96
+ * A code is refused if its RFC 6238 step is at or below the last one already spent:
97
+ * one code is valid across three 30-second steps, so "it verified" is not "it may be
98
+ * spent" (migration 0066, `user_totp.last_used_step`).
99
+ */
100
+ post: operations["completeTotpLogin"];
101
+ delete?: never;
102
+ options?: never;
103
+ head?: never;
104
+ patch?: never;
105
+ trace?: never;
106
+ };
78
107
  "/v1/auth/password/forgot": {
79
108
  parameters: {
80
109
  query?: never;
@@ -335,6 +364,83 @@ export interface paths {
335
364
  patch?: never;
336
365
  trace?: never;
337
366
  };
367
+ "/v1/me/totp": {
368
+ parameters: {
369
+ query?: never;
370
+ header?: never;
371
+ path?: never;
372
+ cookie?: never;
373
+ };
374
+ /** This account's two-factor state */
375
+ get: operations["getTotp"];
376
+ put?: never;
377
+ post?: never;
378
+ /**
379
+ * Turn two-factor authentication off
380
+ * @description Costs a current code or one recovery code. **A session alone is not enough** — a
381
+ * stolen session removing the second factor would make the factor a formality.
382
+ *
383
+ * The recovery codes go with it, in the same transaction. Left behind they would
384
+ * open the *next* enrollment with codes printed for a device that is no longer the
385
+ * factor.
386
+ */
387
+ delete: operations["disableTotp"];
388
+ options?: never;
389
+ head?: never;
390
+ patch?: never;
391
+ trace?: never;
392
+ };
393
+ "/v1/me/totp/enroll": {
394
+ parameters: {
395
+ query?: never;
396
+ header?: never;
397
+ path?: never;
398
+ cookie?: never;
399
+ };
400
+ get?: never;
401
+ put?: never;
402
+ /**
403
+ * Generate an authenticator secret
404
+ * @description Draws a fresh 20-byte secret and returns it with the `otpauth://` URI to scan.
405
+ *
406
+ * **It does not turn the factor on.** `POST /v1/me/totp/confirm` does, and only after
407
+ * the app has proved it can produce a code — enabling here would let a scan that
408
+ * failed halfway lock the account out of its own dashboard.
409
+ *
410
+ * Re-enrolling over a *confirmed* authenticator is refused with 409: turn it off
411
+ * first, which itself costs a code.
412
+ */
413
+ post: operations["enrollTotp"];
414
+ delete?: never;
415
+ options?: never;
416
+ head?: never;
417
+ patch?: never;
418
+ trace?: never;
419
+ };
420
+ "/v1/me/totp/confirm": {
421
+ parameters: {
422
+ query?: never;
423
+ header?: never;
424
+ path?: never;
425
+ cookie?: never;
426
+ };
427
+ get?: never;
428
+ put?: never;
429
+ /**
430
+ * Confirm the authenticator and turn the factor on
431
+ * @description Verifies one code against the secret from `enroll` (RFC 6238, SHA-1, six digits,
432
+ * a 30-second step, ±1 step), turns the factor on, and issues ten recovery codes.
433
+ *
434
+ * **The recovery codes are readable only in this response.** They are argon2id in
435
+ * the table, so there is no endpoint that lists them later.
436
+ */
437
+ post: operations["confirmTotp"];
438
+ delete?: never;
439
+ options?: never;
440
+ head?: never;
441
+ patch?: never;
442
+ trace?: never;
443
+ };
338
444
  "/v1/orgs": {
339
445
  parameters: {
340
446
  query?: never;
@@ -620,6 +726,13 @@ export interface paths {
620
726
  * 200 chars)
621
727
  * X-Runlot-Git-Branch branch name, percent-encoded
622
728
  * X-Runlot-Git-Dirty `true`|`false` — whether there were uncommitted changes
729
+ *
730
+ * **With `?preview=<name>`** (docs/preview.md) this deploys to a preview and **the
731
+ * deployment does not become production's live pointer** — production keeps serving
732
+ * whatever it was serving, and the version numbers are the preview's own. The 201 body
733
+ * is the same `Deployment` with one field added, `preview`, holding the `Preview` this
734
+ * went to; it is the only place the new hostname is reported, because the caller that
735
+ * just created a preview is the one caller that cannot list it yet.
623
736
  */
624
737
  post: operations["createDeployment"];
625
738
  delete?: never;
@@ -663,6 +776,239 @@ export interface paths {
663
776
  patch?: never;
664
777
  trace?: never;
665
778
  };
779
+ "/v1/orgs/{orgSlug}/projects/{projectName}/queues": {
780
+ parameters: {
781
+ query?: never;
782
+ header?: never;
783
+ path: {
784
+ orgSlug: components["parameters"]["OrgSlug"];
785
+ projectName: components["parameters"]["ProjectName"];
786
+ };
787
+ cookie?: never;
788
+ };
789
+ /**
790
+ * Queues: what is declared, how deep each is, what happened (`runlot queue list`)
791
+ * @description Requires viewer or higher. One call, for the same reason as `getProjectCron`
792
+ * (docs/queues.md §6): the declaration, the depth and the last verdict are only useful
793
+ * together.
794
+ *
795
+ * `queues` comes from the **live** deployment's manifest, one row per distinct name
796
+ * across producers, consumers and dead-letter queues, in declaration order. The
797
+ * consumer's numbers are already folded to their defaults (`maxBatchSize` 10,
798
+ * `maxBatchTimeout` 5 s, `maxRetries` 3).
799
+ *
800
+ * **The depth is read from the project's own database** — the messages live in the
801
+ * `runlot_queue` schema there, not on the control plane. A queue nothing has ever sent
802
+ * to reads as empty (the schema is installed on the first send). If the project's
803
+ * database cannot be reached, `depthError` says so and `depth` is absent on every
804
+ * row; the declarations and the history are still answered.
805
+ *
806
+ * History is one row per **batch**, kept for `keepDays` (30 days free, 365 pro) and
807
+ * then pruned. `opsToday` and `opsCap` are the project's daily operation count and
808
+ * its plan's cap (free 10,000, pro 1,000,000; a send is one, a delivery is one).
809
+ */
810
+ get: operations["getProjectQueues"];
811
+ put?: never;
812
+ post?: never;
813
+ delete?: never;
814
+ options?: never;
815
+ head?: never;
816
+ patch?: never;
817
+ trace?: never;
818
+ };
819
+ "/v1/orgs/{orgSlug}/projects/{projectName}/vectors": {
820
+ parameters: {
821
+ query?: never;
822
+ header?: never;
823
+ path: {
824
+ orgSlug: components["parameters"]["OrgSlug"];
825
+ projectName: components["parameters"]["ProjectName"];
826
+ };
827
+ cookie?: never;
828
+ };
829
+ /**
830
+ * Vector store: namespaces, counts, widths and the plan's bounds (`runlot vectors list`)
831
+ * @description Requires viewer or higher. What `env.vectors` holds, namespace by namespace, read
832
+ * from the project's own database (`runlot_vector.items`, docs/vectors.md §4) over
833
+ * the same road the SQL console takes. A project that has never written a vector
834
+ * reads as empty — the schema is installed on the first write. If the project's
835
+ * database cannot be reached, `readError` says so and the bounds are still answered.
836
+ *
837
+ * `limit` and `dimensionsMax` are the plan's bounds (free 5,000 vectors and 3,072
838
+ * dimensions, pro 25,000). `exact` is always true: search is exact k-NN in the
839
+ * worker, there is no approximate index, and a caller porting from Vectorize should
840
+ * be able to read that off the object.
841
+ */
842
+ get: operations["getProjectVectors"];
843
+ put?: never;
844
+ post?: never;
845
+ delete?: never;
846
+ options?: never;
847
+ head?: never;
848
+ patch?: never;
849
+ trace?: never;
850
+ };
851
+ "/v1/orgs/{orgSlug}/projects/{projectName}/vectors/{namespace}": {
852
+ parameters: {
853
+ query?: never;
854
+ header?: never;
855
+ path: {
856
+ orgSlug: components["parameters"]["OrgSlug"];
857
+ projectName: components["parameters"]["ProjectName"];
858
+ namespace: string;
859
+ };
860
+ cookie?: never;
861
+ };
862
+ get?: never;
863
+ put?: never;
864
+ post?: never;
865
+ /**
866
+ * Empties one namespace (`runlot vectors delete`)
867
+ * @description Requires member. Deletes every vector in the namespace and answers with the count.
868
+ * **Irreversible, and there is no confirmation on the server** — the CLI asks for one
869
+ * (or `--yes`), and a member can already run the same `DELETE` from psql. Audited as
870
+ * `vectors.delete` with the count. A namespace that does not exist answers 0.
871
+ */
872
+ delete: operations["deleteVectorNamespace"];
873
+ options?: never;
874
+ head?: never;
875
+ patch?: never;
876
+ trace?: never;
877
+ };
878
+ "/v1/orgs/{orgSlug}/projects/{projectName}/durable-objects": {
879
+ parameters: {
880
+ query?: never;
881
+ header?: never;
882
+ path: {
883
+ orgSlug: components["parameters"]["OrgSlug"];
884
+ projectName: components["parameters"]["ProjectName"];
885
+ };
886
+ cookie?: never;
887
+ };
888
+ /**
889
+ * Durable Objects: how many this project has placed, against the two caps
890
+ * @description Requires viewer or higher — the same role as the `vectors` and `queues` overviews
891
+ * next to it, for the same reason: this is a reading of the project's own usage, and
892
+ * the placement rows it counts are already readable by `runlot_public`.
893
+ *
894
+ * **It reports how much, never which.** There is no actor id and no owner id in the
895
+ * answer, and none is coming: those name individual objects, and an endpoint that
896
+ * listed them would be an object enumeration wearing a quota's name. A viewer asking
897
+ * "am I near my limit" is answered by the counts and the per-node breakdown; a viewer
898
+ * asking "what objects exist" is asking the application, which is the only thing that
899
+ * knows what its ids mean.
900
+ *
901
+ * A project that has placed nothing answers `count: 0` and an empty `nodes` object.
902
+ * That is the answer, not an error.
903
+ *
904
+ * Placing a **new** object once `count` has reached `limit` is refused with 409 and
905
+ * the code `object_capacity`; objects that already exist go on resolving and being
906
+ * served. **It is a limit on growth, not an outage.**
907
+ */
908
+ get: operations["getProjectDurableObjects"];
909
+ put?: never;
910
+ post?: never;
911
+ delete?: never;
912
+ options?: never;
913
+ head?: never;
914
+ patch?: never;
915
+ trace?: never;
916
+ };
917
+ "/v1/orgs/{orgSlug}/projects/{projectName}/queues/{queue}/runs": {
918
+ parameters: {
919
+ query?: never;
920
+ header?: never;
921
+ path: {
922
+ orgSlug: components["parameters"]["OrgSlug"];
923
+ projectName: components["parameters"]["ProjectName"];
924
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
925
+ queue: components["parameters"]["QueueName"];
926
+ };
927
+ cookie?: never;
928
+ };
929
+ /**
930
+ * One queue's batch history
931
+ * @description Requires viewer or higher. Newest first. The same rows `getProjectQueues` returns,
932
+ * narrowed to one queue — for a project whose busy queue would otherwise fill the page.
933
+ */
934
+ get: operations["listQueueRuns"];
935
+ put?: never;
936
+ post?: never;
937
+ delete?: never;
938
+ options?: never;
939
+ head?: never;
940
+ patch?: never;
941
+ trace?: never;
942
+ };
943
+ "/v1/orgs/{orgSlug}/projects/{projectName}/queues/{queue}/messages": {
944
+ parameters: {
945
+ query?: never;
946
+ header?: never;
947
+ path: {
948
+ orgSlug: components["parameters"]["OrgSlug"];
949
+ projectName: components["parameters"]["ProjectName"];
950
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
951
+ queue: components["parameters"]["QueueName"];
952
+ };
953
+ cookie?: never;
954
+ };
955
+ /**
956
+ * The next messages, without leasing them (`runlot queue peek`)
957
+ * @description Requires member. Reads the head of the queue in delivery order and **takes no
958
+ * lease**, so looking cannot delay a delivery. Each row carries a `preview` — the
959
+ * body clipped to 200 characters, or `<n bytes>` for a binary body — never the body
960
+ * itself. A queue whose schema is not installed yet answers an empty list.
961
+ */
962
+ get: operations["peekQueue"];
963
+ put?: never;
964
+ post?: never;
965
+ /**
966
+ * Empties the queue (`runlot queue purge`)
967
+ * @description Requires member. Deletes every message in the queue — visible, delayed and in
968
+ * flight — and answers with the count. **It is irreversible and there is no
969
+ * confirmation on the server**: the CLI asks for one (or `--yes`) and the dashboard
970
+ * asks for the queue's name typed back. A member can already run the same `DELETE`
971
+ * from psql with the credential `…/database/connect` hands out, so a server-side
972
+ * guard would protect nothing. The purge is audited with the count.
973
+ */
974
+ delete: operations["purgeQueue"];
975
+ options?: never;
976
+ head?: never;
977
+ patch?: never;
978
+ trace?: never;
979
+ };
980
+ "/v1/orgs/{orgSlug}/projects/{projectName}/queues/{queue}/redrive": {
981
+ parameters: {
982
+ query?: never;
983
+ header?: never;
984
+ path: {
985
+ orgSlug: components["parameters"]["OrgSlug"];
986
+ projectName: components["parameters"]["ProjectName"];
987
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
988
+ queue: components["parameters"]["QueueName"];
989
+ };
990
+ cookie?: never;
991
+ };
992
+ get?: never;
993
+ put?: never;
994
+ /**
995
+ * Moves a dead-letter queue's messages back (`runlot queue redrive`)
996
+ * @description Requires member. `{queue}` is the **dead-letter queue**. Every message in it that
997
+ * is not in flight moves to the destination with `attempts` reset to 0 — a redriven
998
+ * message gets the full retry budget of the queue it goes back to, which is the
999
+ * intended cost: redriving is a decision a person makes after fixing something.
1000
+ *
1001
+ * The destination is the consumer whose `deadLetterQueue` this is, read from the live
1002
+ * manifest. When two consumers share one dead-letter queue, or the queue is nobody's
1003
+ * dead-letter queue, `to` is required (`400`). The redrive is audited with the count.
1004
+ */
1005
+ post: operations["redriveQueue"];
1006
+ delete?: never;
1007
+ options?: never;
1008
+ head?: never;
1009
+ patch?: never;
1010
+ trace?: never;
1011
+ };
666
1012
  "/v1/orgs/{orgSlug}/projects/{projectName}/rollback": {
667
1013
  parameters: {
668
1014
  query?: never;
@@ -832,6 +1178,55 @@ export interface paths {
832
1178
  patch?: never;
833
1179
  trace?: never;
834
1180
  };
1181
+ "/v1/orgs/{orgSlug}/projects/{projectName}/database/execute": {
1182
+ parameters: {
1183
+ query?: never;
1184
+ header?: never;
1185
+ path: {
1186
+ orgSlug: components["parameters"]["OrgSlug"];
1187
+ projectName: components["parameters"]["ProjectName"];
1188
+ };
1189
+ cookie?: never;
1190
+ };
1191
+ get?: never;
1192
+ put?: never;
1193
+ /**
1194
+ * Run one statement (the dashboard's SQL console)
1195
+ * @description **This is not a second Postgres surface.** `runlot pg execute` deliberately does not
1196
+ * go through the control plane — SQL rides the wire, so the path we test is the path the
1197
+ * customer uses (`web/apps/cli/src/pg.ts`). A browser cannot speak the wire protocol, so
1198
+ * this route exists for the dashboard console, and it is itself **a wire client**: it
1199
+ * dials the same hostname, port and `sslmode` that `…/database/connect` hands a member
1200
+ * for psql, using that same credential. Every rule that lives on the wire — the SNI pin,
1201
+ * the epoch check, the commit gate, the 10 s statement ceiling — applies because the
1202
+ * statement goes through them, not around them. Nothing here sets `statement_timeout`.
1203
+ *
1204
+ * `readOnly` defaults to **true**, and absent means true: a plain boolean would make
1205
+ * "the client forgot the field" and "the user asked for write mode" the same request.
1206
+ * Read-only mode runs inside `BEGIN … READ ONLY` and **rolls back unconditionally** —
1207
+ * there is no branch where it commits. The mode is enforced here rather than in the
1208
+ * browser, because a toggle that only exists in a tab is one a stale tab has lost.
1209
+ *
1210
+ * Values come back as **strings or null**, never JSON numbers: a bigint past 2^53 would
1211
+ * arrive rounded, and a console that silently changes the digits of an id is worse than
1212
+ * one that shows them as text. `NULL` is `null` and the empty string is `""`.
1213
+ *
1214
+ * At most 500 rows are listed. The cap is on the response, **not appended to the
1215
+ * statement** — a console that runs something other than what is in the editor is worse
1216
+ * than one that truncates — so `rowCount` still reports what the statement did and
1217
+ * `truncated` says the listing was cut.
1218
+ *
1219
+ * member or above, the same as `…/database/connect`: that route already hands a member
1220
+ * the password for psql, so this one opens no power the role did not have. A write
1221
+ * leaves a `db.execute` audit line; a read leaves none.
1222
+ */
1223
+ post: operations["executeSQL"];
1224
+ delete?: never;
1225
+ options?: never;
1226
+ head?: never;
1227
+ patch?: never;
1228
+ trace?: never;
1229
+ };
835
1230
  "/v1/orgs/{orgSlug}/projects/{projectName}/database/export": {
836
1231
  parameters: {
837
1232
  query?: never;
@@ -899,6 +1294,29 @@ export interface paths {
899
1294
  *
900
1295
  * **Does not require the database to be enabled.** Because a final safety generation
901
1296
  * remains even after `pg delete`, you can still see it in this list after deletion.
1297
+ *
1298
+ * **`objects` is the Durable Object half of the same history** (0078,
1299
+ * docs/durable-objects.md §3, §5 O4). It is in this response rather than behind a
1300
+ * second endpoint because a project's restorable state is the **union** of the two, and
1301
+ * a caller that has to discover the object half separately is a caller that ships a
1302
+ * restore screen showing only the database and calls it the backup.
1303
+ *
1304
+ * **The two halves share no clock and `objects.atomic` is always `false`.** The
1305
+ * database's generations and each node's object components are timed independently and
1306
+ * nothing coordinates them (docs/durable-objects.md §7: "no atomic backup across objects
1307
+ * and the database"). `objects.restorable` is `objects.available && objects.complete`:
1308
+ * the restore fan-out's own preflight refuses outright when `missing` or `gaps` is
1309
+ * non-empty, so `restorable=false` means that refusal. `restorable=true` means only that
1310
+ * the catalog is eligible — it is checked ahead of paying for a restore's drain and seal,
1311
+ * not a promise that the restore will succeed: the call can still fail afterward on the
1312
+ * environment or on a holder's own local store (unreachable node, a lost or corrupted
1313
+ * on-disk archive, a digest mismatch found only when the file is read).
1314
+ *
1315
+ * **`objects` here is selected at one `at` for the whole project (default now), not per
1316
+ * generation.** A restore targets one specific `(epoch, seq)` generation with its own
1317
+ * `lastAt`; to know whether the object half is eligible **for that generation**, query
1318
+ * this endpoint again with `?at=<that generation's lastAt>` rather than reading the
1319
+ * default response — the two can disagree.
902
1320
  */
903
1321
  get: operations["listGenerations"];
904
1322
  put?: never;
@@ -932,6 +1350,22 @@ export interface paths {
932
1350
  * **Writes made in between are lost.** That is why this requires admin or higher, and the
933
1351
  * CLI asks you to re-enter the project name.
934
1352
  *
1353
+ * **If the project has Durable Objects, the same operation restores them too.** Every
1354
+ * affected holder is fenced, its own way back is archived, its exact selected component
1355
+ * is installed (or, for placements that postdate the restore target, cleared and the
1356
+ * placement removed) — all before the database side commits. An uncovered or missing
1357
+ * object component refuses the whole restore, database included, rather than rolling
1358
+ * back only part of the project.
1359
+ *
1360
+ * **Check `objects.restorable` before calling this — but for the generation you are
1361
+ * about to pass, not at whatever `at` the list happened to return.** Query
1362
+ * `…/database/generations?at=<the chosen generation's lastAt>` first: the object half
1363
+ * is selected on its own `at`, independent of which `(epoch, seq)` you send here, and a
1364
+ * `restorable=true` read at the wrong instant answers a different question than the one
1365
+ * this call is about to act on. Even a correctly-timed `restorable=true` is catalog
1366
+ * eligibility, not a guarantee — the operation itself can still fail on the environment
1367
+ * or on a holder's own local store after it starts.
1368
+ *
935
1369
  * **The server never resolves `latest`.** You must pass the exact `(epoch, seq)` you saw
936
1370
  * in the list — if the server picked "the most recent" itself, a scheduled generation
937
1371
  * created in the meantime could send you to a different generation than the one you saw.
@@ -1076,8 +1510,11 @@ export interface paths {
1076
1510
  * until the client disconnects. A `ping` arrives every 15 seconds — this keeps proxies
1077
1511
  * from closing an idle connection, and lets the client tell whether the stream is dead.
1078
1512
  *
1079
- * **Not stored logs.** Only the most recent lines in node memory; if the process is
1080
- * replaced, the `runlot` stream records that fact in a single line (prod-gap).
1513
+ * **This endpoint is the live lane and reads node memory only.** The lines are also
1514
+ * shipped to the control plane and kept there — ask `…/logs/history` for anything
1515
+ * older than the ring (2,000 lines / 1 MiB, cleared when the node-agent restarts).
1516
+ * The two lanes are independent on purpose: a tail must not wait on a database
1517
+ * write, and a history must not disappear when a process is replaced.
1081
1518
  *
1082
1519
  * Requires member or higher. Read-only, so it does not leave an audit event.
1083
1520
  */
@@ -1090,6 +1527,47 @@ export interface paths {
1090
1527
  patch?: never;
1091
1528
  trace?: never;
1092
1529
  };
1530
+ "/v1/orgs/{orgSlug}/projects/{projectName}/logs/history": {
1531
+ parameters: {
1532
+ query?: never;
1533
+ header?: never;
1534
+ path: {
1535
+ orgSlug: components["parameters"]["OrgSlug"];
1536
+ projectName: components["parameters"]["ProjectName"];
1537
+ };
1538
+ cookie?: never;
1539
+ };
1540
+ /**
1541
+ * Stored worker output (`runlot logs --since`)
1542
+ * @description Searches the lines the node shipped to the control plane (0062,
1543
+ * docs/plan-parity.md §11). Unlike the live tail this does not reach a node at all,
1544
+ * so it answers for a project that is cold, parked, or has moved since the lines
1545
+ * were written.
1546
+ *
1547
+ * **Retention is by plan: Free keeps 3 days, Pro keeps 7 days.** Past that the
1548
+ * sweep deletes the rows, and there is no way to get them back — ship anything you
1549
+ * need to keep to your own store from the worker.
1550
+ *
1551
+ * **There is a daily cap per project: Free 200,000 lines/day, Pro 2,000,000
1552
+ * lines/day**, counted on the UTC day. Past it the live tail carries on unchanged
1553
+ * and storing stops, with one `runlot`-stream line saying so:
1554
+ * `runlot: daily log cap reached (200000 lines); further lines today are dropped`.
1555
+ *
1556
+ * Newest first, keyset-paginated: pass the `cursor` from a response back to get the
1557
+ * next page. An absent `cursor` in the response means there is nothing older.
1558
+ *
1559
+ * Requires member or higher — the same role as the live tail, because these are the
1560
+ * same lines. Read-only, so it does not leave an audit event.
1561
+ */
1562
+ get: operations["getLogHistory"];
1563
+ put?: never;
1564
+ post?: never;
1565
+ delete?: never;
1566
+ options?: never;
1567
+ head?: never;
1568
+ patch?: never;
1569
+ trace?: never;
1570
+ };
1093
1571
  "/v1/orgs/{orgSlug}/projects/{projectName}/secrets": {
1094
1572
  parameters: {
1095
1573
  query?: never;
@@ -1235,7 +1713,68 @@ export interface paths {
1235
1713
  patch?: never;
1236
1714
  trace?: never;
1237
1715
  };
1238
- "/v1/ai/models": {
1716
+ "/v1/orgs/{orgSlug}/projects/{projectName}/storage/public": {
1717
+ parameters: {
1718
+ query?: never;
1719
+ header?: never;
1720
+ path: {
1721
+ orgSlug: components["parameters"]["OrgSlug"];
1722
+ projectName: components["parameters"]["ProjectName"];
1723
+ };
1724
+ cookie?: never;
1725
+ };
1726
+ /**
1727
+ * The published key prefixes (`runlot storage public list`)
1728
+ * @description The key prefixes this project serves **unsigned** at
1729
+ * `https://objects.runlot.io/<org>/<project>/<key>` (docs/storage.md §4.7).
1730
+ *
1731
+ * A stored prefix is normalized: `assets` becomes `assets/`, and `/` becomes the empty
1732
+ * string, which means every key in the project's slice. Matching is a plain string prefix
1733
+ * test, so the trailing slash is what keeps `assets` from also opening
1734
+ * `assets-private/`.
1735
+ *
1736
+ * viewer or above — somebody who cannot see which of their files are public cannot audit
1737
+ * their own project.
1738
+ */
1739
+ get: operations["listStoragePublic"];
1740
+ put?: never;
1741
+ /**
1742
+ * Publish a key prefix (`runlot storage public add`)
1743
+ * @description Makes every key under this prefix readable by anyone, with no signature, over HTTPS.
1744
+ * The bucket itself stays private — the front reads with our credentials **after**
1745
+ * checking this list, so a change to the storage backend's own policy cannot widen it.
1746
+ *
1747
+ * It is idempotent, and it answers with the whole list so that a screen never has to guess
1748
+ * what the list became.
1749
+ *
1750
+ * At most 20 prefixes per project. The bound is there because this is a security list and
1751
+ * a list nobody reads whole is where the accidental entry survives.
1752
+ *
1753
+ * **admin and above.** Publishing makes a project's bytes readable by the internet, which
1754
+ * belongs in the same column as a revoke rather than a deploy. Audited as
1755
+ * `storage.public.add` — and the audit line records what was typed as well as what was
1756
+ * stored, because normalization means the two differ.
1757
+ */
1758
+ post: operations["addStoragePublic"];
1759
+ /**
1760
+ * Unpublish a key prefix (`runlot storage public rm`)
1761
+ * @description The prefix travels in the body rather than the path because a prefix contains slashes,
1762
+ * and a path segment would need encoding that half the clients get wrong.
1763
+ *
1764
+ * Idempotent — removing one that is not there is a 200 with the unchanged list.
1765
+ *
1766
+ * **The world keeps reading for up to 60 seconds.** The object front caches the list with
1767
+ * that TTL, so this call is not a revocation that takes effect the instant it returns.
1768
+ *
1769
+ * admin and above. Audited as `storage.public.remove`.
1770
+ */
1771
+ delete: operations["removeStoragePublic"];
1772
+ options?: never;
1773
+ head?: never;
1774
+ patch?: never;
1775
+ trace?: never;
1776
+ };
1777
+ "/v1/ai/models": {
1239
1778
  parameters: {
1240
1779
  query?: never;
1241
1780
  header?: never;
@@ -1491,6 +2030,107 @@ export interface paths {
1491
2030
  patch?: never;
1492
2031
  trace?: never;
1493
2032
  };
2033
+ "/v1/orgs/{orgSlug}/projects/{projectName}/email/domains": {
2034
+ parameters: {
2035
+ query?: never;
2036
+ header?: never;
2037
+ path: {
2038
+ orgSlug: components["parameters"]["OrgSlug"];
2039
+ projectName: components["parameters"]["ProjectName"];
2040
+ };
2041
+ cookie?: never;
2042
+ };
2043
+ /**
2044
+ * Custom sending domains (`runlot email domain list`)
2045
+ * @description The project's own sending domains and their verification state (docs/email.md §2.4).
2046
+ * Each row carries the DNS records to publish — they are computed and served so the
2047
+ * dashboard, the CLI, and the docs cannot drift apart.
2048
+ *
2049
+ * viewer or above.
2050
+ */
2051
+ get: operations["listEmailDomains"];
2052
+ put?: never;
2053
+ /**
2054
+ * Adds a custom sending domain (`runlot email domain add`)
2055
+ * @description Creates the mail provider's identity for the domain with Easy DKIM and answers with the
2056
+ * records to publish: three `<token>._domainkey.<domain>` CNAMEs (required), an SPF `TXT`
2057
+ * and a DMARC `TXT` (both advisory). The domain becomes usable in
2058
+ * `env.email.send({ from })` only once it reads `verified`.
2059
+ *
2060
+ * `publish: true` writes the records straight into the zone when we host one covering the
2061
+ * domain and it belongs to the same organization. Records the customer wrote themselves
2062
+ * are never overwritten.
2063
+ *
2064
+ * A repeat call is not an error and does not change the tokens — records already published
2065
+ * stay correct. Requires member or higher. Audited as `email.domain.add`.
2066
+ */
2067
+ post: operations["addEmailDomain"];
2068
+ delete?: never;
2069
+ options?: never;
2070
+ head?: never;
2071
+ patch?: never;
2072
+ trace?: never;
2073
+ };
2074
+ "/v1/orgs/{orgSlug}/projects/{projectName}/email/domains/{domain}/verify": {
2075
+ parameters: {
2076
+ query?: never;
2077
+ header?: never;
2078
+ path: {
2079
+ orgSlug: components["parameters"]["OrgSlug"];
2080
+ projectName: components["parameters"]["ProjectName"];
2081
+ domain: string;
2082
+ };
2083
+ cookie?: never;
2084
+ };
2085
+ get?: never;
2086
+ put?: never;
2087
+ /**
2088
+ * Re-checks a sending domain now (`runlot email domain verify`)
2089
+ * @description Asks the mail provider for the identity's DKIM state and moves the row. A background
2090
+ * loop does the same once a minute while a domain is pending; this is the button for
2091
+ * somebody who just published the records and does not want to wait.
2092
+ *
2093
+ * A provider outage leaves the state where it is and puts the reason in `lastError` — an
2094
+ * outage on our side must not fail a customer's domain.
2095
+ *
2096
+ * Requires member or higher.
2097
+ */
2098
+ post: operations["verifyEmailDomain"];
2099
+ delete?: never;
2100
+ options?: never;
2101
+ head?: never;
2102
+ patch?: never;
2103
+ trace?: never;
2104
+ };
2105
+ "/v1/orgs/{orgSlug}/projects/{projectName}/email/domains/{domain}": {
2106
+ parameters: {
2107
+ query?: never;
2108
+ header?: never;
2109
+ path: {
2110
+ orgSlug: components["parameters"]["OrgSlug"];
2111
+ projectName: components["parameters"]["ProjectName"];
2112
+ domain: string;
2113
+ };
2114
+ cookie?: never;
2115
+ };
2116
+ get?: never;
2117
+ put?: never;
2118
+ post?: never;
2119
+ /**
2120
+ * Removes a sending domain (`runlot email domain rm`)
2121
+ * @description Deletes the provider identity and the row, and removes any records we wrote into a zone
2122
+ * we host. From the next convergence every `env.email.send({ from })` naming this domain
2123
+ * is refused with `from_not_verified`.
2124
+ *
2125
+ * Removing one that is not there is also a 204. Requires admin or higher. Audited as
2126
+ * `email.domain.remove`.
2127
+ */
2128
+ delete: operations["removeEmailDomain"];
2129
+ options?: never;
2130
+ head?: never;
2131
+ patch?: never;
2132
+ trace?: never;
2133
+ };
1494
2134
  "/v1/orgs/{orgSlug}/projects/{projectName}/email/log": {
1495
2135
  parameters: {
1496
2136
  query?: never;
@@ -2807,6 +3447,188 @@ export interface paths {
2807
3447
  patch?: never;
2808
3448
  trace?: never;
2809
3449
  };
3450
+ "/v1/orgs/{orgSlug}/projects/{projectName}/repos/{repoName}/deploy-hook": {
3451
+ parameters: {
3452
+ query?: never;
3453
+ header?: never;
3454
+ path: {
3455
+ orgSlug: components["parameters"]["OrgSlug"];
3456
+ projectName: components["parameters"]["ProjectName"];
3457
+ repoName: components["parameters"]["RepoName"];
3458
+ };
3459
+ cookie?: never;
3460
+ };
3461
+ /**
3462
+ * Push-to-deploy settings (`runlot repo hook status`)
3463
+ * @description Requires viewer or higher.
3464
+ *
3465
+ * `configured` is false when no hook has ever been set. It is separate from `enabled`
3466
+ * because "never set up" and "set up and switched off" are different sentences — when
3467
+ * no hook exists, `branch` carries the repository's default branch as the value a form
3468
+ * should offer.
3469
+ */
3470
+ get: operations["getDeployHook"];
3471
+ /**
3472
+ * Turn push-to-deploy on or change it (`runlot repo hook set`)
3473
+ * @description Requires **admin**, unlike deploying, which is member.
3474
+ *
3475
+ * Turning the hook on converts every future push to `branch`, by anyone with write
3476
+ * access, into a production deploy — and it does so under the identity of whoever
3477
+ * turned it on. That is a standing grant, which is why a `deploy`-scoped token cannot
3478
+ * make one.
3479
+ *
3480
+ * An omitted field keeps its current value, so a screen can send the switch and the
3481
+ * branch separately without one resetting the other.
3482
+ */
3483
+ put: operations["setDeployHook"];
3484
+ post?: never;
3485
+ /**
3486
+ * Turn push-to-deploy off entirely (`runlot repo hook unset`)
3487
+ * @description Requires admin. Removes the row. Past builds are kept — they produced the
3488
+ * deployments that are still serving.
3489
+ */
3490
+ delete: operations["deleteDeployHook"];
3491
+ options?: never;
3492
+ head?: never;
3493
+ patch?: never;
3494
+ trace?: never;
3495
+ };
3496
+ "/v1/orgs/{orgSlug}/projects/{projectName}/repos/{repoName}/deploy": {
3497
+ parameters: {
3498
+ query?: never;
3499
+ header?: never;
3500
+ path: {
3501
+ orgSlug: components["parameters"]["OrgSlug"];
3502
+ projectName: components["parameters"]["ProjectName"];
3503
+ repoName: components["parameters"]["RepoName"];
3504
+ };
3505
+ cookie?: never;
3506
+ };
3507
+ get?: never;
3508
+ put?: never;
3509
+ /**
3510
+ * Build and deploy a commit without pushing
3511
+ * @description Requires member. Queues a build of `commitSha`, or of the hooked branch's tip when
3512
+ * it is omitted.
3513
+ *
3514
+ * It admits through the same gate a push does, so a repository whose hook is off or
3515
+ * missing answers `409 deploy_hook_off` rather than building anyway — a build with no
3516
+ * hook has no root directory and no owner to deploy as, and inventing defaults for
3517
+ * both would be a second, undocumented configuration.
3518
+ */
3519
+ post: operations["deployRepoNow"];
3520
+ delete?: never;
3521
+ options?: never;
3522
+ head?: never;
3523
+ patch?: never;
3524
+ trace?: never;
3525
+ };
3526
+ "/v1/orgs/{orgSlug}/projects/{projectName}/builds": {
3527
+ parameters: {
3528
+ query?: never;
3529
+ header?: never;
3530
+ path: {
3531
+ orgSlug: components["parameters"]["OrgSlug"];
3532
+ projectName: components["parameters"]["ProjectName"];
3533
+ };
3534
+ cookie?: never;
3535
+ };
3536
+ /**
3537
+ * Build history (`runlot builds list`)
3538
+ * @description Requires viewer or higher. Newest first, queued builds at the top.
3539
+ *
3540
+ * The month's build minutes ride along because the screen that draws the list is the
3541
+ * screen that has to say how many are left — a second request for one number is a
3542
+ * second thing that can fail on a page that already has the data one join away.
3543
+ *
3544
+ * **The log is not in the rows.** A log is up to 1 MiB and a page draws twenty of
3545
+ * them; `/builds/{buildId}/log` is where it lives.
3546
+ */
3547
+ get: operations["listBuilds"];
3548
+ put?: never;
3549
+ post?: never;
3550
+ delete?: never;
3551
+ options?: never;
3552
+ head?: never;
3553
+ patch?: never;
3554
+ trace?: never;
3555
+ };
3556
+ "/v1/orgs/{orgSlug}/projects/{projectName}/builds/{buildId}": {
3557
+ parameters: {
3558
+ query?: never;
3559
+ header?: never;
3560
+ path: {
3561
+ orgSlug: components["parameters"]["OrgSlug"];
3562
+ projectName: components["parameters"]["ProjectName"];
3563
+ buildId: string;
3564
+ };
3565
+ cookie?: never;
3566
+ };
3567
+ /** One build (`runlot builds show`) */
3568
+ get: operations["getBuild"];
3569
+ put?: never;
3570
+ post?: never;
3571
+ delete?: never;
3572
+ options?: never;
3573
+ head?: never;
3574
+ patch?: never;
3575
+ trace?: never;
3576
+ };
3577
+ "/v1/orgs/{orgSlug}/projects/{projectName}/builds/{buildId}/log": {
3578
+ parameters: {
3579
+ query?: never;
3580
+ header?: never;
3581
+ path: {
3582
+ orgSlug: components["parameters"]["OrgSlug"];
3583
+ projectName: components["parameters"]["ProjectName"];
3584
+ buildId: string;
3585
+ };
3586
+ cookie?: never;
3587
+ };
3588
+ /**
3589
+ * A build's output (`runlot builds log`)
3590
+ * @description Requires viewer or higher. **`text/plain`, not JSON** — it is subprocess output with
3591
+ * newlines, and wrapping a megabyte of it in a JSON string doubles its size in escapes
3592
+ * and forces the client to parse before it can show the first line.
3593
+ *
3594
+ * Capped at 1 MiB with the **tail** kept, because the end of a failed build is where
3595
+ * the error is. When the cap bit, the first line says so.
3596
+ */
3597
+ get: operations["getBuildLog"];
3598
+ put?: never;
3599
+ post?: never;
3600
+ delete?: never;
3601
+ options?: never;
3602
+ head?: never;
3603
+ patch?: never;
3604
+ trace?: never;
3605
+ };
3606
+ "/v1/orgs/{orgSlug}/projects/{projectName}/builds/{buildId}/cancel": {
3607
+ parameters: {
3608
+ query?: never;
3609
+ header?: never;
3610
+ path: {
3611
+ orgSlug: components["parameters"]["OrgSlug"];
3612
+ projectName: components["parameters"]["ProjectName"];
3613
+ buildId: string;
3614
+ };
3615
+ cookie?: never;
3616
+ };
3617
+ get?: never;
3618
+ put?: never;
3619
+ /**
3620
+ * Cancel a queued build (`runlot builds cancel`)
3621
+ * @description Requires member. **Only a queued build can be cancelled.** A running one holds a
3622
+ * subprocess this API cannot reach, and answering "cancelled" while npm keeps running
3623
+ * would be the worst of the three possible answers. It stops on its own at 20 minutes.
3624
+ */
3625
+ post: operations["cancelBuild"];
3626
+ delete?: never;
3627
+ options?: never;
3628
+ head?: never;
3629
+ patch?: never;
3630
+ trace?: never;
3631
+ };
2810
3632
  "/v1/me/ssh-keys": {
2811
3633
  parameters: {
2812
3634
  query?: never;
@@ -2877,6 +3699,14 @@ export interface paths {
2877
3699
  * git sends Basic auth over HTTPS, and we ignore the username and only look at the token
2878
3700
  * in the password field (§5.2). The prefix `runlot_pat_` is fixed — it needs to be
2879
3701
  * mechanically detectable in repositories, logs, and pastes for leak scanning to work.
3702
+ *
3703
+ * The token is narrowed on three axes, and they are separate because they fail separately:
3704
+ * a `scopes` set, an org/project restriction, and an expiry. The default expiry is
3705
+ * **90 days** and the ceiling is 365; `noExpiry` is the only way to get a credential with
3706
+ * no deadline, spelled out so that one cannot be created by leaving a field off.
3707
+ *
3708
+ * The restriction is resolved through the same membership gate every other route uses, so
3709
+ * a token cannot be pinned to an org its issuer is not a member of.
2880
3710
  */
2881
3711
  post: operations["createAccessToken"];
2882
3712
  delete?: never;
@@ -3053,33 +3883,126 @@ export interface paths {
3053
3883
  patch?: never;
3054
3884
  trace?: never;
3055
3885
  };
3056
- }
3057
- export type webhooks = Record<string, never>;
3058
- export interface components {
3059
- schemas: {
3060
- RepoRefs: {
3061
- /**
3062
- * @description **The HEAD on disk is authoritative.** `Repo.defaultBranch` is a copy of it, and if
3063
- * they diverge, this value is correct (0032_repos.sql).
3064
- */
3065
- defaultBranch: string;
3066
- refs: {
3067
- name: string;
3068
- /**
3069
- * @description The **commit** oid it points to. Annotated tags are peeled — returning the tag
3070
- * object's oid would make the screen fail when it tries to open it as a commit.
3071
- */
3072
- target: string;
3073
- /** @enum {string} */
3074
- kind: "branch" | "tag";
3075
- }[];
3886
+ "/v1/orgs/{orgSlug}/projects/{projectName}/previews": {
3887
+ parameters: {
3888
+ query?: never;
3889
+ header?: never;
3890
+ path: {
3891
+ orgSlug: components["parameters"]["OrgSlug"];
3892
+ projectName: components["parameters"]["ProjectName"];
3893
+ };
3894
+ cookie?: never;
3076
3895
  };
3077
- RepoTreeEntry: {
3078
- name: string;
3079
- /** @description path relative to the repository root */
3080
- path: string;
3081
- /** @enum {string} */
3082
- kind: "dir" | "file" | "symlink" | "submodule";
3896
+ /**
3897
+ * The project's live previews
3898
+ * @description Requires viewer or higher. `projectName` is the **parent**; a preview is not
3899
+ * addressable as a project here, which is the same rule that keeps it out of
3900
+ * `listProjects` (docs/preview.md §3.3).
3901
+ *
3902
+ * Deleted previews are not listed. A preview that expired is gone, and saying so
3903
+ * with a row a caller then has to filter out only moves the filter.
3904
+ */
3905
+ get: operations["listPreviews"];
3906
+ put?: never;
3907
+ post?: never;
3908
+ delete?: never;
3909
+ options?: never;
3910
+ head?: never;
3911
+ patch?: never;
3912
+ trace?: never;
3913
+ };
3914
+ "/v1/orgs/{orgSlug}/projects/{projectName}/previews/{previewName}": {
3915
+ parameters: {
3916
+ query?: never;
3917
+ header?: never;
3918
+ path: {
3919
+ orgSlug: components["parameters"]["OrgSlug"];
3920
+ projectName: components["parameters"]["ProjectName"];
3921
+ previewName: components["schemas"]["Slug"];
3922
+ };
3923
+ cookie?: never;
3924
+ };
3925
+ get?: never;
3926
+ put?: never;
3927
+ post?: never;
3928
+ /**
3929
+ * Delete a preview and its branch
3930
+ * @description Requires member or higher. This runs the **project delete operation** on the child
3931
+ * project rather than a teardown of its own, so the store, the placement, the
3932
+ * hostname, the artifacts and the DEK all go by the path that already knows how to
3933
+ * take them down (docs/preview.md §8).
3934
+ *
3935
+ * It answers 204 as soon as the teardown is under way. Unlike `deleteProject` there
3936
+ * is no confirmation string: a preview is a copy taken at a moment, and nothing in it
3937
+ * is the only copy of anything.
3938
+ */
3939
+ delete: operations["deletePreview"];
3940
+ options?: never;
3941
+ head?: never;
3942
+ patch?: never;
3943
+ trace?: never;
3944
+ };
3945
+ "/v1/orgs/{orgSlug}/projects/{projectName}/previews/{previewName}/promote": {
3946
+ parameters: {
3947
+ query?: never;
3948
+ header?: never;
3949
+ path: {
3950
+ orgSlug: components["parameters"]["OrgSlug"];
3951
+ projectName: components["parameters"]["ProjectName"];
3952
+ previewName: components["schemas"]["Slug"];
3953
+ };
3954
+ cookie?: never;
3955
+ };
3956
+ get?: never;
3957
+ put?: never;
3958
+ /**
3959
+ * Make the preview's code production's live deployment
3960
+ * @description Requires member or higher. Takes the preview's **artifact** and commits it as a new
3961
+ * deployment of the parent — a new version number, the same bundle sha. It is the
3962
+ * deploy path minus the upload.
3963
+ *
3964
+ * **It does not touch either database, in either direction** (docs/preview.md §7).
3965
+ * The branch is not merged into production and production is not replaced by the
3966
+ * branch. Someone who wants the branch's data uses `getExport` or a restore; neither
3967
+ * of those hides inside a command whose name is about deployment.
3968
+ *
3969
+ * The preview stays alive afterwards — deleting it would erase the thing the caller
3970
+ * is looking at at the moment they decide it was right.
3971
+ */
3972
+ post: operations["promotePreview"];
3973
+ delete?: never;
3974
+ options?: never;
3975
+ head?: never;
3976
+ patch?: never;
3977
+ trace?: never;
3978
+ };
3979
+ }
3980
+ export type webhooks = Record<string, never>;
3981
+ export interface components {
3982
+ schemas: {
3983
+ RepoRefs: {
3984
+ /**
3985
+ * @description **The HEAD on disk is authoritative.** `Repo.defaultBranch` is a copy of it, and if
3986
+ * they diverge, this value is correct (0032_repos.sql).
3987
+ */
3988
+ defaultBranch: string;
3989
+ refs: {
3990
+ name: string;
3991
+ /**
3992
+ * @description The **commit** oid it points to. Annotated tags are peeled — returning the tag
3993
+ * object's oid would make the screen fail when it tries to open it as a commit.
3994
+ */
3995
+ target: string;
3996
+ /** @enum {string} */
3997
+ kind: "branch" | "tag";
3998
+ }[];
3999
+ };
4000
+ RepoTreeEntry: {
4001
+ name: string;
4002
+ /** @description path relative to the repository root */
4003
+ path: string;
4004
+ /** @enum {string} */
4005
+ kind: "dir" | "file" | "symlink" | "submodule";
3083
4006
  /**
3084
4007
  * Format: int64
3085
4008
  * @description files only. directories are 0
@@ -3132,12 +4055,42 @@ export interface components {
3132
4055
  */
3133
4056
  RepoVisibility: "private" | "public";
3134
4057
  /**
3135
- * @description A token **inherits the user's permissions but can only lower them** (§5.2). There is no
4058
+ * @description The **git** verdict for a token, derived from `scopes` when it is issued (0067). A token
4059
+ * **inherits the user's permissions but can only lower them** (§5.2). There is no
3136
4060
  * arithmetic in the raising direction.
4061
+ *
4062
+ * `repo:none` is a token carrying no repository scope at all — a deploy-only CI
4063
+ * credential. It clones nothing private and pushes nothing.
3137
4064
  * @default repo:write
3138
4065
  * @enum {string}
3139
4066
  */
3140
- TokenScope: "repo:read" | "repo:write";
4067
+ TokenScope: "repo:read" | "repo:write" | "repo:none";
4068
+ /**
4069
+ * @description One permission a personal access token carries. The set is checked on **every** route:
4070
+ * the token acts as its owner, so the org role is read exactly as it is for a browser
4071
+ * session, and the scope then narrows what that person may do with this particular
4072
+ * credential.
4073
+ *
4074
+ * | scope | what it opens |
4075
+ * |---|---|
4076
+ * | `project:read` | projects, deployments, logs, usage, secret *names*, cron, queues (overview, history, peek), hostnames, the deployment access policy |
4077
+ * | `deploy` | deploy, rollback, create a project, write and delete secrets, purge and redrive a queue |
4078
+ * | `db:read` | the connection string, the wire credentials list, generations, operations |
4079
+ * | `db:write` | issue a wire credential, export, restore, drop the database. Implies `db:read` |
4080
+ * | `repo:read` | clone and fetch over HTTPS, and the repository browse routes |
4081
+ * | `repo:write` | push, and create, rename or delete a repository. Implies `repo:read` |
4082
+ * | `org:admin` | everything the person can do — members, billing, domains, DNS, granting storage/email/AI |
4083
+ *
4084
+ * A route that carries no entry in the table requires `org:admin`. That is deliberate: a
4085
+ * route nobody mapped must not be silently reachable by the narrowest token in the system.
4086
+ *
4087
+ * **`deploy` does not carry `project:read`.** `project:read` opens the worker's logs, and
4088
+ * logs are where a printed secret ends up — a credential left in a CI runner should not
4089
+ * also read them unless that was asked for. A CI token names both:
4090
+ * `--scope deploy --scope project:read`.
4091
+ * @enum {string}
4092
+ */
4093
+ ApiScope: "project:read" | "deploy" | "db:read" | "db:write" | "repo:read" | "repo:write" | "org:admin";
3141
4094
  Repo: {
3142
4095
  /** Format: uuid */
3143
4096
  repoId: string;
@@ -3190,6 +4143,61 @@ export interface components {
3190
4143
  /** Format: date-time */
3191
4144
  createdAt: string;
3192
4145
  };
4146
+ DeployHook: {
4147
+ enabled: boolean;
4148
+ /**
4149
+ * @description The branch a push has to update for a build to start. When `configured` is
4150
+ * false this is the repository's default branch — the value a form should offer,
4151
+ * not a setting that exists.
4152
+ * @example main
4153
+ */
4154
+ branch: string;
4155
+ /**
4156
+ * @description The subdirectory the build runs in. Empty is the repository root.
4157
+ * @example apps/web
4158
+ */
4159
+ rootDir: string;
4160
+ /** @description False when no hook row exists. `enabled: false` with `configured: true` is a hook that was set up and switched off. */
4161
+ configured: boolean;
4162
+ /** Format: date-time */
4163
+ updatedAt?: string | null;
4164
+ };
4165
+ Build: {
4166
+ /** Format: uuid */
4167
+ buildId: string;
4168
+ /** @example 9f2c1ab4e7d05c3b8a6f14d29e0b7c5a3d81f6e2 */
4169
+ commitSha: string;
4170
+ /** @example main */
4171
+ branch: string;
4172
+ /**
4173
+ * @description `cancelled` is deliberately not `failed`: a person stopped it, or a newer push
4174
+ * for the same branch superseded it while it was still queued. Writing a designed
4175
+ * outcome down as a failure is how a healthy system reads as a broken one.
4176
+ * @enum {string}
4177
+ */
4178
+ state: "queued" | "building" | "succeeded" | "failed" | "cancelled";
4179
+ /**
4180
+ * @description A **code**, empty on success — `timeout`, `clone_failed`, `no_build_script`,
4181
+ * `install_failed`, `build_failed`, `deploy_failed`, `minutes_exhausted`,
4182
+ * `toolchain_missing`, `superseded`, `cancelled`, `internal`. It is a code and not
4183
+ * a sentence because the screen that renders it is trilingual. The sentence is in
4184
+ * the log.
4185
+ */
4186
+ error: string;
4187
+ /** @description Wall-clock minutes of a builder slot — not CPU. What the control plane spends is a slot for a duration. */
4188
+ minutes: number;
4189
+ /** Format: date-time */
4190
+ startedAt?: string | null;
4191
+ /** Format: date-time */
4192
+ finishedAt?: string | null;
4193
+ /** Format: date-time */
4194
+ createdAt: string;
4195
+ /**
4196
+ * Format: uuid
4197
+ * @description Set only on success, and it is the success marker — a build that produced a deployment has it.
4198
+ */
4199
+ deploymentId?: string | null;
4200
+ };
3193
4201
  SSHKey: {
3194
4202
  /** Format: uuid */
3195
4203
  keyId: string;
@@ -3216,11 +4224,26 @@ export interface components {
3216
4224
  tokenId: string;
3217
4225
  name: string;
3218
4226
  scope: components["schemas"]["TokenScope"];
4227
+ /** @description The authoritative permission set. `scope` above is the git projection of it. */
4228
+ scopes: components["schemas"]["ApiScope"][];
4229
+ /**
4230
+ * @description The org this token is restricted to, as a **slug**. `null` means no restriction.
4231
+ * The list answers with names rather than ids because it is read by a person deciding
4232
+ * whether to revoke, and an id is not a fact that person can act on.
4233
+ */
4234
+ org?: string | null;
4235
+ /** @description The project this token is restricted to. Implies `org`. */
4236
+ project?: string | null;
3219
4237
  /** Format: date-time */
3220
4238
  createdAt: string;
3221
4239
  /** Format: date-time */
3222
4240
  expiresAt?: string | null;
3223
- /** Format: date-time */
4241
+ /**
4242
+ * Format: date-time
4243
+ * @description Written at most **once per minute per token**. A pipeline polling an operation every
4244
+ * second must not put a row write on the path of a read, so this value can lag real
4245
+ * use by up to a minute.
4246
+ */
3224
4247
  lastUsedAt?: string | null;
3225
4248
  /** Format: date-time */
3226
4249
  revokedAt?: string | null;
@@ -3230,6 +4253,9 @@ export interface components {
3230
4253
  tokenId: string;
3231
4254
  name: string;
3232
4255
  scope: components["schemas"]["TokenScope"];
4256
+ scopes: components["schemas"]["ApiScope"][];
4257
+ org?: string;
4258
+ project?: string;
3233
4259
  /**
3234
4260
  * @description **Plaintext. Carried in this response only once.** The server stores only the
3235
4261
  * SHA-256 hash, so it cannot be recreated.
@@ -3258,16 +4284,71 @@ export interface components {
3258
4284
  };
3259
4285
  };
3260
4286
  };
4287
+ /**
4288
+ * @description A finished login **or half of one**.
4289
+ *
4290
+ * When the account has a confirmed authenticator (docs/dashboard-auth.md §10) the
4291
+ * first factor does not mint a session: `token` and `user` are absent, and `mfa`
4292
+ * and `pending` are present instead. Carry `pending` to `POST /v1/auth/totp` with
4293
+ * the six-digit code to get the real session.
4294
+ *
4295
+ * The two shapes never appear together — a body holding both a token and an `mfa`
4296
+ * marker would let a careless client take the token and skip the factor.
4297
+ */
3261
4298
  Session: {
3262
- token: string;
3263
- /** Format: date-time */
4299
+ token?: string;
4300
+ /**
4301
+ * Format: date-time
4302
+ * @description When the session expires — or, on an `mfa` response, when `pending` does
4303
+ */
3264
4304
  expiresAt?: string;
3265
- user: components["schemas"]["User"];
4305
+ user?: components["schemas"]["User"];
4306
+ /**
4307
+ * @description The second factor this account owes. Present only on a half-finished login
4308
+ * @enum {string}
4309
+ */
4310
+ mfa?: "totp";
4311
+ /**
4312
+ * @description A five-minute token that stands for the completed first factor. It is **not** a
4313
+ * session: no other endpoint accepts it.
4314
+ */
4315
+ pending?: string;
3266
4316
  };
3267
4317
  AuthEmailAccepted: {
3268
4318
  /** @constant */
3269
4319
  accepted: true;
3270
4320
  };
4321
+ TotpStatus: {
4322
+ /** @description A confirmed authenticator stands in front of every login to this account */
4323
+ enabled: boolean;
4324
+ /**
4325
+ * @description A secret was generated and never confirmed. The screen says so rather than
4326
+ * silently offering a fresh QR, which would invalidate the one already scanned.
4327
+ */
4328
+ enrollmentPending: boolean;
4329
+ /** Format: date-time */
4330
+ enabledAt?: string;
4331
+ /** @description Unused recovery codes. They are argon2id-hashed, so there is no endpoint that lists them again */
4332
+ recoveryCodesLeft: number;
4333
+ /** @description Slugs of this person's organizations that require the second factor */
4334
+ orgsRequiring: components["schemas"]["Slug"][];
4335
+ };
4336
+ TotpEnrollment: {
4337
+ /** @description The base32 shared secret, for an app that cannot scan. It is readable here and nowhere else */
4338
+ secret: string;
4339
+ /**
4340
+ * @description `otpauth://totp/runlot:<email>?secret=…&issuer=runlot` — the string the QR encodes
4341
+ * @example otpauth://totp/runlot:ryan@example.com?algorithm=SHA1&digits=6&issuer=runlot&period=30&secret=JBSWY3DPEHPK3PXP
4342
+ */
4343
+ uri: string;
4344
+ };
4345
+ TotpRecoveryCodes: {
4346
+ /**
4347
+ * @description Ten one-time codes, **shown once**. They are stored as argon2id hashes, so this
4348
+ * response is the only place they are ever readable.
4349
+ */
4350
+ recoveryCodes: string[];
4351
+ };
3271
4352
  User: {
3272
4353
  /** Format: uuid */
3273
4354
  userId: string;
@@ -3292,6 +4373,22 @@ export interface components {
3292
4373
  OrgMembership: components["schemas"]["Org"] & {
3293
4374
  /** @enum {string} */
3294
4375
  role: "admin" | "member" | "viewer";
4376
+ /**
4377
+ * Format: int64
4378
+ * @description This plan's daily request budget (Free 100,000). The overview's request chart
4379
+ * draws it as the dashed cap line — the same derived-value reasoning as
4380
+ * `projectLimit`: the table belongs to the CP.
4381
+ *
4382
+ * **0 means there is no daily budget**, which is what the paid plans answer. It is
4383
+ * not "the budget is zero", and a chart that drew a line at 0 would paint every
4384
+ * paid project as permanently over.
4385
+ */
4386
+ requestsPerDay: number;
4387
+ /**
4388
+ * Format: int64
4389
+ * @description This plan's daily CPU budget in milliseconds (Free 1,000,000). 0 means no daily budget.
4390
+ */
4391
+ cpuMsPerDay: number;
3295
4392
  /**
3296
4393
  * @description This org's plan (docs/limits.md §1)
3297
4394
  * @enum {string}
@@ -3314,6 +4411,13 @@ export interface components {
3314
4411
  * Nothing rejects a write at the cap; see `/docs/data/database/size-cap`.
3315
4412
  */
3316
4413
  dbCapBytes: number;
4414
+ /**
4415
+ * @description This organization requires two-factor authentication of its members
4416
+ * (migration 0066). It rides here for the same reason as `projectLimit`: the
4417
+ * banner that tells a member to enroll is drawn by a screen already holding
4418
+ * this response.
4419
+ */
4420
+ requireTotp?: boolean;
3317
4421
  };
3318
4422
  Notification: {
3319
4423
  /** Format: int64 */
@@ -3324,7 +4428,7 @@ export interface components {
3324
4428
  * email templates.
3325
4429
  * @enum {string}
3326
4430
  */
3327
- kind: "project_limit" | "db_near_cap" | "storage_near_quota" | "backup_failed" | "cron_failed" | "restore_done" | "dns_publish_stalled" | "billing_past_due" | "backup_stalled" | "backup_no_restore_point" | "backup_chain_broken" | "backup_always_full" | "budget_exhausted" | "ai_credit_low" | "ai_credit_exhausted" | "ai_autotopup_failed" | "ai_autotopup_disabled";
4431
+ kind: "project_limit" | "db_near_cap" | "storage_near_quota" | "storage_quota_hit" | "backup_failed" | "cron_failed" | "queue_failed" | "queue_ops_cap" | "build_failed" | "restore_done" | "dns_publish_stalled" | "billing_past_due" | "backup_stalled" | "backup_no_restore_point" | "backup_chain_broken" | "backup_always_full" | "budget_exhausted" | "ai_credit_low" | "ai_credit_exhausted" | "ai_autotopup_failed" | "ai_autotopup_disabled";
3328
4432
  /** @description If this is a project-related notification, the name of that project. Absent for org-level notifications (`project_limit`) */
3329
4433
  projectName?: string;
3330
4434
  /** @description A deduplication key per kind. Only one is created per (kind, key) in 24 hours. */
@@ -3332,8 +4436,9 @@ export interface components {
3332
4436
  /**
3333
4437
  * @description A few numbers that differ by kind. `project_limit` is `{limit, count}`,
3334
4438
  * a usage alert is `{bytes, capBytes}`, an operation alert is
3335
- * `{opId, opKind, reason?}`, and `cron_failed` is
3336
- * `{cron, reason, scheduledAt}`.
4439
+ * `{opId, opKind, reason?}`, `cron_failed` is
4440
+ * `{cron, reason, scheduledAt}`, `queue_failed` is `{queue, reason, runs}` and
4441
+ * `queue_ops_cap` is `{used, limit, plan}`.
3337
4442
  */
3338
4443
  detail: {
3339
4444
  [key: string]: unknown;
@@ -3473,6 +4578,73 @@ export interface components {
3473
4578
  /** @description Whether the deployment shipped with uncommitted changes. If true, `gitCommit` is not exactly the code. */
3474
4579
  gitDirty?: boolean;
3475
4580
  };
4581
+ /**
4582
+ * @description One preview of a project (docs/preview.md). A preview is a **child project row**,
4583
+ * so placement, routing, parking, the access policy and usage metering all treat it
4584
+ * as a project; this schema carries only what is *about being a preview* — which
4585
+ * parent, which database mode, when it expires.
4586
+ *
4587
+ * Creating one over the plan's per-project limit answers **409 `preview_limit`**.
4588
+ */
4589
+ Preview: {
4590
+ /** Format: uuid */
4591
+ previewId: string;
4592
+ /** @description What the user called it (`--preview feat-42`). */
4593
+ name: components["schemas"]["Slug"];
4594
+ /**
4595
+ * @description `<preview>--<project>.<org>.<app-domain>`. One label under the org, because the
4596
+ * per-org certificate is the wildcard `*.<org>.<app-domain>` and a wildcard covers
4597
+ * exactly one label — a third label would sit outside its own org's certificate
4598
+ * (docs/preview.md §3.2).
4599
+ * @example feat-42--shop.wickedev.runlot.app
4600
+ */
4601
+ hostname: string;
4602
+ /** @description `https://` + `hostname`. Built by the CP so the local shape cannot leak into a client. */
4603
+ url?: string;
4604
+ /**
4605
+ * @description `branch` is its own store poured from the parent's generation; `shared` runs
4606
+ * against **production's** database, so a destructive statement in the preview is
4607
+ * destructive in production; `none` has no `env.db`.
4608
+ * @enum {string}
4609
+ */
4610
+ dbMode: "branch" | "shared" | "none";
4611
+ /**
4612
+ * @description `creating` is not cosmetic — pouring a chain takes as long as a restore, and a
4613
+ * hostname answering 503 with nothing to read during it is the shape of every "is
4614
+ * it broken" question. Render this rather than guessing from whether the hostname
4615
+ * answers.
4616
+ * @enum {string}
4617
+ */
4618
+ state: "creating" | "ready" | "failed" | "deleted";
4619
+ /**
4620
+ * Format: uuid
4621
+ * @description What is serving on the preview. Null between creating the row and committing the first deployment.
4622
+ */
4623
+ deploymentId?: string | null;
4624
+ /** @description The preview's own version counter. It is not the parent's, and promoting does not carry it over. */
4625
+ version?: number | null;
4626
+ /**
4627
+ * @description The generation the branch was poured from. Null for `shared` and `none`, and for
4628
+ * a branch of a project that had taken no generation yet — an empty store is a
4629
+ * legitimate branch of a database nobody has written to.
4630
+ */
4631
+ sourceGeneration?: string | null;
4632
+ /** Format: date-time */
4633
+ createdAt: string;
4634
+ /**
4635
+ * Format: date-time
4636
+ * @description Derived from `lastRequestAt` and the org's **current** plan and recomputed on
4637
+ * every touch, so upgrading the plan extends previews that already exist.
4638
+ */
4639
+ expiresAt?: string | null;
4640
+ /**
4641
+ * Format: date-time
4642
+ * @description The TTL runs from here, not from `createdAt` — the difference between "your
4643
+ * preview vanished while you were using it" and "your preview vanished because you
4644
+ * stopped". It starts at `createdAt`, so one that was never opened still expires.
4645
+ */
4646
+ lastRequestAt?: string;
4647
+ };
3476
4648
  /**
3477
4649
  * @description One round of one schedule (docs/cron.md §8). A round that never started — an
3478
4650
  * overlap, or one that came up past the grace period — is recorded too, with
@@ -3552,6 +4724,215 @@ export interface components {
3552
4724
  */
3553
4725
  keepDays: number;
3554
4726
  };
4727
+ /**
4728
+ * @description One delivered **batch** of one queue (docs/queues.md §5). One row per batch, not
4729
+ * per message: the four counters add up to the batch, and a batch that never reached
4730
+ * the handler has `delivered > 0` with zeros across the rest — which is what says the
4731
+ * messages went back to the queue untouched.
4732
+ */
4733
+ QueueRun: {
4734
+ /** @example jobs */
4735
+ queue: string;
4736
+ /** Format: date-time */
4737
+ startedAt: string;
4738
+ /**
4739
+ * Format: date-time
4740
+ * @description Absent for a batch that never began (`outcome: skipped`).
4741
+ */
4742
+ finishedAt?: string;
4743
+ /** @description Wall clock, wake included. null when nothing ran. */
4744
+ durationMs?: number | null;
4745
+ /** @description How many messages were leased into this batch. */
4746
+ delivered: number;
4747
+ acked: number;
4748
+ retried: number;
4749
+ /** @description How many left for the dead-letter queue, or were dropped because there is none. */
4750
+ dead: number;
4751
+ /**
4752
+ * @description Split by who has to act, the same four as `CronRun.outcome`. `failed` is the
4753
+ * worker's code — it threw, or exports no `queue` handler. `error` never reached
4754
+ * the handler (no socket, a project that would not wake, a transport failure,
4755
+ * the wall-clock bound) and is ours. `skipped` is the poller deciding not to
4756
+ * deliver on purpose.
4757
+ * @enum {string}
4758
+ */
4759
+ outcome: "ok" | "failed" | "error" | "skipped";
4760
+ /**
4761
+ * @description A code, never a sentence. For `failed` it is workerd's own outcome, untranslated
4762
+ * (`exception`, `canceled`). Ours are `no_socket`, `wake_failed`, `drive_failed`,
4763
+ * `timeout`, `consumers_changed`.
4764
+ */
4765
+ reason?: string;
4766
+ /** @description One line of human-readable context when there is one. May be empty. */
4767
+ detail?: string;
4768
+ };
4769
+ /** @description A consumer's declaration as the screen shows it — the manifest's numbers, defaults folded. */
4770
+ QueueConsumer: {
4771
+ /** @description 1–100, default 10. */
4772
+ maxBatchSize: number;
4773
+ /** @description Seconds, 1–60, default 5. */
4774
+ maxBatchTimeout: number;
4775
+ /** @description 0–10, default 3. */
4776
+ maxRetries: number;
4777
+ /** @description Where a message goes once it is out of retries. Absent means it is deleted instead. */
4778
+ deadLetterQueue?: string;
4779
+ };
4780
+ /**
4781
+ * @description Three numbers and not one total: a queue that is all `delayed` is working, and a
4782
+ * queue that is all `inflight` is stuck. A single depth cannot tell those apart.
4783
+ */
4784
+ QueueDepth: {
4785
+ /**
4786
+ * Format: int64
4787
+ * @description Could be delivered right now.
4788
+ */
4789
+ visible: number;
4790
+ /**
4791
+ * Format: int64
4792
+ * @description Waiting on its own delay or backoff.
4793
+ */
4794
+ delayed: number;
4795
+ /**
4796
+ * Format: int64
4797
+ * @description Leased to a handler that has not answered yet.
4798
+ */
4799
+ inflight: number;
4800
+ };
4801
+ QueueStatus: {
4802
+ /** @example jobs */
4803
+ queue: string;
4804
+ /** @description The binding names (`env.<BINDING>`) that send into this queue. */
4805
+ producers: string[];
4806
+ /** @description Absent for a queue nothing drains — a fan-out target, or a dead-letter queue nobody consumes. */
4807
+ consumer?: components["schemas"]["QueueConsumer"];
4808
+ /** @description The queues whose dead-letter queue this one is. Non-empty is what makes redrive apply to this row. */
4809
+ deadLetterFor?: string[];
4810
+ /** @description Absent when the project's database could not be read (`QueueOverview.depthError`). */
4811
+ depth?: components["schemas"]["QueueDepth"];
4812
+ /**
4813
+ * Format: int64
4814
+ * @description How many messages sit in this queue's dead-letter queue. Absent without one, or when the depth is unknown.
4815
+ */
4816
+ deadLetters?: number;
4817
+ /** @description The most recent batch of this queue, taken from the whole history and not just the page below it. */
4818
+ lastRun?: components["schemas"]["QueueRun"];
4819
+ };
4820
+ /** @description How the last `windowHours` went, counted by outcome. */
4821
+ QueueSummary: {
4822
+ /** @example 24 */
4823
+ windowHours: number;
4824
+ ok: number;
4825
+ failed: number;
4826
+ errored: number;
4827
+ skipped: number;
4828
+ };
4829
+ QueueOverview: {
4830
+ /** @description What the live deployment declares, in declaration order. Empty means no queues, not unknown. */
4831
+ queues: components["schemas"]["QueueStatus"][];
4832
+ /** @description Newest first, across every queue. */
4833
+ runs: components["schemas"]["QueueRun"][];
4834
+ summary: components["schemas"]["QueueSummary"];
4835
+ /** @description How far back the history goes on this org's plan, in days (30 free, 365 pro). */
4836
+ keepDays: number;
4837
+ /**
4838
+ * Format: int64
4839
+ * @description The project's queue operations today (UTC). A send is one, a delivery is one. 0 when the depth could not be read.
4840
+ */
4841
+ opsToday: number;
4842
+ /** @description The plan's daily bound (free 10,000, pro 1,000,000). Past it, `send` throws `QueueLimitError` until 00:00 UTC. */
4843
+ opsCap: number;
4844
+ /** @description Present when the project's database could not be read. The declarations and the history are still answered. */
4845
+ depthError?: string;
4846
+ };
4847
+ /** @description One row as `peekQueue` shows it. `preview` is a clipped rendering of the body, never the body. */
4848
+ QueueMessage: {
4849
+ /** @description The row id, as a string. It names the row only while the row exists. */
4850
+ id: string;
4851
+ /** @description Deliveries so far in this queue. */
4852
+ attempts: number;
4853
+ /** @enum {string} */
4854
+ contentType: "json" | "text" | "bytes";
4855
+ /** Format: date-time */
4856
+ enqueuedAt: string;
4857
+ /**
4858
+ * Format: date-time
4859
+ * @description When it becomes deliverable. In the past for a visible message.
4860
+ */
4861
+ visibleAt: string;
4862
+ /** @description Leased to a handler right now. */
4863
+ inflight: boolean;
4864
+ /** @description The first 200 characters of the body, or `<n bytes>` for a binary one. */
4865
+ preview: string;
4866
+ };
4867
+ VectorNamespace: {
4868
+ /** @example docs */
4869
+ namespace: string;
4870
+ /** Format: int64 */
4871
+ count: number;
4872
+ /** @description The width every vector in the namespace has. Absent when the namespace holds more than one width — a state the worker refuses to search. */
4873
+ dimensions?: number;
4874
+ };
4875
+ /** @description Counts and sizes come from different places, and that difference is the shape of this schema. `count` is read from the placement map, which the control plane owns and which is always right. `bytes` and `files` are summed from reports the holding nodes push, which the control plane cannot compute and which can be missing or old. **That is why `complete` and `measuredAt` exist**, and why they are not decoration. */
4876
+ DurableObjectUsage: {
4877
+ /** @description How many Durable Objects this project has placed, across every node. */
4878
+ count: number;
4879
+ /** @description The project-wide cap. **It is an initial product cap**: nothing has been benchmarked to it, it is not a measured ceiling and not a competitive claim, and it is expected to move. */
4880
+ limit: number;
4881
+ /**
4882
+ * Format: int64
4883
+ * @description The stores' size, summed over the nodes that have reported. **Read it with `complete`.** When `complete` is false this is a lower bound over part of the fleet, not the project's size, and a screen showing it as a total shows a number that is wrong by an unknown amount in one direction.
4884
+ */
4885
+ bytes: number;
4886
+ /** @description Store files counted, summed the same way and under the same caveat. It is **not** the object count — an object that has never written has no file — and both are kept because the two disagreeing is a fact worth being able to see. */
4887
+ files: number;
4888
+ /**
4889
+ * @description Whether every node holding this project's objects has reported.
4890
+ * **A node that has never reported has an unknown size, not an empty one.** Summing its absence as zero would tell a user they are using nothing while their disk fills, so any holder without a report makes this false, and the answer then sums what is known and is a lower bound rather than a total.
4891
+ * A project with no objects at all is `true` with zero — there is nothing unmeasured. That case has to stay distinguishable from the one above.
4892
+ */
4893
+ complete: boolean;
4894
+ /**
4895
+ * Format: date-time
4896
+ * @description The **oldest** measurement in the sum, and absent when nothing has been reported.
4897
+ * The oldest rather than the newest, because it is the one that bounds how stale the total is. Reporting the newest would let one node's fresh sweep make a total look current while another node's month-old number sat inside it.
4898
+ */
4899
+ measuredAt?: string;
4900
+ /** @description The per-node breakdown, keyed by node id. It is here because `nodeLimit` is a separate bound that can refuse a placement while the project-wide cap still has room, and because a missing or stale measurement is a property of one node — a total alone cannot say which. */
4901
+ nodes: {
4902
+ [key: string]: {
4903
+ /** @description From the placement map, and always present. */
4904
+ count: number;
4905
+ /** Format: int64 */
4906
+ bytes: number;
4907
+ files: number;
4908
+ /**
4909
+ * Format: date-time
4910
+ * @description When that node took its measurement. **Absent means the node has not reported**, and then its `bytes` and `files` are zero because there is nothing to put there — not because the node holds nothing. The missing timestamp is what tells those two apart.
4911
+ */
4912
+ measuredAt?: string;
4913
+ };
4914
+ };
4915
+ /** @description The per-node bound. Separate from `limit` on purpose: it protects one authority snapshot's owner mapping, and it stays where it is even when the product cap moves. */
4916
+ nodeLimit: number;
4917
+ };
4918
+ VectorOverview: {
4919
+ /** @description Every namespace with vectors in it, sorted by name. Empty means nothing stored, not unknown. */
4920
+ namespaces: components["schemas"]["VectorNamespace"][];
4921
+ /**
4922
+ * Format: int64
4923
+ * @description Vectors across every namespace. 0 when the store could not be read.
4924
+ */
4925
+ count: number;
4926
+ /** @description The plan's bound on vectors per project (free 5,000, pro 25,000). Past it, `upsert` throws `VectorsError` with code `vector_limit`. */
4927
+ limit: number;
4928
+ /** @description The widest vector the store accepts (3,072). */
4929
+ dimensionsMax: number;
4930
+ plan: string;
4931
+ /** @description Always true — search is exact k-NN in the worker; there is no approximate index. */
4932
+ exact: boolean;
4933
+ /** @description Present when the project's database could not be read. The bounds are still answered. */
4934
+ readError?: string;
4935
+ };
3555
4936
  DatabaseEndpoint: {
3556
4937
  host: string;
3557
4938
  port: number;
@@ -3682,16 +5063,81 @@ export interface components {
3682
5063
  lastCheckedAt?: string;
3683
5064
  /** @description Newest first. An empty array is an array, not `null` */
3684
5065
  generations: components["schemas"]["GenerationRow"][];
5066
+ objects?: components["schemas"]["ObjectBackupSet"];
3685
5067
  };
3686
5068
  /**
3687
- * @description A single backup generation. The field names are **the same** as `GenerationRow` in
3688
- * `internal/backupproto`. The actor metadata, the generation the node reports to the CP,
3689
- * and the records included in this API must use the same names, so that a change in one
3690
- * place is not silently interpreted as 0 elsewhere.
5069
+ * @description What an object restore would select, beside the database generations it is **not**
5070
+ * consistent with (0078, docs/durable-objects.md §3, §5 O4).
5071
+ *
5072
+ * **Unavailable is not empty.** If the control plane cannot be asked, `available` is
5073
+ * false, `complete` is false, and the lists are empty — the same distinction the Durable
5074
+ * Object usage view draws between unreported and zero. An empty list rendered as "no
5075
+ * object backups" when the truth is "we could not ask" tells a user their data is
5076
+ * unprotected, or lets them believe a restore would be complete. The database listing
5077
+ * still answers: a person asking what generations exist is not served by a 502 because a
5078
+ * second query failed.
3691
5079
  */
3692
- GenerationRow: {
3693
- /** Format: int64 */
3694
- epoch: number;
5080
+ ObjectBackupSet: {
5081
+ /** @description Whether the object half could be read at all. */
5082
+ available: boolean;
5083
+ /** @description **Always `false`.** A field rather than a sentence in a document, because a client that renders one restore time for the database and the objects is wrong and the only way to stop it being wrong by default is to hand it the disclaimer in the payload it is already parsing. */
5084
+ atomic: boolean;
5085
+ /** @description `available && complete` — catalog eligibility, not a success guarantee. The restore fan-out (`POST /orgs/{orgSlug}/projects/{projectName}/database/restore`) refuses outright when `missing` or `gaps` is non-empty, so `false` here means that refusal and the call is not worth attempting. `true` means only that the preflight would pass; the operation can still fail afterward on the environment (lifecycle disabled, no enforcement path) or on a holder's own local store (unreachable node, a lost or corrupted archive, a digest mismatch found only when the file is read). Also computed at this response's `at`, which is one instant for the whole project — a restore targets one generation's own `lastAt`, so re-query with `?at=<that generation's lastAt>` before trusting this field for that restore. */
5086
+ restorable: boolean;
5087
+ /** Format: date-time */
5088
+ at?: string;
5089
+ /** @description Every node holding an initialized object of this project. */
5090
+ holders: string[];
5091
+ /** @description The newest component at or before `at`, one per node. */
5092
+ components: {
5093
+ nodeId: string;
5094
+ objectKey: string;
5095
+ /**
5096
+ * Format: date-time
5097
+ * @description **This component's own time.** A surface above this one is required to show it: docs/durable-objects.md §5 O4 asks that "a project restored to 14:00 shows which hour each node's objects came from", which is only answerable if the time survives to the screen.
5098
+ */
5099
+ takenAt: string;
5100
+ /** Format: int64 */
5101
+ bytes: number;
5102
+ files: number;
5103
+ manifestDigest: string;
5104
+ required: boolean;
5105
+ }[];
5106
+ /** @description Initialized holders with nothing at or before `at`. **Their current bytes are not substituted** — a restore that quietly took live bytes for a historical component would return a combination that never existed. */
5107
+ missing: string[];
5108
+ /**
5109
+ * @description Holders with an object initialized strictly after their selected component but
5110
+ * **at or before `at`** — the object existed at the restore target and the archive
5111
+ * has no file for it. An object initialized *after* `at` is not a gap: it did not
5112
+ * exist at the target, and a restore removes its placement through a controlled
5113
+ * delete instead of needing it covered.
5114
+ *
5115
+ * It is separate from `missing` because the two mean different things to the person
5116
+ * reading the screen: `missing` is "this node has no backup", and this is "this
5117
+ * node's backup is from before some of its objects existed, and still are as of the
5118
+ * restore target". A restore to this point would leave those objects unopenable, and
5119
+ * the system has no way to withdraw their initialization.
5120
+ */
5121
+ gaps: {
5122
+ nodeId: string;
5123
+ objects: number;
5124
+ /** Format: date-time */
5125
+ since: string;
5126
+ }[];
5127
+ /** @description `available` with neither `missing` nor `gaps`. It means the pieces are identified and cover every object that existed at `at` — see `restorable` for whether the restore fan-out's preflight would accept them; neither field promises the restore itself will succeed. */
5128
+ complete: boolean;
5129
+ /** @description The retention window in days, from the org plan's value. */
5130
+ keepDays: number;
5131
+ };
5132
+ /**
5133
+ * @description A single backup generation. The field names are **the same** as `GenerationRow` in
5134
+ * `internal/backupproto`. The actor metadata, the generation the node reports to the CP,
5135
+ * and the records included in this API must use the same names, so that a change in one
5136
+ * place is not silently interpreted as 0 elsewhere.
5137
+ */
5138
+ GenerationRow: {
5139
+ /** Format: int64 */
5140
+ epoch: number;
3695
5141
  /**
3696
5142
  * Format: int64
3697
5143
  * @description Increases monotonically within an epoch. Restore identifies a generation by `(epoch, seq)`.
@@ -3929,6 +5375,28 @@ export interface components {
3929
5375
  */
3930
5376
  framework?: "next";
3931
5377
  triggers?: components["schemas"]["ManifestTriggers"];
5378
+ queues?: components["schemas"]["ManifestQueues"];
5379
+ durable_objects?: components["schemas"]["ManifestDurableObjects"];
5380
+ /**
5381
+ * @description The append-only history that creates this project's Durable Object classes
5382
+ * (docs/durable-objects.md §2.1). It is top-level, as in wrangler, because it
5383
+ * outlives the bindings: a class stays created after the binding that reached
5384
+ * it is deleted.
5385
+ *
5386
+ * The array **is** the history and its order is the order it happened in.
5387
+ * Nothing sorts it and nothing rewrites a tag. A tag is unique across the
5388
+ * history, every step has to create at least one class no earlier step created,
5389
+ * and the per-project bound is 32 distinct classes
5390
+ * (`bundle.MaxDurableObjectClasses`). Every binding's `class_name` has to appear
5391
+ * in one of these steps or the deployment is refused; a class no binding reaches
5392
+ * is accepted with a warning.
5393
+ *
5394
+ * Only `new_classes` and `new_sqlite_classes` are supported. `renamed_classes`,
5395
+ * `deleted_classes` and `transferred_classes` are refused **by name** rather
5396
+ * than ignored — a dropped migration key is a deployment that reports success
5397
+ * while the class the worker now exports has no objects under it.
5398
+ */
5399
+ migrations?: components["schemas"]["ManifestDurableObjectMigration"][];
3932
5400
  /**
3933
5401
  * @description Declares email sending and receiving (docs/email.md). When `true`, the worker
3934
5402
  * receives `env.email`, and `export default { email() }` becomes the receiving
@@ -3943,6 +5411,28 @@ export interface components {
3943
5411
  * code requested the binding.
3944
5412
  */
3945
5413
  ai?: boolean;
5414
+ /**
5415
+ * @description PEM files inside the bundle whose certificates are added to the trust store used
5416
+ * for **outbound** TLS by this project's worker (docs/outbound-tls.md).
5417
+ *
5418
+ * It exists because an origin that omits its intermediate certificate cannot be
5419
+ * reached from a worker at all: kj-tls does not chase AIA, so the handshake fails
5420
+ * before any JavaScript runs and nothing in the app can repair it.
5421
+ *
5422
+ * Unlike `email` and `ai` this is not a declaration the control plane grants
5423
+ * against — it is a path into the bundle, so it is validated like `main` and
5424
+ * `assets`. Every entry must sit under `certs/`, which is what lets the
5425
+ * certificate be parsed while the bundle is read rather than trusted on sight.
5426
+ * Each file is parsed at deploy time and an expired certificate is rejected; one
5427
+ * inside its last 90 days is accepted with a warning.
5428
+ *
5429
+ * The system trust store is always kept (`trustBrowserCas`), so this adds trust
5430
+ * and never replaces it. Requires `main`.
5431
+ * @example [
5432
+ * "certs/sectigo-rsa-dv.pem"
5433
+ * ]
5434
+ */
5435
+ trustedCertificates?: string[];
3946
5436
  };
3947
5437
  /**
3948
5438
  * @description Scheduled execution (docs/cron.md). It ships in the bundle exactly as the user wrote it
@@ -3973,6 +5463,124 @@ export interface components {
3973
5463
  */
3974
5464
  crons?: string[];
3975
5465
  };
5466
+ /**
5467
+ * @description Queues (docs/queues.md §2). Two lists, exactly as wrangler names them, because a
5468
+ * project moving off Cloudflare copies those lines across unchanged. A project may
5469
+ * produce into a queue it does not consume, and consume a queue it never produces
5470
+ * into — the dead-letter queue is that case — so neither list implies the other.
5471
+ *
5472
+ * Every distinct name across both lists, dead-letter queues included, counts against
5473
+ * the per-project bound of 5 (`bundle.MaxQueuesPerProject`); the org-wide bound is the
5474
+ * plan's (`plan.QueueLimitFor`: free 5, pro 25) and a deployment past it is refused
5475
+ * with `400 queue_limit`. Requires `main` and `database`: the messages are rows in the
5476
+ * project's own database.
5477
+ */
5478
+ ManifestQueues: {
5479
+ producers?: {
5480
+ /**
5481
+ * @description The name the worker reads it as — `env.JOBS`. `^[A-Z][A-Z0-9_]{0,63}$`; `DB`, `ASSETS`, `STORAGE`, `AUTH`, `AI`, `EMAIL`, `MAIN` and the `RUNLOT_` prefix are reserved.
5482
+ * @example JOBS
5483
+ */
5484
+ binding: string;
5485
+ /**
5486
+ * @description The queue's name, `^[a-z0-9-]{1,63}$`. Two bindings may point at one queue.
5487
+ * @example jobs
5488
+ */
5489
+ queue: string;
5490
+ }[];
5491
+ consumers?: {
5492
+ /** @example jobs */
5493
+ queue: string;
5494
+ /** @description 1–100. Default 10. */
5495
+ maxBatchSize?: number;
5496
+ /** @description Seconds a partial batch waits for more messages, 1–60. Default 5. */
5497
+ maxBatchTimeout?: number;
5498
+ /**
5499
+ * @description 0–10. Default 3. `0` folds to the default — "deliver once, then it is dead"
5500
+ * is written as `maxRetries: 0` plus a `deadLetterQueue`, the shape that
5501
+ * actually keeps the message.
5502
+ */
5503
+ maxRetries?: number;
5504
+ /** @description Where a message goes once it is out of retries. Omitted means it is **deleted** instead. Cannot be the queue itself. */
5505
+ deadLetterQueue?: string;
5506
+ }[];
5507
+ };
5508
+ /**
5509
+ * @description Durable Objects (docs/durable-objects.md §2.1). One list of bindings, exactly as
5510
+ * wrangler names them — **including the snake_case keys**, which the rest of this
5511
+ * manifest does not use. A `durable_objects` block is copied across as a whole
5512
+ * rather than typed a key at a time, and renaming the keys would make that copy
5513
+ * silently wrong.
5514
+ *
5515
+ * It rides in the bundle for `triggers`' reason and one of its own: which namespaces
5516
+ * a node stands up has to be answerable from the bundle alone, and the class a
5517
+ * binding points at is a property of the code, not of any grant. Requires `main` —
5518
+ * a Durable Object is a class the worker exports, and static-only deployments
5519
+ * export none.
5520
+ */
5521
+ ManifestDurableObjects: {
5522
+ bindings?: {
5523
+ /**
5524
+ * @description The name the worker reads it as — `env.ROOMS`. Any JavaScript identifier
5525
+ * of at most 64 characters, in any case, because Cloudflare permits any
5526
+ * identifier here and a project carries whatever case it already chose.
5527
+ * `db`, `auth`, `storage`, `email`, `ai`, `vectors`, `assets`, `ASSETS`,
5528
+ * the JavaScript reserved words and the `RUNLOT_` prefix are reserved. A
5529
+ * name already taken by a queue producer is refused.
5530
+ * @example ROOMS
5531
+ */
5532
+ name: string;
5533
+ /**
5534
+ * @description The class the worker exports. It is not the binding: two bindings may
5535
+ * point at one class. It has to be created by one of the `migrations`
5536
+ * steps, and it cannot be a JavaScript reserved word — the generated entry
5537
+ * module re-exports the worker's names explicitly, and a class called
5538
+ * `default` produces a module that does not parse.
5539
+ * @example Room
5540
+ */
5541
+ class_name: string;
5542
+ /**
5543
+ * @description wrangler's cross-script binding — a namespace defined by another Worker.
5544
+ * It is **accepted into the schema and refused with a value**, which is
5545
+ * not the same as leaving it out: a project that has one copies the whole
5546
+ * block across, and dropping the key quietly would bind `env.ROOMS` to a
5547
+ * class this worker does not export.
5548
+ */
5549
+ script_name?: string;
5550
+ }[];
5551
+ };
5552
+ /**
5553
+ * @description One step of the Durable Object migration history.
5554
+ *
5555
+ * **The two kinds are not the same class.** Both are stored on SQLite, but
5556
+ * `enableSql` is false for a class created as `new_classes`, and that is the upstream
5557
+ * compatibility contract: a class created as a KV class never gains a SQL surface.
5558
+ * The split therefore survives into the generated configuration rather than being
5559
+ * folded here.
5560
+ */
5561
+ ManifestDurableObjectMigration: {
5562
+ /**
5563
+ * @description Names this step, `^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$`, unique across the
5564
+ * history. It is what an operator compares between two deployments to see what
5565
+ * moved, so it has to be printable in a log line without quoting.
5566
+ * @example v1
5567
+ */
5568
+ tag: string;
5569
+ /**
5570
+ * @description Classes created **without** `ctx.storage.sql` (`enableSql = false`).
5571
+ * @example [
5572
+ * "Counter"
5573
+ * ]
5574
+ */
5575
+ new_classes?: string[];
5576
+ /**
5577
+ * @description Classes created with `ctx.storage.sql`.
5578
+ * @example [
5579
+ * "Room"
5580
+ * ]
5581
+ */
5582
+ new_sqlite_classes?: string[];
5583
+ };
3976
5584
  ManifestModule: {
3977
5585
  /**
3978
5586
  * @description The specifier the worker imports. Alphanumeric and `._-`, slash-separated, does not start with `.`. `worker` cannot be used because it is the entry module.
@@ -4121,6 +5729,54 @@ export interface components {
4121
5729
  /** @description Reason for `end`: `process_exited`, `client_gone`, `node_shutdown` */
4122
5730
  reason?: string;
4123
5731
  };
5732
+ /**
5733
+ * @description One stored line (0062). It is not a `LogEvent`: there is no `type`, because a
5734
+ * stored line is never a heartbeat or an end-of-stream, and there is a `seq`,
5735
+ * because the cursor needs a tiebreaker for lines that share a timestamp.
5736
+ */
5737
+ LogHistoryLine: {
5738
+ /**
5739
+ * Format: date-time
5740
+ * @description When the **node** received the line, not when it was stored.
5741
+ */
5742
+ ts: string;
5743
+ /**
5744
+ * Format: int64
5745
+ * @description Monotonic insert order. With `ts` it forms the page cursor.
5746
+ */
5747
+ seq: number;
5748
+ /** Format: int64 */
5749
+ epoch?: number;
5750
+ /** @description The process generation within the node. Increments on replacement. */
5751
+ generation?: number;
5752
+ /**
5753
+ * @description `runlot` is a line written by us, not the worker — startup, exit code,
5754
+ * dropped-line counts, and the daily-cap marker.
5755
+ * @enum {string}
5756
+ */
5757
+ stream: "stdout" | "stderr" | "runlot";
5758
+ line: string;
5759
+ };
5760
+ LogHistoryPage: {
5761
+ /** @description Newest first. */
5762
+ lines: components["schemas"]["LogHistoryLine"][];
5763
+ /**
5764
+ * @description Pass back as `cursor` for the next (older) page. **Absent means there is
5765
+ * nothing older** — an empty `lines` with a cursor present never happens.
5766
+ */
5767
+ cursor?: string;
5768
+ /**
5769
+ * @description This org's retention in days (Free 3, Pro 7). A client needs it to say how far
5770
+ * back there is anything to ask for: without it an empty page reads as "nothing
5771
+ * happened" when it means "that is older than we keep".
5772
+ */
5773
+ keepDays: number;
5774
+ /**
5775
+ * Format: int64
5776
+ * @description This org's daily stored-line cap (Free 200000, Pro 2000000).
5777
+ */
5778
+ linesPerDay: number;
5779
+ };
4124
5780
  Usage: {
4125
5781
  /** Format: uuid */
4126
5782
  projectId: string;
@@ -4131,6 +5787,37 @@ export interface components {
4131
5787
  requests: number;
4132
5788
  /** Format: int64 */
4133
5789
  cpuMs: number;
5790
+ /**
5791
+ * Format: int64
5792
+ * @description Requests that answered 5xx (migration 0063). Cumulative, and **a subset of
5793
+ * `requests`** — the two are counted on the same line of node-front's serve, so
5794
+ * `errors5xx / requests` is the window's error rate with no denominator mismatch.
5795
+ */
5796
+ errors5xx: number;
5797
+ /**
5798
+ * Format: int64
5799
+ * @description The median request duration over the whole window, in milliseconds. It is derived
5800
+ * from the folded fixed-bucket histogram of every row — **not** the mean of the
5801
+ * rows' medians, which would move when an idle hour joined the window. Percentiles
5802
+ * are never stored: a stored percentile cannot be added, and an hour is the sum of
5803
+ * every report that landed in it.
5804
+ */
5805
+ p50Ms: number;
5806
+ /**
5807
+ * Format: int64
5808
+ * @description The 99th percentile, same derivation. A sample past the histogram's last edge
5809
+ * (10,000 ms) reports that edge — the overflow bucket has no upper bound to
5810
+ * interpolate towards, and inventing one would put a number on screen that no
5811
+ * measurement supports.
5812
+ */
5813
+ p99Ms: number;
5814
+ /**
5815
+ * Format: int64
5816
+ * @description How many durations the window's histogram holds. **0 means there is no percentile
5817
+ * at all**, which is a different fact from "the percentile is 0 ms" — every row
5818
+ * written before 0063 is the first case, and the two are otherwise the same zero.
5819
+ */
5820
+ latSamples: number;
4134
5821
  /**
4135
5822
  * Format: int64
4136
5823
  * @description The number of object operations. It is a cumulative value, so it is included in the total
@@ -4175,6 +5862,49 @@ export interface components {
4175
5862
  */
4176
5863
  objBytes: number;
4177
5864
  };
5865
+ ExecuteRequest: {
5866
+ /** @description The statement, exactly as typed. Nothing is appended to it. */
5867
+ sql: string;
5868
+ /**
5869
+ * @description **Absent means true.** Read-only runs inside `BEGIN … READ ONLY` and rolls back
5870
+ * unconditionally; write mode runs outside a transaction so the statement commits on
5871
+ * its own.
5872
+ * @default true
5873
+ */
5874
+ readOnly: boolean;
5875
+ /**
5876
+ * @description Values for `$1`, `$2`, … They are sent separately rather than pasted into the text.
5877
+ * The console's own table listing uses one, because a console that interpolates its
5878
+ * own strings teaches the habit that ends in an injection.
5879
+ */
5880
+ params?: unknown[];
5881
+ };
5882
+ ExecuteResult: {
5883
+ /** @description Column names in the order the server returned them. Empty for a statement with no result set. */
5884
+ columns: string[];
5885
+ /**
5886
+ * @description One entry per listed row, each an array parallel to `columns`. **Every value is a
5887
+ * string or null** — JSON numbers are IEEE doubles, so a bigint past 2^53 would arrive
5888
+ * rounded. `null` is SQL NULL; `""` is the empty string.
5889
+ */
5890
+ rows: (string | null)[][];
5891
+ /**
5892
+ * Format: int64
5893
+ * @description What the statement reported — rows produced or rows touched. Not `rows.length`: with truncation the two differ, and that difference is what `truncated` is about.
5894
+ */
5895
+ rowCount: number;
5896
+ /** @description the 500-row listing cap cut the response */
5897
+ truncated: boolean;
5898
+ /** @description the server's command tag (SELECT, UPDATE, CREATE TABLE …) */
5899
+ command: string;
5900
+ /** @description which mode actually ran — the server saying what it did, which can differ from what was asked (absent is read-only) */
5901
+ readOnly: boolean;
5902
+ /**
5903
+ * Format: int64
5904
+ * @description The round trip as the control plane measured it. It includes the dial, so it is not the statement's own time.
5905
+ */
5906
+ elapsedMs: number;
5907
+ };
4178
5908
  UsageRow: {
4179
5909
  /**
4180
5910
  * Format: date-time
@@ -4222,11 +5952,44 @@ export interface components {
4222
5952
  * @description cumulative (sum of deltas)
4223
5953
  */
4224
5954
  aiTokensOut: number;
5955
+ /**
5956
+ * Format: int64
5957
+ * @description cumulative; a subset of `requests` (0063)
5958
+ */
5959
+ errors5xx: number;
5960
+ /**
5961
+ * Format: int64
5962
+ * @description this hour's median duration, derived from its histogram at read time
5963
+ */
5964
+ p50Ms: number;
5965
+ /**
5966
+ * Format: int64
5967
+ * @description this hour's 99th percentile, same derivation
5968
+ */
5969
+ p99Ms: number;
5970
+ /**
5971
+ * Format: int64
5972
+ * @description How many durations this hour's histogram holds. 0 means the hour has **no**
5973
+ * percentile — rows written before 0063 are exactly that, and a chart that cannot
5974
+ * tell them from "0 ms" draws a flat floor that never happened.
5975
+ */
5976
+ latSamples: number;
4225
5977
  };
4226
5978
  /** @description One row of the catalog (docs/ai.md §2.3). */
4227
5979
  AIModel: {
4228
- /** @description The string you write in `env.ai.run()`. Frontier models are `<provider>/<model>`, value models are `@runlot/<model>` */
5980
+ /** @description The string you write in `env.ai.run()` or `env.ai.embed()`. Frontier models are `<provider>/<model>`, value models are `@runlot/<model>` */
4229
5981
  id: string;
5982
+ /**
5983
+ * @description What the model does (docs/vectors.md §2). `chat` is `env.ai.run` — tokens in, tokens out.
5984
+ * `embedding` is `env.ai.embed` — text in, a vector out: `maxOutputTokens` and `outPerMTok` are 0,
5985
+ * and `dimensions` says how wide the vector is.
5986
+ * @enum {string}
5987
+ */
5988
+ kind: "chat" | "embedding";
5989
+ /** @description Embedding models only: the width of the vector the model answers by default. */
5990
+ dimensions?: number;
5991
+ /** @description Embedding models only: every width `env.ai.embed(model, input, { dimensions })` may ask for. Absent when only the default is answered. */
5992
+ dimensionOptions?: number[];
4230
5993
  /** @enum {string} */
4231
5994
  lane: "frontier" | "value";
4232
5995
  display: string;
@@ -4380,6 +6143,57 @@ export interface components {
4380
6143
  /** @description The mail domain suffix for this installation. Email cannot be enabled if it is empty. */
4381
6144
  mailDomain: string;
4382
6145
  };
6146
+ /**
6147
+ * @description One line the customer publishes in their own DNS (docs/email.md §2.4). The values are
6148
+ * computed by the server so that the dashboard, the CLI, and the docs cannot disagree.
6149
+ */
6150
+ EmailDNSRecord: {
6151
+ /** @enum {string} */
6152
+ type: "CNAME" | "TXT";
6153
+ /** @example 4x7z…._domainkey.acme.com */
6154
+ name: string;
6155
+ /** @example 4x7z….dkim.amazonses.com */
6156
+ value: string;
6157
+ /**
6158
+ * @description `true` for the three DKIM CNAMEs — verification does not pass without them. `false`
6159
+ * for SPF and DMARC: they improve alignment and do not gate anything, and a customer
6160
+ * who already has their own SPF record should keep it.
6161
+ */
6162
+ required: boolean;
6163
+ };
6164
+ /** @description One custom sending domain and its verification state (docs/email.md §2.4). */
6165
+ EmailDomain: {
6166
+ /** @example acme.com */
6167
+ domain: string;
6168
+ /**
6169
+ * @description `pending` — the identity exists and DKIM is not signing yet. `verified` — the only
6170
+ * state `env.email.send({ from })` accepts. `failed` — the provider gave up, or the
6171
+ * records were not visible within 72 hours.
6172
+ * @enum {string}
6173
+ */
6174
+ state: "pending" | "verified" | "failed";
6175
+ /** @description At most one per project. */
6176
+ isDefault: boolean;
6177
+ /** @description The fact `state` is computed from. */
6178
+ dkimOk: boolean;
6179
+ /** @description Measured and never gating — a missing SPF record does not stop delivery. */
6180
+ spfOk: boolean;
6181
+ /** @description The sentence the customer reads. Empty once verified — a stale sentence reads as a live fault. */
6182
+ lastError?: string;
6183
+ /** Format: date-time */
6184
+ createdAt: string;
6185
+ /**
6186
+ * Format: date-time
6187
+ * @description Stamped once; it does not move on re-verification.
6188
+ */
6189
+ verifiedAt?: string;
6190
+ /** Format: date-time */
6191
+ lastCheckedAt?: string;
6192
+ /** @description Served in every state — a customer debugging a failed domain compares what they published against this. */
6193
+ records: components["schemas"]["EmailDNSRecord"][];
6194
+ /** @description We wrote the records into a zone we host, so there is nothing for the customer to publish. */
6195
+ published: boolean;
6196
+ };
4383
6197
  /** @description One line of the email log (docs/email.md §6.1). */
4384
6198
  MailLogEntry: {
4385
6199
  /** Format: uuid */
@@ -4491,6 +6305,47 @@ export interface components {
4491
6305
  */
4492
6306
  usedBytes: number;
4493
6307
  };
6308
+ /** @description One key prefix to publish or unpublish (docs/storage.md §4.7). */
6309
+ StoragePublicRequest: {
6310
+ /**
6311
+ * @description The prefix, relative to the project's slice — `assets`, `assets/`, or `avatars/img`.
6312
+ * It is stored normalized with a trailing slash, because matching is a plain string
6313
+ * prefix test and `assets` without the slash would also open `assets-private/`.
6314
+ *
6315
+ * `/` means **every key in the project's slice**. The empty string is refused: the
6316
+ * spelling exists so that an accidentally empty argument cannot publish a whole
6317
+ * bucket by looking like the default.
6318
+ * @example assets/
6319
+ */
6320
+ prefix: string;
6321
+ };
6322
+ /**
6323
+ * @description The prefixes this project serves unsigned. All three verbs answer with it, so a screen
6324
+ * never has to guess what the list became after a change.
6325
+ */
6326
+ StoragePublicList: {
6327
+ prefixes: {
6328
+ /**
6329
+ * @description The normalized value — it ends with `/`, or is empty for every key.
6330
+ * @example assets/
6331
+ */
6332
+ prefix: string;
6333
+ /**
6334
+ * Format: date-time
6335
+ * @description When it was published. This is the answer to "when did this become public".
6336
+ */
6337
+ createdAt: string;
6338
+ }[];
6339
+ /**
6340
+ * @description `https://<objects host>/<org>/<project>` — the address every prefix in the list is
6341
+ * readable under (a key `assets/logo.png` is at `<publicBase>/assets/logo.png`). It is
6342
+ * the same value `env.storage.publicUrl` builds on. **Absent when the deployment has
6343
+ * no public object front**, in which case nothing is served unsigned and `publicUrl`
6344
+ * answers null everywhere.
6345
+ * @example https://objects.runlot.io/acme/shop
6346
+ */
6347
+ publicBase?: string;
6348
+ };
4494
6349
  /**
4495
6350
  * @description Deployment access policy (docs/access.md §3.1). **Provides only non-secret state.**
4496
6351
  * Passwords and bypass keys are stored only as hashes, and the read API does not return
@@ -4897,6 +6752,13 @@ export interface components {
4897
6752
  };
4898
6753
  DomainList: {
4899
6754
  domains: components["schemas"]["Domain"][];
6755
+ /**
6756
+ * @description If true, the registrar is a sandbox (OTE) — nothing on this list was
6757
+ * really registered. It rides the listing as well as the search because
6758
+ * a screen that only ever lists never calls the search, and without it
6759
+ * that screen shows names that look bought and are not.
6760
+ */
6761
+ sandbox: boolean;
4900
6762
  };
4901
6763
  };
4902
6764
  responses: {
@@ -4918,7 +6780,15 @@ export interface components {
4918
6780
  "application/json": components["schemas"]["Error"];
4919
6781
  };
4920
6782
  };
4921
- /** @description Insufficient permissions */
6783
+ /**
6784
+ * @description Insufficient permissions.
6785
+ *
6786
+ * Two codes arrive with this status and they have different fixes. `forbidden` is the org
6787
+ * role — ask an admin. `insufficient_scope` is the credential — reissue the token, and
6788
+ * `error.details.requiredScope` names what it needs. A token restricted to another org or
6789
+ * project answers `insufficient_scope` with no `requiredScope`, because no scope would
6790
+ * have helped.
6791
+ */
4922
6792
  Forbidden: {
4923
6793
  headers: {
4924
6794
  [name: string]: unknown;
@@ -4949,6 +6819,8 @@ export interface components {
4949
6819
  parameters: {
4950
6820
  OrgSlug: components["schemas"]["Slug"];
4951
6821
  ProjectName: components["schemas"]["Slug"];
6822
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
6823
+ QueueName: string;
4952
6824
  /**
4953
6825
  * @description The operation id. **Not a credential** — the server checks whether the operation with
4954
6826
  * this id belongs to the project in the path, and returns 404 otherwise.
@@ -5066,7 +6938,11 @@ export interface operations {
5066
6938
  };
5067
6939
  };
5068
6940
  responses: {
5069
- /** @description Session token */
6941
+ /**
6942
+ * @description A session token — or, for an account with two-factor authentication on, a
6943
+ * `{"mfa":"totp","pending":…}` body carrying no token. Finish with
6944
+ * `POST /v1/auth/totp`.
6945
+ */
5070
6946
  200: {
5071
6947
  headers: {
5072
6948
  [name: string]: unknown;
@@ -5103,6 +6979,70 @@ export interface operations {
5103
6979
  };
5104
6980
  };
5105
6981
  };
6982
+ completeTotpLogin: {
6983
+ parameters: {
6984
+ query?: never;
6985
+ header?: never;
6986
+ path?: never;
6987
+ cookie?: never;
6988
+ };
6989
+ requestBody: {
6990
+ content: {
6991
+ "application/json": {
6992
+ pending: string;
6993
+ code?: string;
6994
+ /** @description One recovery code. Dashes, spaces and case are ignored. Spent whether or not it is the right one */
6995
+ recovery?: string;
6996
+ };
6997
+ };
6998
+ };
6999
+ responses: {
7000
+ /** @description Session token */
7001
+ 200: {
7002
+ headers: {
7003
+ [name: string]: unknown;
7004
+ };
7005
+ content: {
7006
+ "application/json": components["schemas"]["Session"];
7007
+ };
7008
+ };
7009
+ 400: components["responses"]["BadRequest"];
7010
+ /** @description The code did not match (`invalid_code`), or the pending token expired (`mfa_expired`) */
7011
+ 401: {
7012
+ headers: {
7013
+ [name: string]: unknown;
7014
+ };
7015
+ content: {
7016
+ "application/json": components["schemas"]["Error"];
7017
+ };
7018
+ };
7019
+ /** @description This account has no authenticator (`totp_disabled`) */
7020
+ 409: {
7021
+ headers: {
7022
+ [name: string]: unknown;
7023
+ };
7024
+ content: {
7025
+ "application/json": components["schemas"]["Error"];
7026
+ };
7027
+ };
7028
+ /** @description Too many attempts (5 per 5 minutes per account); retry after `Retry-After` */
7029
+ 429: {
7030
+ headers: {
7031
+ [name: string]: unknown;
7032
+ };
7033
+ content?: never;
7034
+ };
7035
+ /** @description This deployment cannot read the account's secret (`totp_unreadable`, `no_totp_key`) — use a recovery code */
7036
+ 503: {
7037
+ headers: {
7038
+ [name: string]: unknown;
7039
+ };
7040
+ content: {
7041
+ "application/json": components["schemas"]["Error"];
7042
+ };
7043
+ };
7044
+ };
7045
+ };
5106
7046
  passwordForgot: {
5107
7047
  parameters: {
5108
7048
  query?: never;
@@ -5463,13 +7403,20 @@ export interface operations {
5463
7403
  "application/json": {
5464
7404
  user: components["schemas"]["User"];
5465
7405
  orgs: components["schemas"]["OrgMembership"][];
7406
+ /**
7407
+ * @description Whether this account has a confirmed authenticator (migration 0066).
7408
+ * It is answered here rather than on `User` because `User` is loaded on
7409
+ * every authenticated request and this value is read by one screen — the
7410
+ * banner an organization's `requireTotp` draws.
7411
+ */
7412
+ totpEnabled: boolean;
5466
7413
  };
5467
7414
  };
5468
7415
  };
5469
7416
  401: components["responses"]["Unauthorized"];
5470
7417
  };
5471
7418
  };
5472
- listOrgs: {
7419
+ getTotp: {
5473
7420
  parameters: {
5474
7421
  query?: never;
5475
7422
  header?: never;
@@ -5478,21 +7425,19 @@ export interface operations {
5478
7425
  };
5479
7426
  requestBody?: never;
5480
7427
  responses: {
5481
- /** @description The owning organization */
7428
+ /** @description Status */
5482
7429
  200: {
5483
7430
  headers: {
5484
7431
  [name: string]: unknown;
5485
7432
  };
5486
7433
  content: {
5487
- "application/json": {
5488
- orgs: components["schemas"]["OrgMembership"][];
5489
- };
7434
+ "application/json": components["schemas"]["TotpStatus"];
5490
7435
  };
5491
7436
  };
5492
7437
  401: components["responses"]["Unauthorized"];
5493
7438
  };
5494
7439
  };
5495
- createOrg: {
7440
+ disableTotp: {
5496
7441
  parameters: {
5497
7442
  query?: never;
5498
7443
  header?: never;
@@ -5502,22 +7447,187 @@ export interface operations {
5502
7447
  requestBody: {
5503
7448
  content: {
5504
7449
  "application/json": {
5505
- slug: components["schemas"]["Slug"];
5506
- name: string;
7450
+ code?: string;
7451
+ recovery?: string;
5507
7452
  };
5508
7453
  };
5509
7454
  };
5510
7455
  responses: {
5511
- /** @description The created organization */
5512
- 201: {
7456
+ /** @description Two-factor authentication is off */
7457
+ 204: {
5513
7458
  headers: {
5514
7459
  [name: string]: unknown;
5515
7460
  };
5516
- content: {
5517
- "application/json": components["schemas"]["Org"];
5518
- };
7461
+ content?: never;
5519
7462
  };
5520
- 401: components["responses"]["Unauthorized"];
7463
+ 400: components["responses"]["BadRequest"];
7464
+ /** @description The code did not match (`invalid_code`) */
7465
+ 401: {
7466
+ headers: {
7467
+ [name: string]: unknown;
7468
+ };
7469
+ content: {
7470
+ "application/json": components["schemas"]["Error"];
7471
+ };
7472
+ };
7473
+ /** @description This account has no authenticator (`totp_disabled`) */
7474
+ 409: {
7475
+ headers: {
7476
+ [name: string]: unknown;
7477
+ };
7478
+ content: {
7479
+ "application/json": components["schemas"]["Error"];
7480
+ };
7481
+ };
7482
+ /** @description Too many attempts; retry after `Retry-After` */
7483
+ 429: {
7484
+ headers: {
7485
+ [name: string]: unknown;
7486
+ };
7487
+ content?: never;
7488
+ };
7489
+ };
7490
+ };
7491
+ enrollTotp: {
7492
+ parameters: {
7493
+ query?: never;
7494
+ header?: never;
7495
+ path?: never;
7496
+ cookie?: never;
7497
+ };
7498
+ requestBody?: never;
7499
+ responses: {
7500
+ /** @description The secret and the URI to scan */
7501
+ 200: {
7502
+ headers: {
7503
+ [name: string]: unknown;
7504
+ };
7505
+ content: {
7506
+ "application/json": components["schemas"]["TotpEnrollment"];
7507
+ };
7508
+ };
7509
+ 401: components["responses"]["Unauthorized"];
7510
+ /** @description Two-factor authentication is already on (`totp_enabled`) */
7511
+ 409: {
7512
+ headers: {
7513
+ [name: string]: unknown;
7514
+ };
7515
+ content: {
7516
+ "application/json": components["schemas"]["Error"];
7517
+ };
7518
+ };
7519
+ /** @description This deployment has no sealing key (`no_totp_key`) */
7520
+ 503: {
7521
+ headers: {
7522
+ [name: string]: unknown;
7523
+ };
7524
+ content: {
7525
+ "application/json": components["schemas"]["Error"];
7526
+ };
7527
+ };
7528
+ };
7529
+ };
7530
+ confirmTotp: {
7531
+ parameters: {
7532
+ query?: never;
7533
+ header?: never;
7534
+ path?: never;
7535
+ cookie?: never;
7536
+ };
7537
+ requestBody: {
7538
+ content: {
7539
+ "application/json": {
7540
+ code: string;
7541
+ };
7542
+ };
7543
+ };
7544
+ responses: {
7545
+ /** @description Two-factor authentication is on; here are the recovery codes */
7546
+ 200: {
7547
+ headers: {
7548
+ [name: string]: unknown;
7549
+ };
7550
+ content: {
7551
+ "application/json": components["schemas"]["TotpRecoveryCodes"];
7552
+ };
7553
+ };
7554
+ 400: components["responses"]["BadRequest"];
7555
+ /** @description The code did not match (`invalid_code`) */
7556
+ 401: {
7557
+ headers: {
7558
+ [name: string]: unknown;
7559
+ };
7560
+ content: {
7561
+ "application/json": components["schemas"]["Error"];
7562
+ };
7563
+ };
7564
+ /** @description There is nothing to confirm (`no_enrollment`), or it is already on (`totp_enabled`) */
7565
+ 409: {
7566
+ headers: {
7567
+ [name: string]: unknown;
7568
+ };
7569
+ content: {
7570
+ "application/json": components["schemas"]["Error"];
7571
+ };
7572
+ };
7573
+ /** @description Too many attempts; retry after `Retry-After` */
7574
+ 429: {
7575
+ headers: {
7576
+ [name: string]: unknown;
7577
+ };
7578
+ content?: never;
7579
+ };
7580
+ };
7581
+ };
7582
+ listOrgs: {
7583
+ parameters: {
7584
+ query?: never;
7585
+ header?: never;
7586
+ path?: never;
7587
+ cookie?: never;
7588
+ };
7589
+ requestBody?: never;
7590
+ responses: {
7591
+ /** @description The owning organization */
7592
+ 200: {
7593
+ headers: {
7594
+ [name: string]: unknown;
7595
+ };
7596
+ content: {
7597
+ "application/json": {
7598
+ orgs: components["schemas"]["OrgMembership"][];
7599
+ };
7600
+ };
7601
+ };
7602
+ 401: components["responses"]["Unauthorized"];
7603
+ };
7604
+ };
7605
+ createOrg: {
7606
+ parameters: {
7607
+ query?: never;
7608
+ header?: never;
7609
+ path?: never;
7610
+ cookie?: never;
7611
+ };
7612
+ requestBody: {
7613
+ content: {
7614
+ "application/json": {
7615
+ slug: components["schemas"]["Slug"];
7616
+ name: string;
7617
+ };
7618
+ };
7619
+ };
7620
+ responses: {
7621
+ /** @description The created organization */
7622
+ 201: {
7623
+ headers: {
7624
+ [name: string]: unknown;
7625
+ };
7626
+ content: {
7627
+ "application/json": components["schemas"]["Org"];
7628
+ };
7629
+ };
7630
+ 401: components["responses"]["Unauthorized"];
5521
7631
  409: components["responses"]["Conflict"];
5522
7632
  };
5523
7633
  };
@@ -5575,6 +7685,19 @@ export interface operations {
5575
7685
  content: {
5576
7686
  "application/json": {
5577
7687
  name: string;
7688
+ /**
7689
+ * @description Require two-factor authentication of every member (migration 0066).
7690
+ * Audited separately as `org.require_totp`.
7691
+ *
7692
+ * **Omitting the field leaves the setting alone.** A plain boolean would
7693
+ * mean every rename by an older client silently switched the requirement
7694
+ * off, and a security setting must never be changed by omission.
7695
+ *
7696
+ * While it is on, a member with no authenticator can still *read* the
7697
+ * org — the banner telling them to enroll is drawn by a screen they have
7698
+ * to be able to load — and every write answers 403 `totp_required`.
7699
+ */
7700
+ requireTotp?: boolean;
5578
7701
  };
5579
7702
  };
5580
7703
  };
@@ -5857,7 +7980,33 @@ export interface operations {
5857
7980
  };
5858
7981
  createDeployment: {
5859
7982
  parameters: {
5860
- query?: never;
7983
+ query?: {
7984
+ /**
7985
+ * @description Deploy to the named preview instead of production. Slug rules, at most 30
7986
+ * characters — it becomes half of the DNS label `<preview>--<project>`.
7987
+ *
7988
+ * Creates the preview if it does not exist. Exceeding the plan's per-project
7989
+ * preview count answers **409 `preview_limit`**.
7990
+ */
7991
+ preview?: components["schemas"]["Slug"];
7992
+ /**
7993
+ * @description What the preview's `env.db` points at (docs/preview.md §3.1). Ignored without
7994
+ * `preview`.
7995
+ *
7996
+ * - `branch` — its own store, poured from the parent's newest generation. The
7997
+ * default, and a **full copy** of the parent's pages at the moment it was taken.
7998
+ * - `shared` — the preview runs against **production's** database. A destructive
7999
+ * statement in the preview is destructive in production.
8000
+ * - `none` — no `env.db` at all.
8001
+ */
8002
+ db?: "branch" | "shared" | "none";
8003
+ /**
8004
+ * @description Pour the branch from this generation instead of the newest one — any key
8005
+ * `getGenerations` lists for the parent. Only meaningful with `db=branch`; a
8006
+ * chain that is not whole answers **409 `chain_broken`**, the same as a restore.
8007
+ */
8008
+ from?: string;
8009
+ };
5861
8010
  header?: {
5862
8011
  "X-Runlot-Git-Commit"?: string;
5863
8012
  "X-Runlot-Git-Message"?: string;
@@ -5927,9 +8076,12 @@ export interface operations {
5927
8076
  404: components["responses"]["NotFound"];
5928
8077
  };
5929
8078
  };
5930
- rollback: {
8079
+ getProjectQueues: {
5931
8080
  parameters: {
5932
- query?: never;
8081
+ query?: {
8082
+ /** @description How many history rows. Default 50, capped at 200. */
8083
+ limit?: number;
8084
+ };
5933
8085
  header?: never;
5934
8086
  path: {
5935
8087
  orgSlug: components["parameters"]["OrgSlug"];
@@ -5937,28 +8089,22 @@ export interface operations {
5937
8089
  };
5938
8090
  cookie?: never;
5939
8091
  };
5940
- requestBody: {
5941
- content: {
5942
- "application/json": {
5943
- version: number;
5944
- };
5945
- };
5946
- };
8092
+ requestBody?: never;
5947
8093
  responses: {
5948
- /** @description Rolled-back deployment */
8094
+ /** @description The declared queues with their depth, and the recent history */
5949
8095
  200: {
5950
8096
  headers: {
5951
8097
  [name: string]: unknown;
5952
8098
  };
5953
8099
  content: {
5954
- "application/json": components["schemas"]["Deployment"];
8100
+ "application/json": components["schemas"]["QueueOverview"];
5955
8101
  };
5956
8102
  };
5957
8103
  403: components["responses"]["Forbidden"];
5958
8104
  404: components["responses"]["NotFound"];
5959
8105
  };
5960
8106
  };
5961
- getDatabase: {
8107
+ getProjectVectors: {
5962
8108
  parameters: {
5963
8109
  query?: never;
5964
8110
  header?: never;
@@ -5970,47 +8116,63 @@ export interface operations {
5970
8116
  };
5971
8117
  requestBody?: never;
5972
8118
  responses: {
5973
- /** @description Whether the database is available */
8119
+ /** @description The namespaces and the bounds */
5974
8120
  200: {
5975
8121
  headers: {
5976
8122
  [name: string]: unknown;
5977
8123
  };
5978
8124
  content: {
5979
- "application/json": {
5980
- db: boolean;
5981
- };
8125
+ "application/json": components["schemas"]["VectorOverview"];
5982
8126
  };
5983
8127
  };
5984
8128
  403: components["responses"]["Forbidden"];
5985
8129
  404: components["responses"]["NotFound"];
5986
8130
  };
5987
8131
  };
5988
- createDatabase: {
8132
+ deleteVectorNamespace: {
5989
8133
  parameters: {
5990
8134
  query?: never;
5991
8135
  header?: never;
5992
8136
  path: {
5993
8137
  orgSlug: components["parameters"]["OrgSlug"];
5994
8138
  projectName: components["parameters"]["ProjectName"];
8139
+ namespace: string;
5995
8140
  };
5996
8141
  cookie?: never;
5997
8142
  };
5998
8143
  requestBody?: never;
5999
8144
  responses: {
6000
- /** @description Credentials and connection info */
8145
+ /** @description Deleted */
6001
8146
  200: {
6002
8147
  headers: {
6003
8148
  [name: string]: unknown;
6004
8149
  };
6005
8150
  content: {
6006
- "application/json": components["schemas"]["DatabaseConnect"];
8151
+ "application/json": {
8152
+ namespace: string;
8153
+ /**
8154
+ * Format: int64
8155
+ * @description How many vectors were deleted.
8156
+ */
8157
+ deleted: number;
8158
+ };
6007
8159
  };
6008
8160
  };
8161
+ 400: components["responses"]["BadRequest"];
6009
8162
  403: components["responses"]["Forbidden"];
6010
8163
  404: components["responses"]["NotFound"];
8164
+ /** @description `console_unreachable` — the project's database could not be reached */
8165
+ 502: {
8166
+ headers: {
8167
+ [name: string]: unknown;
8168
+ };
8169
+ content: {
8170
+ "application/json": components["schemas"]["Error"];
8171
+ };
8172
+ };
6011
8173
  };
6012
8174
  };
6013
- getDatabaseConnect: {
8175
+ getProjectDurableObjects: {
6014
8176
  parameters: {
6015
8177
  query?: never;
6016
8178
  header?: never;
@@ -6022,96 +8184,367 @@ export interface operations {
6022
8184
  };
6023
8185
  requestBody?: never;
6024
8186
  responses: {
6025
- /** @description Connection info */
8187
+ /** @description The counts and the two caps */
6026
8188
  200: {
6027
8189
  headers: {
6028
8190
  [name: string]: unknown;
6029
8191
  };
6030
8192
  content: {
6031
- "application/json": components["schemas"]["DatabaseConnect"];
8193
+ "application/json": components["schemas"]["DurableObjectUsage"];
6032
8194
  };
6033
8195
  };
6034
8196
  403: components["responses"]["Forbidden"];
6035
- /** @description The project does not exist, or its database has not been created yet */
6036
- 404: {
6037
- headers: {
6038
- [name: string]: unknown;
6039
- };
6040
- content: {
6041
- "application/json": components["schemas"]["Error"];
6042
- };
6043
- };
8197
+ 404: components["responses"]["NotFound"];
6044
8198
  };
6045
8199
  };
6046
- getDatabaseEndpoint: {
8200
+ listQueueRuns: {
6047
8201
  parameters: {
6048
- query?: never;
8202
+ query?: {
8203
+ /** @description Default 50, capped at 200. */
8204
+ limit?: number;
8205
+ };
6049
8206
  header?: never;
6050
8207
  path: {
6051
8208
  orgSlug: components["parameters"]["OrgSlug"];
6052
8209
  projectName: components["parameters"]["ProjectName"];
8210
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
8211
+ queue: components["parameters"]["QueueName"];
6053
8212
  };
6054
8213
  cookie?: never;
6055
8214
  };
6056
8215
  requestBody?: never;
6057
8216
  responses: {
6058
- /** @description Endpoint */
8217
+ /** @description Batches of this queue */
6059
8218
  200: {
6060
8219
  headers: {
6061
8220
  [name: string]: unknown;
6062
8221
  };
6063
8222
  content: {
6064
8223
  "application/json": {
6065
- db: boolean;
6066
- endpoint: components["schemas"]["DatabaseEndpoint"];
8224
+ queue: string;
8225
+ runs: components["schemas"]["QueueRun"][];
6067
8226
  };
6068
8227
  };
6069
8228
  };
8229
+ 400: components["responses"]["BadRequest"];
6070
8230
  403: components["responses"]["Forbidden"];
6071
8231
  404: components["responses"]["NotFound"];
6072
8232
  };
6073
8233
  };
6074
- listDatabaseTokens: {
8234
+ peekQueue: {
6075
8235
  parameters: {
6076
- query?: never;
8236
+ query?: {
8237
+ /** @description Default 10, capped at 100. */
8238
+ limit?: number;
8239
+ };
6077
8240
  header?: never;
6078
8241
  path: {
6079
8242
  orgSlug: components["parameters"]["OrgSlug"];
6080
8243
  projectName: components["parameters"]["ProjectName"];
8244
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
8245
+ queue: components["parameters"]["QueueName"];
6081
8246
  };
6082
8247
  cookie?: never;
6083
8248
  };
6084
8249
  requestBody?: never;
6085
8250
  responses: {
6086
- /** @description List */
8251
+ /** @description The head of the queue */
6087
8252
  200: {
6088
8253
  headers: {
6089
8254
  [name: string]: unknown;
6090
8255
  };
6091
8256
  content: {
6092
8257
  "application/json": {
6093
- tokens: components["schemas"]["DatabaseTokenMeta"][];
8258
+ queue: string;
8259
+ messages: components["schemas"]["QueueMessage"][];
6094
8260
  };
6095
8261
  };
6096
8262
  };
8263
+ 400: components["responses"]["BadRequest"];
6097
8264
  403: components["responses"]["Forbidden"];
6098
- 404: components["responses"]["NotFound"];
8265
+ /** @description No such project, or the project has no database (`not_found`) */
8266
+ 404: {
8267
+ headers: {
8268
+ [name: string]: unknown;
8269
+ };
8270
+ content: {
8271
+ "application/json": components["schemas"]["Error"];
8272
+ };
8273
+ };
8274
+ /** @description `console_unreachable` — the project's database could not be reached */
8275
+ 502: {
8276
+ headers: {
8277
+ [name: string]: unknown;
8278
+ };
8279
+ content: {
8280
+ "application/json": components["schemas"]["Error"];
8281
+ };
8282
+ };
6099
8283
  };
6100
8284
  };
6101
- createDatabaseToken: {
8285
+ purgeQueue: {
6102
8286
  parameters: {
6103
8287
  query?: never;
6104
8288
  header?: never;
6105
8289
  path: {
6106
8290
  orgSlug: components["parameters"]["OrgSlug"];
6107
8291
  projectName: components["parameters"]["ProjectName"];
8292
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
8293
+ queue: components["parameters"]["QueueName"];
6108
8294
  };
6109
8295
  cookie?: never;
6110
8296
  };
6111
- requestBody?: {
6112
- content: {
6113
- "application/json": {
6114
- /** @description Default 3600, maximum 86400. */
8297
+ requestBody?: never;
8298
+ responses: {
8299
+ /** @description Purged */
8300
+ 200: {
8301
+ headers: {
8302
+ [name: string]: unknown;
8303
+ };
8304
+ content: {
8305
+ "application/json": {
8306
+ queue: string;
8307
+ /**
8308
+ * Format: int64
8309
+ * @description How many messages were deleted.
8310
+ */
8311
+ purged: number;
8312
+ };
8313
+ };
8314
+ };
8315
+ 400: components["responses"]["BadRequest"];
8316
+ 403: components["responses"]["Forbidden"];
8317
+ 404: components["responses"]["NotFound"];
8318
+ };
8319
+ };
8320
+ redriveQueue: {
8321
+ parameters: {
8322
+ query?: never;
8323
+ header?: never;
8324
+ path: {
8325
+ orgSlug: components["parameters"]["OrgSlug"];
8326
+ projectName: components["parameters"]["ProjectName"];
8327
+ /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
8328
+ queue: components["parameters"]["QueueName"];
8329
+ };
8330
+ cookie?: never;
8331
+ };
8332
+ requestBody?: {
8333
+ content: {
8334
+ "application/json": {
8335
+ /** @description The destination queue. Optional when exactly one consumer names `{queue}` as its dead-letter queue. */
8336
+ to?: string;
8337
+ };
8338
+ };
8339
+ };
8340
+ responses: {
8341
+ /** @description Redriven */
8342
+ 200: {
8343
+ headers: {
8344
+ [name: string]: unknown;
8345
+ };
8346
+ content: {
8347
+ "application/json": {
8348
+ from: string;
8349
+ to: string;
8350
+ /**
8351
+ * Format: int64
8352
+ * @description How many messages moved.
8353
+ */
8354
+ moved: number;
8355
+ };
8356
+ };
8357
+ };
8358
+ 400: components["responses"]["BadRequest"];
8359
+ 403: components["responses"]["Forbidden"];
8360
+ 404: components["responses"]["NotFound"];
8361
+ };
8362
+ };
8363
+ rollback: {
8364
+ parameters: {
8365
+ query?: never;
8366
+ header?: never;
8367
+ path: {
8368
+ orgSlug: components["parameters"]["OrgSlug"];
8369
+ projectName: components["parameters"]["ProjectName"];
8370
+ };
8371
+ cookie?: never;
8372
+ };
8373
+ requestBody: {
8374
+ content: {
8375
+ "application/json": {
8376
+ version: number;
8377
+ };
8378
+ };
8379
+ };
8380
+ responses: {
8381
+ /** @description Rolled-back deployment */
8382
+ 200: {
8383
+ headers: {
8384
+ [name: string]: unknown;
8385
+ };
8386
+ content: {
8387
+ "application/json": components["schemas"]["Deployment"];
8388
+ };
8389
+ };
8390
+ 403: components["responses"]["Forbidden"];
8391
+ 404: components["responses"]["NotFound"];
8392
+ };
8393
+ };
8394
+ getDatabase: {
8395
+ parameters: {
8396
+ query?: never;
8397
+ header?: never;
8398
+ path: {
8399
+ orgSlug: components["parameters"]["OrgSlug"];
8400
+ projectName: components["parameters"]["ProjectName"];
8401
+ };
8402
+ cookie?: never;
8403
+ };
8404
+ requestBody?: never;
8405
+ responses: {
8406
+ /** @description Whether the database is available */
8407
+ 200: {
8408
+ headers: {
8409
+ [name: string]: unknown;
8410
+ };
8411
+ content: {
8412
+ "application/json": {
8413
+ db: boolean;
8414
+ };
8415
+ };
8416
+ };
8417
+ 403: components["responses"]["Forbidden"];
8418
+ 404: components["responses"]["NotFound"];
8419
+ };
8420
+ };
8421
+ createDatabase: {
8422
+ parameters: {
8423
+ query?: never;
8424
+ header?: never;
8425
+ path: {
8426
+ orgSlug: components["parameters"]["OrgSlug"];
8427
+ projectName: components["parameters"]["ProjectName"];
8428
+ };
8429
+ cookie?: never;
8430
+ };
8431
+ requestBody?: never;
8432
+ responses: {
8433
+ /** @description Credentials and connection info */
8434
+ 200: {
8435
+ headers: {
8436
+ [name: string]: unknown;
8437
+ };
8438
+ content: {
8439
+ "application/json": components["schemas"]["DatabaseConnect"];
8440
+ };
8441
+ };
8442
+ 403: components["responses"]["Forbidden"];
8443
+ 404: components["responses"]["NotFound"];
8444
+ };
8445
+ };
8446
+ getDatabaseConnect: {
8447
+ parameters: {
8448
+ query?: never;
8449
+ header?: never;
8450
+ path: {
8451
+ orgSlug: components["parameters"]["OrgSlug"];
8452
+ projectName: components["parameters"]["ProjectName"];
8453
+ };
8454
+ cookie?: never;
8455
+ };
8456
+ requestBody?: never;
8457
+ responses: {
8458
+ /** @description Connection info */
8459
+ 200: {
8460
+ headers: {
8461
+ [name: string]: unknown;
8462
+ };
8463
+ content: {
8464
+ "application/json": components["schemas"]["DatabaseConnect"];
8465
+ };
8466
+ };
8467
+ 403: components["responses"]["Forbidden"];
8468
+ /** @description The project does not exist, or its database has not been created yet */
8469
+ 404: {
8470
+ headers: {
8471
+ [name: string]: unknown;
8472
+ };
8473
+ content: {
8474
+ "application/json": components["schemas"]["Error"];
8475
+ };
8476
+ };
8477
+ };
8478
+ };
8479
+ getDatabaseEndpoint: {
8480
+ parameters: {
8481
+ query?: never;
8482
+ header?: never;
8483
+ path: {
8484
+ orgSlug: components["parameters"]["OrgSlug"];
8485
+ projectName: components["parameters"]["ProjectName"];
8486
+ };
8487
+ cookie?: never;
8488
+ };
8489
+ requestBody?: never;
8490
+ responses: {
8491
+ /** @description Endpoint */
8492
+ 200: {
8493
+ headers: {
8494
+ [name: string]: unknown;
8495
+ };
8496
+ content: {
8497
+ "application/json": {
8498
+ db: boolean;
8499
+ endpoint: components["schemas"]["DatabaseEndpoint"];
8500
+ };
8501
+ };
8502
+ };
8503
+ 403: components["responses"]["Forbidden"];
8504
+ 404: components["responses"]["NotFound"];
8505
+ };
8506
+ };
8507
+ listDatabaseTokens: {
8508
+ parameters: {
8509
+ query?: never;
8510
+ header?: never;
8511
+ path: {
8512
+ orgSlug: components["parameters"]["OrgSlug"];
8513
+ projectName: components["parameters"]["ProjectName"];
8514
+ };
8515
+ cookie?: never;
8516
+ };
8517
+ requestBody?: never;
8518
+ responses: {
8519
+ /** @description List */
8520
+ 200: {
8521
+ headers: {
8522
+ [name: string]: unknown;
8523
+ };
8524
+ content: {
8525
+ "application/json": {
8526
+ tokens: components["schemas"]["DatabaseTokenMeta"][];
8527
+ };
8528
+ };
8529
+ };
8530
+ 403: components["responses"]["Forbidden"];
8531
+ 404: components["responses"]["NotFound"];
8532
+ };
8533
+ };
8534
+ createDatabaseToken: {
8535
+ parameters: {
8536
+ query?: never;
8537
+ header?: never;
8538
+ path: {
8539
+ orgSlug: components["parameters"]["OrgSlug"];
8540
+ projectName: components["parameters"]["ProjectName"];
8541
+ };
8542
+ cookie?: never;
8543
+ };
8544
+ requestBody?: {
8545
+ content: {
8546
+ "application/json": {
8547
+ /** @description Default 3600, maximum 86400. */
6115
8548
  ttlSeconds?: number;
6116
8549
  };
6117
8550
  };
@@ -6155,6 +8588,64 @@ export interface operations {
6155
8588
  404: components["responses"]["NotFound"];
6156
8589
  };
6157
8590
  };
8591
+ executeSQL: {
8592
+ parameters: {
8593
+ query?: never;
8594
+ header?: never;
8595
+ path: {
8596
+ orgSlug: components["parameters"]["OrgSlug"];
8597
+ projectName: components["parameters"]["ProjectName"];
8598
+ };
8599
+ cookie?: never;
8600
+ };
8601
+ requestBody: {
8602
+ content: {
8603
+ "application/json": components["schemas"]["ExecuteRequest"];
8604
+ };
8605
+ };
8606
+ responses: {
8607
+ /** @description The statement ran */
8608
+ 200: {
8609
+ headers: {
8610
+ [name: string]: unknown;
8611
+ };
8612
+ content: {
8613
+ "application/json": components["schemas"]["ExecuteResult"];
8614
+ };
8615
+ };
8616
+ /**
8617
+ * @description The statement was refused. `code` is `sql_error` and `details.sqlstate` carries
8618
+ * PostgreSQL's own five-character code — the string every manual and every answer is
8619
+ * indexed by. `details` may also hold `detail`, `hint` and `position`. It is a 400
8620
+ * and not a 500 because a statement the database refused is the user's statement
8621
+ * being wrong.
8622
+ */
8623
+ 400: {
8624
+ headers: {
8625
+ [name: string]: unknown;
8626
+ };
8627
+ content: {
8628
+ "application/json": components["schemas"]["Error"];
8629
+ };
8630
+ };
8631
+ 403: components["responses"]["Forbidden"];
8632
+ 404: components["responses"]["NotFound"];
8633
+ /** @description could not reach this project's database (`console_unreachable`) */
8634
+ 502: {
8635
+ headers: {
8636
+ [name: string]: unknown;
8637
+ };
8638
+ content?: never;
8639
+ };
8640
+ /** @description the database did not answer within the round-trip deadline (`console_timeout`) */
8641
+ 504: {
8642
+ headers: {
8643
+ [name: string]: unknown;
8644
+ };
8645
+ content?: never;
8646
+ };
8647
+ };
8648
+ };
6158
8649
  exportDatabase: {
6159
8650
  parameters: {
6160
8651
  query?: never;
@@ -6224,7 +8715,10 @@ export interface operations {
6224
8715
  };
6225
8716
  listGenerations: {
6226
8717
  parameters: {
6227
- query?: never;
8718
+ query?: {
8719
+ /** @description Narrows the **object half only**, to the newest component at or before this instant per holder. The database generations are listed in full and the user picks among them; an object restore takes one component per holder, so the only question there is which instant. */
8720
+ at?: string;
8721
+ };
6228
8722
  header?: never;
6229
8723
  path: {
6230
8724
  orgSlug: components["parameters"]["OrgSlug"];
@@ -6512,6 +9006,64 @@ export interface operations {
6512
9006
  };
6513
9007
  };
6514
9008
  };
9009
+ getLogHistory: {
9010
+ parameters: {
9011
+ query?: {
9012
+ /** @description Oldest line to return (RFC3339). Omit for everything still kept */
9013
+ since?: string;
9014
+ /** @description Newest line to return (RFC3339) */
9015
+ until?: string;
9016
+ /**
9017
+ * @description Plain substring, matched case-insensitively against the line. It is not a
9018
+ * regular expression — `%` and `_` match themselves.
9019
+ */
9020
+ q?: string;
9021
+ /** @description Narrow to one stream. Omit for all three */
9022
+ stream?: "stdout" | "stderr" | "runlot";
9023
+ /** @description Lines per page. Capped at 1000 */
9024
+ limit?: number;
9025
+ /** @description The `cursor` of the previous page */
9026
+ cursor?: string;
9027
+ };
9028
+ header?: never;
9029
+ path: {
9030
+ orgSlug: components["parameters"]["OrgSlug"];
9031
+ projectName: components["parameters"]["ProjectName"];
9032
+ };
9033
+ cookie?: never;
9034
+ };
9035
+ requestBody?: never;
9036
+ responses: {
9037
+ /** @description One page, newest first */
9038
+ 200: {
9039
+ headers: {
9040
+ [name: string]: unknown;
9041
+ };
9042
+ content: {
9043
+ "application/json": components["schemas"]["LogHistoryPage"];
9044
+ };
9045
+ };
9046
+ /** @description `since`/`until` is not RFC3339, `stream` is not one of the three, or the cursor is unreadable */
9047
+ 400: {
9048
+ headers: {
9049
+ [name: string]: unknown;
9050
+ };
9051
+ content: {
9052
+ "application/json": components["schemas"]["Error"];
9053
+ };
9054
+ };
9055
+ 403: components["responses"]["Forbidden"];
9056
+ /** @description The organization or project does not exist */
9057
+ 404: {
9058
+ headers: {
9059
+ [name: string]: unknown;
9060
+ };
9061
+ content: {
9062
+ "application/json": components["schemas"]["Error"];
9063
+ };
9064
+ };
9065
+ };
9066
+ };
6515
9067
  listSecrets: {
6516
9068
  parameters: {
6517
9069
  query?: never;
@@ -6530,47 +9082,168 @@ export interface operations {
6530
9082
  [name: string]: unknown;
6531
9083
  };
6532
9084
  content: {
6533
- "application/json": components["schemas"]["SecretList"];
9085
+ "application/json": components["schemas"]["SecretList"];
9086
+ };
9087
+ };
9088
+ 403: components["responses"]["Forbidden"];
9089
+ 404: components["responses"]["NotFound"];
9090
+ };
9091
+ };
9092
+ setSecret: {
9093
+ parameters: {
9094
+ query?: never;
9095
+ header?: never;
9096
+ path: {
9097
+ orgSlug: components["parameters"]["OrgSlug"];
9098
+ projectName: components["parameters"]["ProjectName"];
9099
+ secretName: components["parameters"]["SecretName"];
9100
+ };
9101
+ cookie?: never;
9102
+ };
9103
+ requestBody: {
9104
+ content: {
9105
+ "application/json": {
9106
+ value: string;
9107
+ };
9108
+ };
9109
+ };
9110
+ responses: {
9111
+ /** @description Stored name and version */
9112
+ 200: {
9113
+ headers: {
9114
+ [name: string]: unknown;
9115
+ };
9116
+ content: {
9117
+ "application/json": components["schemas"]["SecretMeta"];
9118
+ };
9119
+ };
9120
+ /**
9121
+ * @description The name does not follow the rules (`bad_request`) or is a reserved name
9122
+ * (`reserved_name`: `DB`, `ASSETS`, `RUNLOT_*` — the uppercase counterparts of
9123
+ * the `env.db` and `env.assets` bindings, and the node prefix)
9124
+ */
9125
+ 400: {
9126
+ headers: {
9127
+ [name: string]: unknown;
9128
+ };
9129
+ content: {
9130
+ "application/json": components["schemas"]["Error"];
9131
+ };
9132
+ };
9133
+ 403: components["responses"]["Forbidden"];
9134
+ 404: components["responses"]["NotFound"];
9135
+ };
9136
+ };
9137
+ deleteSecret: {
9138
+ parameters: {
9139
+ query?: never;
9140
+ header?: never;
9141
+ path: {
9142
+ orgSlug: components["parameters"]["OrgSlug"];
9143
+ projectName: components["parameters"]["ProjectName"];
9144
+ secretName: components["parameters"]["SecretName"];
9145
+ };
9146
+ cookie?: never;
9147
+ };
9148
+ requestBody?: never;
9149
+ responses: {
9150
+ /** @description deleted */
9151
+ 204: {
9152
+ headers: {
9153
+ [name: string]: unknown;
9154
+ };
9155
+ content?: never;
9156
+ };
9157
+ 403: components["responses"]["Forbidden"];
9158
+ 404: components["responses"]["NotFound"];
9159
+ };
9160
+ };
9161
+ getUsage: {
9162
+ parameters: {
9163
+ query?: {
9164
+ hours?: number;
9165
+ };
9166
+ header?: never;
9167
+ path: {
9168
+ orgSlug: components["parameters"]["OrgSlug"];
9169
+ projectName: components["parameters"]["ProjectName"];
9170
+ };
9171
+ cookie?: never;
9172
+ };
9173
+ requestBody?: never;
9174
+ responses: {
9175
+ /** @description Usage */
9176
+ 200: {
9177
+ headers: {
9178
+ [name: string]: unknown;
9179
+ };
9180
+ content: {
9181
+ "application/json": components["schemas"]["Usage"];
9182
+ };
9183
+ };
9184
+ 403: components["responses"]["Forbidden"];
9185
+ 404: components["responses"]["NotFound"];
9186
+ };
9187
+ };
9188
+ getStorage: {
9189
+ parameters: {
9190
+ query?: never;
9191
+ header?: never;
9192
+ path: {
9193
+ orgSlug: components["parameters"]["OrgSlug"];
9194
+ projectName: components["parameters"]["ProjectName"];
9195
+ };
9196
+ cookie?: never;
9197
+ };
9198
+ requestBody?: never;
9199
+ responses: {
9200
+ /** @description Storage status */
9201
+ 200: {
9202
+ headers: {
9203
+ [name: string]: unknown;
9204
+ };
9205
+ content: {
9206
+ "application/json": components["schemas"]["StorageStatus"];
9207
+ };
9208
+ };
9209
+ 403: components["responses"]["Forbidden"];
9210
+ 404: components["responses"]["NotFound"];
9211
+ /** @description `no_core` — no connection to cp-core */
9212
+ 503: {
9213
+ headers: {
9214
+ [name: string]: unknown;
9215
+ };
9216
+ content: {
9217
+ "application/json": components["schemas"]["Error"];
6534
9218
  };
6535
9219
  };
6536
- 403: components["responses"]["Forbidden"];
6537
- 404: components["responses"]["NotFound"];
6538
9220
  };
6539
9221
  };
6540
- setSecret: {
9222
+ grantStorage: {
6541
9223
  parameters: {
6542
9224
  query?: never;
6543
9225
  header?: never;
6544
9226
  path: {
6545
9227
  orgSlug: components["parameters"]["OrgSlug"];
6546
9228
  projectName: components["parameters"]["ProjectName"];
6547
- secretName: components["parameters"]["SecretName"];
6548
9229
  };
6549
9230
  cookie?: never;
6550
9231
  };
6551
- requestBody: {
6552
- content: {
6553
- "application/json": {
6554
- value: string;
6555
- };
6556
- };
6557
- };
9232
+ requestBody?: never;
6558
9233
  responses: {
6559
- /** @description Stored name and version */
9234
+ /** @description Grant status (existing value if it was already there) */
6560
9235
  200: {
6561
9236
  headers: {
6562
9237
  [name: string]: unknown;
6563
9238
  };
6564
9239
  content: {
6565
- "application/json": components["schemas"]["SecretMeta"];
9240
+ "application/json": components["schemas"]["StorageStatus"];
6566
9241
  };
6567
9242
  };
6568
- /**
6569
- * @description The name does not follow the rules (`bad_request`) or is a reserved name
6570
- * (`reserved_name`: `DB`, `ASSETS`, `RUNLOT_*` — the uppercase counterparts of
6571
- * the `env.db` and `env.assets` bindings, and the node prefix)
6572
- */
6573
- 400: {
9243
+ 403: components["responses"]["Forbidden"];
9244
+ 404: components["responses"]["NotFound"];
9245
+ /** @description `no_core` */
9246
+ 503: {
6574
9247
  headers: {
6575
9248
  [name: string]: unknown;
6576
9249
  };
@@ -6578,24 +9251,21 @@ export interface operations {
6578
9251
  "application/json": components["schemas"]["Error"];
6579
9252
  };
6580
9253
  };
6581
- 403: components["responses"]["Forbidden"];
6582
- 404: components["responses"]["NotFound"];
6583
9254
  };
6584
9255
  };
6585
- deleteSecret: {
9256
+ revokeStorage: {
6586
9257
  parameters: {
6587
9258
  query?: never;
6588
9259
  header?: never;
6589
9260
  path: {
6590
9261
  orgSlug: components["parameters"]["OrgSlug"];
6591
9262
  projectName: components["parameters"]["ProjectName"];
6592
- secretName: components["parameters"]["SecretName"];
6593
9263
  };
6594
9264
  cookie?: never;
6595
9265
  };
6596
9266
  requestBody?: never;
6597
9267
  responses: {
6598
- /** @description deleted */
9268
+ /** @description detached */
6599
9269
  204: {
6600
9270
  headers: {
6601
9271
  [name: string]: unknown;
@@ -6604,36 +9274,18 @@ export interface operations {
6604
9274
  };
6605
9275
  403: components["responses"]["Forbidden"];
6606
9276
  404: components["responses"]["NotFound"];
6607
- };
6608
- };
6609
- getUsage: {
6610
- parameters: {
6611
- query?: {
6612
- hours?: number;
6613
- };
6614
- header?: never;
6615
- path: {
6616
- orgSlug: components["parameters"]["OrgSlug"];
6617
- projectName: components["parameters"]["ProjectName"];
6618
- };
6619
- cookie?: never;
6620
- };
6621
- requestBody?: never;
6622
- responses: {
6623
- /** @description Usage */
6624
- 200: {
9277
+ /** @description `no_core` */
9278
+ 503: {
6625
9279
  headers: {
6626
9280
  [name: string]: unknown;
6627
9281
  };
6628
9282
  content: {
6629
- "application/json": components["schemas"]["Usage"];
9283
+ "application/json": components["schemas"]["Error"];
6630
9284
  };
6631
9285
  };
6632
- 403: components["responses"]["Forbidden"];
6633
- 404: components["responses"]["NotFound"];
6634
9286
  };
6635
9287
  };
6636
- getStorage: {
9288
+ listStoragePublic: {
6637
9289
  parameters: {
6638
9290
  query?: never;
6639
9291
  header?: never;
@@ -6645,18 +9297,18 @@ export interface operations {
6645
9297
  };
6646
9298
  requestBody?: never;
6647
9299
  responses: {
6648
- /** @description Storage status */
9300
+ /** @description The list */
6649
9301
  200: {
6650
9302
  headers: {
6651
9303
  [name: string]: unknown;
6652
9304
  };
6653
9305
  content: {
6654
- "application/json": components["schemas"]["StorageStatus"];
9306
+ "application/json": components["schemas"]["StoragePublicList"];
6655
9307
  };
6656
9308
  };
6657
9309
  403: components["responses"]["Forbidden"];
6658
9310
  404: components["responses"]["NotFound"];
6659
- /** @description `no_core` — no connection to cp-core */
9311
+ /** @description `no_core` */
6660
9312
  503: {
6661
9313
  headers: {
6662
9314
  [name: string]: unknown;
@@ -6667,7 +9319,7 @@ export interface operations {
6667
9319
  };
6668
9320
  };
6669
9321
  };
6670
- grantStorage: {
9322
+ addStoragePublic: {
6671
9323
  parameters: {
6672
9324
  query?: never;
6673
9325
  header?: never;
@@ -6677,19 +9329,41 @@ export interface operations {
6677
9329
  };
6678
9330
  cookie?: never;
6679
9331
  };
6680
- requestBody?: never;
9332
+ requestBody: {
9333
+ content: {
9334
+ "application/json": components["schemas"]["StoragePublicRequest"];
9335
+ };
9336
+ };
6681
9337
  responses: {
6682
- /** @description Grant status (existing value if it was already there) */
9338
+ /** @description The list after the change */
6683
9339
  200: {
6684
9340
  headers: {
6685
9341
  [name: string]: unknown;
6686
9342
  };
6687
9343
  content: {
6688
- "application/json": components["schemas"]["StorageStatus"];
9344
+ "application/json": components["schemas"]["StoragePublicList"];
9345
+ };
9346
+ };
9347
+ /** @description The prefix is empty, not normalizable, or would leave the project's slice */
9348
+ 400: {
9349
+ headers: {
9350
+ [name: string]: unknown;
9351
+ };
9352
+ content: {
9353
+ "application/json": components["schemas"]["Error"];
6689
9354
  };
6690
9355
  };
6691
9356
  403: components["responses"]["Forbidden"];
6692
9357
  404: components["responses"]["NotFound"];
9358
+ /** @description `storage_not_granted`, or `too_many_public_prefixes` */
9359
+ 409: {
9360
+ headers: {
9361
+ [name: string]: unknown;
9362
+ };
9363
+ content: {
9364
+ "application/json": components["schemas"]["Error"];
9365
+ };
9366
+ };
6693
9367
  /** @description `no_core` */
6694
9368
  503: {
6695
9369
  headers: {
@@ -6701,7 +9375,7 @@ export interface operations {
6701
9375
  };
6702
9376
  };
6703
9377
  };
6704
- revokeStorage: {
9378
+ removeStoragePublic: {
6705
9379
  parameters: {
6706
9380
  query?: never;
6707
9381
  header?: never;
@@ -6711,14 +9385,29 @@ export interface operations {
6711
9385
  };
6712
9386
  cookie?: never;
6713
9387
  };
6714
- requestBody?: never;
9388
+ requestBody: {
9389
+ content: {
9390
+ "application/json": components["schemas"]["StoragePublicRequest"];
9391
+ };
9392
+ };
6715
9393
  responses: {
6716
- /** @description detached */
6717
- 204: {
9394
+ /** @description The list after the change */
9395
+ 200: {
6718
9396
  headers: {
6719
9397
  [name: string]: unknown;
6720
9398
  };
6721
- content?: never;
9399
+ content: {
9400
+ "application/json": components["schemas"]["StoragePublicList"];
9401
+ };
9402
+ };
9403
+ /** @description The prefix is empty or not normalizable */
9404
+ 400: {
9405
+ headers: {
9406
+ [name: string]: unknown;
9407
+ };
9408
+ content: {
9409
+ "application/json": components["schemas"]["Error"];
9410
+ };
6722
9411
  };
6723
9412
  403: components["responses"]["Forbidden"];
6724
9413
  404: components["responses"]["NotFound"];
@@ -7121,7 +9810,168 @@ export interface operations {
7121
9810
  };
7122
9811
  requestBody?: never;
7123
9812
  responses: {
7124
- /** @description turned off */
9813
+ /** @description turned off */
9814
+ 204: {
9815
+ headers: {
9816
+ [name: string]: unknown;
9817
+ };
9818
+ content?: never;
9819
+ };
9820
+ 403: components["responses"]["Forbidden"];
9821
+ 404: components["responses"]["NotFound"];
9822
+ /** @description `no_core` */
9823
+ 503: {
9824
+ headers: {
9825
+ [name: string]: unknown;
9826
+ };
9827
+ content: {
9828
+ "application/json": components["schemas"]["Error"];
9829
+ };
9830
+ };
9831
+ };
9832
+ };
9833
+ listEmailDomains: {
9834
+ parameters: {
9835
+ query?: never;
9836
+ header?: never;
9837
+ path: {
9838
+ orgSlug: components["parameters"]["OrgSlug"];
9839
+ projectName: components["parameters"]["ProjectName"];
9840
+ };
9841
+ cookie?: never;
9842
+ };
9843
+ requestBody?: never;
9844
+ responses: {
9845
+ /** @description The sending domains */
9846
+ 200: {
9847
+ headers: {
9848
+ [name: string]: unknown;
9849
+ };
9850
+ content: {
9851
+ "application/json": {
9852
+ domains: components["schemas"]["EmailDomain"][];
9853
+ };
9854
+ };
9855
+ };
9856
+ 403: components["responses"]["Forbidden"];
9857
+ 404: components["responses"]["NotFound"];
9858
+ /** @description `no_core` */
9859
+ 503: {
9860
+ headers: {
9861
+ [name: string]: unknown;
9862
+ };
9863
+ content: {
9864
+ "application/json": components["schemas"]["Error"];
9865
+ };
9866
+ };
9867
+ };
9868
+ };
9869
+ addEmailDomain: {
9870
+ parameters: {
9871
+ query?: never;
9872
+ header?: never;
9873
+ path: {
9874
+ orgSlug: components["parameters"]["OrgSlug"];
9875
+ projectName: components["parameters"]["ProjectName"];
9876
+ };
9877
+ cookie?: never;
9878
+ };
9879
+ requestBody: {
9880
+ content: {
9881
+ "application/json": {
9882
+ /** @description The domain itself, not an address (`acme.com`) */
9883
+ domain: string;
9884
+ /** @description Write the records into a zone we host */
9885
+ publish?: boolean;
9886
+ };
9887
+ };
9888
+ };
9889
+ responses: {
9890
+ /** @description The domain and the records to publish */
9891
+ 200: {
9892
+ headers: {
9893
+ [name: string]: unknown;
9894
+ };
9895
+ content: {
9896
+ "application/json": components["schemas"]["EmailDomain"];
9897
+ };
9898
+ };
9899
+ 400: components["responses"]["BadRequest"];
9900
+ 403: components["responses"]["Forbidden"];
9901
+ 404: components["responses"]["NotFound"];
9902
+ /**
9903
+ * @description `email_not_granted` — this project does not have email. `email_domains_unavailable` —
9904
+ * this deployment has no mail provider credentials. `email_domain_taken` — another
9905
+ * project already proved this domain. `email_domain_provider` — the provider refused
9906
+ */
9907
+ 409: {
9908
+ headers: {
9909
+ [name: string]: unknown;
9910
+ };
9911
+ content: {
9912
+ "application/json": components["schemas"]["Error"];
9913
+ };
9914
+ };
9915
+ /** @description `no_core` */
9916
+ 503: {
9917
+ headers: {
9918
+ [name: string]: unknown;
9919
+ };
9920
+ content: {
9921
+ "application/json": components["schemas"]["Error"];
9922
+ };
9923
+ };
9924
+ };
9925
+ };
9926
+ verifyEmailDomain: {
9927
+ parameters: {
9928
+ query?: never;
9929
+ header?: never;
9930
+ path: {
9931
+ orgSlug: components["parameters"]["OrgSlug"];
9932
+ projectName: components["parameters"]["ProjectName"];
9933
+ domain: string;
9934
+ };
9935
+ cookie?: never;
9936
+ };
9937
+ requestBody?: never;
9938
+ responses: {
9939
+ /** @description The domain after the check */
9940
+ 200: {
9941
+ headers: {
9942
+ [name: string]: unknown;
9943
+ };
9944
+ content: {
9945
+ "application/json": components["schemas"]["EmailDomain"];
9946
+ };
9947
+ };
9948
+ 403: components["responses"]["Forbidden"];
9949
+ 404: components["responses"]["NotFound"];
9950
+ /** @description `no_core` */
9951
+ 503: {
9952
+ headers: {
9953
+ [name: string]: unknown;
9954
+ };
9955
+ content: {
9956
+ "application/json": components["schemas"]["Error"];
9957
+ };
9958
+ };
9959
+ };
9960
+ };
9961
+ removeEmailDomain: {
9962
+ parameters: {
9963
+ query?: never;
9964
+ header?: never;
9965
+ path: {
9966
+ orgSlug: components["parameters"]["OrgSlug"];
9967
+ projectName: components["parameters"]["ProjectName"];
9968
+ domain: string;
9969
+ };
9970
+ cookie?: never;
9971
+ };
9972
+ requestBody?: never;
9973
+ responses: {
9974
+ /** @description removed */
7125
9975
  204: {
7126
9976
  headers: {
7127
9977
  [name: string]: unknown;
@@ -7130,6 +9980,15 @@ export interface operations {
7130
9980
  };
7131
9981
  403: components["responses"]["Forbidden"];
7132
9982
  404: components["responses"]["NotFound"];
9983
+ /** @description `email_domain_provider` — the provider would not delete the identity, so the row is kept and the call can be retried */
9984
+ 409: {
9985
+ headers: {
9986
+ [name: string]: unknown;
9987
+ };
9988
+ content: {
9989
+ "application/json": components["schemas"]["Error"];
9990
+ };
9991
+ };
7133
9992
  /** @description `no_core` */
7134
9993
  503: {
7135
9994
  headers: {
@@ -8318,7 +11177,18 @@ export interface operations {
8318
11177
  };
8319
11178
  403: components["responses"]["Forbidden"];
8320
11179
  404: components["responses"]["NotFound"];
8321
- /** @description A name already in use by another project. `code` is `hostname_taken` */
11180
+ /**
11181
+ * @description Two refusals share this status.
11182
+ *
11183
+ * `hostname_taken` — the name already belongs to another project.
11184
+ *
11185
+ * `hostname_limit` — the project is already at its plan's ceiling on
11186
+ * custom domains (Free 1, Pro 50 per project; docs/limits.md §1).
11187
+ * `details` carries `limit`, `count` and `plan`, so a client builds its
11188
+ * sentence from the numbers rather than by reading the message back
11189
+ * with a regex. The idempotent re-POST of a name the project already
11190
+ * owns is **not** refused this way — it still answers 200.
11191
+ */
8322
11192
  409: {
8323
11193
  headers: {
8324
11194
  [name: string]: unknown;
@@ -9055,197 +11925,456 @@ export interface operations {
9055
11925
  headers: {
9056
11926
  [name: string]: unknown;
9057
11927
  };
9058
- content: {
9059
- "application/json": components["schemas"]["Domain"];
9060
- };
11928
+ content: {
11929
+ "application/json": components["schemas"]["Domain"];
11930
+ };
11931
+ };
11932
+ 400: components["responses"]["BadRequest"];
11933
+ 403: components["responses"]["Forbidden"];
11934
+ 404: components["responses"]["NotFound"];
11935
+ };
11936
+ };
11937
+ setDomainAutoRenew: {
11938
+ parameters: {
11939
+ query?: never;
11940
+ header?: never;
11941
+ path: {
11942
+ orgSlug: components["parameters"]["OrgSlug"];
11943
+ /** @description Domain name (punycode, lowercase) */
11944
+ name: string;
11945
+ };
11946
+ cookie?: never;
11947
+ };
11948
+ requestBody: {
11949
+ content: {
11950
+ "application/json": {
11951
+ enabled: boolean;
11952
+ };
11953
+ };
11954
+ };
11955
+ responses: {
11956
+ /** @description The domain that changed */
11957
+ 200: {
11958
+ headers: {
11959
+ [name: string]: unknown;
11960
+ };
11961
+ content: {
11962
+ "application/json": components["schemas"]["Domain"];
11963
+ };
11964
+ };
11965
+ 400: components["responses"]["BadRequest"];
11966
+ 403: components["responses"]["Forbidden"];
11967
+ 404: components["responses"]["NotFound"];
11968
+ };
11969
+ };
11970
+ setDomainLock: {
11971
+ parameters: {
11972
+ query?: never;
11973
+ header?: never;
11974
+ path: {
11975
+ orgSlug: components["parameters"]["OrgSlug"];
11976
+ /** @description Domain name (punycode, lowercase) */
11977
+ name: string;
11978
+ };
11979
+ cookie?: never;
11980
+ };
11981
+ requestBody: {
11982
+ content: {
11983
+ "application/json": {
11984
+ locked: boolean;
11985
+ };
11986
+ };
11987
+ };
11988
+ responses: {
11989
+ /** @description The domain that changed */
11990
+ 200: {
11991
+ headers: {
11992
+ [name: string]: unknown;
11993
+ };
11994
+ content: {
11995
+ "application/json": components["schemas"]["Domain"];
11996
+ };
11997
+ };
11998
+ 400: components["responses"]["BadRequest"];
11999
+ 403: components["responses"]["Forbidden"];
12000
+ 404: components["responses"]["NotFound"];
12001
+ };
12002
+ };
12003
+ getDomainAuthCode: {
12004
+ parameters: {
12005
+ query?: never;
12006
+ header?: never;
12007
+ path: {
12008
+ orgSlug: components["parameters"]["OrgSlug"];
12009
+ /** @description Domain name (punycode, lowercase) */
12010
+ name: string;
12011
+ };
12012
+ cookie?: never;
12013
+ };
12014
+ requestBody?: never;
12015
+ responses: {
12016
+ /** @description Code */
12017
+ 200: {
12018
+ headers: {
12019
+ [name: string]: unknown;
12020
+ };
12021
+ content: {
12022
+ "application/json": {
12023
+ name: string;
12024
+ authCode: string;
12025
+ };
12026
+ };
12027
+ };
12028
+ 403: components["responses"]["Forbidden"];
12029
+ 404: components["responses"]["NotFound"];
12030
+ };
12031
+ };
12032
+ syncDomain: {
12033
+ parameters: {
12034
+ query?: never;
12035
+ header?: never;
12036
+ path: {
12037
+ orgSlug: components["parameters"]["OrgSlug"];
12038
+ /** @description Domain name (punycode, lowercase) */
12039
+ name: string;
12040
+ };
12041
+ cookie?: never;
12042
+ };
12043
+ requestBody?: never;
12044
+ responses: {
12045
+ /** @description The matched domain */
12046
+ 200: {
12047
+ headers: {
12048
+ [name: string]: unknown;
12049
+ };
12050
+ content: {
12051
+ "application/json": components["schemas"]["Domain"];
12052
+ };
12053
+ };
12054
+ 403: components["responses"]["Forbidden"];
12055
+ 404: components["responses"]["NotFound"];
12056
+ };
12057
+ };
12058
+ listRepos: {
12059
+ parameters: {
12060
+ query?: never;
12061
+ header?: never;
12062
+ path: {
12063
+ orgSlug: components["parameters"]["OrgSlug"];
12064
+ projectName: components["parameters"]["ProjectName"];
12065
+ };
12066
+ cookie?: never;
12067
+ };
12068
+ requestBody?: never;
12069
+ responses: {
12070
+ /** @description List of repositories */
12071
+ 200: {
12072
+ headers: {
12073
+ [name: string]: unknown;
12074
+ };
12075
+ content: {
12076
+ "application/json": {
12077
+ repos: components["schemas"]["Repo"][];
12078
+ };
12079
+ };
12080
+ };
12081
+ 403: components["responses"]["Forbidden"];
12082
+ 404: components["responses"]["NotFound"];
12083
+ };
12084
+ };
12085
+ createRepo: {
12086
+ parameters: {
12087
+ query?: never;
12088
+ header?: never;
12089
+ path: {
12090
+ orgSlug: components["parameters"]["OrgSlug"];
12091
+ projectName: components["parameters"]["ProjectName"];
12092
+ };
12093
+ cookie?: never;
12094
+ };
12095
+ requestBody: {
12096
+ content: {
12097
+ "application/json": {
12098
+ name: components["schemas"]["RepoName"];
12099
+ visibility?: components["schemas"]["RepoVisibility"];
12100
+ /** @default main */
12101
+ defaultBranch?: string;
12102
+ };
12103
+ };
12104
+ };
12105
+ responses: {
12106
+ /** @description The repository that was created */
12107
+ 201: {
12108
+ headers: {
12109
+ [name: string]: unknown;
12110
+ };
12111
+ content: {
12112
+ "application/json": components["schemas"]["Repo"];
12113
+ };
12114
+ };
12115
+ 400: components["responses"]["BadRequest"];
12116
+ 403: components["responses"]["Forbidden"];
12117
+ 404: components["responses"]["NotFound"];
12118
+ /** @description This project has a repository with the same name (`repo_exists`) */
12119
+ 409: {
12120
+ headers: {
12121
+ [name: string]: unknown;
12122
+ };
12123
+ content: {
12124
+ "application/json": components["schemas"]["Error"];
12125
+ };
12126
+ };
12127
+ };
12128
+ };
12129
+ getRepo: {
12130
+ parameters: {
12131
+ query?: never;
12132
+ header?: never;
12133
+ path: {
12134
+ orgSlug: components["parameters"]["OrgSlug"];
12135
+ projectName: components["parameters"]["ProjectName"];
12136
+ repoName: components["parameters"]["RepoName"];
12137
+ };
12138
+ cookie?: never;
12139
+ };
12140
+ requestBody?: never;
12141
+ responses: {
12142
+ /** @description Repository */
12143
+ 200: {
12144
+ headers: {
12145
+ [name: string]: unknown;
12146
+ };
12147
+ content: {
12148
+ "application/json": components["schemas"]["Repo"];
12149
+ };
12150
+ };
12151
+ 403: components["responses"]["Forbidden"];
12152
+ 404: components["responses"]["NotFound"];
12153
+ };
12154
+ };
12155
+ deleteRepo: {
12156
+ parameters: {
12157
+ query?: never;
12158
+ header?: never;
12159
+ path: {
12160
+ orgSlug: components["parameters"]["OrgSlug"];
12161
+ projectName: components["parameters"]["ProjectName"];
12162
+ repoName: components["parameters"]["RepoName"];
12163
+ };
12164
+ cookie?: never;
12165
+ };
12166
+ requestBody?: never;
12167
+ responses: {
12168
+ /** @description deleted */
12169
+ 204: {
12170
+ headers: {
12171
+ [name: string]: unknown;
12172
+ };
12173
+ content?: never;
9061
12174
  };
9062
- 400: components["responses"]["BadRequest"];
9063
12175
  403: components["responses"]["Forbidden"];
9064
12176
  404: components["responses"]["NotFound"];
9065
12177
  };
9066
12178
  };
9067
- setDomainAutoRenew: {
12179
+ updateRepo: {
9068
12180
  parameters: {
9069
12181
  query?: never;
9070
12182
  header?: never;
9071
12183
  path: {
9072
12184
  orgSlug: components["parameters"]["OrgSlug"];
9073
- /** @description Domain name (punycode, lowercase) */
9074
- name: string;
12185
+ projectName: components["parameters"]["ProjectName"];
12186
+ repoName: components["parameters"]["RepoName"];
9075
12187
  };
9076
12188
  cookie?: never;
9077
12189
  };
9078
12190
  requestBody: {
9079
12191
  content: {
9080
12192
  "application/json": {
9081
- enabled: boolean;
12193
+ name?: components["schemas"]["RepoName"];
12194
+ visibility?: components["schemas"]["RepoVisibility"];
12195
+ defaultBranch?: string;
9082
12196
  };
9083
12197
  };
9084
12198
  };
9085
12199
  responses: {
9086
- /** @description The domain that changed */
9087
- 200: {
12200
+ /** @description changed */
12201
+ 204: {
9088
12202
  headers: {
9089
12203
  [name: string]: unknown;
9090
12204
  };
9091
- content: {
9092
- "application/json": components["schemas"]["Domain"];
9093
- };
12205
+ content?: never;
9094
12206
  };
9095
12207
  400: components["responses"]["BadRequest"];
9096
12208
  403: components["responses"]["Forbidden"];
9097
12209
  404: components["responses"]["NotFound"];
12210
+ /** @description A repository with that name already exists (`repo_exists`) */
12211
+ 409: {
12212
+ headers: {
12213
+ [name: string]: unknown;
12214
+ };
12215
+ content: {
12216
+ "application/json": components["schemas"]["Error"];
12217
+ };
12218
+ };
9098
12219
  };
9099
12220
  };
9100
- setDomainLock: {
12221
+ listRefUpdates: {
9101
12222
  parameters: {
9102
12223
  query?: never;
9103
12224
  header?: never;
9104
12225
  path: {
9105
12226
  orgSlug: components["parameters"]["OrgSlug"];
9106
- /** @description Domain name (punycode, lowercase) */
9107
- name: string;
12227
+ projectName: components["parameters"]["ProjectName"];
12228
+ repoName: components["parameters"]["RepoName"];
9108
12229
  };
9109
12230
  cookie?: never;
9110
12231
  };
9111
- requestBody: {
9112
- content: {
9113
- "application/json": {
9114
- locked: boolean;
9115
- };
9116
- };
9117
- };
12232
+ requestBody?: never;
9118
12233
  responses: {
9119
- /** @description The domain that changed */
12234
+ /** @description Ref history */
9120
12235
  200: {
9121
12236
  headers: {
9122
12237
  [name: string]: unknown;
9123
12238
  };
9124
12239
  content: {
9125
- "application/json": components["schemas"]["Domain"];
12240
+ "application/json": {
12241
+ refUpdates: components["schemas"]["RefUpdate"][];
12242
+ };
9126
12243
  };
9127
12244
  };
9128
- 400: components["responses"]["BadRequest"];
9129
12245
  403: components["responses"]["Forbidden"];
9130
12246
  404: components["responses"]["NotFound"];
9131
12247
  };
9132
12248
  };
9133
- getDomainAuthCode: {
12249
+ getDeployHook: {
9134
12250
  parameters: {
9135
12251
  query?: never;
9136
12252
  header?: never;
9137
12253
  path: {
9138
12254
  orgSlug: components["parameters"]["OrgSlug"];
9139
- /** @description Domain name (punycode, lowercase) */
9140
- name: string;
12255
+ projectName: components["parameters"]["ProjectName"];
12256
+ repoName: components["parameters"]["RepoName"];
9141
12257
  };
9142
12258
  cookie?: never;
9143
12259
  };
9144
12260
  requestBody?: never;
9145
12261
  responses: {
9146
- /** @description Code */
12262
+ /** @description The hook */
9147
12263
  200: {
9148
12264
  headers: {
9149
12265
  [name: string]: unknown;
9150
12266
  };
9151
12267
  content: {
9152
- "application/json": {
9153
- name: string;
9154
- authCode: string;
9155
- };
12268
+ "application/json": components["schemas"]["DeployHook"];
9156
12269
  };
9157
12270
  };
9158
12271
  403: components["responses"]["Forbidden"];
9159
12272
  404: components["responses"]["NotFound"];
9160
12273
  };
9161
12274
  };
9162
- syncDomain: {
12275
+ setDeployHook: {
9163
12276
  parameters: {
9164
12277
  query?: never;
9165
12278
  header?: never;
9166
12279
  path: {
9167
12280
  orgSlug: components["parameters"]["OrgSlug"];
9168
- /** @description Domain name (punycode, lowercase) */
9169
- name: string;
12281
+ projectName: components["parameters"]["ProjectName"];
12282
+ repoName: components["parameters"]["RepoName"];
9170
12283
  };
9171
12284
  cookie?: never;
9172
12285
  };
9173
- requestBody?: never;
12286
+ requestBody: {
12287
+ content: {
12288
+ "application/json": {
12289
+ enabled?: boolean;
12290
+ /**
12291
+ * @description One branch, not a pattern — a pattern makes "why did my push not deploy" a question about glob semantics.
12292
+ * @example main
12293
+ */
12294
+ branch?: string;
12295
+ /**
12296
+ * @description The subdirectory the build runs in. Empty is the repository root.
12297
+ * @example apps/web
12298
+ */
12299
+ rootDir?: string;
12300
+ };
12301
+ };
12302
+ };
9174
12303
  responses: {
9175
- /** @description The matched domain */
12304
+ /** @description The hook as it now stands */
9176
12305
  200: {
9177
12306
  headers: {
9178
12307
  [name: string]: unknown;
9179
12308
  };
9180
12309
  content: {
9181
- "application/json": components["schemas"]["Domain"];
12310
+ "application/json": components["schemas"]["DeployHook"];
9182
12311
  };
9183
12312
  };
12313
+ 400: components["responses"]["BadRequest"];
9184
12314
  403: components["responses"]["Forbidden"];
9185
12315
  404: components["responses"]["NotFound"];
9186
12316
  };
9187
12317
  };
9188
- listRepos: {
12318
+ deleteDeployHook: {
9189
12319
  parameters: {
9190
12320
  query?: never;
9191
12321
  header?: never;
9192
12322
  path: {
9193
12323
  orgSlug: components["parameters"]["OrgSlug"];
9194
12324
  projectName: components["parameters"]["ProjectName"];
12325
+ repoName: components["parameters"]["RepoName"];
9195
12326
  };
9196
12327
  cookie?: never;
9197
12328
  };
9198
12329
  requestBody?: never;
9199
12330
  responses: {
9200
- /** @description List of repositories */
9201
- 200: {
12331
+ /** @description Removed */
12332
+ 204: {
9202
12333
  headers: {
9203
12334
  [name: string]: unknown;
9204
12335
  };
9205
- content: {
9206
- "application/json": {
9207
- repos: components["schemas"]["Repo"][];
9208
- };
9209
- };
12336
+ content?: never;
9210
12337
  };
9211
12338
  403: components["responses"]["Forbidden"];
9212
12339
  404: components["responses"]["NotFound"];
9213
12340
  };
9214
12341
  };
9215
- createRepo: {
12342
+ deployRepoNow: {
9216
12343
  parameters: {
9217
12344
  query?: never;
9218
12345
  header?: never;
9219
12346
  path: {
9220
12347
  orgSlug: components["parameters"]["OrgSlug"];
9221
12348
  projectName: components["parameters"]["ProjectName"];
12349
+ repoName: components["parameters"]["RepoName"];
9222
12350
  };
9223
12351
  cookie?: never;
9224
12352
  };
9225
- requestBody: {
12353
+ requestBody?: {
9226
12354
  content: {
9227
12355
  "application/json": {
9228
- name: components["schemas"]["RepoName"];
9229
- visibility?: components["schemas"]["RepoVisibility"];
9230
- /** @default main */
9231
- defaultBranch?: string;
12356
+ /** @description Omit to build the hooked branch's tip. */
12357
+ commitSha?: string;
9232
12358
  };
9233
12359
  };
9234
12360
  };
9235
12361
  responses: {
9236
- /** @description The repository that was created */
9237
- 201: {
12362
+ /** @description Queued */
12363
+ 202: {
9238
12364
  headers: {
9239
12365
  [name: string]: unknown;
9240
12366
  };
9241
12367
  content: {
9242
- "application/json": components["schemas"]["Repo"];
12368
+ "application/json": {
12369
+ /** Format: uuid */
12370
+ buildId: string;
12371
+ };
9243
12372
  };
9244
12373
  };
9245
12374
  400: components["responses"]["BadRequest"];
9246
12375
  403: components["responses"]["Forbidden"];
9247
12376
  404: components["responses"]["NotFound"];
9248
- /** @description This project has a repository with the same name (`repo_exists`) */
12377
+ /** @description `deploy_hook_off` — push-to-deploy is not on for this repository */
9249
12378
  409: {
9250
12379
  headers: {
9251
12380
  [name: string]: unknown;
@@ -9256,124 +12385,122 @@ export interface operations {
9256
12385
  };
9257
12386
  };
9258
12387
  };
9259
- getRepo: {
12388
+ listBuilds: {
9260
12389
  parameters: {
9261
- query?: never;
12390
+ query?: {
12391
+ limit?: number;
12392
+ };
9262
12393
  header?: never;
9263
12394
  path: {
9264
12395
  orgSlug: components["parameters"]["OrgSlug"];
9265
12396
  projectName: components["parameters"]["ProjectName"];
9266
- repoName: components["parameters"]["RepoName"];
9267
12397
  };
9268
12398
  cookie?: never;
9269
12399
  };
9270
12400
  requestBody?: never;
9271
12401
  responses: {
9272
- /** @description Repository */
12402
+ /** @description Builds */
9273
12403
  200: {
9274
12404
  headers: {
9275
12405
  [name: string]: unknown;
9276
12406
  };
9277
12407
  content: {
9278
- "application/json": components["schemas"]["Repo"];
12408
+ "application/json": {
12409
+ builds: components["schemas"]["Build"][];
12410
+ /** @description Wall-clock build minutes this organization has used this month. */
12411
+ minutesUsed: number;
12412
+ /** @description The monthly allowance for this organization's plan (free 300, pro 3000). */
12413
+ minutesLimit: number;
12414
+ };
9279
12415
  };
9280
12416
  };
12417
+ 400: components["responses"]["BadRequest"];
9281
12418
  403: components["responses"]["Forbidden"];
9282
- 404: components["responses"]["NotFound"];
9283
12419
  };
9284
12420
  };
9285
- deleteRepo: {
12421
+ getBuild: {
9286
12422
  parameters: {
9287
12423
  query?: never;
9288
12424
  header?: never;
9289
12425
  path: {
9290
12426
  orgSlug: components["parameters"]["OrgSlug"];
9291
12427
  projectName: components["parameters"]["ProjectName"];
9292
- repoName: components["parameters"]["RepoName"];
12428
+ buildId: string;
9293
12429
  };
9294
12430
  cookie?: never;
9295
12431
  };
9296
12432
  requestBody?: never;
9297
12433
  responses: {
9298
- /** @description deleted */
9299
- 204: {
12434
+ /** @description The build */
12435
+ 200: {
9300
12436
  headers: {
9301
12437
  [name: string]: unknown;
9302
12438
  };
9303
- content?: never;
12439
+ content: {
12440
+ "application/json": components["schemas"]["Build"];
12441
+ };
9304
12442
  };
9305
12443
  403: components["responses"]["Forbidden"];
9306
12444
  404: components["responses"]["NotFound"];
9307
12445
  };
9308
12446
  };
9309
- updateRepo: {
12447
+ getBuildLog: {
9310
12448
  parameters: {
9311
12449
  query?: never;
9312
12450
  header?: never;
9313
12451
  path: {
9314
12452
  orgSlug: components["parameters"]["OrgSlug"];
9315
12453
  projectName: components["parameters"]["ProjectName"];
9316
- repoName: components["parameters"]["RepoName"];
12454
+ buildId: string;
9317
12455
  };
9318
12456
  cookie?: never;
9319
12457
  };
9320
- requestBody: {
9321
- content: {
9322
- "application/json": {
9323
- name?: components["schemas"]["RepoName"];
9324
- visibility?: components["schemas"]["RepoVisibility"];
9325
- defaultBranch?: string;
9326
- };
9327
- };
9328
- };
12458
+ requestBody?: never;
9329
12459
  responses: {
9330
- /** @description changed */
9331
- 204: {
9332
- headers: {
9333
- [name: string]: unknown;
9334
- };
9335
- content?: never;
9336
- };
9337
- 400: components["responses"]["BadRequest"];
9338
- 403: components["responses"]["Forbidden"];
9339
- 404: components["responses"]["NotFound"];
9340
- /** @description A repository with that name already exists (`repo_exists`) */
9341
- 409: {
12460
+ /** @description The log */
12461
+ 200: {
9342
12462
  headers: {
9343
12463
  [name: string]: unknown;
9344
12464
  };
9345
12465
  content: {
9346
- "application/json": components["schemas"]["Error"];
12466
+ "text/plain": string;
9347
12467
  };
9348
12468
  };
12469
+ 403: components["responses"]["Forbidden"];
12470
+ 404: components["responses"]["NotFound"];
9349
12471
  };
9350
12472
  };
9351
- listRefUpdates: {
12473
+ cancelBuild: {
9352
12474
  parameters: {
9353
12475
  query?: never;
9354
12476
  header?: never;
9355
12477
  path: {
9356
12478
  orgSlug: components["parameters"]["OrgSlug"];
9357
12479
  projectName: components["parameters"]["ProjectName"];
9358
- repoName: components["parameters"]["RepoName"];
12480
+ buildId: string;
9359
12481
  };
9360
12482
  cookie?: never;
9361
12483
  };
9362
12484
  requestBody?: never;
9363
12485
  responses: {
9364
- /** @description Ref history */
9365
- 200: {
12486
+ /** @description Cancelled */
12487
+ 204: {
9366
12488
  headers: {
9367
12489
  [name: string]: unknown;
9368
12490
  };
9369
- content: {
9370
- "application/json": {
9371
- refUpdates: components["schemas"]["RefUpdate"][];
9372
- };
9373
- };
12491
+ content?: never;
9374
12492
  };
9375
12493
  403: components["responses"]["Forbidden"];
9376
12494
  404: components["responses"]["NotFound"];
12495
+ /** @description `build_not_queued` — it is already building, or already over */
12496
+ 409: {
12497
+ headers: {
12498
+ [name: string]: unknown;
12499
+ };
12500
+ content: {
12501
+ "application/json": components["schemas"]["Error"];
12502
+ };
12503
+ };
9377
12504
  };
9378
12505
  };
9379
12506
  listSSHKeys: {
@@ -9490,9 +12617,23 @@ export interface operations {
9490
12617
  content: {
9491
12618
  "application/json": {
9492
12619
  name: string;
12620
+ /**
12621
+ * @description 0032's single-valued field, still accepted. It means the same as a
12622
+ * one-element `scopes`, and `scopes` wins when both are sent.
12623
+ */
9493
12624
  scope?: components["schemas"]["TokenScope"];
9494
- /** @description 0 means no expiration */
12625
+ /** @description Defaults to `[repo:write]` — what a caller from before scopes meant. */
12626
+ scopes?: components["schemas"]["ApiScope"][];
12627
+ /** @description Restrict the token to one org, by slug. */
12628
+ org?: string;
12629
+ /** @description Restrict it further to one project. Requires `org`. */
12630
+ project?: string;
12631
+ /** @description 0032's field. Capped at 365 days. */
9495
12632
  ttlHours?: number;
12633
+ /** @description 1–365. Defaults to 90. */
12634
+ expiresInDays?: number;
12635
+ /** @description A token with no deadline. Explicit on purpose. */
12636
+ noExpiry?: boolean;
9496
12637
  };
9497
12638
  };
9498
12639
  };
@@ -9693,5 +12834,91 @@ export interface operations {
9693
12834
  404: components["responses"]["NotFound"];
9694
12835
  };
9695
12836
  };
12837
+ listPreviews: {
12838
+ parameters: {
12839
+ query?: never;
12840
+ header?: never;
12841
+ path: {
12842
+ orgSlug: components["parameters"]["OrgSlug"];
12843
+ projectName: components["parameters"]["ProjectName"];
12844
+ };
12845
+ cookie?: never;
12846
+ };
12847
+ requestBody?: never;
12848
+ responses: {
12849
+ /** @description List of previews */
12850
+ 200: {
12851
+ headers: {
12852
+ [name: string]: unknown;
12853
+ };
12854
+ content: {
12855
+ "application/json": {
12856
+ previews: components["schemas"]["Preview"][];
12857
+ };
12858
+ };
12859
+ };
12860
+ 403: components["responses"]["Forbidden"];
12861
+ 404: components["responses"]["NotFound"];
12862
+ };
12863
+ };
12864
+ deletePreview: {
12865
+ parameters: {
12866
+ query?: never;
12867
+ header?: never;
12868
+ path: {
12869
+ orgSlug: components["parameters"]["OrgSlug"];
12870
+ projectName: components["parameters"]["ProjectName"];
12871
+ previewName: components["schemas"]["Slug"];
12872
+ };
12873
+ cookie?: never;
12874
+ };
12875
+ requestBody?: never;
12876
+ responses: {
12877
+ /** @description Teardown started */
12878
+ 204: {
12879
+ headers: {
12880
+ [name: string]: unknown;
12881
+ };
12882
+ content?: never;
12883
+ };
12884
+ 403: components["responses"]["Forbidden"];
12885
+ 404: components["responses"]["NotFound"];
12886
+ };
12887
+ };
12888
+ promotePreview: {
12889
+ parameters: {
12890
+ query?: never;
12891
+ header?: never;
12892
+ path: {
12893
+ orgSlug: components["parameters"]["OrgSlug"];
12894
+ projectName: components["parameters"]["ProjectName"];
12895
+ previewName: components["schemas"]["Slug"];
12896
+ };
12897
+ cookie?: never;
12898
+ };
12899
+ requestBody?: never;
12900
+ responses: {
12901
+ /** @description The parent's new live deployment */
12902
+ 201: {
12903
+ headers: {
12904
+ [name: string]: unknown;
12905
+ };
12906
+ content: {
12907
+ "application/json": components["schemas"]["Deployment"];
12908
+ };
12909
+ };
12910
+ 403: components["responses"]["Forbidden"];
12911
+ 404: components["responses"]["NotFound"];
12912
+ /** @description The preview has no deployment to promote, or is not `ready` */
12913
+ 409: {
12914
+ headers: {
12915
+ [name: string]: unknown;
12916
+ };
12917
+ content: {
12918
+ "application/json": components["schemas"]["Error"];
12919
+ };
12920
+ };
12921
+ };
12922
+ };
9696
12923
  }
9697
12924
  //# sourceMappingURL=schema.d.ts.map