@runlot/api 0.1.0-rc.206 → 0.1.0-rc.207

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
@@ -1028,7 +1028,7 @@ export interface paths {
1028
1028
  * Delete a project (`runlot project delete`)
1029
1029
  * @description Requires admin or higher. **This cannot be undone, and there is no recovery
1030
1030
  * generation to restore from afterwards.** Export anything you need first with
1031
- * `runlot pg export`.
1031
+ * `runlot db export`.
1032
1032
  *
1033
1033
  * The `confirm` field must carry the exact project name.
1034
1034
  *
@@ -1045,6 +1045,11 @@ export interface paths {
1045
1045
  * The 202 carries an operation id you can read with
1046
1046
  * `GET /v1/orgs/{orgSlug}/operations/{opId}`, which reports the first step. Clients
1047
1047
  * should not block on it.
1048
+ *
1049
+ * **Deleting a project never deletes a database.** A project with a database of its
1050
+ * own leaves it in the organization under the project's name (`databaseKept`), with
1051
+ * its data, backups and the projects that bind it; delete it separately with
1052
+ * `runlot db delete`. The project's own bindings to other databases go with it.
1048
1053
  */
1049
1054
  delete: operations["deleteProject"];
1050
1055
  options?: never;
@@ -2548,51 +2553,42 @@ export interface paths {
2548
2553
  patch?: never;
2549
2554
  trace?: never;
2550
2555
  };
2551
- "/v1/orgs/{orgSlug}/projects/{projectName}/database": {
2556
+ "/v1/orgs/{orgSlug}/databases/{databaseName}": {
2552
2557
  parameters: {
2553
2558
  query?: never;
2554
2559
  header?: never;
2555
2560
  path: {
2556
2561
  orgSlug: components["parameters"]["OrgSlug"];
2557
- projectName: components["parameters"]["ProjectName"];
2562
+ /** @description A database's name in the organization */
2563
+ databaseName: components["parameters"]["DatabaseName"];
2558
2564
  };
2559
2565
  cookie?: never;
2560
2566
  };
2561
2567
  /**
2562
- * Whether the database is available
2563
- * @description The response is just `{db: bool}`. Size and generation are not reported here.
2568
+ * One database in the organization
2569
+ * @description The database's size, state and the projects that bind it — the same row as the
2570
+ * list. A project whose name matches a database but which has none answers 404.
2564
2571
  *
2565
2572
  * **No credentials are returned.** Viewer and above may call this; connection details
2566
- * live at `/database/connect`.
2573
+ * live at `…/connect`.
2567
2574
  */
2568
2575
  get: operations["getDatabase"];
2569
2576
  put?: never;
2570
- /**
2571
- * Creates the project's database
2572
- * @description A database is created when your app uses one; this creates it by name, whether the
2573
- * project never had one or its database was deleted. A new database starts empty. It
2574
- * also clears the turn-off, so later deploys keep it. It returns the connection
2575
- * details. Shortly afterwards
2576
- * the running worker picks up a connected `env.db`. No redeploy is needed.
2577
- *
2578
- * **It is idempotent and never rotates the password.** A second call returns the same
2579
- * connection details, so a connection string saved from the first response keeps
2580
- * working.
2581
- */
2582
- post: operations["createDatabase"];
2577
+ post?: never;
2583
2578
  delete?: never;
2584
2579
  options?: never;
2585
2580
  head?: never;
2586
2581
  patch?: never;
2587
2582
  trace?: never;
2588
2583
  };
2589
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/connect": {
2584
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/connect": {
2590
2585
  parameters: {
2591
2586
  query?: never;
2592
2587
  header?: never;
2593
2588
  path: {
2594
2589
  orgSlug: components["parameters"]["OrgSlug"];
2595
- projectName: components["parameters"]["ProjectName"];
2590
+ /** @description A database's name in the organization */
2591
+ databaseName: components["parameters"]["DatabaseName"];
2596
2592
  };
2597
2593
  cookie?: never;
2598
2594
  };
@@ -2611,20 +2607,21 @@ export interface paths {
2611
2607
  patch?: never;
2612
2608
  trace?: never;
2613
2609
  };
2614
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/endpoint": {
2610
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/endpoint": {
2615
2611
  parameters: {
2616
2612
  query?: never;
2617
2613
  header?: never;
2618
2614
  path: {
2619
2615
  orgSlug: components["parameters"]["OrgSlug"];
2620
- projectName: components["parameters"]["ProjectName"];
2616
+ /** @description A database's name in the organization */
2617
+ databaseName: components["parameters"]["DatabaseName"];
2621
2618
  };
2622
2619
  cookie?: never;
2623
2620
  };
2624
2621
  /**
2625
- * Connection info without credentials (`runlot port-forward`)
2622
+ * Connection info without credentials (`runlot db forward`)
2626
2623
  * @description Only host, port, database and `sslmode` — no secret, so viewer and above may call it.
2627
- * `runlot port-forward` authenticates with your login session rather than a password,
2624
+ * `runlot db forward` authenticates with your login session rather than a password,
2628
2625
  * so this endpoint is all it needs.
2629
2626
  */
2630
2627
  get: operations["getDatabaseEndpoint"];
@@ -2636,13 +2633,14 @@ export interface paths {
2636
2633
  patch?: never;
2637
2634
  trace?: never;
2638
2635
  };
2639
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/tokens": {
2636
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/tokens": {
2640
2637
  parameters: {
2641
2638
  query?: never;
2642
2639
  header?: never;
2643
2640
  path: {
2644
2641
  orgSlug: components["parameters"]["OrgSlug"];
2645
- projectName: components["parameters"]["ProjectName"];
2642
+ /** @description A database's name in the organization */
2643
+ databaseName: components["parameters"]["DatabaseName"];
2646
2644
  };
2647
2645
  cookie?: never;
2648
2646
  };
@@ -2653,7 +2651,7 @@ export interface paths {
2653
2651
  get: operations["listDatabaseTokens"];
2654
2652
  put?: never;
2655
2653
  /**
2656
- * Issue a credential for short-lived automation (`runlot pg token`)
2654
+ * Issue a credential for short-lived automation (`runlot db token`)
2657
2655
  * @description Issues a user/password pair for use in a connection string. **The password appears
2658
2656
  * only in this response** — only its SCRAM verifier is stored, so a lost password must
2659
2657
  * be reissued. The session still opens under the project's own database role; the token
@@ -2666,13 +2664,14 @@ export interface paths {
2666
2664
  patch?: never;
2667
2665
  trace?: never;
2668
2666
  };
2669
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/tokens/{tokenUser}": {
2667
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/tokens/{tokenUser}": {
2670
2668
  parameters: {
2671
2669
  query?: never;
2672
2670
  header?: never;
2673
2671
  path: {
2674
2672
  orgSlug: components["parameters"]["OrgSlug"];
2675
- projectName: components["parameters"]["ProjectName"];
2673
+ /** @description A database's name in the organization */
2674
+ databaseName: components["parameters"]["DatabaseName"];
2676
2675
  tokenUser: string;
2677
2676
  };
2678
2677
  cookie?: never;
@@ -2690,13 +2689,14 @@ export interface paths {
2690
2689
  patch?: never;
2691
2690
  trace?: never;
2692
2691
  };
2693
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/execute": {
2692
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/execute": {
2694
2693
  parameters: {
2695
2694
  query?: never;
2696
2695
  header?: never;
2697
2696
  path: {
2698
2697
  orgSlug: components["parameters"]["OrgSlug"];
2699
- projectName: components["parameters"]["ProjectName"];
2698
+ /** @description A database's name in the organization */
2699
+ databaseName: components["parameters"]["DatabaseName"];
2700
2700
  };
2701
2701
  cookie?: never;
2702
2702
  };
@@ -2705,11 +2705,11 @@ export interface paths {
2705
2705
  /**
2706
2706
  * Run one statement (the dashboard's SQL console)
2707
2707
  * @description Runs a single SQL statement against the project's database and returns the rows. This
2708
- * backs the dashboard's SQL console; from a terminal, use `runlot pg execute`, which
2708
+ * backs the dashboard's SQL console; from a terminal, use `runlot db execute`, which
2709
2709
  * connects directly instead.
2710
2710
  *
2711
2711
  * The statement is executed over an ordinary PostgreSQL connection using the same
2712
- * host, port, `sslmode` and credential that `…/database/connect` hands a member for
2712
+ * host, port, `sslmode` and credential that `…/databases/{databaseName}/connect` hands a member for
2713
2713
  * psql, so every rule that applies to a normal connection applies here too, including
2714
2714
  * the 10 s statement ceiling.
2715
2715
  *
@@ -2726,7 +2726,7 @@ export interface paths {
2726
2726
  * **Write mode belongs to a dashboard session.** A personal access token reaches this
2727
2727
  * route with `db:read` and runs read-only statements; asking for `readOnly: false`
2728
2728
  * with a token is 403 `console_write_needs_session`. No scope opens it — a credential
2729
- * that has to write goes through `…/database/connect` or `…/database/tokens` and
2729
+ * that has to write goes through `…/databases/{databaseName}/connect` or `…/databases/{databaseName}/tokens` and
2730
2730
  * connects, where the power it carries is named on the token.
2731
2731
  *
2732
2732
  * Requires member or higher. A write leaves a `db.execute` audit event; a read leaves
@@ -2739,26 +2739,27 @@ export interface paths {
2739
2739
  patch?: never;
2740
2740
  trace?: never;
2741
2741
  };
2742
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/export": {
2742
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/export": {
2743
2743
  parameters: {
2744
2744
  query?: never;
2745
2745
  header?: never;
2746
2746
  path: {
2747
2747
  orgSlug: components["parameters"]["OrgSlug"];
2748
- projectName: components["parameters"]["ProjectName"];
2748
+ /** @description A database's name in the organization */
2749
+ databaseName: components["parameters"]["DatabaseName"];
2749
2750
  };
2750
2751
  cookie?: never;
2751
2752
  };
2752
2753
  get?: never;
2753
2754
  put?: never;
2754
2755
  /**
2755
- * Creates a diagnostic image (`runlot pg export`)
2756
+ * Creates a diagnostic image (`runlot db export`)
2756
2757
  * @description **This is not a backup.** It creates an immutable diagnostic image of the database as
2757
2758
  * it is right now. It does not move any backup pointer, does not affect retention, and
2758
2759
  * cannot be selected by a restore.
2759
2760
  *
2760
2761
  * Scheduled backups are separate and run on their own hourly schedule. List them at
2761
- * `…/database/generations` and pick one at `…/database/restore`. Diagnostic images stay
2762
+ * `…/databases/{databaseName}/generations` and pick one at `…/databases/{databaseName}/restore`. Diagnostic images stay
2762
2763
  * outside that history entirely: restore cannot choose one and pruning ignores them.
2763
2764
  *
2764
2765
  * **This is not idempotent.** Each call creates one more image.
@@ -2775,18 +2776,19 @@ export interface paths {
2775
2776
  patch?: never;
2776
2777
  trace?: never;
2777
2778
  };
2778
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/generations": {
2779
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/generations": {
2779
2780
  parameters: {
2780
2781
  query?: never;
2781
2782
  header?: never;
2782
2783
  path: {
2783
2784
  orgSlug: components["parameters"]["OrgSlug"];
2784
- projectName: components["parameters"]["ProjectName"];
2785
+ /** @description A database's name in the organization */
2786
+ databaseName: components["parameters"]["DatabaseName"];
2785
2787
  };
2786
2788
  cookie?: never;
2787
2789
  };
