@runlot/api 0.1.0-rc.95 → 0.1.0-rc.97

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
@@ -336,6 +336,183 @@ export interface paths {
336
336
  patch?: never;
337
337
  trace?: never;
338
338
  };
339
+ "/.well-known/oauth-authorization-server": {
340
+ parameters: {
341
+ query?: never;
342
+ header?: never;
343
+ path?: never;
344
+ cookie?: never;
345
+ };
346
+ /**
347
+ * Authorization server metadata (RFC 8414)
348
+ * @description What a client reads before it has any credential, so it is open by definition.
349
+ *
350
+ * `authorization_endpoint` points at the **dashboard**, not at this API: the
351
+ * authorization step has to see the user's login session, which lives in the browser
352
+ * (docs/studio.md §8.1). `runlot_access_token_audience` is not in RFC 8414 — it is here
353
+ * so a resource server learns the `aud` it must require from the issuer rather than from
354
+ * a second configured value that can disagree.
355
+ */
356
+ get: operations["oauthMetadata"];
357
+ put?: never;
358
+ post?: never;
359
+ delete?: never;
360
+ options?: never;
361
+ head?: never;
362
+ patch?: never;
363
+ trace?: never;
364
+ };
365
+ "/.well-known/jwks.json": {
366
+ parameters: {
367
+ query?: never;
368
+ header?: never;
369
+ path?: never;
370
+ cookie?: never;
371
+ };
372
+ /**
373
+ * The access tokens' public keys
374
+ * @description Every non-retired signing key. **Two are published during a rotation**, which is the
375
+ * whole reason this is a set: a verifier that cached one key would refuse tokens minted
376
+ * with the other. Cacheable for a minute, and no longer — a stale copy refuses fresh
377
+ * tokens.
378
+ */
379
+ get: operations["oauthJwks"];
380
+ put?: never;
381
+ post?: never;
382
+ delete?: never;
383
+ options?: never;
384
+ head?: never;
385
+ patch?: never;
386
+ trace?: never;
387
+ };
388
+ "/v1/oauth/authorize": {
389
+ parameters: {
390
+ query?: never;
391
+ header?: never;
392
+ path?: never;
393
+ cookie?: never;
394
+ };
395
+ get?: never;
396
+ put?: never;
397
+ /**
398
+ * Approve a connected app and mint an authorization code
399
+ * @description Called by the dashboard's `/oauth/authorize` screen with the **user's login session**.
400
+ * A personal access token is refused whatever its scopes: a credential must never be
401
+ * able to widen itself into a longer-lived one.
402
+ *
403
+ * The parameters carry OAuth's own names rather than this document's camelCase, because
404
+ * the screen forwards the query string it was handed.
405
+ */
406
+ post: operations["oauthAuthorize"];
407
+ delete?: never;
408
+ options?: never;
409
+ head?: never;
410
+ patch?: never;
411
+ trace?: never;
412
+ };
413
+ "/oauth/token": {
414
+ parameters: {
415
+ query?: never;
416
+ header?: never;
417
+ path?: never;
418
+ cookie?: never;
419
+ };
420
+ get?: never;
421
+ put?: never;
422
+ /**
423
+ * Exchange a code, or refresh (RFC 6749)
424
+ * @description Form-encoded, not JSON — RFC 6749 §4.1.3, and what every client library sends.
425
+ *
426
+ * **The failures are RFC 6749 §5.2's body, not this document's error envelope**, because
427
+ * these two endpoints are read by generic OAuth clients that cannot parse ours.
428
+ *
429
+ * Refresh tokens rotate: using one invalidates it and returns the next. Rate limited per
430
+ * client and per address (`429`).
431
+ */
432
+ post: operations["oauthToken"];
433
+ delete?: never;
434
+ options?: never;
435
+ head?: never;
436
+ patch?: never;
437
+ trace?: never;
438
+ };
439
+ "/oauth/revoke": {
440
+ parameters: {
441
+ query?: never;
442
+ header?: never;
443
+ path?: never;
444
+ cookie?: never;
445
+ };
446
+ get?: never;
447
+ put?: never;
448
+ /**
449
+ * Sign a connected app out (RFC 7009)
450
+ * @description Form-encoded. **It answers 200 for a token it does not know** — RFC 7009 §2.2 requires
451
+ * it, and the reason is that any other answer turns the endpoint into an oracle for which
452
+ * tokens exist.
453
+ *
454
+ * Revoking a refresh token revokes **the whole grant**, not one rotation generation:
455
+ * "sign out in Studio" means the device is gone from Connected apps too (docs/studio.md
456
+ * §8.4). Rate limited per client and per address (`429`).
457
+ */
458
+ post: operations["oauthRevoke"];
459
+ delete?: never;
460
+ options?: never;
461
+ head?: never;
462
+ patch?: never;
463
+ trace?: never;
464
+ };
465
+ "/v1/oauth/grants": {
466
+ parameters: {
467
+ query?: never;
468
+ header?: never;
469
+ path?: never;
470
+ cookie?: never;
471
+ };
472
+ /**
473
+ * Connected apps
474
+ * @description What can reach this account right now (docs/studio.md §8.4). Revoked grants are not
475
+ * listed: a list that keeps dead rows makes the answer a filter the reader has to apply.
476
+ *
477
+ * Session only, for `POST /v1/oauth/authorize`'s reason.
478
+ */
479
+ get: operations["listOAuthGrants"];
480
+ put?: never;
481
+ post?: never;
482
+ delete?: never;
483
+ options?: never;
484
+ head?: never;
485
+ patch?: never;
486
+ trace?: never;
487
+ };
488
+ "/v1/oauth/grants/{sid}": {
489
+ parameters: {
490
+ query?: never;
491
+ header?: never;
492
+ path: {
493
+ /** @description The grant's session id, as `GET /v1/oauth/grants` returned it. */
494
+ sid: string;
495
+ };
496
+ cookie?: never;
497
+ };
498
+ get?: never;
499
+ put?: never;
500
+ post?: never;
501
+ /**
502
+ * Remove a connected app
503
+ * @description Its refresh tokens die with it, its access token dies on the next request through the
504
+ * `sid` check, and the revocation reaches the Studio service through cp-core's feed — so
505
+ * a lent model drops at once rather than within the access token's fifteen minutes.
506
+ *
507
+ * A grant that is not this user's is a **404**, not a 403: telling a caller that somebody
508
+ * else's grant id exists is a probe for grant ids.
509
+ */
510
+ delete: operations["revokeOAuthGrant"];
511
+ options?: never;
512
+ head?: never;
513
+ patch?: never;
514
+ trace?: never;
515
+ };
339
516
  "/v1/me": {
340
517
  parameters: {
341
518
  query?: never;
@@ -692,6 +869,41 @@ export interface paths {
692
869
  patch?: never;
693
870
  trace?: never;
694
871
  };
872
+ "/v1/orgs/{orgSlug}/projects/{projectName}/deployments/{deploymentId}": {
873
+ parameters: {
874
+ query?: never;
875
+ header?: never;
876
+ path: {
877
+ orgSlug: components["parameters"]["OrgSlug"];
878
+ projectName: components["parameters"]["ProjectName"];
879
+ deploymentId: string;
880
+ };
881
+ cookie?: never;
882
+ };
883
+ /**
884
+ * One deployment, with the status of any migrations the CP applied
885
+ * @description The same object the history lists, plus `migrations` — which only a deployment the
886
+ * control plane migrates for you carries.
887
+ *
888
+ * Normally `migrations/` is applied by the **client**: `runlot deploy` connects over the
889
+ * wire and runs the files, watched by the person who typed the command. A **preview**
890
+ * deploy is the exception, because the CLI can only name the parent project's database
891
+ * and running a preview's migrations there is the accident `db=branch` exists to
892
+ * prevent. For those the control plane applies them to the branch instead, after the
893
+ * branch finishes pouring, and this is where the outcome is read.
894
+ *
895
+ * A preview whose id was returned by `createDeployment` is readable **under its parent
896
+ * project's name** — the name the caller deployed through.
897
+ */
898
+ get: operations["getDeployment"];
899
+ put?: never;
900
+ post?: never;
901
+ delete?: never;
902
+ options?: never;
903
+ head?: never;
904
+ patch?: never;
905
+ trace?: never;
906
+ };
695
907
  "/v1/orgs/{orgSlug}/projects/{projectName}/cron": {
696
908
  parameters: {
697
909
  query?: never;
@@ -1202,6 +1414,12 @@ export interface paths {
1202
1414
  * to your statement**, so `rowCount` still reports what the statement actually did and
1203
1415
  * `truncated` tells you the listing was cut.
1204
1416
  *
1417
+ * **Write mode belongs to a dashboard session.** A personal access token reaches this
1418
+ * route with `db:read` and runs read-only statements; asking for `readOnly: false`
1419
+ * with a token is 403 `console_write_needs_session`. No scope opens it — a credential
1420
+ * that has to write goes through `…/database/connect` or `…/database/tokens` and
1421
+ * connects, where the power it carries is named on the token.
1422
+ *
1205
1423
  * Requires member or higher. A write leaves a `db.execute` audit event; a read leaves
1206
1424
  * none.
1207
1425
  */
@@ -1717,6 +1935,81 @@ export interface paths {
1717
1935
  patch?: never;
1718
1936
  trace?: never;
1719
1937
  };
1938
+ "/v1/orgs/{orgSlug}/projects/{projectName}/storage/objects": {
1939
+ parameters: {
1940
+ query?: never;
1941
+ header?: never;
1942
+ path: {
1943
+ orgSlug: components["parameters"]["OrgSlug"];
1944
+ projectName: components["parameters"]["ProjectName"];
1945
+ };
1946
+ cookie?: never;
1947
+ };
1948
+ /**
1949
+ * List objects (`runlot storage ls`)
1950
+ * @description One page of the project's objects, **grouped by `/`** the way a file browser groups
1951
+ * them: `entries` are the objects directly under `prefix`, and `prefixes` are the
1952
+ * directories one level down.
1953
+ *
1954
+ * Keys are the ones the worker writes — `env.storage.put(key, …)` — never the
1955
+ * internal `p/<projectId>/` prefix, which is an isolation boundary and not part of
1956
+ * any address.
1957
+ *
1958
+ * `public` is true when the key sits under a prefix this project has published
1959
+ * (`…/storage/public`), and `url` is then the unsigned address anyone can read. A
1960
+ * private object carries no `url`: this field means "anyone can read this", and a
1961
+ * signed URL in it would show a private object as a public one. For those, ask
1962
+ * `…/storage/objects/{key}`.
1963
+ *
1964
+ * **Paging is by `cursor`, and the boundary lands between groups** — no directory is
1965
+ * listed twice and none is skipped. Feed `cursor` back unchanged; its absence is the
1966
+ * end.
1967
+ *
1968
+ * Requires viewer or higher.
1969
+ */
1970
+ get: operations["listStorageObjects"];
1971
+ put?: never;
1972
+ post?: never;
1973
+ delete?: never;
1974
+ options?: never;
1975
+ head?: never;
1976
+ patch?: never;
1977
+ trace?: never;
1978
+ };
1979
+ "/v1/orgs/{orgSlug}/projects/{projectName}/storage/objects/{key}": {
1980
+ parameters: {
1981
+ query?: never;
1982
+ header?: never;
1983
+ path: {
1984
+ orgSlug: components["parameters"]["OrgSlug"];
1985
+ projectName: components["parameters"]["ProjectName"];
1986
+ /** @description The object key. It may contain `/`; the segments are part of the path. */
1987
+ key: string;
1988
+ };
1989
+ cookie?: never;
1990
+ };
1991
+ /**
1992
+ * A short-lived signed URL for one object (`runlot storage download`)
1993
+ * @description A **GET** URL valid for five minutes, which the browser or the CLI then fetches
1994
+ * directly from the object front. The bytes never pass through this API.
1995
+ *
1996
+ * The object is looked up before it is signed, so a key that holds nothing is a 404
1997
+ * here rather than a URL that 404s minutes later somewhere you cannot correlate it.
1998
+ *
1999
+ * Only GET is signed. Uploading and deleting are not on this surface — write through
2000
+ * `env.storage` from the worker.
2001
+ *
2002
+ * Requires viewer or higher.
2003
+ */
2004
+ get: operations["signStorageObject"];
2005
+ put?: never;
2006
+ post?: never;
2007
+ delete?: never;
2008
+ options?: never;
2009
+ head?: never;
2010
+ patch?: never;
2011
+ trace?: never;
2012
+ };
1720
2013
  "/v1/ai/models": {
1721
2014
  parameters: {
1722
2015
  query?: never;
@@ -2268,6 +2561,70 @@ export interface paths {
2268
2561
  patch?: never;
2269
2562
  trace?: never;
2270
2563
  };
2564
+ "/v1/orgs/{orgSlug}/projects/{projectName}/auth/users": {
2565
+ parameters: {
2566
+ query?: never;
2567
+ header?: never;
2568
+ path: {
2569
+ orgSlug: components["parameters"]["OrgSlug"];
2570
+ projectName: components["parameters"]["ProjectName"];
2571
+ };
2572
+ cookie?: never;
2573
+ };
2574
+ /**
2575
+ * The app's end users (`runlot auth users`)
2576
+ * @description The people who signed up to **your app** — not the members of your organization.
2577
+ * They live in the project's own database, under the `runlot_auth` schema, and this
2578
+ * route reads them over the same connection `…/database/connect` hands you for psql.
2579
+ * Everything here is also visible through `env.db` and `psql`; this is a convenience,
2580
+ * not a second source.
2581
+ *
2582
+ * **It is read-only.** Blocking a user, deleting one, or resetting a password is not
2583
+ * on this surface — write through `env.db`.
2584
+ *
2585
+ * An app whose login has never been used has no schema yet (it is created on the
2586
+ * first call), and that answers an **empty list** rather than an error.
2587
+ *
2588
+ * Paging is by `cursor`, newest first. Feed it back unchanged; its absence is the
2589
+ * end.
2590
+ *
2591
+ * Requires member or higher, and `db:read` on a token — the subscriber list is the
2592
+ * project's data, the same class as the SQL console.
2593
+ */
2594
+ get: operations["listAppUsers"];
2595
+ put?: never;
2596
+ post?: never;
2597
+ delete?: never;
2598
+ options?: never;
2599
+ head?: never;
2600
+ patch?: never;
2601
+ trace?: never;
2602
+ };
2603
+ "/v1/orgs/{orgSlug}/projects/{projectName}/auth/users/{userId}": {
2604
+ parameters: {
2605
+ query?: never;
2606
+ header?: never;
2607
+ path: {
2608
+ orgSlug: components["parameters"]["OrgSlug"];
2609
+ projectName: components["parameters"]["ProjectName"];
2610
+ userId: string;
2611
+ };
2612
+ cookie?: never;
2613
+ };
2614
+ /**
2615
+ * One end user
2616
+ * @description The same record as the list, for one id. Requires member or higher, and `db:read`
2617
+ * on a token.
2618
+ */
2619
+ get: operations["getAppUser"];
2620
+ put?: never;
2621
+ post?: never;
2622
+ delete?: never;
2623
+ options?: never;
2624
+ head?: never;
2625
+ patch?: never;
2626
+ trace?: never;
2627
+ };
2271
2628
  "/v1/orgs/{orgSlug}/projects/{projectName}/access": {
2272
2629
  parameters: {
2273
2630
  query?: never;
@@ -3841,29 +4198,80 @@ export interface paths {
3841
4198
  patch?: never;
3842
4199
  trace?: never;
3843
4200
  };
3844
- }
3845
- export type webhooks = Record<string, never>;
3846
- export interface components {
3847
- schemas: {
3848
- RepoRefs: {
3849
- /**
3850
- * @description The repository's current default branch. If this ever disagrees with
3851
- * `Repo.defaultBranch`, this value is the correct one.
3852
- */
3853
- defaultBranch: string;
3854
- refs: {
3855
- name: string;
3856
- /**
3857
- * @description The **commit** oid this ref points to. Annotated tags are peeled, so this is
3858
- * always a commit and never a tag object.
3859
- */
3860
- target: string;
3861
- /** @enum {string} */
3862
- kind: "branch" | "tag";
3863
- }[];
3864
- };
3865
- RepoTreeEntry: {
3866
- name: string;
4201
+ "/v1/orgs/{orgSlug}/projects/{projectName}/share": {
4202
+ parameters: {
4203
+ query?: never;
4204
+ header?: never;
4205
+ path: {
4206
+ orgSlug: components["parameters"]["OrgSlug"];
4207
+ projectName: components["parameters"]["ProjectName"];
4208
+ };
4209
+ cookie?: never;
4210
+ };
4211
+ /**
4212
+ * The project's share link
4213
+ * @description Requires viewer or higher. **404 when the project has never been shared** — a link is
4214
+ * minted by `putShareLink`, never as a side effect of reading.
4215
+ */
4216
+ get: operations["getShareLink"];
4217
+ /**
4218
+ * Point the share link at a preview, minting it if there is none
4219
+ * @description Requires member or higher: handing out a public address for the app is publishing, not
4220
+ * reading.
4221
+ *
4222
+ * **Idempotent.** The label is minted once and kept, so somebody who already has the
4223
+ * link keeps working — calling this again with the same preview changes nothing. What it
4224
+ * does change is *which* preview the link resolves to, so a share from another branch
4225
+ * moves the same address rather than issuing a second one.
4226
+ *
4227
+ * `rotate: true` mints a new label and detaches the old name in the same request ("링크
4228
+ * 재발급"), so there is never a moment with two live links. Anyone holding the old link
4229
+ * stops being able to open it, which is the point.
4230
+ *
4231
+ * The named preview has to exist. Studio deploys it first
4232
+ * (`createDeployment?preview=studio&db=branch`) and shares it second.
4233
+ */
4234
+ put: operations["putShareLink"];
4235
+ post?: never;
4236
+ /**
4237
+ * Stop the share link answering
4238
+ * @description Requires member or higher. The name stops resolving and the label is forgotten; a
4239
+ * later share mints a different one.
4240
+ *
4241
+ * **The preview is not deleted.** Sharing and running are separate decisions, and a link
4242
+ * that also destroyed a database branch would be a surprising amount of destruction.
4243
+ *
4244
+ * A project that is not shared answers 204 — the caller is turning something off.
4245
+ */
4246
+ delete: operations["deleteShareLink"];
4247
+ options?: never;
4248
+ head?: never;
4249
+ patch?: never;
4250
+ trace?: never;
4251
+ };
4252
+ }
4253
+ export type webhooks = Record<string, never>;
4254
+ export interface components {
4255
+ schemas: {
4256
+ RepoRefs: {
4257
+ /**
4258
+ * @description The repository's current default branch. If this ever disagrees with
4259
+ * `Repo.defaultBranch`, this value is the correct one.
4260
+ */
4261
+ defaultBranch: string;
4262
+ refs: {
4263
+ name: string;
4264
+ /**
4265
+ * @description The **commit** oid this ref points to. Annotated tags are peeled, so this is
4266
+ * always a commit and never a tag object.
4267
+ */
4268
+ target: string;
4269
+ /** @enum {string} */
4270
+ kind: "branch" | "tag";
4271
+ }[];
4272
+ };
4273
+ RepoTreeEntry: {
4274
+ name: string;
3867
4275
  /** @description Path relative to the repository root */
3868
4276
  path: string;
3869
4277
  /** @enum {string} */
@@ -3927,6 +4335,54 @@ export interface components {
3927
4335
  * @enum {string}
3928
4336
  */
3929
4337
  TokenScope: "repo:read" | "repo:write" | "repo:none";
4338
+ /** @description RFC 6749 §5.1. */
4339
+ OAuthTokenResponse: {
4340
+ /** @description An Ed25519 JWT (RFC 9068). Fifteen minutes. */
4341
+ access_token: string;
4342
+ /** @example Bearer */
4343
+ token_type: string;
4344
+ /**
4345
+ * @description Seconds. It is present so a client refreshes ahead of time instead of discovering
4346
+ * expiry as a 401 in the middle of something.
4347
+ * @example 900
4348
+ */
4349
+ expires_in: number;
4350
+ /** @description Rotated: using one invalidates it and returns the next. */
4351
+ refresh_token: string;
4352
+ /** @example project:read deploy repo:read repo:write db:read */
4353
+ scope: string;
4354
+ };
4355
+ /**
4356
+ * @description RFC 6749 §5.2. **Not this document's error envelope**: `/oauth/token` and
4357
+ * `/oauth/revoke` are read by generic OAuth clients that cannot parse ours.
4358
+ */
4359
+ OAuthError: {
4360
+ /** @example invalid_grant */
4361
+ error: string;
4362
+ error_description?: string;
4363
+ };
4364
+ /** @description One connected app, as `/account/apps` lists it (docs/studio.md §8.4). */
4365
+ OAuthGrant: {
4366
+ /** @description The grant's session id. It is the `sid` claim in every access token it minted, and what revocation is keyed by. */
4367
+ sid: string;
4368
+ /** @example studio-desktop */
4369
+ clientId: string;
4370
+ /** @example runlot Studio */
4371
+ clientName: string;
4372
+ /**
4373
+ * @description What the device called itself when it connected. Null for a client that did not say.
4374
+ * @example Ryan의 MacBook Pro
4375
+ */
4376
+ deviceName: string | null;
4377
+ scopes: components["schemas"]["ApiScope"][];
4378
+ /** Format: date-time */
4379
+ createdAt: string;
4380
+ /**
4381
+ * Format: date-time
4382
+ * @description Null when the grant has never been used — a sign-in that was never followed by a call.
4383
+ */
4384
+ lastUsedAt: string | null;
4385
+ };
3930
4386
  /**
3931
4387
  * @description One permission a personal access token carries. Scopes are checked on **every** route:
3932
4388
  * the token acts as its owner, subject to that person's organization role, and the scope
@@ -4282,7 +4738,7 @@ export interface components {
4282
4738
  * human-readable wording is produced separately by the dashboard and by email.
4283
4739
  * @enum {string}
4284
4740
  */
4285
- 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" | "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";
4741
+ 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" | "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" | "new_device";
4286
4742
  /** @description If this is a project-related notification, the name of that project. Absent for org-level notifications (`project_limit`) */
4287
4743
  projectName?: string;
4288
4744
  /**
@@ -4294,8 +4750,9 @@ export interface components {
4294
4750
  * @description Extra values, which differ by kind. `project_limit` is `{limit, count}`,
4295
4751
  * a usage alert is `{bytes, capBytes}`, an operation alert is
4296
4752
  * `{opId, opKind, reason?}`, `cron_failed` is
4297
- * `{cron, reason, scheduledAt}`, `queue_failed` is `{queue, reason, runs}` and
4298
- * `queue_ops_cap` is `{used, limit, plan}`.
4753
+ * `{cron, reason, scheduledAt}`, `queue_failed` is `{queue, reason, runs}`,
4754
+ * `queue_ops_cap` is `{used, limit, plan}` and `new_device` is
4755
+ * `{app, clientId, device}`.
4299
4756
  */
4300
4757
  detail: {
4301
4758
  [key: string]: unknown;
@@ -4458,6 +4915,83 @@ export interface components {
4458
4915
  */
4459
4916
  gitDirty?: boolean;
4460
4917
  };
4918
+ /**
4919
+ * @description The one address Studio hands to a person who is not a developer
4920
+ * (`docs/studio.md §6.9`).
4921
+ *
4922
+ * A preview's own hostname is `<preview>--<project>.<org>.<app-domain>`. The `--` is what
4923
+ * keeps a preview name from colliding with a project name and it is right for a CLI user,
4924
+ * but it is not a link to send to somebody — and it carries the project's name, which the
4925
+ * author of a half-finished app may not want published. So a shared preview gets a second
4926
+ * hostname, and this is it.
4927
+ *
4928
+ * The label is 12 characters of lowercase base32 (`[a-z2-7]`, 60 bits). **It contains no
4929
+ * hyphen** — that is why the project name is not in it, since a slug may contain one — and
4930
+ * it is the only thing between the link and the app, so it is minted from a CSPRNG.
4931
+ *
4932
+ * It lives under `share.<app-domain>`, not under an org, so it cannot collide with a
4933
+ * project or preview name. `share` is a reserved org slug for that reason.
4934
+ */
4935
+ ShareLink: {
4936
+ /** @description The 12-character label. Minted once and kept across shares. */
4937
+ label: string;
4938
+ /** @description `<label>.share.<app-domain>`. */
4939
+ hostname: string;
4940
+ /**
4941
+ * Format: uri
4942
+ * @description The address to hand out. Built by the server — the scheme and port are a deployment matter.
4943
+ */
4944
+ url: string;
4945
+ /**
4946
+ * @description The preview the link currently resolves to (`studio`, or `studio-<branch>`).
4947
+ * Present so that "the link works but shows the wrong branch" is diagnosable.
4948
+ */
4949
+ preview?: components["schemas"]["Slug"];
4950
+ /** Format: date-time */
4951
+ createdAt: string;
4952
+ /**
4953
+ * Format: date-time
4954
+ * @description When the label was last re-minted. Absent if it never was.
4955
+ */
4956
+ rotatedAt?: string;
4957
+ };
4958
+ /**
4959
+ * @description Whether the control plane applied this deployment's `migrations/`, and how far it got.
4960
+ *
4961
+ * Present only on deployments the control plane migrates — today that is a preview
4962
+ * deployed with `db=branch`. Absent means the schema is the client's to apply, which is
4963
+ * what `runlot deploy` does.
4964
+ *
4965
+ * `applied` with `total: 0` is the answer for a bundle that carries no migrations at
4966
+ * all; it is a state rather than an absence so that a caller waiting on this can tell
4967
+ * "not started yet" from "there is nothing to run".
4968
+ */
4969
+ DeploymentMigrations: {
4970
+ /**
4971
+ * @description `pending` — not started, or waiting for the preview's database branch to finish
4972
+ * being poured. A database that could not be reached also returns here, so that the
4973
+ * next sweep retries: an unreachable node is not a failed migration.
4974
+ *
4975
+ * `failed` — one file threw, and it is named in `failedName`. Nothing after it ran.
4976
+ * @enum {string}
4977
+ */
4978
+ state: "pending" | "running" | "applied" | "failed";
4979
+ /** @description How many migration files the bundle carries. */
4980
+ total: number;
4981
+ /** @description How many of them went through. */
4982
+ applied: number;
4983
+ /** @description The file that threw, as `0003_posts`. Only on `failed`. */
4984
+ failedName?: string;
4985
+ /** @description The database's own message, truncated. Only on `failed`. */
4986
+ detail?: string;
4987
+ /** Format: date-time */
4988
+ startedAt: string;
4989
+ /**
4990
+ * Format: date-time
4991
+ * @description Absent while `pending` or `running`.
4992
+ */
4993
+ finishedAt?: string;
4994
+ };
4461
4995
  /**
4462
4996
  * @description One preview of a project. A preview behaves like a project of its own — it has its
4463
4997
  * own hostname, deployments, access policy and usage — and this schema carries what is
@@ -5923,9 +6457,98 @@ export interface components {
5923
6457
  /** @description the most automatic top-ups that can run in one day */
5924
6458
  autoTopupPerDay: number;
5925
6459
  };
6460
+ StorageObject: {
6461
+ /**
6462
+ * @description The key as the worker writes it, without the internal project prefix.
6463
+ * @example avatars/a.png
6464
+ */
6465
+ key: string;
6466
+ /** Format: int64 */
6467
+ size: number;
6468
+ /**
6469
+ * @description the stored content type
6470
+ * @example image/png
6471
+ */
6472
+ type: string;
6473
+ /** Format: date-time */
6474
+ modified: string;
6475
+ /** @description Whether this key sits under one of the project's published prefixes. */
6476
+ public: boolean;
6477
+ /**
6478
+ * @description The unsigned public address, present only when `public` is true and this
6479
+ * installation has a public object front. It is never a signed URL.
6480
+ * @example https://objects.runlot.io/acme/app/avatars/a.png
6481
+ */
6482
+ url?: string;
6483
+ };
6484
+ StorageObjectPage: {
6485
+ entries: components["schemas"]["StorageObject"][];
6486
+ /**
6487
+ * @description The directories one level under the requested prefix, each ending in `/`. Pass one back as `prefix`.
6488
+ * @example [
6489
+ * "avatars/",
6490
+ * "uploads/"
6491
+ * ]
6492
+ */
6493
+ prefixes: string[];
6494
+ /** @description Pass it back to get the next page. Absent means the end. */
6495
+ cursor?: string;
6496
+ /** @description The project's published prefixes, carried on every page so a client can explain the `public` marks without a second call. */
6497
+ publicPrefixes: string[];
6498
+ /** @description `https://<objects host>/<org>/<project>`. Absent when this installation has no public object front. */
6499
+ publicBase?: string;
6500
+ };
6501
+ StorageObjectSigned: {
6502
+ key: string;
6503
+ /** @description A signed GET. Fetch it directly; the bytes do not pass through this API. */
6504
+ url: string;
6505
+ /**
6506
+ * Format: date-time
6507
+ * @description When the signature stops working. It travels with the URL so a client does not learn the lifetime from documentation and then cache past it.
6508
+ */
6509
+ expiresAt: string;
6510
+ /** Format: int64 */
6511
+ size: number;
6512
+ type: string;
6513
+ /** Format: date-time */
6514
+ modified: string;
6515
+ public: boolean;
6516
+ };
6517
+ /** @description One end user of the app (`runlot_auth.users`, docs/auth.md §6). */
6518
+ AppUser: {
6519
+ /** Format: uuid */
6520
+ id: string;
6521
+ /** @description Lowercased. Empty for an account that has only a social identity. */
6522
+ email: string;
6523
+ name?: string;
6524
+ /** @description `password`, `github`, `google`, `kakao` … sorted, from the linked identities. */
6525
+ providers: string[];
6526
+ /** Format: date-time */
6527
+ createdAt: string;
6528
+ /**
6529
+ * Format: date-time
6530
+ * @description Absent for somebody who has never signed in.
6531
+ */
6532
+ lastSignIn?: string;
6533
+ /** @description `banned_at` is set. Changing it is not on this surface. */
6534
+ blocked: boolean;
6535
+ /** @description **Live** sessions only. Expired rows stay until the sweeper runs and counting them would show a signed-out person as signed in. */
6536
+ sessions: number;
6537
+ };
6538
+ AppUserPage: {
6539
+ users: components["schemas"]["AppUser"][];
6540
+ /** @description Pass it back to get the next page. Absent means the end. */
6541
+ cursor?: string;
6542
+ };
5926
6543
  AILedgerRow: {
5927
6544
  /** @enum {string} */
5928
6545
  kind: "call" | "topup" | "adjust";
6546
+ /**
6547
+ * @description Which caller spent it. It is present on every row including a top-up, where it
6548
+ * is `app` and means nothing.
6549
+ * @enum {string}
6550
+ */
6551
+ lane: "app" | "dev" | "studio";
5929
6552
  model?: string;
5930
6553
  project?: string;
5931
6554
  /** Format: int64 */
@@ -7177,6 +7800,327 @@ export interface operations {
7177
7800
  };
7178
7801
  };
7179
7802
  };
7803
+ oauthMetadata: {
7804
+ parameters: {
7805
+ query?: never;
7806
+ header?: never;
7807
+ path?: never;
7808
+ cookie?: never;
7809
+ };
7810
+ requestBody?: never;
7811
+ responses: {
7812
+ /** @description The metadata document */
7813
+ 200: {
7814
+ headers: {
7815
+ [name: string]: unknown;
7816
+ };
7817
+ content: {
7818
+ "application/json": {
7819
+ /** @example https://api.runlot.io */
7820
+ issuer: string;
7821
+ /** @example https://api.runlot.io/oauth/authorize */
7822
+ authorization_endpoint: string;
7823
+ /** @example https://api.runlot.io/oauth/token */
7824
+ token_endpoint: string;
7825
+ /** @example https://api.runlot.io/oauth/revoke */
7826
+ revocation_endpoint?: string;
7827
+ /** @example https://api.runlot.io/.well-known/jwks.json */
7828
+ jwks_uri: string;
7829
+ /**
7830
+ * @example [
7831
+ * "code"
7832
+ * ]
7833
+ */
7834
+ response_types_supported?: string[];
7835
+ /**
7836
+ * @example [
7837
+ * "authorization_code",
7838
+ * "refresh_token"
7839
+ * ]
7840
+ */
7841
+ grant_types_supported?: string[];
7842
+ /**
7843
+ * @description `S256` only. `plain` is not accepted and so is not advertised.
7844
+ * @example [
7845
+ * "S256"
7846
+ * ]
7847
+ */
7848
+ code_challenge_methods_supported?: string[];
7849
+ /**
7850
+ * @description `none`: the clients are public and PKCE takes the secret's place.
7851
+ * @example [
7852
+ * "none"
7853
+ * ]
7854
+ */
7855
+ token_endpoint_auth_methods_supported?: string[];
7856
+ scopes_supported?: components["schemas"]["ApiScope"][];
7857
+ /**
7858
+ * @example [
7859
+ * "EdDSA"
7860
+ * ]
7861
+ */
7862
+ access_token_signing_alg_values_supported?: string[];
7863
+ /** @description The `aud` every access token carries, and the one a resource server must require. */
7864
+ runlot_access_token_audience?: string;
7865
+ } & {
7866
+ [key: string]: unknown;
7867
+ };
7868
+ };
7869
+ };
7870
+ /** @description Connected-app sign-in is not configured on this deployment */
7871
+ 503: {
7872
+ headers: {
7873
+ [name: string]: unknown;
7874
+ };
7875
+ content: {
7876
+ "application/json": components["schemas"]["Error"];
7877
+ };
7878
+ };
7879
+ };
7880
+ };
7881
+ oauthJwks: {
7882
+ parameters: {
7883
+ query?: never;
7884
+ header?: never;
7885
+ path?: never;
7886
+ cookie?: never;
7887
+ };
7888
+ requestBody?: never;
7889
+ responses: {
7890
+ /** @description The key set */
7891
+ 200: {
7892
+ headers: {
7893
+ [name: string]: unknown;
7894
+ };
7895
+ content: {
7896
+ "application/json": {
7897
+ keys: ({
7898
+ kid?: string;
7899
+ /** @example OKP */
7900
+ kty?: string;
7901
+ /** @example Ed25519 */
7902
+ crv?: string;
7903
+ /** @example EdDSA */
7904
+ alg?: string;
7905
+ /** @example sig */
7906
+ use?: string;
7907
+ /** @description base64url of the public key */
7908
+ x?: string;
7909
+ } & {
7910
+ [key: string]: unknown;
7911
+ })[];
7912
+ };
7913
+ };
7914
+ };
7915
+ };
7916
+ };
7917
+ oauthAuthorize: {
7918
+ parameters: {
7919
+ query?: never;
7920
+ header?: never;
7921
+ path?: never;
7922
+ cookie?: never;
7923
+ };
7924
+ requestBody: {
7925
+ content: {
7926
+ "application/json": {
7927
+ /** @example studio-desktop */
7928
+ client_id: string;
7929
+ /** @description Must be registered for the client. It is **not** echoed in a refusal — that would make the endpoint a probe for accepted redirects. */
7930
+ redirect_uri: string;
7931
+ /** @enum {string} */
7932
+ response_type?: "code";
7933
+ /**
7934
+ * @description Space-separated. Empty means the client's whole set. A scope the client does not carry is an error, never a silent drop.
7935
+ * @example project:read deploy repo:read repo:write db:read
7936
+ */
7937
+ scope?: string;
7938
+ state?: string;
7939
+ code_challenge: string;
7940
+ /** @enum {string} */
7941
+ code_challenge_method: "S256";
7942
+ /**
7943
+ * @description Ours, not OAuth's: what Connected apps shows beside the client (docs/studio.md §8.1).
7944
+ * @example Ryan의 MacBook Pro
7945
+ */
7946
+ device_name?: string;
7947
+ };
7948
+ };
7949
+ };
7950
+ responses: {
7951
+ /** @description Approved. The browser is sent to `redirect`. */
7952
+ 200: {
7953
+ headers: {
7954
+ [name: string]: unknown;
7955
+ };
7956
+ content: {
7957
+ "application/json": {
7958
+ /** @description `redirect_uri` with `code` and `state`. */
7959
+ redirect: string;
7960
+ };
7961
+ };
7962
+ };
7963
+ 400: components["responses"]["BadRequest"];
7964
+ 401: components["responses"]["Unauthorized"];
7965
+ };
7966
+ };
7967
+ oauthToken: {
7968
+ parameters: {
7969
+ query?: never;
7970
+ header?: never;
7971
+ path?: never;
7972
+ cookie?: never;
7973
+ };
7974
+ requestBody: {
7975
+ content: {
7976
+ "application/x-www-form-urlencoded": {
7977
+ /** @enum {string} */
7978
+ grant_type: "authorization_code" | "refresh_token";
7979
+ client_id: string;
7980
+ /** @description `authorization_code` only. */
7981
+ code?: string;
7982
+ /** @description `authorization_code` only. PKCE, S256. */
7983
+ code_verifier?: string;
7984
+ /** @description `authorization_code` only. Must match the one the code was issued for. */
7985
+ redirect_uri?: string;
7986
+ /** @description `refresh_token` only. */
7987
+ refresh_token?: string;
7988
+ };
7989
+ };
7990
+ };
7991
+ responses: {
7992
+ /** @description A new access token, and the next refresh token */
7993
+ 200: {
7994
+ headers: {
7995
+ "Cache-Control"?: string;
7996
+ [name: string]: unknown;
7997
+ };
7998
+ content: {
7999
+ "application/json": components["schemas"]["OAuthTokenResponse"];
8000
+ };
8001
+ };
8002
+ /** @description RFC 6749 §5.2 */
8003
+ 400: {
8004
+ headers: {
8005
+ [name: string]: unknown;
8006
+ };
8007
+ content: {
8008
+ "application/json": components["schemas"]["OAuthError"];
8009
+ };
8010
+ };
8011
+ /** @description Too many attempts from this client or this address */
8012
+ 429: {
8013
+ headers: {
8014
+ [name: string]: unknown;
8015
+ };
8016
+ content: {
8017
+ "application/json": components["schemas"]["OAuthError"];
8018
+ };
8019
+ };
8020
+ /** @description Connected-app sign-in is not configured on this deployment */
8021
+ 503: {
8022
+ headers: {
8023
+ [name: string]: unknown;
8024
+ };
8025
+ content: {
8026
+ "application/json": components["schemas"]["OAuthError"];
8027
+ };
8028
+ };
8029
+ };
8030
+ };
8031
+ oauthRevoke: {
8032
+ parameters: {
8033
+ query?: never;
8034
+ header?: never;
8035
+ path?: never;
8036
+ cookie?: never;
8037
+ };
8038
+ requestBody: {
8039
+ content: {
8040
+ "application/x-www-form-urlencoded": {
8041
+ /** @description A refresh token or an access token. */
8042
+ token: string;
8043
+ /** @enum {string} */
8044
+ token_type_hint?: "refresh_token" | "access_token";
8045
+ client_id?: string;
8046
+ };
8047
+ };
8048
+ };
8049
+ responses: {
8050
+ /** @description Revoked, or the token was unknown — the two are deliberately the same answer */
8051
+ 200: {
8052
+ headers: {
8053
+ "Cache-Control"?: string;
8054
+ [name: string]: unknown;
8055
+ };
8056
+ content?: never;
8057
+ };
8058
+ /** @description RFC 6749 §5.2 */
8059
+ 400: {
8060
+ headers: {
8061
+ [name: string]: unknown;
8062
+ };
8063
+ content: {
8064
+ "application/json": components["schemas"]["OAuthError"];
8065
+ };
8066
+ };
8067
+ /** @description Too many attempts from this client or this address */
8068
+ 429: {
8069
+ headers: {
8070
+ [name: string]: unknown;
8071
+ };
8072
+ content: {
8073
+ "application/json": components["schemas"]["OAuthError"];
8074
+ };
8075
+ };
8076
+ };
8077
+ };
8078
+ listOAuthGrants: {
8079
+ parameters: {
8080
+ query?: never;
8081
+ header?: never;
8082
+ path?: never;
8083
+ cookie?: never;
8084
+ };
8085
+ requestBody?: never;
8086
+ responses: {
8087
+ /** @description The grants */
8088
+ 200: {
8089
+ headers: {
8090
+ [name: string]: unknown;
8091
+ };
8092
+ content: {
8093
+ "application/json": {
8094
+ grants: components["schemas"]["OAuthGrant"][];
8095
+ };
8096
+ };
8097
+ };
8098
+ 401: components["responses"]["Unauthorized"];
8099
+ };
8100
+ };
8101
+ revokeOAuthGrant: {
8102
+ parameters: {
8103
+ query?: never;
8104
+ header?: never;
8105
+ path: {
8106
+ /** @description The grant's session id, as `GET /v1/oauth/grants` returned it. */
8107
+ sid: string;
8108
+ };
8109
+ cookie?: never;
8110
+ };
8111
+ requestBody?: never;
8112
+ responses: {
8113
+ /** @description Removed */
8114
+ 204: {
8115
+ headers: {
8116
+ [name: string]: unknown;
8117
+ };
8118
+ content?: never;
8119
+ };
8120
+ 401: components["responses"]["Unauthorized"];
8121
+ 404: components["responses"]["NotFound"];
8122
+ };
8123
+ };
7180
8124
  getMe: {
7181
8125
  parameters: {
7182
8126
  query?: never;
@@ -7848,6 +8792,34 @@ export interface operations {
7848
8792
  };
7849
8793
  };
7850
8794
  };
8795
+ getDeployment: {
8796
+ parameters: {
8797
+ query?: never;
8798
+ header?: never;
8799
+ path: {
8800
+ orgSlug: components["parameters"]["OrgSlug"];
8801
+ projectName: components["parameters"]["ProjectName"];
8802
+ deploymentId: string;
8803
+ };
8804
+ cookie?: never;
8805
+ };
8806
+ requestBody?: never;
8807
+ responses: {
8808
+ /** @description The deployment */
8809
+ 200: {
8810
+ headers: {
8811
+ [name: string]: unknown;
8812
+ };
8813
+ content: {
8814
+ "application/json": components["schemas"]["Deployment"] & {
8815
+ migrations?: components["schemas"]["DeploymentMigrations"];
8816
+ };
8817
+ };
8818
+ };
8819
+ 403: components["responses"]["Forbidden"];
8820
+ 404: components["responses"]["NotFound"];
8821
+ };
8822
+ };
7851
8823
  getProjectCron: {
7852
8824
  parameters: {
7853
8825
  query?: {
@@ -8488,7 +9460,19 @@ export interface operations {
8488
9460
  "application/json": components["schemas"]["Error"];
8489
9461
  };
8490
9462
  };
8491
- 403: components["responses"]["Forbidden"];
9463
+ /**
9464
+ * @description `insufficient_scope` — the token carries neither `db:read` nor a wider scope; or
9465
+ * `console_write_needs_session` — `readOnly: false` from something other than a
9466
+ * dashboard session.
9467
+ */
9468
+ 403: {
9469
+ headers: {
9470
+ [name: string]: unknown;
9471
+ };
9472
+ content: {
9473
+ "application/json": components["schemas"]["Error"];
9474
+ };
9475
+ };
8492
9476
  404: components["responses"]["NotFound"];
8493
9477
  /** @description could not reach this project's database (`console_unreachable`) */
8494
9478
  502: {
@@ -9129,10 +10113,100 @@ export interface operations {
9129
10113
  headers: {
9130
10114
  [name: string]: unknown;
9131
10115
  };
9132
- content?: never;
10116
+ content?: never;
10117
+ };
10118
+ 403: components["responses"]["Forbidden"];
10119
+ 404: components["responses"]["NotFound"];
10120
+ /** @description `no_core` — the service is temporarily unavailable */
10121
+ 503: {
10122
+ headers: {
10123
+ [name: string]: unknown;
10124
+ };
10125
+ content: {
10126
+ "application/json": components["schemas"]["Error"];
10127
+ };
10128
+ };
10129
+ };
10130
+ };
10131
+ listStoragePublic: {
10132
+ parameters: {
10133
+ query?: never;
10134
+ header?: never;
10135
+ path: {
10136
+ orgSlug: components["parameters"]["OrgSlug"];
10137
+ projectName: components["parameters"]["ProjectName"];
10138
+ };
10139
+ cookie?: never;
10140
+ };
10141
+ requestBody?: never;
10142
+ responses: {
10143
+ /** @description The list */
10144
+ 200: {
10145
+ headers: {
10146
+ [name: string]: unknown;
10147
+ };
10148
+ content: {
10149
+ "application/json": components["schemas"]["StoragePublicList"];
10150
+ };
10151
+ };
10152
+ 403: components["responses"]["Forbidden"];
10153
+ 404: components["responses"]["NotFound"];
10154
+ /** @description `no_core` — the service is temporarily unavailable */
10155
+ 503: {
10156
+ headers: {
10157
+ [name: string]: unknown;
10158
+ };
10159
+ content: {
10160
+ "application/json": components["schemas"]["Error"];
10161
+ };
10162
+ };
10163
+ };
10164
+ };
10165
+ addStoragePublic: {
10166
+ parameters: {
10167
+ query?: never;
10168
+ header?: never;
10169
+ path: {
10170
+ orgSlug: components["parameters"]["OrgSlug"];
10171
+ projectName: components["parameters"]["ProjectName"];
10172
+ };
10173
+ cookie?: never;
10174
+ };
10175
+ requestBody: {
10176
+ content: {
10177
+ "application/json": components["schemas"]["StoragePublicRequest"];
10178
+ };
10179
+ };
10180
+ responses: {
10181
+ /** @description The list after the change */
10182
+ 200: {
10183
+ headers: {
10184
+ [name: string]: unknown;
10185
+ };
10186
+ content: {
10187
+ "application/json": components["schemas"]["StoragePublicList"];
10188
+ };
10189
+ };
10190
+ /** @description The prefix is empty, not normalizable, or would leave the project's slice */
10191
+ 400: {
10192
+ headers: {
10193
+ [name: string]: unknown;
10194
+ };
10195
+ content: {
10196
+ "application/json": components["schemas"]["Error"];
10197
+ };
10198
+ };
10199
+ 403: components["responses"]["Forbidden"];
10200
+ 404: components["responses"]["NotFound"];
10201
+ /** @description `storage_not_granted`, or `too_many_public_prefixes` */
10202
+ 409: {
10203
+ headers: {
10204
+ [name: string]: unknown;
10205
+ };
10206
+ content: {
10207
+ "application/json": components["schemas"]["Error"];
10208
+ };
9133
10209
  };
9134
- 403: components["responses"]["Forbidden"];
9135
- 404: components["responses"]["NotFound"];
9136
10210
  /** @description `no_core` — the service is temporarily unavailable */
9137
10211
  503: {
9138
10212
  headers: {
@@ -9144,7 +10218,7 @@ export interface operations {
9144
10218
  };
9145
10219
  };
9146
10220
  };
9147
- listStoragePublic: {
10221
+ removeStoragePublic: {
9148
10222
  parameters: {
9149
10223
  query?: never;
9150
10224
  header?: never;
@@ -9154,9 +10228,13 @@ export interface operations {
9154
10228
  };
9155
10229
  cookie?: never;
9156
10230
  };
9157
- requestBody?: never;
10231
+ requestBody: {
10232
+ content: {
10233
+ "application/json": components["schemas"]["StoragePublicRequest"];
10234
+ };
10235
+ };
9158
10236
  responses: {
9159
- /** @description The list */
10237
+ /** @description The list after the change */
9160
10238
  200: {
9161
10239
  headers: {
9162
10240
  [name: string]: unknown;
@@ -9165,6 +10243,15 @@ export interface operations {
9165
10243
  "application/json": components["schemas"]["StoragePublicList"];
9166
10244
  };
9167
10245
  };
10246
+ /** @description The prefix is empty or not normalizable */
10247
+ 400: {
10248
+ headers: {
10249
+ [name: string]: unknown;
10250
+ };
10251
+ content: {
10252
+ "application/json": components["schemas"]["Error"];
10253
+ };
10254
+ };
9168
10255
  403: components["responses"]["Forbidden"];
9169
10256
  404: components["responses"]["NotFound"];
9170
10257
  /** @description `no_core` — the service is temporarily unavailable */
@@ -9178,9 +10265,16 @@ export interface operations {
9178
10265
  };
9179
10266
  };
9180
10267
  };
9181
- addStoragePublic: {
10268
+ listStorageObjects: {
9182
10269
  parameters: {
9183
- query?: never;
10270
+ query?: {
10271
+ /** @description Key prefix to list under. It is normalized the same way a published prefix is: `assets` becomes `assets/`, and empty means the project root. */
10272
+ prefix?: string;
10273
+ /** @description the `cursor` of the previous page */
10274
+ cursor?: string;
10275
+ /** @description entries plus prefixes on one page */
10276
+ limit?: number;
10277
+ };
9184
10278
  header?: never;
9185
10279
  path: {
9186
10280
  orgSlug: components["parameters"]["OrgSlug"];
@@ -9188,22 +10282,18 @@ export interface operations {
9188
10282
  };
9189
10283
  cookie?: never;
9190
10284
  };
9191
- requestBody: {
9192
- content: {
9193
- "application/json": components["schemas"]["StoragePublicRequest"];
9194
- };
9195
- };
10285
+ requestBody?: never;
9196
10286
  responses: {
9197
- /** @description The list after the change */
10287
+ /** @description One page */
9198
10288
  200: {
9199
10289
  headers: {
9200
10290
  [name: string]: unknown;
9201
10291
  };
9202
10292
  content: {
9203
- "application/json": components["schemas"]["StoragePublicList"];
10293
+ "application/json": components["schemas"]["StorageObjectPage"];
9204
10294
  };
9205
10295
  };
9206
- /** @description The prefix is empty, not normalizable, or would leave the project's slice */
10296
+ /** @description `prefix` is not normalizable, or `limit` is out of range */
9207
10297
  400: {
9208
10298
  headers: {
9209
10299
  [name: string]: unknown;
@@ -9214,7 +10304,7 @@ export interface operations {
9214
10304
  };
9215
10305
  403: components["responses"]["Forbidden"];
9216
10306
  404: components["responses"]["NotFound"];
9217
- /** @description `storage_not_granted`, or `too_many_public_prefixes` */
10307
+ /** @description `storage_not_granted` — this project has no file storage */
9218
10308
  409: {
9219
10309
  headers: {
9220
10310
  [name: string]: unknown;
@@ -9223,7 +10313,16 @@ export interface operations {
9223
10313
  "application/json": components["schemas"]["Error"];
9224
10314
  };
9225
10315
  };
9226
- /** @description `no_core` — the service is temporarily unavailable */
10316
+ /** @description `objects_unreachable` — the object store did not answer */
10317
+ 502: {
10318
+ headers: {
10319
+ [name: string]: unknown;
10320
+ };
10321
+ content: {
10322
+ "application/json": components["schemas"]["Error"];
10323
+ };
10324
+ };
10325
+ /** @description `objects_unavailable` — this installation has no object store; or `no_core` */
9227
10326
  503: {
9228
10327
  headers: {
9229
10328
  [name: string]: unknown;
@@ -9234,32 +10333,30 @@ export interface operations {
9234
10333
  };
9235
10334
  };
9236
10335
  };
9237
- removeStoragePublic: {
10336
+ signStorageObject: {
9238
10337
  parameters: {
9239
10338
  query?: never;
9240
10339
  header?: never;
9241
10340
  path: {
9242
10341
  orgSlug: components["parameters"]["OrgSlug"];
9243
10342
  projectName: components["parameters"]["ProjectName"];
10343
+ /** @description The object key. It may contain `/`; the segments are part of the path. */
10344
+ key: string;
9244
10345
  };
9245
10346
  cookie?: never;
9246
10347
  };
9247
- requestBody: {
9248
- content: {
9249
- "application/json": components["schemas"]["StoragePublicRequest"];
9250
- };
9251
- };
10348
+ requestBody?: never;
9252
10349
  responses: {
9253
- /** @description The list after the change */
10350
+ /** @description The signed URL and the object's metadata */
9254
10351
  200: {
9255
10352
  headers: {
9256
10353
  [name: string]: unknown;
9257
10354
  };
9258
10355
  content: {
9259
- "application/json": components["schemas"]["StoragePublicList"];
10356
+ "application/json": components["schemas"]["StorageObjectSigned"];
9260
10357
  };
9261
10358
  };
9262
- /** @description The prefix is empty or not normalizable */
10359
+ /** @description the key is empty, escapes the project prefix, or is over 1024 bytes */
9263
10360
  400: {
9264
10361
  headers: {
9265
10362
  [name: string]: unknown;
@@ -9270,7 +10367,16 @@ export interface operations {
9270
10367
  };
9271
10368
  403: components["responses"]["Forbidden"];
9272
10369
  404: components["responses"]["NotFound"];
9273
- /** @description `no_core` — the service is temporarily unavailable */
10370
+ /** @description `storage_not_granted` — this project has no file storage */
10371
+ 409: {
10372
+ headers: {
10373
+ [name: string]: unknown;
10374
+ };
10375
+ content: {
10376
+ "application/json": components["schemas"]["Error"];
10377
+ };
10378
+ };
10379
+ /** @description `objects_unavailable` — this installation has no object store; or `no_core` */
9274
10380
  503: {
9275
10381
  headers: {
9276
10382
  [name: string]: unknown;
@@ -9443,6 +10549,25 @@ export interface operations {
9443
10549
  limit?: number;
9444
10550
  /** @description rows before this ledger_id */
9445
10551
  before?: number;
10552
+ /**
10553
+ * @description Only rows spent by this lane. `app` is the deployed worker's `env.ai`, `dev` is
10554
+ * the same app running on a developer's machine or tab, and `studio` is Studio's
10555
+ * own agent turns. Absent means every lane; an unknown value is a 400 rather than
10556
+ * an empty page.
10557
+ */
10558
+ lane?: "app" | "dev" | "studio";
10559
+ /**
10560
+ * @description Only rows of this kind. `kind=topup&limit=1` is the last top-up, which is
10561
+ * otherwise an unbounded walk backwards through a busy day's calls. An unknown
10562
+ * value is a 400.
10563
+ */
10564
+ kind?: "call" | "topup" | "adjust";
10565
+ /**
10566
+ * @description Only rows at or after this instant (RFC 3339). It is an instant and not a
10567
+ * date on purpose: the day boundary belongs to the caller, whose midnight is
10568
+ * their own zone's. A value that is not RFC 3339 is a 400.
10569
+ */
10570
+ since?: string;
9446
10571
  };
9447
10572
  header?: never;
9448
10573
  path: {
@@ -10196,6 +11321,110 @@ export interface operations {
10196
11321
  };
10197
11322
  };
10198
11323
  };
11324
+ listAppUsers: {
11325
+ parameters: {
11326
+ query?: {
11327
+ /** @description matches the email or the name, case-insensitively */
11328
+ search?: string;
11329
+ /** @description the `cursor` of the previous page */
11330
+ cursor?: string;
11331
+ limit?: number;
11332
+ };
11333
+ header?: never;
11334
+ path: {
11335
+ orgSlug: components["parameters"]["OrgSlug"];
11336
+ projectName: components["parameters"]["ProjectName"];
11337
+ };
11338
+ cookie?: never;
11339
+ };
11340
+ requestBody?: never;
11341
+ responses: {
11342
+ /** @description One page */
11343
+ 200: {
11344
+ headers: {
11345
+ [name: string]: unknown;
11346
+ };
11347
+ content: {
11348
+ "application/json": components["schemas"]["AppUserPage"];
11349
+ };
11350
+ };
11351
+ /** @description `cursor` is not one this endpoint issued, or `limit` is out of range */
11352
+ 400: {
11353
+ headers: {
11354
+ [name: string]: unknown;
11355
+ };
11356
+ content: {
11357
+ "application/json": components["schemas"]["Error"];
11358
+ };
11359
+ };
11360
+ 403: components["responses"]["Forbidden"];
11361
+ /** @description no such project, or the project has no database (so it can have no users) */
11362
+ 404: {
11363
+ headers: {
11364
+ [name: string]: unknown;
11365
+ };
11366
+ content: {
11367
+ "application/json": components["schemas"]["Error"];
11368
+ };
11369
+ };
11370
+ /** @description could not reach this project's database (`console_unreachable`) */
11371
+ 502: {
11372
+ headers: {
11373
+ [name: string]: unknown;
11374
+ };
11375
+ content?: never;
11376
+ };
11377
+ /** @description the database did not answer within the round-trip deadline (`console_timeout`) */
11378
+ 504: {
11379
+ headers: {
11380
+ [name: string]: unknown;
11381
+ };
11382
+ content?: never;
11383
+ };
11384
+ };
11385
+ };
11386
+ getAppUser: {
11387
+ parameters: {
11388
+ query?: never;
11389
+ header?: never;
11390
+ path: {
11391
+ orgSlug: components["parameters"]["OrgSlug"];
11392
+ projectName: components["parameters"]["ProjectName"];
11393
+ userId: string;
11394
+ };
11395
+ cookie?: never;
11396
+ };
11397
+ requestBody?: never;
11398
+ responses: {
11399
+ /** @description The user */
11400
+ 200: {
11401
+ headers: {
11402
+ [name: string]: unknown;
11403
+ };
11404
+ content: {
11405
+ "application/json": components["schemas"]["AppUser"];
11406
+ };
11407
+ };
11408
+ /** @description `userId` is not a uuid */
11409
+ 400: {
11410
+ headers: {
11411
+ [name: string]: unknown;
11412
+ };
11413
+ content: {
11414
+ "application/json": components["schemas"]["Error"];
11415
+ };
11416
+ };
11417
+ 403: components["responses"]["Forbidden"];
11418
+ 404: components["responses"]["NotFound"];
11419
+ /** @description could not reach this project's database (`console_unreachable`) */
11420
+ 502: {
11421
+ headers: {
11422
+ [name: string]: unknown;
11423
+ };
11424
+ content?: never;
11425
+ };
11426
+ };
11427
+ };
10199
11428
  getAccess: {
10200
11429
  parameters: {
10201
11430
  query?: never;
@@ -12772,5 +14001,103 @@ export interface operations {
12772
14001
  };
12773
14002
  };
12774
14003
  };
14004
+ getShareLink: {
14005
+ parameters: {
14006
+ query?: never;
14007
+ header?: never;
14008
+ path: {
14009
+ orgSlug: components["parameters"]["OrgSlug"];
14010
+ projectName: components["parameters"]["ProjectName"];
14011
+ };
14012
+ cookie?: never;
14013
+ };
14014
+ requestBody?: never;
14015
+ responses: {
14016
+ /** @description The share link */
14017
+ 200: {
14018
+ headers: {
14019
+ [name: string]: unknown;
14020
+ };
14021
+ content: {
14022
+ "application/json": components["schemas"]["ShareLink"];
14023
+ };
14024
+ };
14025
+ 403: components["responses"]["Forbidden"];
14026
+ 404: components["responses"]["NotFound"];
14027
+ };
14028
+ };
14029
+ putShareLink: {
14030
+ parameters: {
14031
+ query?: never;
14032
+ header?: never;
14033
+ path: {
14034
+ orgSlug: components["parameters"]["OrgSlug"];
14035
+ projectName: components["parameters"]["ProjectName"];
14036
+ };
14037
+ cookie?: never;
14038
+ };
14039
+ requestBody?: {
14040
+ content: {
14041
+ "application/json": {
14042
+ /**
14043
+ * @description Which preview the link resolves to. Default `studio` — the single slug
14044
+ * Studio shares `main` from, which is what makes every share of main count
14045
+ * as one preview against the plan.
14046
+ */
14047
+ preview?: components["schemas"]["Slug"];
14048
+ /**
14049
+ * @description Mint a new label and retire the old one.
14050
+ * @default false
14051
+ */
14052
+ rotate?: boolean;
14053
+ };
14054
+ };
14055
+ };
14056
+ responses: {
14057
+ /** @description The share link */
14058
+ 200: {
14059
+ headers: {
14060
+ [name: string]: unknown;
14061
+ };
14062
+ content: {
14063
+ "application/json": components["schemas"]["ShareLink"];
14064
+ };
14065
+ };
14066
+ 400: components["responses"]["BadRequest"];
14067
+ 403: components["responses"]["Forbidden"];
14068
+ /** @description The project, or the named preview, does not exist */
14069
+ 404: {
14070
+ headers: {
14071
+ [name: string]: unknown;
14072
+ };
14073
+ content: {
14074
+ "application/json": components["schemas"]["Error"];
14075
+ };
14076
+ };
14077
+ };
14078
+ };
14079
+ deleteShareLink: {
14080
+ parameters: {
14081
+ query?: never;
14082
+ header?: never;
14083
+ path: {
14084
+ orgSlug: components["parameters"]["OrgSlug"];
14085
+ projectName: components["parameters"]["ProjectName"];
14086
+ };
14087
+ cookie?: never;
14088
+ };
14089
+ requestBody?: never;
14090
+ responses: {
14091
+ /** @description No longer shared */
14092
+ 204: {
14093
+ headers: {
14094
+ [name: string]: unknown;
14095
+ };
14096
+ content?: never;
14097
+ };
14098
+ 403: components["responses"]["Forbidden"];
14099
+ 404: components["responses"]["NotFound"];
14100
+ };
14101
+ };
12775
14102
  }
12776
14103
  //# sourceMappingURL=schema.d.ts.map