2788
2790
  /**
2789
- * List of backup generations (`runlot pg generations`)
2791
+ * List of backup generations (`runlot db backups`)
2790
2792
  * @description Lists the backup generations a restore can choose from, newest first, each with its
2791
2793
  * storage key, size and `sha256` digest so the restore can verify what it receives.
2792
2794
  *
@@ -2797,7 +2799,7 @@ export interface paths {
2797
2799
  * Requires member or higher.
2798
2800
  *
2799
2801
  * **The database does not have to be enabled.** A final safety generation is kept even
2800
- * after `runlot pg delete`, so it still appears here after deletion.
2802
+ * after `runlot db delete`, so it still appears here after deletion.
2801
2803
  *
2802
2804
  * **`objects` is the Durable Object half of the same history**, returned alongside the
2803
2805
  * database generations because a project's restorable state is the union of the two.
@@ -2824,20 +2826,21 @@ export interface paths {
2824
2826
  patch?: never;
2825
2827
  trace?: never;
2826
2828
  };
2827
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/restore": {
2829
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/restore": {
2828
2830
  parameters: {
2829
2831
  query?: never;
2830
2832
  header?: never;
2831
2833
  path: {
2832
2834
  orgSlug: components["parameters"]["OrgSlug"];
2833
- projectName: components["parameters"]["ProjectName"];
2835
+ /** @description A database's name in the organization */
2836
+ databaseName: components["parameters"]["DatabaseName"];
2834
2837
  };
2835
2838
  cookie?: never;
2836
2839
  };
2837
2840
  get?: never;
2838
2841
  put?: never;
2839
2842
  /**
2840
- * Restore to a generation (`runlot pg restore`)
2843
+ * Restore to a generation (`runlot db restore`)
2841
2844
  * @description A restore stops the project's database, replaces its contents with the chosen
2842
2845
  * generation, and starts it again. The data as it stands immediately before the restore
2843
2846
  * is archived first, so there is a way back.
@@ -2851,7 +2854,7 @@ export interface paths {
2851
2854
  * whole restore, database included, rather than restoring only part of the project.
2852
2855
  *
2853
2856
  * **Check `objects.restorable` before calling this, for the generation you are about to
2854
- * pass.** Call `…/database/generations?at=<the chosen generation's lastAt>` first: the
2857
+ * pass.** Call `…/databases/{databaseName}/generations?at=<the chosen generation's lastAt>` first: the
2855
2858
  * object half is selected on its own instant, independent of the `(epoch, seq)` you
2856
2859
  * send here, so a `restorable=true` read at another instant answers a different
2857
2860
  * question. Even a correctly timed `restorable=true` is eligibility, not a guarantee —
@@ -2861,7 +2864,7 @@ export interface paths {
2861
2864
  * list, so a generation created in the meantime cannot send you somewhere else.
2862
2865
  *
2863
2866
  * Returns 202 with an operation id, not the result. Poll
2864
- * `…/database/operations/{opId}` for progress.
2867
+ * `…/databases/{databaseName}/operations/{opId}` for progress.
2865
2868
  */
2866
2869
  post: operations["restoreDatabase"];
2867
2870
  delete?: never;
@@ -2870,29 +2873,37 @@ export interface paths {
2870
2873
  patch?: never;
2871
2874
  trace?: never;
2872
2875
  };
2873
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/delete": {
2876
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/delete": {
2874
2877
  parameters: {
2875
2878
  query?: never;
2876
2879
  header?: never;
2877
2880
  path: {
2878
2881
  orgSlug: components["parameters"]["OrgSlug"];
2879
- projectName: components["parameters"]["ProjectName"];
2882
+ /** @description A database's name in the organization */
2883
+ databaseName: components["parameters"]["DatabaseName"];
2880
2884
  };
2881
2885
  cookie?: never;
2882
2886
  };
2883
2887
  get?: never;
2884
2888
  put?: never;
2885
2889
  /**
2886
- * Delete a database (`runlot pg delete`)
2887
- * @description Deletes the project's database. A final safety generation is kept, so the data can
2888
- * still be listed and restored afterwards. Once the deletion completes, the worker runs
2889
- * without `env.db`. Requires admin or higher.
2890
+ * Delete a database (`runlot db delete`)
2891
+ * @description Deletes a database in the organization. Requires admin or higher.
2892
+ *
2893
+ * **A bound database is not deleted.** The call answers 409 `database_bound` with
2894
+ * `details.bindings` (`project`, `binding`); the project whose name the database
2895
+ * shares counts as a binding (`db`). Remove the `databases` entry from each project's
2896
+ * `runlot.json` and deploy, or send `unbindAll: true`, which removes every binding
2897
+ * (each recorded in the audit log). Bound projects then fail calls on that binding
2898
+ * with `DatabaseNotAttached`, and their next deploy is refused with
2899
+ * `database_not_found` until their `runlot.json` drops the entry.
2890
2900
  *
2891
- * **This also turns end-user auth off.** The subscriber records live inside the
2892
- * project's database, so they go with it, and `env.auth` is disabled in the same step.
2893
- * The stored OAuth provider secrets are removed with it and are not recoverable.
2901
+ * While the project of the same name exists, a final safety generation is kept and
2902
+ * that project runs without `env.db` afterwards; this also turns end-user auth off,
2903
+ * because the subscriber records live in the database. A database with no project of
2904
+ * its name is erased with no generation left — export it first (`runlot db export`).
2894
2905
  *
2895
- * **`confirm` must match the project name exactly.** If it does not, the call returns
2906
+ * **`confirm` must match the database name exactly.** If it does not, the call returns
2896
2907
  * 400 `confirm_mismatch` and nothing starts.
2897
2908
  *
2898
2909
  * This is a `POST` rather than a `DELETE` because it is a long-running operation that
@@ -2906,13 +2917,14 @@ export interface paths {
2906
2917
  patch?: never;
2907
2918
  trace?: never;
2908
2919
  };
2909
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}": {
2920
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/operations/{opId}": {
2910
2921
  parameters: {
2911
2922
  query?: never;
2912
2923
  header?: never;
2913
2924
  path: {
2914
2925
  orgSlug: components["parameters"]["OrgSlug"];
2915
- projectName: components["parameters"]["ProjectName"];
2926
+ /** @description A database's name in the organization */
2927
+ databaseName: components["parameters"]["DatabaseName"];
2916
2928
  /**
2917
2929
  * @description The operation id. **Not a credential** — an operation that does not belong to the
2918
2930
  * project in the path returns 404.
@@ -2940,13 +2952,14 @@ export interface paths {
2940
2952
  patch?: never;
2941
2953
  trace?: never;
2942
2954
  };
2943
- "/v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}/abort": {
2955
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/operations/{opId}/abort": {
2944
2956
  parameters: {
2945
2957
  query?: never;
2946
2958
  header?: never;
2947
2959
  path: {
2948
2960
  orgSlug: components["parameters"]["OrgSlug"];
2949
- projectName: components["parameters"]["ProjectName"];
2961
+ /** @description A database's name in the organization */
2962
+ databaseName: components["parameters"]["DatabaseName"];
2950
2963
  /**
2951
2964
  * @description The operation id. **Not a credential** — an operation that does not belong to the
2952
2965
  * project in the path returns 404.
@@ -2958,7 +2971,7 @@ export interface paths {
2958
2971
  get?: never;
2959
2972
  put?: never;
2960
2973
  /**
2961
- * Aborts an in-progress operation (`runlot pg abort`)
2974
+ * Aborts an in-progress operation (`runlot db abort`)
2962
2975
  * @description Only possible **before** the operation reaches a point of no return: evict,
2963
2976
  * restore_generation and delete can be aborted up to the committing phase; restore
2964
2977
  * cannot. Aborting returns the project to active and leaves `terminalCode=aborted`.
@@ -3570,8 +3583,9 @@ export interface paths {
3570
3583
  /**
3571
3584
  * Desktops of the org's members that can lend to this project right now
3572
3585
  * @description Each desktop lending to apps, with the models it lends and whether its Runlot Studio is
3573
- * too old to carry `reasoning` or `responseFormat` (`outdated`). `reachable` is false when
3574
- * the lending service could not be asked. Requires `observability:read`.
3586
+ * too old to carry `reasoning` or `responseFormat` (`outdated`), followed by the members'
3587
+ * desktops that are online with lending switched off (`lending: false`). `reachable` is
3588
+ * false when the lending service could not be asked. Requires `observability:read`.
3575
3589
  */
3576
3590
  get: operations["getAILenders"];
3577
3591
  put?: never;
@@ -3713,7 +3727,10 @@ export interface paths {
3713
3727
  * @description The call a local `runlot dev` makes when your worker calls `env.ai.run`. It is forwarded to the
3714
3728
  * same lane Studio's local runtime uses: catalog models only, the free plan's caps on every plan
3715
3729
  * (4,096 output tokens, 30 calls a minute, two at a time), the org's balance checked before and
3716
- * debited after, recorded in the ledger as `lane = dev`. No streaming — one JSON answer.
3730
+ * debited after, recorded in the ledger as `lane = dev`. One JSON answer, or with `stream: true`
3731
+ * server-sent events: `data: {"delta"}` pieces, then `event: done` (model, stopReason, usage,
3732
+ * usageComplete) or `event: error` (code, message, usage). A stream takes no tools and no
3733
+ * `responseFormat` (`400 stream_unsupported`, `400 format_unsupported`).
3717
3734
  *
3718
3735
  * This is not an API for calling models from outside a worker: it needs a member's login and a
3719
3736
  * project with AI turned on, and it answers `env.ai.run`'s own shape. Requires member or higher.
@@ -4016,7 +4033,7 @@ export interface paths {
4016
4033
  *
4017
4034
  * **The end-user table is not part of this API.** User records live in the `runlot_auth`
4018
4035
  * schema of the project's database; read them through the worker's `env.auth.users.*` or
4019
- * with `runlot pg shell`.
4036
+ * with `runlot db shell`.
4020
4037
  *
4021
4038
  * `providers` carries only the client id. Client secrets are stored encrypted and never
4022
4039
  * appear in any response.
@@ -4032,10 +4049,10 @@ export interface paths {
4032
4049
  *
4033
4050
  * **Login creates the database it needs.** The end-user tables live inside the
4034
4051
  * project's database, so a project without one gets it first, as if you had run
4035
- * `runlot pg on`. Two cases are refused instead, each with a 409 that says why: the
4052
+ * `runlot db create <project>`. Two cases are refused instead, each with a 409 that says why: the
4036
4053
  * project's database was deleted (`database_required`), or the live deployment's
4037
4054
  * `runlot.json` says `"database": false` (`database_disabled`). Create the database with
4038
- * `POST …/database` (`runlot pg on`) and call this again.
4055
+ * `POST /v1/orgs/{orgSlug}/databases` (`runlot db create <project>`) and call this again.
4039
4056
  *
4040
4057
  * Once enabled, the built-in login endpoints start serving shortly afterwards. As with
4041
4058
  * `env.db` and `env.storage`, no redeploy is needed. Table initialization is idempotent,
@@ -4050,7 +4067,7 @@ export interface paths {
4050
4067
  * Disables auth (`runlot auth delete`)
4051
4068
  * @description **End-user data is not deleted.** The `runlot_auth` tables stay in the project's
4052
4069
  * database as they are — deleting them is a database operation you run yourself with
4053
- * `runlot pg`. Turning auth back on lets the same people log in as before.
4070
+ * `runlot db`. Turning auth back on lets the same people log in as before.
4054
4071
  *
4055
4072
  * Shortly afterwards the built-in login endpoints stop serving, and `/__runlot/auth/*`
4056
4073
  * passes straight through to your worker — if that path has no route, it is a 404.
@@ -4258,7 +4275,7 @@ export interface paths {
4258
4275
  * The app's end users (`runlot auth users`)
4259
4276
  * @description The people who signed up to **your app** — not the members of your organization.
4260
4277
  * They live in the project's own database, under the `runlot_auth` schema, and this
4261
- * route reads them over the same connection `…/database/connect` hands you for psql.
4278
+ * route reads them over the same connection `…/databases/{databaseName}/connect` hands you for psql.
4262
4279
  * Everything here is also visible through `env.db` and `psql`; this is a convenience,
4263
4280
  * not a second source.
4264
4281
  *
@@ -4579,6 +4596,119 @@ export interface paths {
4579
4596
  patch?: never;
4580
4597
  trace?: never;
4581
4598
  };
4599
+ "/v1/orgs/{orgSlug}/billing/spending-limit": {
4600
+ parameters: {
4601
+ query?: never;
4602
+ header?: never;
4603
+ path: {
4604
+ orgSlug: components["parameters"]["OrgSlug"];
4605
+ };
4606
+ cookie?: never;
4607
+ };
4608
+ /**
4609
+ * The org's spending limit, this month's overage and the lock
4610
+ * @description The spending limit is the most a Pro organization is billed in a month for usage above
4611
+ * the included amounts. It is always on (default $20) and has no "unlimited" value: when
4612
+ * this month's overage reaches it, every HTTP request to the organization's projects is
4613
+ * refused with `429 budget_exhausted` until the first of next month, and uploads past the
4614
+ * storage quota get `507`. Raising the limit releases the lock within one map poll.
4615
+ *
4616
+ * `overageMicroCents` is this month's accrued overage; `breakdown` names the axes that
4617
+ * made it (requests, CPU, storage held, memory above the plan, and collection). Held
4618
+ * storage and memory never take the month past the limit; requests and CPU in the
4619
+ * 2–3 minute enforcement lag can. `applies` is false on Free (Free is never billed past
4620
+ * its included amounts) and on a granted Pro (not billed). `projects` lists every project
4621
+ * with its own spending limit (null where it has none) and its share of this month's
4622
+ * overage (see `getProjectLimits`). Requires viewer or higher.
4623
+ */
4624
+ get: operations["getSpendingLimit"];
4625
+ /**
4626
+ * Set the org's spending limit
4627
+ * @description Sets the limit in cents, from 0 (stop at the first cent past the included amounts) up to
4628
+ * `maxCents` ($1,000); above that, contact us. The lock is judged again at once: a limit
4629
+ * above this month's overage releases it, and a limit below it locks the organization now —
4630
+ * the answer's `throttled` shows the lock the change left. Pro only:
4631
+ * `409 spending_limit_not_applicable` on Free and on a granted Pro, with
4632
+ * `details.reason` `free` or `granted`. A value out of range is
4633
+ * `400 spending_limit_out_of_range`. Requires admin. Audited as `org.spending_limit`.
4634
+ */
4635
+ put: operations["setSpendingLimit"];
4636
+ post?: never;
4637
+ delete?: never;
4638
+ options?: never;
4639
+ head?: never;
4640
+ patch?: never;
4641
+ trace?: never;
4642
+ };
4643
+ "/v1/orgs/{orgSlug}/projects/{projectName}/limits": {
4644
+ parameters: {
4645
+ query?: never;
4646
+ header?: never;
4647
+ path: {
4648
+ orgSlug: components["parameters"]["OrgSlug"];
4649
+ projectName: components["parameters"]["ProjectName"];
4650
+ };
4651
+ cookie?: never;
4652
+ };
4653
+ /**
4654
+ * A project's app memory, per-request CPU and spending limits
4655
+ * @description `appMemory` is the most one copy of the app may use. For a project with a database this
4656
+ * is the app process's own limit (the database keeps the plan's memory); the project's
4657
+ * memory cap, `projectBytes`, is raised to twice it, because a deploy runs two copies side
4658
+ * by side. For a project without a database it is the project's whole cap. An app over its
4659
+ * limit is restarted and reported as an `app_out_of_memory` issue.
4660
+ *
4661
+ * A limit is a ceiling, not reserved memory. On Pro, memory the project actually holds
4662
+ * above `includedProjectBytes` (the plan's project cap) is billed per hour of use within
4663
+ * the organization's spending limit, when `billed` is true. `p99Bytes` is the project's
4664
+ * 14-day p99 hourly peak, database and app together.
4665
+ *
4666
+ * `requestCpu` is the CPU one request may spend before it fails with `exceededCpu`.
4667
+ *
4668
+ * `spend` is the project's own spending limit, under the organization's. Optional: with
4669
+ * none (`cents` null) only the organization's limit applies. The project's share of the
4670
+ * organization's overage this month (`shareMicroCents`) is, per axis, that axis's overage
4671
+ * times the project's fraction of the organization's use of it — requests, CPU and file
4672
+ * storage held — plus the memory the project held above the plan. Error and observability
4673
+ * collection is not part of it. Because the included amounts are the organization's, a
4674
+ * project's share can grow while it is idle when another project takes the organization
4675
+ * further past them. When the share reaches the limit, only this project's HTTP requests
4676
+ * are refused, with `429 project_budget_exhausted`, until the first of next month
4677
+ * (`throttledUntil`); the organization's other projects keep serving, and the
4678
+ * organization's own limit still applies on top. Requires viewer or higher.
4679
+ */
4680
+ get: operations["getProjectLimits"];
4681
+ /**
4682
+ * Set a project's app memory, per-request CPU or spending limit
4683
+ * @description A field left out is unchanged; `null` puts it back on the plan's value. Free may lower
4684
+ * either limit and raising one needs Pro (`403 plan_required`). Pro may raise app memory to
4685
+ * `maxBytes` (at most 2 GiB) and the CPU limit to 300 s. The change reaches the running app
4686
+ * by a zero-downtime replacement.
4687
+ *
4688
+ * `spendCents` sets the project's own spending limit, from 0 (stop at the first cent of the
4689
+ * project's share) up to the organization's limit (`spend.orgCents`); `null` removes it.
4690
+ * The lock is judged again at once: a limit above the project's share releases it within
4691
+ * one map poll, and a limit at or below it refuses the project's requests now — the
4692
+ * answer's `spend.throttled` shows the lock the change left. Pro only:
4693
+ * `409 spending_limit_not_applicable` on Free and on a granted Pro (`details.reason`). Out
4694
+ * of range is `400 limit_out_of_range` with `details.maxCents`. Audited as
4695
+ * `project.spending_limit`.
4696
+ *
4697
+ * Refusals: `409 memory_limit_below_use` lowers app memory below the 14-day p99
4698
+ * (`details.p99Bytes`) — send `confirm: true` to set it anyway; `409
4699
+ * memory_limit_exceeds_node` raises past what the project's server can offer
4700
+ * (`details.maxBytes`); `409 memory_limit_set_by_operator` raises past a value Runlot set;
4701
+ * `400 limit_out_of_range` is outside the bounds (`details.field`). Requires admin. Memory
4702
+ * and CPU changes are audited as `project.limits`.
4703
+ */
4704
+ put: operations["setProjectLimits"];
4705
+ post?: never;
4706
+ delete?: never;
4707
+ options?: never;
4708
+ head?: never;
4709
+ patch?: never;
4710
+ trace?: never;
4711
+ };
4582
4712
  "/v1/orgs/{orgSlug}/members": {
4583
4713
  parameters: {
4584
4714
  query?: never;
@@ -7168,6 +7298,126 @@ export interface paths {
7168
7298
  patch?: never;
7169
7299
  trace?: never;
7170
7300
  };
7301
+ "/v1/orgs/{orgSlug}/projects/{projectName}/health": {
7302
+ parameters: {
7303
+ query?: never;
7304
+ header?: never;
7305
+ path: {
7306
+ orgSlug: string;
7307
+ projectName: string;
7308
+ };
7309
+ cookie?: never;
7310
+ };
7311
+ /**
7312
+ * Read a project's capacity risks
7313
+ * @description The project's capacity risks: how close its memory, CPU, database, AI calls and the
7314
+ * organization's budget are to the hard limits they will hit, each with its evidence
7315
+ * and the next step. Call before a launch, after a deploy, and when the app is slow or
7316
+ * restarting. `checks` lists every signal: `unknown` means it was not measured (the
7317
+ * reason says why), which is not the same as `ok`. Every plan. Viewer.
7318
+ */
7319
+ get: operations["getProjectHealth"];
7320
+ put?: never;
7321
+ post?: never;
7322
+ delete?: never;
7323
+ options?: never;
7324
+ head?: never;
7325
+ patch?: never;
7326
+ trace?: never;
7327
+ };
7328
+ "/v1/orgs/{orgSlug}/databases": {
7329
+ parameters: {
7330
+ query?: never;
7331
+ header?: never;
7332
+ path: {
7333
+ orgSlug: components["parameters"]["OrgSlug"];
7334
+ };
7335
+ cookie?: never;
7336
+ };
7337
+ /**
7338
+ * Every database in the organization, with the projects that bind it
7339
+ * @description One row per database: its size against the plan's cap, whether it is running, and
7340
+ * every project that binds it with the binding name and mode — including the project
7341
+ * whose name it shares, as `db`. A database no project binds is `unbound`: it keeps
7342
+ * its data and its bill until it is deleted. Viewer and above.
7343
+ */
7344
+ get: operations["listOrgDatabases"];
7345
+ put?: never;
7346
+ /**
7347
+ * Create a database in the organization (`runlot db create`)
7348
+ * @description Creates a database named `name` and places it, so it runs before any project binds
7349
+ * it. Projects bind it by name in `runlot.json`
7350
+ * (`"databases": [{"binding": "shared", "database": "<name>"}]`) and deploy. Member
7351
+ * and above.
7352
+ *
7353
+ * If `name` is a project without a database, this creates that project's own
7354
+ * database (its `env.db`), on every plan. A database that stands alone is Pro.
7355
+ *
7356
+ * Names share one namespace with projects: a name held by a project with a database
7357
+ * or by another database answers 409 `name_taken`. The plan's database count applies
7358
+ * (`database_limit`). It is idempotent for a project's own database: a second call
7359
+ * returns the same connection details.
7360
+ */
7361
+ post: operations["createOrgDatabase"];
7362
+ delete?: never;
7363
+ options?: never;
7364
+ head?: never;
7365
+ patch?: never;
7366
+ trace?: never;
7367
+ };
7368
+ "/v1/orgs/{orgSlug}/databases/{databaseName}/bindings/{projectName}": {
7369
+ parameters: {
7370
+ query?: never;
7371
+ header?: never;
7372
+ path: {
7373
+ orgSlug: components["parameters"]["OrgSlug"];
7374
+ /** @description A database's name in the organization */
7375
+ databaseName: components["parameters"]["DatabaseName"];
7376
+ projectName: components["parameters"]["ProjectName"];
7377
+ };
7378
+ cookie?: never;
7379
+ };
7380
+ get?: never;
7381
+ put?: never;
7382
+ post?: never;
7383
+ /**
7384
+ * Remove a project's binding to this database
7385
+ * @description For a project nobody will redeploy: its running app loses `env.<binding>` shortly
7386
+ * and calls on it fail with `DatabaseNotAttached`. A binding is otherwise written and
7387
+ * removed by the project's own deploy from its `runlot.json`, so a later deploy that
7388
+ * still names this database binds it again. The project whose name the database
7389
+ * shares cannot be unbound (delete the database instead). Admin and above.
7390
+ */
7391
+ delete: operations["unbindDatabase"];
7392
+ options?: never;
7393
+ head?: never;
7394
+ patch?: never;
7395
+ trace?: never;
7396
+ };
7397
+ "/v1/orgs/{orgSlug}/health": {
7398
+ parameters: {
7399
+ query?: never;
7400
+ header?: never;
7401
+ path: {
7402
+ orgSlug: string;
7403
+ };
7404
+ cookie?: never;
7405
+ };
7406
+ /**
7407
+ * Read every project's capacity status
7408
+ * @description One line per project of the organization: its worst open capacity risk and how many
7409
+ * are open, and the organization's budget check. Use it to find the project that needs
7410
+ * `getProjectHealth`. Viewer.
7411
+ */
7412
+ get: operations["getOrgHealth"];
7413
+ put?: never;
7414
+ post?: never;
7415
+ delete?: never;
7416
+ options?: never;
7417
+ head?: never;
7418
+ patch?: never;
7419
+ trace?: never;
7420
+ };
7171
7421
  "/v1/orgs/{orgSlug}/projects/{projectName}/synthetics": {
7172
7422
  parameters: {
7173
7423
  query?: never;
@@ -9062,7 +9312,7 @@ export interface components {
9062
9312
  MonitorQuery: {
9063
9313
  /** @enum {string} */
9064
9314
  source?: "apm" | "database" | "infra" | "custom";
9065
- /** @description apm: requests, errors, error_rate (percent), status_4xx, status_5xx, latency_avg, latency_p50, latency_p75, latency_p90, latency_p95, latency_p99, latency_p999. database: calls, errors, latency_avg, latency_p50, latency_p95, latency_p99, wait_share (percent of route wall time). infra: memory_pct, memory_bytes, psi_cpu_some, psi_mem_some, psi_mem_full, psi_io_some, oom_kills, oom_exits, high_events, cpu_throttled_us. */
9315
+ /** @description apm: requests, errors, error_rate (percent), status_4xx, status_5xx, latency_avg, latency_p50, latency_p75, latency_p90, latency_p95, latency_p99, latency_p999. database: calls, errors, latency_avg, latency_p50, latency_p95, latency_p99, wait_share (percent of route wall time). infra: memory_pct, memory_bytes, cpu_cores (cores used over the sampled minutes; an app uses at most one), psi_cpu_some, psi_mem_some, psi_mem_full, psi_io_some, oom_kills, oom_exits, high_events, cpu_throttled_us. */
9066
9316
  metric?: string;
9067
9317
  name?: string;
9068
9318
  /** @enum {string} */
@@ -9900,7 +10150,7 @@ export interface components {
9900
10150
  * human-readable wording is produced separately by the dashboard and by email.
9901
10151
  * @enum {string}
9902
10152
  */
9903
- 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" | "overage_charge_failed" | "domain_renewal_failed" | "disabled_project_deletion" | "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" | "license_expiring" | "license_grace" | "license_restricted" | "new_device" | "error_issue_new" | "app_out_of_memory" | "monitor_alert" | "watchdog_digest";
10153
+ 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" | "overage_charge_failed" | "domain_renewal_failed" | "disabled_project_deletion" | "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" | "license_expiring" | "license_grace" | "license_restricted" | "new_device" | "error_issue_new" | "app_out_of_memory" | "monitor_alert" | "watchdog_digest" | "capacity_risk" | "budget_near";
9904
10154
  /** @description If this is a project-related notification, the name of that project. Absent for org-level notifications (`project_limit`) */
9905
10155
  projectName?: string;
9906
10156
  /**
@@ -9917,6 +10167,11 @@ export interface components {
9917
10167
  * `{app, clientId, device}`, `error_issue_new` is `{issueId, shortId, title, origin}` and
9918
10168
  * `app_out_of_memory` is `{issueId, limitMiB, peakMiB, release}`.
9919
10169
  * `monitor_alert` is `{monitorId, monitorName, monitorKind, monitorState, monitorGroup, monitorValue, monitorThreshold, monitorMessage, monitorLink}`.
10170
+ * `capacity_risk` is `{insightId, signal, severity, route, summary, magnitude}` and
10171
+ * `budget_near` is `{kind, used, limit, period, until}` (kind is `requests`, `cpu` or `spend`,
10172
+ * or `project_spend` for a project's own spending limit, with the project set and `used`
10173
+ * and `limit` in cents). `budget_exhausted` is `{throttled, until, plan}`; a project's own
10174
+ * limit carries `throttled: ["project_spend"]`, the project and the limit in `cents`.
9920
10175
  */
9921
10176
  detail: {
9922
10177
  [key: string]: unknown;
@@ -9932,6 +10187,15 @@ export interface components {
9932
10187
  Project: {
9933
10188
  /** Format: uuid */
9934
10189
  projectId: string;
10190
+ /**
10191
+ * @description Only on the answer to creating a project: the organization already had a database
10192
+ * with this name (its project was deleted earlier), and the new project uses it as
10193
+ * `env.db`. `runlot deploy` prints it on its first line.
10194
+ */
10195
+ existingDatabase?: {
10196
+ /** Format: int64 */
10197
+ sizeBytes: number | null;
10198
+ };
9935
10199
  orgSlug: components["schemas"]["Slug"];
9936
10200
  name: components["schemas"]["Slug"];
9937
10201
  hostnames: string[];
@@ -10020,7 +10284,7 @@ export interface components {
10020
10284
  /** @description A deployment in the overview. Same shape as `Deployment`, including `actor`. */
10021
10285
  OverviewDeployment: components["schemas"]["Deployment"];
10022
10286
  OverviewDatabase: {
10023
- /** @description Whether the project has a database. One is created when the app uses it, or by `runlot pg on`. */
10287
+ /** @description Whether the project has a database. One is created when the app uses it, or by `runlot db create <project>`. */
10024
10288
  granted: boolean;
10025
10289
  /**
10026
10290
  * Format: date-time
@@ -10110,6 +10374,8 @@ export interface components {
10110
10374
  * contradicts, or a recognised framework deployed without `runWorkerFirst: false`.
10111
10375
  */
10112
10376
  warnings?: string[];
10377
+ /** @description What the deploy-time static checks found in this deployment's code. Absent when it was not checked. */
10378
+ staticChecks?: components["schemas"]["DeployStaticChecks"];
10113
10379
  };
10114
10380
  /**
10115
10381
  * @description The one address Studio hands to a person who is not a developer
@@ -11633,7 +11899,7 @@ export interface components {
11633
11899
  available: boolean;
11634
11900
  /** @description **Always `false`.** The database and the objects are not restored to one consistent instant, so do not present a single restore time for both. */
11635
11901
  atomic: boolean;
11636
- /** @description `available && complete` — eligibility, not a success guarantee. The restore call (`POST /orgs/{orgSlug}/projects/{projectName}/database/restore`) refuses outright when `missing` or `gaps` is non-empty, so `false` here means the call is not worth attempting. `true` means only that the preflight would pass; the restore can still fail afterwards on a holder's own store (unreachable node, a lost or corrupted archive, a digest mismatch found only when the file is read). It is 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. */
11902
+ /** @description `available && complete` — eligibility, not a success guarantee. The restore call (`POST /orgs/{orgSlug}/databases/{databaseName}/restore`) refuses outright when `missing` or `gaps` is non-empty, so `false` here means the call is not worth attempting. `true` means only that the preflight would pass; the restore can still fail afterwards on a holder's own store (unreachable node, a lost or corrupted archive, a digest mismatch found only when the file is read). It is 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. */
11637
11903
  restorable: boolean;
11638
11904
  /** Format: date-time */
11639
11905
  at?: string;
@@ -11801,17 +12067,64 @@ export interface components {
11801
12067
  * @example app
11802
12068
  */
11803
12069
  confirm: string;
12070
+ /**
12071
+ * @description Remove every binding of this database first. Without it, a bound database
12072
+ * refuses the deletion with 409 `database_bound`.
12073
+ */
12074
+ unbindAll?: boolean;
12075
+ };
12076
+ OrgDatabase: {
12077
+ /** @description The database's name in the organization */
12078
+ name: string;
12079
+ /** Format: date-time */
12080
+ createdAt: string;
12081
+ /**
12082
+ * Format: int64
12083
+ * @description The last measured size, when one has been reported
12084
+ */
12085
+ sizeBytes: number | null;
12086
+ /**
12087
+ * Format: int64
12088
+ * @description The plan's size cap for one database
12089
+ */
12090
+ capBytes: number;
12091
+ /**
12092
+ * @description `running`: placed on a node (an idle database stops after a few minutes and
12093
+ * starts again on the next connection). `cold`: stored offsite, woken by the next
12094
+ * connection. `none`: not placed yet (its project was never deployed).
12095
+ * @enum {string}
12096
+ */
12097
+ state: "running" | "cold" | "none";
12098
+ /** @description No project of the same name exists: the database stands alone */
12099
+ standalone: boolean;
12100
+ /** @description No project binds it, including one of the same name */
12101
+ unbound: boolean;
12102
+ /**
12103
+ * @description Projects that reach this database. The project of the same name, if any, is listed
12104
+ * with `binding: db`.
12105
+ */
12106
+ bindings: components["schemas"]["DatabaseBinding"][];
12107
+ };
12108
+ DatabaseBinding: {
12109
+ project: string;
12110
+ /** @example service_db */
12111
+ binding: string;
12112
+ /** @enum {string} */
12113
+ mode: "write" | "read";
12114
+ };
12115
+ OrgDatabases: {
12116
+ databases: components["schemas"]["OrgDatabase"][];
11804
12117
  };
11805
12118
  /**
11806
12119
  * @description This response means the multi-step operation was queued (202). **It does not mean it
11807
- * finished** — check progress at `…/database/operations/{opId}`.
12120
+ * finished** — check progress at `…/databases/{databaseName}/operations/{opId}`.
11808
12121
  */
11809
12122
  OperationStarted: {
11810
12123
  /** Format: uuid */
11811
12124
  projectId: string;
11812
12125
  opId: string;
11813
12126
  /** @enum {string} */
11814
- kind: "restore_generation" | "delete_database" | "delete_project" | "purge_project" | "evict" | "restore";
12127
+ kind: "restore_generation" | "delete_database" | "delete_project" | "purge_project" | "retire_app" | "evict" | "restore";
11815
12128
  /** Format: int64 */
11816
12129
  epoch: number;
11817
12130
  node?: string;
@@ -11822,6 +12135,12 @@ export interface components {
11822
12135
  * value rather than computing it from a retention window.
11823
12136
  */
11824
12137
  purgeAfter?: string;
12138
+ /**
12139
+ * @description Project deletion only: the name of the project's database, which stays in the
12140
+ * organization (listed under databases; delete it with `runlot db delete`). Absent
12141
+ * when the project had no database.
12142
+ */
12143
+ databaseKept?: string;
11825
12144
  };
11826
12145
  Operation: {
11827
12146
  opId: string;
@@ -12016,11 +12335,42 @@ export interface components {
12016
12335
  * of `@runlot/auth`; a `migrations/NNNN_*.sql` file; or `env.db` / `env.DB` in the
12017
12336
  * project's own sources. A value set in your `runlot.json` wins over that guess.
12018
12337
  * - **`false`** — never create one. Neither the deployment nor a call creates it, and
12019
- * `env.db` rejects with `DatabaseNotEnabled`. `runlot pg on` still creates one,
12338
+ * `env.db` rejects with `DatabaseNotEnabled`. `runlot db create <project>` still creates one,
12020
12339
  * because it asks by name. Declaring `queues` with `false` is refused with a 400:
12021
12340
  * queue messages are kept in the database.
12022
12341
  */
12023
12342
  database?: boolean;
12343
+ /**
12344
+ * @description Databases in the organization this code reaches, each as `env.<binding>`. The
12345
+ * deployment binds them: it adds, changes and removes this project's bindings to
12346
+ * match this list, and a database that does not exist is refused with 409
12347
+ * `database_not_found` (create it with `runlot db create`). At most two besides
12348
+ * `db`; binding a database into a second project is Pro.
12349
+ *
12350
+ * `{"binding": "db", "database": "<this project's name>"}` is the explicit form of
12351
+ * the default `env.db`; `db` cannot name another database yet. A bound database is
12352
+ * not this project's own `env.db`, and naming one does not create a database for
12353
+ * this project.
12354
+ */
12355
+ databases?: {
12356
+ /** @example service_db */
12357
+ binding: string;
12358
+ /** @description The database's name, in the same organization */
12359
+ database: string;
12360
+ /**
12361
+ * @description `write` runs statements as the database owner. `read` runs every statement
12362
+ * as a read-only role.
12363
+ * @default write
12364
+ * @enum {string}
12365
+ */
12366
+ mode: "write" | "read";
12367
+ /**
12368
+ * @description Path to the database's `migrations/`, used only by `runlot dev` to prepare
12369
+ * the local stand-in database. A deployment never applies it
12370
+ * (`runlot db migrate <name>` does).
12371
+ */
12372
+ migrations?: string;
12373
+ }[];
12024
12374
  /**
12025
12375
  * @description Declares email sending and receiving. When `true`, the worker receives
12026
12376
  * `env.email`, and `export default { email() }` becomes the receiving handler.
@@ -12783,8 +13133,9 @@ export interface components {
12783
13133
  byosCreditFallback?: boolean;
12784
13134
  /**
12785
13135
  * @description How many members of the project's organization have a Studio desktop lending to
12786
- * apps right now. Present only on the answer to a PATCH that leaves `byos` on, and
12787
- * only when Studio could be asked. With `byos` on, `byosCreditFallback` off and 0
13136
+ * apps right now. Present on the answer to a PATCH that leaves `byos` on, on a GET
13137
+ * while `byos` is on and `byosCreditFallback` off, and only when Studio could be
13138
+ * asked. With `byos` on, `byosCreditFallback` off and 0
12788
13139
  * here, every lendable call is refused.
12789
13140
  */
12790
13141
  byosLenders?: number;
@@ -12970,6 +13321,8 @@ export interface components {
12970
13321
  tags: string[];
12971
13322
  hasBody: boolean;
12972
13323
  deploymentVersion: number;
13324
+ /** @description The cache counts the provider did not report: their 0 above means unknown, not none. Absent when both were reported, or on a call recorded before the field existed. */
13325
+ cacheUnreported?: ("cachedInputTokens" | "cacheWriteInputTokens")[];
12973
13326
  };
12974
13327
  AICallDetail: components["schemas"]["AICallRow"] & {
12975
13328
  input?: string;
@@ -13029,6 +13382,16 @@ export interface components {
13029
13382
  p50Ms: number;
13030
13383
  p95Ms: number;
13031
13384
  ttftP50Ms: number;
13385
+ /**
13386
+ * Format: int64
13387
+ * @description tokensIn over the chat calls whose provider reported a read count. The hit rate is tokensCachedReadKnown / tokensInReadKnown; 0 here (no such call, or only hours rolled up before the field) means no hit rate, not 0 %.
13388
+ */
13389
+ tokensInReadKnown?: number;
13390
+ /**
13391
+ * Format: int64
13392
+ * @description tokensCached over the same calls as tokensInReadKnown.
13393
+ */
13394
+ tokensCachedReadKnown?: number;
13032
13395
  };
13033
13396
  series?: {
13034
13397
  /** Format: date-time */
@@ -13069,6 +13432,16 @@ export interface components {
13069
13432
  byosServed: number;
13070
13433
  p50Ms: number;
13071
13434
  p95Ms: number;
13435
+ /**
13436
+ * Format: int64
13437
+ * @description As in totals.
13438
+ */
13439
+ tokensInReadKnown?: number;
13440
+ /**
13441
+ * Format: int64
13442
+ * @description As in totals.
13443
+ */
13444
+ tokensCachedReadKnown?: number;
13072
13445
  }[];
13073
13446
  byosReasons?: {
13074
13447
  code: string;
@@ -13116,6 +13489,10 @@ export interface components {
13116
13489
  email: string;
13117
13490
  };
13118
13491
  device: string;
13492
+ /** @description False for a desktop that is online but has lending to apps switched off in Studio. Such a desktop is never offered a call, and its `models` is empty. */
13493
+ lending: boolean;
13494
+ /** @description The desktop app's own version. Absent from a desktop that does not announce it. */
13495
+ studioVersion?: string;
13119
13496
  models: string[];
13120
13497
  options: string[];
13121
13498
  outdated: boolean;
@@ -13123,6 +13500,10 @@ export interface components {
13123
13500
  vendor: string;
13124
13501
  connected: boolean;
13125
13502
  version?: string;
13503
+ /** @description How the vendor is signed in on the desktop: `claudeai`, `console`, `bedrock`, `vertex`, `foundry`, `chatgpt`, `device` or `apikey` */
13504
+ via?: string;
13505
+ /** @description The vendor's plan code for the signed-in account (`plus`, `pro`, `max` …), when the desktop knows it. The vendor account's email is never sent. */
13506
+ planType?: string;
13126
13507
  }[];
13127
13508
  inflight: number;
13128
13509
  /** @description How many lent calls at once this desktop's owner allows (1–8; 2 when the desktop does not say) */
@@ -13324,72 +13705,259 @@ export interface components {
13324
13705
  pro: components["schemas"]["PlanLimits"];
13325
13706
  };
13326
13707
  };
13327
- /** @description The limits that apply to one plan */
13328
- PlanLimits: {
13329
- projects: number;
13330
- /** Format: int64 */
13331
- storageBytes: number;
13708
+ /** @description The org's spending limit and this month's overage against it. */
13709
+ SpendingLimit: {
13710
+ orgId: string;
13711
+ /** @enum {string} */
13712
+ plan: "free" | "pro";
13713
+ /** @description The plan's billing status (active, past_due, canceled, granted), empty on Free */
13714
+ status: string;
13715
+ /** @description False on Free and on a granted Pro: the limit does nothing there */
13716
+ applies: boolean;
13717
+ /** @enum {string} */
13718
+ notApplicableReason?: "free" | "granted";
13719
+ /** @description The limit, in cents per month above the included amounts */
13720
+ cents: number;
13721
+ /** @description The default limit ($20) */
13722
+ defaultCents: number;
13723
+ /** @description The most it can be set to here ($1,000) */
13724
+ maxCents: number;
13332
13725
  /**
13333
- * Format: int64
13334
- * @description The project Postgres size cap for this plan (Free 500 MiB, Pro 8 GiB). The
13335
- * dashboard's usage meter and chart read this value, and you are notified when a
13336
- * project passes 90% of it.
13726
+ * Format: date
13727
+ * @description First day of the month the overage belongs to
13337
13728
  */
13338
- dbCapBytes: number;
13339
- /** @description how many database generations are retained */
13340
- backupKeep: number;
13341
- crons: number;
13342
- mailPerHour: number;
13343
- };
13344
- /**
13345
- * @description The state of the project's dedicated object storage.
13346
- *
13347
- * **Objects are not part of database generations** — `runlot pg restore` does not roll back
13348
- * files. Read-after-write is guaranteed, but `list` may lag.
13349
- */
13350
- StorageStatus: {
13729
+ month: string;
13351
13730
  /**
13352
- * @description Whether object storage is turned on for this project. When it is off, there is no
13353
- * bucket at all, and `prefix` and `quotaBytes` are empty.
13731
+ * Format: int64
13732
+ * @description This month's accrued overage (1 cent = 1,000,000)
13354
13733
  */
13355
- granted: boolean;
13734
+ overageMicroCents: number;
13356
13735
  /**
13357
- * @description The prefix every object of this project is stored under. It is added for you, so
13358
- * your own keys stay relative to it and no key you send can reach another project's
13359
- * storage. Empty when storage is not configured.
13360
- * @example p/6f1a0b4c-0000-0000-0000-000000000001/
13736
+ * @description This month's overage by axis, in microcents. The platform axes are the nominal price
13737
+ * of what was used; `collection` is what error and observability collection was billed
13738
+ * within the limit. Their sum can exceed `overageMicroCents` when held storage and memory
13739
+ * were stopped at the limit.
13361
13740
  */
13362
- prefix: string;
13741
+ breakdown: {
13742
+ /** Format: int64 */
13743
+ requests: number;
13744
+ /** Format: int64 */
13745
+ cpu: number;
13746
+ /** Format: int64 */
13747
+ storage: number;
13748
+ /** Format: int64 */
13749
+ memory: number;
13750
+ /** Format: int64 */
13751
+ collection: number;
13752
+ };
13753
+ /** @description The locks in force; `spend` is the spending limit */
13754
+ throttled: ("requests" | "cpu" | "spend")[];
13363
13755
  /**
13364
- * Format: int64
13365
- * @description The quota (10 GiB on Free, 100 GiB on Pro). Once you exceed it, only `put` and
13366
- * `presign(PUT)` are rejected — `get`, `list`, and `delete` keep working, so you can
13367
- * always delete your way back under the cap. Without storage enabled, it is 0.
13756
+ * Format: date-time
13757
+ * @description When the locks end
13368
13758
  */
13369
- quotaBytes: number;
13759
+ throttledUntil: string | null;
13760
+ /** @description The limit before the change (PUT only) */
13761
+ previousCents?: number;
13762
+ /** @description The organization's projects, by name, with their own spending limits and shares */
13763
+ projects?: components["schemas"]["ProjectSpendLine"][];
13764
+ };
13765
+ /** @description One project's own spending limit and its share of this month's overage. */
13766
+ ProjectSpendLine: {
13767
+ name: string;
13768
+ /** @description The project's own limit in cents; null is none (only the organization's applies) */
13769
+ cents: number | null;
13370
13770
  /**
13371
13771
  * Format: int64
13372
- * @description The last observed byte count. It lags a little behind your writes, so usage can
13373
- * briefly go past the quota in between. 0 if there is no observation yet.
13772
+ * @description The project's share of the organization's overage this month (1 cent = 1,000,000)
13374
13773
  */
13375
- usedBytes: number;
13376
- };
13377
- /** @description One key prefix to publish or unpublish. */
13378
- StoragePublicRequest: {
13774
+ shareMicroCents: number;
13775
+ breakdown: components["schemas"]["ProjectSpendBreakdown"];
13776
+ /** @description The project's own limit is spent: its requests get 429 project_budget_exhausted */
13777
+ throttled: boolean;
13379
13778
  /**
13380
- * @description The prefix, relative to the project's own storage — `assets`, `assets/`, or
13381
- * `avatars/img`. It is stored with a trailing slash, because matching is a plain string
13382
- * prefix test and `assets` without the slash would also open `assets-private/`.
13383
- *
13384
- * `/` means **every key in the project**. The empty string is refused, so an
13385
- * accidentally empty argument cannot publish everything by looking like a default.
13386
- * @example assets/
13779
+ * Format: date-time
13780
+ * @description When the project's lock ends
13387
13781
  */
13388
- prefix: string;
13782
+ throttledUntil: string | null;
13389
13783
  };
13390
- /**
13391
- * @description The prefixes this project serves without a signature. All three verbs answer with the
13392
- * full list, so a screen never has to guess what the list became after a change.
13784
+ /** @description A project's share by axis, in microcents. Collection is not part of a project's share. */
13785
+ ProjectSpendBreakdown: {
13786
+ /** Format: int64 */
13787
+ requests: number;
13788
+ /** Format: int64 */
13789
+ cpu: number;
13790
+ /** Format: int64 */
13791
+ storage: number;
13792
+ /** Format: int64 */
13793
+ memory: number;
13794
+ };
13795
+ SpendingLimitUpdate: {
13796
+ /** @description The new limit in cents */
13797
+ cents: number;
13798
+ };
13799
+ /** @description A project's app memory, per-request CPU and spending limits. */
13800
+ ProjectLimits: {
13801
+ projectId: string;
13802
+ /** @enum {string} */
13803
+ plan: "free" | "pro";
13804
+ hasDatabase: boolean;
13805
+ appMemory: {
13806
+ /**
13807
+ * Format: int64
13808
+ * @description The most one copy of the app may use
13809
+ */
13810
+ bytes: number;
13811
+ /**
13812
+ * Format: int64
13813
+ * @description The value with no project setting
13814
+ */
13815
+ planBytes: number;
13816
+ /** Format: int64 */
13817
+ minBytes: number;
13818
+ /**
13819
+ * Format: int64
13820
+ * @description The most it can be set to now (plan and server together)
13821
+ */
13822
+ maxBytes: number;
13823
+ /**
13824
+ * Format: int64
13825
+ * @description The project's memory cap, database and app together
13826
+ */
13827
+ projectBytes: number;
13828
+ /**
13829
+ * Format: int64
13830
+ * @description Memory a project-hour holds without being billed
13831
+ */
13832
+ includedProjectBytes: number;
13833
+ /** @description Memory above includedProjectBytes is billed for this project */
13834
+ billed: boolean;
13835
+ /**
13836
+ * @description Who set the value; null is the plan's
13837
+ * @enum {string|null}
13838
+ */
13839
+ setBy: "customer" | "operator" | null;
13840
+ /**
13841
+ * Format: int64
13842
+ * @description 14-day p99 hourly peak, database and app together
13843
+ */
13844
+ p99Bytes: number | null;
13845
+ };
13846
+ requestCpu: {
13847
+ /** @description CPU one request may spend, in milliseconds */
13848
+ ms: number;
13849
+ planMs: number;
13850
+ minMs: number;
13851
+ maxMs: number;
13852
+ /** @enum {string|null} */
13853
+ setBy: "customer" | null;
13854
+ };
13855
+ /** @description The project's own spending limit, under the organization's, and its share this month */
13856
+ spend: {
13857
+ /** @description False on Free and on a granted Pro: a limit does nothing there */
13858
+ applies: boolean;
13859
+ /** @enum {string} */
13860
+ notApplicableReason?: "free" | "granted";
13861
+ /** @description The project's own limit in cents a month; null is none */
13862
+ cents: number | null;
13863
+ /** @description The organization's spending limit, the most this one can be set to */
13864
+ orgCents: number;
13865
+ /**
13866
+ * Format: date
13867
+ * @description First day of the month the share belongs to
13868
+ */
13869
+ month: string;
13870
+ /**
13871
+ * Format: int64
13872
+ * @description The project's share of the organization's overage this month (1 cent = 1,000,000)
13873
+ */
13874
+ shareMicroCents: number;
13875
+ breakdown: components["schemas"]["ProjectSpendBreakdown"];
13876
+ /** @description The limit is spent: this project's requests get 429 project_budget_exhausted */
13877
+ throttled: boolean;
13878
+ /**
13879
+ * Format: date-time
13880
+ * @description When the project's lock ends
13881
+ */
13882
+ throttledUntil: string | null;
13883
+ };
13884
+ };
13885
+ /** @description A field left out is unchanged; null puts it back on the plan's value (for spendCents: no limit of the project's own). */
13886
+ ProjectLimitsUpdate: {
13887
+ /** Format: int64 */
13888
+ appMemoryBytes?: number | null;
13889
+ requestCpuMs?: number | null;
13890
+ /** @description The project's own spending limit in cents a month, at most the organization's */
13891
+ spendCents?: number | null;
13892
+ /** @description Set app memory below the 14-day p99 anyway */
13893
+ confirm?: boolean;
13894
+ };
13895
+ /** @description The limits that apply to one plan */
13896
+ PlanLimits: {
13897
+ projects: number;
13898
+ /** Format: int64 */
13899
+ storageBytes: number;
13900
+ /**
13901
+ * Format: int64
13902
+ * @description The project Postgres size cap for this plan (Free 500 MiB, Pro 8 GiB). The
13903
+ * dashboard's usage meter and chart read this value, and you are notified when a
13904
+ * project passes 90% of it.
13905
+ */
13906
+ dbCapBytes: number;
13907
+ /** @description how many database generations are retained */
13908
+ backupKeep: number;
13909
+ crons: number;
13910
+ mailPerHour: number;
13911
+ };
13912
+ /**
13913
+ * @description The state of the project's dedicated object storage.
13914
+ *
13915
+ * **Objects are not part of database generations** — `runlot db restore` does not roll back
13916
+ * files. Read-after-write is guaranteed, but `list` may lag.
13917
+ */
13918
+ StorageStatus: {
13919
+ /**
13920
+ * @description Whether object storage is turned on for this project. When it is off, there is no
13921
+ * bucket at all, and `prefix` and `quotaBytes` are empty.
13922
+ */
13923
+ granted: boolean;
13924
+ /**
13925
+ * @description The prefix every object of this project is stored under. It is added for you, so
13926
+ * your own keys stay relative to it and no key you send can reach another project's
13927
+ * storage. Empty when storage is not configured.
13928
+ * @example p/6f1a0b4c-0000-0000-0000-000000000001/
13929
+ */
13930
+ prefix: string;
13931
+ /**
13932
+ * Format: int64
13933
+ * @description The quota (10 GiB on Free, 100 GiB on Pro). Once you exceed it, only `put` and
13934
+ * `presign(PUT)` are rejected — `get`, `list`, and `delete` keep working, so you can
13935
+ * always delete your way back under the cap. Without storage enabled, it is 0.
13936
+ */
13937
+ quotaBytes: number;
13938
+ /**
13939
+ * Format: int64
13940
+ * @description The last observed byte count. It lags a little behind your writes, so usage can
13941
+ * briefly go past the quota in between. 0 if there is no observation yet.
13942
+ */
13943
+ usedBytes: number;
13944
+ };
13945
+ /** @description One key prefix to publish or unpublish. */
13946
+ StoragePublicRequest: {
13947
+ /**
13948
+ * @description The prefix, relative to the project's own storage — `assets`, `assets/`, or
13949
+ * `avatars/img`. It is stored with a trailing slash, because matching is a plain string
13950
+ * prefix test and `assets` without the slash would also open `assets-private/`.
13951
+ *
13952
+ * `/` means **every key in the project**. The empty string is refused, so an
13953
+ * accidentally empty argument cannot publish everything by looking like a default.
13954
+ * @example assets/
13955
+ */
13956
+ prefix: string;
13957
+ };
13958
+ /**
13959
+ * @description The prefixes this project serves without a signature. All three verbs answer with the
13960
+ * full list, so a screen never has to guess what the list became after a change.
13393
13961
  */
13394
13962
  StoragePublicList: {
13395
13963
  prefixes: {
@@ -14224,6 +14792,150 @@ export interface components {
14224
14792
  /** @description false on Free: deploy regressions only. */
14225
14793
  full: boolean;
14226
14794
  };
14795
+ /**
14796
+ * @description The worst open risk: alert, then warn; ok when none is open.
14797
+ * @enum {string}
14798
+ */
14799
+ HealthStatus: "ok" | "warn" | "alert";
14800
+ HealthCheck: {
14801
+ /** @description app_memory, app_restarts, db_memory, app_cpu, request_cpu, app_stall, busy_latency, db_admission, rpc_not_disposed, ai_refusals, org_budget, project_budget, db_size, file_storage, log_cap or cron_overlap. */
14802
+ signal: string;
14803
+ /** @enum {string} */
14804
+ state: "ok" | "warn" | "alert" | "unknown";
14805
+ /** @description Why an `unknown` check was not measured. */
14806
+ reason?: string;
14807
+ };
14808
+ HealthEvidence: {
14809
+ /** @description What was measured, for example `peak`, `cores` or `share`. */
14810
+ name: string;
14811
+ value: number;
14812
+ /** @description bytes, fraction, cores, ms, count, per_second or cents. */
14813
+ unit: string;
14814
+ /** @description The hard limit the value is compared with, in the same unit. */
14815
+ limit?: number;
14816
+ /** @description The span the value covers, for example `24h` or `3d`. */
14817
+ window: string;
14818
+ };
14819
+ HealthRisk: {
14820
+ /** Format: uuid */
14821
+ id: string;
14822
+ signal: string;
14823
+ /** @enum {string} */
14824
+ severity: "warn" | "alert";
14825
+ /** @description The route, cron expression or log template the risk is about; absent when it is the whole project. */
14826
+ route?: string;
14827
+ /** Format: date-time */
14828
+ since: string;
14829
+ /** Format: date-time */
14830
+ updatedAt: string;
14831
+ /** @description One sentence: what, how close. */
14832
+ summary: string;
14833
+ evidence: components["schemas"]["HealthEvidence"][];
14834
+ /** @description Concrete steps, the most useful first. */
14835
+ next: string[];
14836
+ links: {
14837
+ label: string;
14838
+ /** @description A dashboard path under the project, for example `/observability/infrastructure?range=24h`. */
14839
+ path: string;
14840
+ }[];
14841
+ };
14842
+ CapacityEstimate: {
14843
+ /** @description The span the estimate reads: `3d`, the per-minute samples of the last three days. */
14844
+ window: string;
14845
+ /** @description Requests in the window that reached the app. Below 1,000 there is no estimate. */
14846
+ requests: number;
14847
+ /** @description Requests in the same minutes that Runlot answered before the app ran (outcome `unavailable`: the rate limit, the budget, the access gate, a failed wake). They cost the app no CPU, so the mean leaves them out. */
14848
+ refusedRequests?: number;
14849
+ busiestMinute?: {
14850
+ /** Format: date-time */
14851
+ at: string;
14852
+ /** @description Requests that reached the app, per second, in the busiest minute. */
14853
+ requestsPerSecond: number;
14854
+ appCores: number;
14855
+ ownerCores?: number;
14856
+ };
14857
+ appCpuMsPerRequest?: {
14858
+ mean: number;
14859
+ };
14860
+ /** @description 0.7 of one core divided by the mean app CPU per request. */
14861
+ ceilingRequestsPerSecond?: number;
14862
+ /** @description The ceiling divided by the busiest minute's rate. */
14863
+ headroom?: number;
14864
+ /** @description The app's peak memory as a fraction of its limit over the window. */
14865
+ memoryPeakFraction?: number;
14866
+ /** @description What the estimate cannot see. */
14867
+ notCovered: string[];
14868
+ };
14869
+ ProjectHealth: {
14870
+ /**
14871
+ * Format: date-time
14872
+ * @description When the checks last ran. Absent when they have never run for this project.
14873
+ */
14874
+ checkedAt?: string;
14875
+ status: components["schemas"]["HealthStatus"];
14876
+ /** @description Open risks, alert first, then warn. */
14877
+ risks: components["schemas"]["HealthRisk"][];
14878
+ checks: components["schemas"]["HealthCheck"][];
14879
+ capacity?: components["schemas"]["CapacityEstimate"];
14880
+ /** @description The live deployment's deploy-time static checks. They do not change `status`: the checks read code, `status` reads production. Absent when nothing is deployed. */
14881
+ staticChecks?: {
14882
+ /** @description The live deployment's version. */
14883
+ version: number;
14884
+ /** Format: date-time */
14885
+ deployedAt: string;
14886
+ /** @description Absent when that deployment was not checked. */
14887
+ report?: components["schemas"]["DeployStaticChecks"];
14888
+ };
14889
+ };
14890
+ OrgHealth: {
14891
+ /** Format: date-time */
14892
+ checkedAt?: string;
14893
+ status: components["schemas"]["HealthStatus"];
14894
+ budget: components["schemas"]["HealthCheck"];
14895
+ projects: {
14896
+ name: string;
14897
+ status: components["schemas"]["HealthStatus"];
14898
+ alerts: number;
14899
+ warns: number;
14900
+ /** Format: date-time */
14901
+ checkedAt?: string;
14902
+ }[];
14903
+ };
14904
+ DeployStaticCheckFinding: {
14905
+ /** @description The rule's id: `rpc-result-not-disposed`, `module-cache-unbounded`, `module-state-per-request`, `interval-in-request`, `time-loop-never-ends`, `sync-cpu-in-request`, `bundle-size`, `source-map-size`. New ids may appear. */
14906
+ rule: string;
14907
+ /**
14908
+ * @description No finding refuses a deploy.
14909
+ * @enum {string}
14910
+ */
14911
+ severity: "warn" | "info";
14912
+ /** @description Project-relative path of the user's own source file. Absent for a finding about the whole bundle. */
14913
+ file?: string;
14914
+ line?: number;
14915
+ column?: number;
14916
+ /** @description This occurrence, one sentence. */
14917
+ message: string;
14918
+ /** @description The Runlot limit it runs into. */
14919
+ why: string;
14920
+ fix: string;
14921
+ };
14922
+ /**
14923
+ * @description What `runlot deploy` found in the project's own code (never node_modules) before the
14924
+ * upload: known patterns that hurt an app on Runlot under traffic. Warnings only.
14925
+ * Silence one line with `// runlot-ignore <rule>` on it or the line above.
14926
+ */
14927
+ DeployStaticChecks: {
14928
+ findings: components["schemas"]["DeployStaticCheckFinding"][];
14929
+ /** @description Findings past the 50 listed. */
14930
+ omitted: number;
14931
+ filesScanned: number;
14932
+ /** @description Files that did not parse or were too large to read. */
14933
+ filesSkipped: number;
14934
+ /** @description Why some or all of the code was not read, when it was not. */
14935
+ note?: string;
14936
+ /** @description The CLI that ran the checks. */
14937
+ analyzer?: string;
14938
+ };
14227
14939
  UptimeAssertion: {
14228
14940
  /** @enum {string} */
14229
14941
  source: "status" | "header" | "body" | "jsonPath" | "latency";
@@ -15181,6 +15893,8 @@ export interface components {
15181
15893
  ReleaseIssueCursor: string;
15182
15894
  OrgSlug: components["schemas"]["Slug"];
15183
15895
  ProjectName: components["schemas"]["Slug"];
15896
+ /** @description A database's name in the organization */
15897
+ DatabaseName: components["schemas"]["Slug"];
15184
15898
  /** @description A queue name as the manifest wrote it (`^[a-z0-9-]{1,63}$`). */
15185
15899
  QueueName: string;
15186
15900
  /**
@@ -16842,7 +17556,10 @@ export interface operations {
16842
17556
  403: components["responses"]["Forbidden"];
16843
17557
  /**
16844
17558
  * @description The name is already taken (`project_name_taken`, `hostname_taken`), or the plan's
16845
- * project limit has been reached (`project_limit`).
17559
+ * project limit has been reached (`project_limit`). A database of the same name
17560
+ * whose earlier project's leftovers are still being erased answers
17561
+ * `database_name_pending` (`details.purgeAfter`); otherwise the new project takes
17562
+ * that database over as `env.db` and the answer carries `existingDatabase`.
16846
17563
  *
16847
17564
  * The `details` of `project_limit` is `{limit, count, plan}` — read the numbers from
16848
17565
  * there rather than parsing the message. It is 409 because retrying will not change
@@ -16913,7 +17630,7 @@ export interface operations {
16913
17630
  400: components["responses"]["BadRequest"];
16914
17631
  403: components["responses"]["Forbidden"];
16915
17632
  404: components["responses"]["NotFound"];
16916
- /** @description Another operation is in progress (`op_in_flight`) */
17633
+ /** @description Another operation is in progress (`op_in_flight`). */
16917
17634
  409: {
16918
17635
  headers: {
16919
17636
  [name: string]: unknown;
@@ -17111,6 +17828,11 @@ export interface operations {
17111
17828
  * allows (usually after a downgrade). Every project's deploys are paused until one is
17112
17829
  * disabled or deleted, or the plan is upgraded; nothing is deleted automatically.
17113
17830
  * `project_disabled` — this project is disabled; enable it first.
17831
+ * `database_not_found` — `runlot.json` names a database (`databases`) the
17832
+ * organization does not have; `details` carries `binding` and `database`.
17833
+ * `binding_needs_colocation` — this project already runs where it cannot reach a
17834
+ * database it binds. `database_limit`, `plan_required` (binding a database into a
17835
+ * second project is Pro), `database_name_pending`.
17114
17836
  */
17115
17837
  409: {
17116
17838
  headers: {
@@ -17247,7 +17969,18 @@ export interface operations {
17247
17969
  };
17248
17970
  cookie?: never;
17249
17971
  };
17250
- requestBody?: never;
17972
+ /**
17973
+ * @description Optional. What the deploy-time static checks found in this bundle's code, stored with
17974
+ * the deployment. A report that does not fit the schema is dropped and named in the
17975
+ * deployment's `warnings`; it never refuses the deploy.
17976
+ */
17977
+ requestBody?: {
17978
+ content: {
17979
+ "application/json": {
17980
+ staticChecks?: components["schemas"]["DeployStaticChecks"];
17981
+ };
17982
+ };
17983
+ };
17251
17984
  responses: {
17252
17985
  /** @description The created deployment */
17253
17986
  201: {
@@ -19005,46 +19738,20 @@ export interface operations {
19005
19738
  header?: never;
19006
19739
  path: {
19007
19740
  orgSlug: components["parameters"]["OrgSlug"];
19008
- projectName: components["parameters"]["ProjectName"];
19741
+ /** @description A database's name in the organization */
19742
+ databaseName: components["parameters"]["DatabaseName"];
19009
19743
  };
19010
19744
  cookie?: never;
19011
19745
  };
19012
19746
  requestBody?: never;
19013
19747
  responses: {
19014
- /** @description Whether the database is available */
19748
+ /** @description The database */
19015
19749
  200: {
19016
19750
  headers: {
19017
19751
  [name: string]: unknown;
19018
19752
  };
19019
19753
  content: {
19020
- "application/json": {
19021
- db: boolean;
19022
- };
19023
- };
19024
- };
19025
- 403: components["responses"]["Forbidden"];
19026
- 404: components["responses"]["NotFound"];
19027
- };
19028
- };
19029
- createDatabase: {
19030
- parameters: {
19031
- query?: never;
19032
- header?: never;
19033
- path: {
19034
- orgSlug: components["parameters"]["OrgSlug"];
19035
- projectName: components["parameters"]["ProjectName"];
19036
- };
19037
- cookie?: never;
19038
- };
19039
- requestBody?: never;
19040
- responses: {
19041
- /** @description Credentials and connection info */
19042
- 200: {
19043
- headers: {
19044
- [name: string]: unknown;
19045
- };
19046
- content: {
19047
- "application/json": components["schemas"]["DatabaseConnect"];
19754
+ "application/json": components["schemas"]["OrgDatabase"];
19048
19755
  };
19049
19756
  };
19050
19757
  403: components["responses"]["Forbidden"];
@@ -19057,7 +19764,8 @@ export interface operations {
19057
19764
  header?: never;
19058
19765
  path: {
19059
19766
  orgSlug: components["parameters"]["OrgSlug"];
19060
- projectName: components["parameters"]["ProjectName"];
19767
+ /** @description A database's name in the organization */
19768
+ databaseName: components["parameters"]["DatabaseName"];
19061
19769
  };
19062
19770
  cookie?: never;
19063
19771
  };
@@ -19090,7 +19798,8 @@ export interface operations {
19090
19798
  header?: never;
19091
19799
  path: {
19092
19800
  orgSlug: components["parameters"]["OrgSlug"];
19093
- projectName: components["parameters"]["ProjectName"];
19801
+ /** @description A database's name in the organization */
19802
+ databaseName: components["parameters"]["DatabaseName"];
19094
19803
  };
19095
19804
  cookie?: never;
19096
19805
  };
@@ -19118,7 +19827,8 @@ export interface operations {
19118
19827
  header?: never;
19119
19828
  path: {
19120
19829
  orgSlug: components["parameters"]["OrgSlug"];
19121
- projectName: components["parameters"]["ProjectName"];
19830
+ /** @description A database's name in the organization */
19831
+ databaseName: components["parameters"]["DatabaseName"];
19122
19832
  };
19123
19833
  cookie?: never;
19124
19834
  };
@@ -19145,7 +19855,8 @@ export interface operations {
19145
19855
  header?: never;
19146
19856
  path: {
19147
19857
  orgSlug: components["parameters"]["OrgSlug"];
19148
- projectName: components["parameters"]["ProjectName"];
19858
+ /** @description A database's name in the organization */
19859
+ databaseName: components["parameters"]["DatabaseName"];
19149
19860
  };
19150
19861
  cookie?: never;
19151
19862
  };
@@ -19178,7 +19889,8 @@ export interface operations {
19178
19889
  header?: never;
19179
19890
  path: {
19180
19891
  orgSlug: components["parameters"]["OrgSlug"];
19181
- projectName: components["parameters"]["ProjectName"];
19892
+ /** @description A database's name in the organization */
19893
+ databaseName: components["parameters"]["DatabaseName"];
19182
19894
  tokenUser: string;
19183
19895
  };
19184
19896
  cookie?: never;
@@ -19202,7 +19914,8 @@ export interface operations {
19202
19914
  header?: never;
19203
19915
  path: {
19204
19916
  orgSlug: components["parameters"]["OrgSlug"];
19205
- projectName: components["parameters"]["ProjectName"];
19917
+ /** @description A database's name in the organization */
19918
+ databaseName: components["parameters"]["DatabaseName"];
19206
19919
  };
19207
19920
  cookie?: never;
19208
19921
  };
@@ -19270,7 +19983,8 @@ export interface operations {
19270
19983
  header?: never;
19271
19984
  path: {
19272
19985
  orgSlug: components["parameters"]["OrgSlug"];
19273
- projectName: components["parameters"]["ProjectName"];
19986
+ /** @description A database's name in the organization */
19987
+ databaseName: components["parameters"]["DatabaseName"];
19274
19988
  };
19275
19989
  cookie?: never;
19276
19990
  };
@@ -19339,7 +20053,8 @@ export interface operations {
19339
20053
  header?: never;
19340
20054
  path: {
19341
20055
  orgSlug: components["parameters"]["OrgSlug"];
19342
- projectName: components["parameters"]["ProjectName"];
20056
+ /** @description A database's name in the organization */
20057
+ databaseName: components["parameters"]["DatabaseName"];
19343
20058
  };
19344
20059
  cookie?: never;
19345
20060
  };
@@ -19364,7 +20079,8 @@ export interface operations {
19364
20079
  header?: never;
19365
20080
  path: {
19366
20081
  orgSlug: components["parameters"]["OrgSlug"];
19367
- projectName: components["parameters"]["ProjectName"];
20082
+ /** @description A database's name in the organization */
20083
+ databaseName: components["parameters"]["DatabaseName"];
19368
20084
  };
19369
20085
  cookie?: never;
19370
20086
  };
@@ -19423,7 +20139,8 @@ export interface operations {
19423
20139
  header?: never;
19424
20140
  path: {
19425
20141
  orgSlug: components["parameters"]["OrgSlug"];
19426
- projectName: components["parameters"]["ProjectName"];
20142
+ /** @description A database's name in the organization */
20143
+ databaseName: components["parameters"]["DatabaseName"];
19427
20144
  };
19428
20145
  cookie?: never;
19429
20146
  };
@@ -19442,7 +20159,7 @@ export interface operations {
19442
20159
  "application/json": components["schemas"]["OperationStarted"];
19443
20160
  };
19444
20161
  };
19445
- /** @description The confirmation string does not match the project name (`confirm_mismatch`) */
20162
+ /** @description The confirmation string does not match the database name (`confirm_mismatch`) */
19446
20163
  400: {
19447
20164
  headers: {
19448
20165
  [name: string]: unknown;
@@ -19461,7 +20178,11 @@ export interface operations {
19461
20178
  "application/json": components["schemas"]["Error"];
19462
20179
  };
19463
20180
  };
19464
- /** @description Another operation is already in progress (`operation_in_progress`) */
20181
+ /**
20182
+ * @description Another operation is already in progress (`operation_in_progress`), or the
20183
+ * database is bound into projects (`database_bound`, `details.bindings` lists
20184
+ * them).
20185
+ */
19465
20186
  409: {
19466
20187
  headers: {
19467
20188
  [name: string]: unknown;
@@ -19478,7 +20199,8 @@ export interface operations {
19478
20199
  header?: never;
19479
20200
  path: {
19480
20201
  orgSlug: components["parameters"]["OrgSlug"];
19481
- projectName: components["parameters"]["ProjectName"];
20202
+ /** @description A database's name in the organization */
20203
+ databaseName: components["parameters"]["DatabaseName"];
19482
20204
  /**
19483
20205
  * @description The operation id. **Not a credential** — an operation that does not belong to the
19484
20206
  * project in the path returns 404.
@@ -19516,7 +20238,8 @@ export interface operations {
19516
20238
  header?: never;
19517
20239
  path: {
19518
20240
  orgSlug: components["parameters"]["OrgSlug"];
19519
- projectName: components["parameters"]["ProjectName"];
20241
+ /** @description A database's name in the organization */
20242
+ databaseName: components["parameters"]["DatabaseName"];
19520
20243
  /**
19521
20244
  * @description The operation id. **Not a credential** — an operation that does not belong to the
19522
20245
  * project in the path returns 404.
@@ -20788,6 +21511,8 @@ export interface operations {
20788
21511
  /** @description capped at 4,096 by the lane */
20789
21512
  maxTokens?: number;
20790
21513
  temperature?: number;
21514
+ /** @description answer as server-sent events instead of one JSON body */
21515
+ stream?: boolean;
20791
21516
  /** @description `env.ai.run`'s reasoning option. cp-core checks `effort` against the model's catalog row. */
20792
21517
  reasoning?: {
20793
21518
  /** @description one of the model's `effortLevels` */
@@ -20841,8 +21566,11 @@ export interface operations {
20841
21566
  * @description the part of inputTokens written to the prompt cache
20842
21567
  */
20843
21568
  cacheWriteInputTokens?: number;
21569
+ /** @description the cache counts the provider did not report; each is 0 above for lack of information. Absent when every count was reported */
21570
+ unreported?: ("cachedInputTokens" | "cacheWriteInputTokens")[];
20844
21571
  };
20845
21572
  };
21573
+ "text/event-stream": string;
20846
21574
  };
20847
21575
  };
20848
21576
  400: components["responses"]["BadRequest"];
@@ -21454,7 +22182,7 @@ export interface operations {
21454
22182
  /**
21455
22183
  * @description `database_required` — this project's database was deleted.
21456
22184
  * `database_disabled` — `runlot.json` says `"database": false`.
21457
- * Either way, create the database with `POST …/database` (`runlot pg on`) first.
22185
+ * Either way, create the database with `POST /v1/orgs/{orgSlug}/databases` (`runlot db create <project>`) first.
21458
22186
  */
21459
22187
  409: {
21460
22188
  headers: {
@@ -22445,6 +23173,132 @@ export interface operations {
22445
23173
  };
22446
23174
  };
22447
23175
  };
23176
+ getSpendingLimit: {
23177
+ parameters: {
23178
+ query?: never;
23179
+ header?: never;
23180
+ path: {
23181
+ orgSlug: components["parameters"]["OrgSlug"];
23182
+ };
23183
+ cookie?: never;
23184
+ };
23185
+ requestBody?: never;
23186
+ responses: {
23187
+ /** @description The spending limit */
23188
+ 200: {
23189
+ headers: {
23190
+ [name: string]: unknown;
23191
+ };
23192
+ content: {
23193
+ "application/json": components["schemas"]["SpendingLimit"];
23194
+ };
23195
+ };
23196
+ 403: components["responses"]["Forbidden"];
23197
+ 404: components["responses"]["NotFound"];
23198
+ };
23199
+ };
23200
+ setSpendingLimit: {
23201
+ parameters: {
23202
+ query?: never;
23203
+ header?: never;
23204
+ path: {
23205
+ orgSlug: components["parameters"]["OrgSlug"];
23206
+ };
23207
+ cookie?: never;
23208
+ };
23209
+ requestBody: {
23210
+ content: {
23211
+ "application/json": components["schemas"]["SpendingLimitUpdate"];
23212
+ };
23213
+ };
23214
+ responses: {
23215
+ /** @description The spending limit after the change */
23216
+ 200: {
23217
+ headers: {
23218
+ [name: string]: unknown;
23219
+ };
23220
+ content: {
23221
+ "application/json": components["schemas"]["SpendingLimit"];
23222
+ };
23223
+ };
23224
+ 400: components["responses"]["BadRequest"];
23225
+ 403: components["responses"]["Forbidden"];
23226
+ 404: components["responses"]["NotFound"];
23227
+ /** @description `spending_limit_not_applicable` */
23228
+ 409: {
23229
+ headers: {
23230
+ [name: string]: unknown;
23231
+ };
23232
+ content: {
23233
+ "application/json": components["schemas"]["Error"];
23234
+ };
23235
+ };
23236
+ };
23237
+ };
23238
+ getProjectLimits: {
23239
+ parameters: {
23240
+ query?: never;
23241
+ header?: never;
23242
+ path: {
23243
+ orgSlug: components["parameters"]["OrgSlug"];
23244
+ projectName: components["parameters"]["ProjectName"];
23245
+ };
23246
+ cookie?: never;
23247
+ };
23248
+ requestBody?: never;
23249
+ responses: {
23250
+ /** @description The limits */
23251
+ 200: {
23252
+ headers: {
23253
+ [name: string]: unknown;
23254
+ };
23255
+ content: {
23256
+ "application/json": components["schemas"]["ProjectLimits"];
23257
+ };
23258
+ };
23259
+ 403: components["responses"]["Forbidden"];
23260
+ 404: components["responses"]["NotFound"];
23261
+ };
23262
+ };
23263
+ setProjectLimits: {
23264
+ parameters: {
23265
+ query?: never;
23266
+ header?: never;
23267
+ path: {
23268
+ orgSlug: components["parameters"]["OrgSlug"];
23269
+ projectName: components["parameters"]["ProjectName"];
23270
+ };
23271
+ cookie?: never;
23272
+ };
23273
+ requestBody: {
23274
+ content: {
23275
+ "application/json": components["schemas"]["ProjectLimitsUpdate"];
23276
+ };
23277
+ };
23278
+ responses: {
23279
+ /** @description The limits after the change */
23280
+ 200: {
23281
+ headers: {
23282
+ [name: string]: unknown;
23283
+ };
23284
+ content: {
23285
+ "application/json": components["schemas"]["ProjectLimits"];
23286
+ };
23287
+ };
23288
+ 400: components["responses"]["BadRequest"];
23289
+ 403: components["responses"]["Forbidden"];
23290
+ 404: components["responses"]["NotFound"];
23291
+ /** @description `memory_limit_below_use`, `memory_limit_exceeds_node`, `memory_limit_set_by_operator` or `spending_limit_not_applicable` */
23292
+ 409: {
23293
+ headers: {
23294
+ [name: string]: unknown;
23295
+ };
23296
+ content: {
23297
+ "application/json": components["schemas"]["Error"];
23298
+ };
23299
+ };
23300
+ };
23301
+ };
22448
23302
  listMembers: {
22449
23303
  parameters: {
22450
23304
  query?: never;
@@ -27781,6 +28635,203 @@ export interface operations {
27781
28635
  };
27782
28636
  };
27783
28637
  };
28638
+ getProjectHealth: {
28639
+ parameters: {
28640
+ query?: never;
28641
+ header?: never;
28642
+ path: {
28643
+ orgSlug: string;
28644
+ projectName: string;
28645
+ };
28646
+ cookie?: never;
28647
+ };
28648
+ requestBody?: never;
28649
+ responses: {
28650
+ /** @description Health */
28651
+ 200: {
28652
+ headers: {
28653
+ [name: string]: unknown;
28654
+ };
28655
+ content: {
28656
+ "application/json": components["schemas"]["ProjectHealth"];
28657
+ };
28658
+ };
28659
+ /** @description Request refused */
28660
+ 401: {
28661
+ headers: {
28662
+ [name: string]: unknown;
28663
+ };
28664
+ content?: never;
28665
+ };
28666
+ /** @description Request refused */
28667
+ 403: {
28668
+ headers: {
28669
+ [name: string]: unknown;
28670
+ };
28671
+ content?: never;
28672
+ };
28673
+ /** @description Request refused */
28674
+ 404: {
28675
+ headers: {
28676
+ [name: string]: unknown;
28677
+ };
28678
+ content?: never;
28679
+ };
28680
+ };
28681
+ };
28682
+ listOrgDatabases: {
28683
+ parameters: {
28684
+ query?: never;
28685
+ header?: never;
28686
+ path: {
28687
+ orgSlug: components["parameters"]["OrgSlug"];
28688
+ };
28689
+ cookie?: never;
28690
+ };
28691
+ requestBody?: never;
28692
+ responses: {
28693
+ /** @description Databases */
28694
+ 200: {
28695
+ headers: {
28696
+ [name: string]: unknown;
28697
+ };
28698
+ content: {
28699
+ "application/json": components["schemas"]["OrgDatabases"];
28700
+ };
28701
+ };
28702
+ 403: components["responses"]["Forbidden"];
28703
+ 404: components["responses"]["NotFound"];
28704
+ };
28705
+ };
28706
+ createOrgDatabase: {
28707
+ parameters: {
28708
+ query?: never;
28709
+ header?: never;
28710
+ path: {
28711
+ orgSlug: components["parameters"]["OrgSlug"];
28712
+ };
28713
+ cookie?: never;
28714
+ };
28715
+ requestBody: {
28716
+ content: {
28717
+ "application/json": {
28718
+ name: components["schemas"]["Slug"];
28719
+ };
28720
+ };
28721
+ };
28722
+ responses: {
28723
+ /** @description The project's own database already existed or was created */
28724
+ 200: {
28725
+ headers: {
28726
+ [name: string]: unknown;
28727
+ };
28728
+ content: {
28729
+ "application/json": components["schemas"]["DatabaseConnect"];
28730
+ };
28731
+ };
28732
+ /** @description A new database */
28733
+ 201: {
28734
+ headers: {
28735
+ [name: string]: unknown;
28736
+ };
28737
+ content: {
28738
+ "application/json": components["schemas"]["DatabaseConnect"];
28739
+ };
28740
+ };
28741
+ 400: components["responses"]["BadRequest"];
28742
+ /** @description Not a member, or a standalone database on a plan without it (`plan_required`) */
28743
+ 403: {
28744
+ headers: {
28745
+ [name: string]: unknown;
28746
+ };
28747
+ content: {
28748
+ "application/json": components["schemas"]["Error"];
28749
+ };
28750
+ };
28751
+ /**
28752
+ * @description `name_taken` (`details.kind` is `project` or `database`), `database_limit`
28753
+ * (`details.limit`, `details.unbound` names databases no project binds),
28754
+ * `database_name_pending` (a deleted project's leftovers are still being erased
28755
+ * under this name; `details.purgeAfter`).
28756
+ */
28757
+ 409: {
28758
+ headers: {
28759
+ [name: string]: unknown;
28760
+ };
28761
+ content: {
28762
+ "application/json": components["schemas"]["Error"];
28763
+ };
28764
+ };
28765
+ };
28766
+ };
28767
+ unbindDatabase: {
28768
+ parameters: {
28769
+ query?: never;
28770
+ header?: never;
28771
+ path: {
28772
+ orgSlug: components["parameters"]["OrgSlug"];
28773
+ /** @description A database's name in the organization */
28774
+ databaseName: components["parameters"]["DatabaseName"];
28775
+ projectName: components["parameters"]["ProjectName"];
28776
+ };
28777
+ cookie?: never;
28778
+ };
28779
+ requestBody?: never;
28780
+ responses: {
28781
+ /** @description Unbound */
28782
+ 204: {
28783
+ headers: {
28784
+ [name: string]: unknown;
28785
+ };
28786
+ content?: never;
28787
+ };
28788
+ 403: components["responses"]["Forbidden"];
28789
+ 404: components["responses"]["NotFound"];
28790
+ };
28791
+ };
28792
+ getOrgHealth: {
28793
+ parameters: {
28794
+ query?: never;
28795
+ header?: never;
28796
+ path: {
28797
+ orgSlug: string;
28798
+ };
28799
+ cookie?: never;
28800
+ };
28801
+ requestBody?: never;
28802
+ responses: {
28803
+ /** @description Health */
28804
+ 200: {
28805
+ headers: {
28806
+ [name: string]: unknown;
28807
+ };
28808
+ content: {
28809
+ "application/json": components["schemas"]["OrgHealth"];
28810
+ };
28811
+ };
28812
+ /** @description Request refused */
28813
+ 401: {
28814
+ headers: {
28815
+ [name: string]: unknown;
28816
+ };
28817
+ content?: never;
28818
+ };
28819
+ /** @description Request refused */
28820
+ 403: {
28821
+ headers: {
28822
+ [name: string]: unknown;
28823
+ };
28824
+ content?: never;
28825
+ };
28826
+ /** @description Request refused */
28827
+ 404: {
28828
+ headers: {
28829
+ [name: string]: unknown;
28830
+ };
28831
+ content?: never;
28832
+ };
28833
+ };
28834
+ };
27784
28835
  listSynthetics: {
27785
28836
  parameters: {
27786
28837
  query?: never;