@krovacloud/sdk 0.4.0 → 0.4.2

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/index.d.ts CHANGED
@@ -1,2040 +1,2041 @@
1
- import { Client } from 'openapi-fetch';
2
-
1
+ import { Client } from "openapi-fetch";
2
+ //#region src/generated/types.d.ts
3
3
  /**
4
4
  * This file was auto-generated by openapi-typescript.
5
5
  * Do not make direct changes to the file.
6
6
  */
7
7
  interface paths {
8
- "/regions": {
9
- parameters: {
10
- query?: never;
11
- header?: never;
12
- path?: never;
13
- cookie?: never;
14
- };
15
- /** List regions with available capacity */
16
- get: {
17
- parameters: {
18
- query?: never;
19
- header?: never;
20
- path?: never;
21
- cookie?: never;
22
- };
23
- requestBody?: never;
24
- responses: {
25
- /** @description Region list */
26
- 200: {
27
- headers: {
28
- [name: string]: unknown;
29
- };
30
- content: {
31
- "application/json": {
32
- regions: components["schemas"]["Region"][];
33
- };
34
- };
35
- };
36
- };
37
- };
38
- put?: never;
39
- post?: never;
40
- delete?: never;
41
- options?: never;
42
- head?: never;
43
- patch?: never;
44
- trace?: never;
45
- };
46
- "/images": {
47
- parameters: {
48
- query?: never;
49
- header?: never;
50
- path?: never;
51
- cookie?: never;
52
- };
53
- /** List available OS images */
54
- get: {
55
- parameters: {
56
- query?: never;
57
- header?: never;
58
- path?: never;
59
- cookie?: never;
60
- };
61
- requestBody?: never;
62
- responses: {
63
- /** @description Image list */
64
- 200: {
65
- headers: {
66
- [name: string]: unknown;
67
- };
68
- content: {
69
- "application/json": {
70
- images: components["schemas"]["Image"][];
71
- };
72
- };
73
- };
74
- };
75
- };
76
- put?: never;
77
- post?: never;
78
- delete?: never;
79
- options?: never;
80
- head?: never;
81
- patch?: never;
82
- trace?: never;
83
- };
84
- "/pricing": {
85
- parameters: {
86
- query?: never;
87
- header?: never;
88
- path?: never;
89
- cookie?: never;
90
- };
91
- /** Per-resource hourly rates and volume pricing tiers */
92
- get: {
93
- parameters: {
94
- query?: never;
95
- header?: never;
96
- path?: never;
97
- cookie?: never;
98
- };
99
- requestBody?: never;
100
- responses: {
101
- /** @description Pricing data */
102
- 200: {
103
- headers: {
104
- [name: string]: unknown;
105
- };
106
- content: {
107
- "application/json": {
108
- currency: string;
109
- rates: {
110
- vcpuPerHour: number;
111
- ramGbPerHour: number;
112
- diskGbPerHour: number;
113
- };
114
- tiers: components["schemas"]["PricingTier"][];
115
- note: string;
116
- };
117
- };
118
- };
119
- };
120
- };
121
- put?: never;
122
- post?: never;
123
- delete?: never;
124
- options?: never;
125
- head?: never;
126
- patch?: never;
127
- trace?: never;
128
- };
129
- "/auth/cli/start": {
130
- parameters: {
131
- query?: never;
132
- header?: never;
133
- path?: never;
134
- cookie?: never;
135
- };
136
- get?: never;
137
- put?: never;
138
- /**
139
- * Begin a CLI device-authorization login (RFC 8628)
140
- * @description Public, unauthenticated. Mints a device code (returned once) and a short human user code, and returns the verification URIs the user opens in a browser to approve. The CLI then polls /auth/cli/poll. Rate-limited per client IP.
141
- */
142
- post: {
143
- parameters: {
144
- query?: never;
145
- header?: never;
146
- path?: never;
147
- cookie?: never;
148
- };
149
- requestBody?: never;
150
- responses: {
151
- /** @description Device-authorization request created */
152
- 200: {
153
- headers: {
154
- [name: string]: unknown;
155
- };
156
- content: {
157
- "application/json": {
158
- /** @description High-entropy code the CLI keeps secret and presents on each poll. Only its hash is stored server-side. */
159
- deviceCode: string;
160
- /** @description Short human-readable code (KROVA-XXXX-XXXX) the user confirms in the browser. */
161
- userCode: string;
162
- /**
163
- * Format: uri
164
- * @description Browser URL where the user approves.
165
- */
166
- verificationUri: string;
167
- /**
168
- * Format: uri
169
- * @description verificationUri with the user code pre-filled.
170
- */
171
- verificationUriComplete: string;
172
- /** @description Seconds to wait between polls. */
173
- interval: number;
174
- /** @description Seconds until the device code expires (~600). */
175
- expiresIn: number;
176
- };
177
- };
178
- };
179
- 429: components["responses"]["RateLimited"];
180
- /** @description Could not allocate a login code; retry */
181
- 503: {
182
- headers: {
183
- [name: string]: unknown;
184
- };
185
- content?: never;
186
- };
187
- };
188
- };
189
- delete?: never;
190
- options?: never;
191
- head?: never;
192
- patch?: never;
193
- trace?: never;
194
- };
195
- "/auth/cli/poll": {
196
- parameters: {
197
- query?: never;
198
- header?: never;
199
- path?: never;
200
- cookie?: never;
201
- };
202
- get?: never;
203
- put?: never;
204
- /**
205
- * Poll for CLI device-authorization approval (RFC 8628)
206
- * @description Public, unauthenticated. The CLI submits its deviceCode until the user approves or denies. On approval a real API key is minted ONCE, scoped to the approved Space and the approving user's membership, and returned a single time. Rate-limited per client IP.
207
- */
208
- post: {
209
- parameters: {
210
- query?: never;
211
- header?: never;
212
- path?: never;
213
- cookie?: never;
214
- };
215
- requestBody: {
216
- content: {
217
- "application/json": {
218
- /** @description The device code from /auth/cli/start. */
219
- deviceCode: string;
220
- };
221
- };
222
- };
223
- responses: {
224
- /** @description Approved — API key minted (returned once) */
225
- 200: {
226
- headers: {
227
- [name: string]: unknown;
228
- };
229
- content: {
230
- "application/json": {
231
- /** @description The full API key. Shown once and never returned again — store it securely. */
232
- apiKey: string;
233
- /** @description The Space the key is scoped to. */
234
- spaceId: string;
235
- };
236
- };
237
- };
238
- 400: components["responses"]["BadRequest"];
239
- /** @description The user denied the login request */
240
- 403: {
241
- headers: {
242
- [name: string]: unknown;
243
- };
244
- content?: never;
245
- };
246
- /** @description The device code expired, was already consumed, or is unknown */
247
- 410: {
248
- headers: {
249
- [name: string]: unknown;
250
- };
251
- content?: never;
252
- };
253
- /** @description Authorization still pending — keep polling at the given interval */
254
- 428: {
255
- headers: {
256
- [name: string]: unknown;
257
- };
258
- content?: never;
259
- };
260
- 429: components["responses"]["RateLimited"];
261
- };
262
- };
263
- delete?: never;
264
- options?: never;
265
- head?: never;
266
- patch?: never;
267
- trace?: never;
268
- };
269
- "/space": {
270
- parameters: {
271
- query?: never;
272
- header?: never;
273
- path?: never;
274
- cookie?: never;
275
- };
276
- /**
277
- * Resolve the space this API key is scoped to
278
- * @description Returns the single space the API key belongs to. Lets a client auto-resolve the space id from the key alone (no spaceId in the URL).
279
- */
280
- get: {
281
- parameters: {
282
- query?: never;
283
- header?: never;
284
- path?: never;
285
- cookie?: never;
286
- };
287
- requestBody?: never;
288
- responses: {
289
- /** @description The key's space */
290
- 200: {
291
- headers: {
292
- [name: string]: unknown;
293
- };
294
- content: {
295
- "application/json": components["schemas"]["Space"];
296
- };
297
- };
298
- 401: components["responses"]["Unauthorized"];
299
- 404: components["responses"]["NotFound"];
300
- };
301
- };
302
- put?: never;
303
- post?: never;
304
- delete?: never;
305
- options?: never;
306
- head?: never;
307
- patch?: never;
308
- trace?: never;
309
- };
310
- "/spaces/{spaceId}/cubes": {
311
- parameters: {
312
- query?: never;
313
- header?: never;
314
- path?: never;
315
- cookie?: never;
316
- };
317
- /** List Cubes in a Space */
318
- get: {
319
- parameters: {
320
- query?: never;
321
- header?: never;
322
- path: {
323
- spaceId: string;
324
- };
325
- cookie?: never;
326
- };
327
- requestBody?: never;
328
- responses: {
329
- /** @description Paginated Cube list */
330
- 200: {
331
- headers: {
332
- [name: string]: unknown;
333
- };
334
- content: {
335
- "application/json": {
336
- cubes: components["schemas"]["Cube"][];
337
- pagination: components["schemas"]["Pagination"];
338
- };
339
- };
340
- };
341
- 401: components["responses"]["Unauthorized"];
342
- 403: components["responses"]["Forbidden"];
343
- };
344
- };
345
- put?: never;
346
- /** Create a Cube */
347
- post: {
348
- parameters: {
349
- query?: never;
350
- header?: {
351
- /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
352
- "Idempotency-Key"?: string;
353
- };
354
- path: {
355
- spaceId: string;
356
- };
357
- cookie?: never;
358
- };
359
- requestBody: {
360
- content: {
361
- "application/json": {
362
- name: string;
363
- image: string;
364
- resources: {
365
- vcpu: number;
366
- ramGb: number;
367
- diskGb: number;
368
- };
369
- /** @description SSH public key written to the Cube login user's authorized_keys at boot (~/.ssh/authorized_keys for the ubuntu or debian user; /root/.ssh/authorized_keys on Cubes created before the default-user change). GET /cubes/{cubeId}/ssh reports the login user for a given Cube. Must start with ssh-ed25519, ssh-rsa, ecdsa-sha2-*, ssh-dss, or sk-*@openssh.com. */
370
- sshPublicKey: string;
371
- /** @description Region slug from /v1/regions (optional). */
372
- region?: string;
373
- /** @description cloud-init script (max 16 KB, optional). */
374
- userData?: string;
375
- };
376
- };
377
- };
378
- responses: {
379
- /** @description Cube created */
380
- 201: {
381
- headers: {
382
- [name: string]: unknown;
383
- };
384
- content: {
385
- "application/json": {
386
- cube?: components["schemas"]["Cube"];
387
- };
388
- };
389
- };
390
- 400: components["responses"]["BadRequest"];
391
- 401: components["responses"]["Unauthorized"];
392
- 403: components["responses"]["Forbidden"];
393
- 429: components["responses"]["RateLimited"];
394
- };
395
- };
396
- delete?: never;
397
- options?: never;
398
- head?: never;
399
- patch?: never;
400
- trace?: never;
401
- };
402
- "/spaces/{spaceId}/cubes/{cubeId}": {
403
- parameters: {
404
- query?: never;
405
- header?: never;
406
- path?: never;
407
- cookie?: never;
408
- };
409
- /** Get a Cube */
410
- get: {
411
- parameters: {
412
- query?: never;
413
- header?: never;
414
- path: {
415
- spaceId: string;
416
- cubeId: string;
417
- };
418
- cookie?: never;
419
- };
420
- requestBody?: never;
421
- responses: {
422
- /** @description Cube */
423
- 200: {
424
- headers: {
425
- [name: string]: unknown;
426
- };
427
- content: {
428
- "application/json": {
429
- cube: components["schemas"]["Cube"];
430
- };
431
- };
432
- };
433
- 404: components["responses"]["NotFound"];
434
- };
435
- };
436
- put?: never;
437
- post?: never;
438
- /** Delete a Cube (asynchronous) */
439
- delete: {
440
- parameters: {
441
- query?: never;
442
- header?: never;
443
- path: {
444
- spaceId: string;
445
- cubeId: string;
446
- };
447
- cookie?: never;
448
- };
449
- requestBody?: never;
450
- responses: {
451
- /** @description Deletion enqueued */
452
- 200: {
453
- headers: {
454
- [name: string]: unknown;
455
- };
456
- content: {
457
- "application/json": {
458
- success: boolean;
459
- };
460
- };
461
- };
462
- 404: components["responses"]["NotFound"];
463
- 429: components["responses"]["RateLimited"];
464
- };
465
- };
466
- options?: never;
467
- head?: never;
468
- patch?: never;
469
- trace?: never;
470
- };
471
- "/spaces/{spaceId}/cubes/{cubeId}/power-off": {
472
- parameters: {
473
- query?: never;
474
- header?: never;
475
- path?: never;
476
- cookie?: never;
477
- };
478
- get?: never;
479
- put?: never;
480
- /** Power off a running Cube */
481
- post: {
482
- parameters: {
483
- query?: never;
484
- header?: never;
485
- path: {
486
- spaceId: string;
487
- cubeId: string;
488
- };
489
- cookie?: never;
490
- };
491
- requestBody?: never;
492
- responses: {
493
- /** @description Power off enqueued */
494
- 200: {
495
- headers: {
496
- [name: string]: unknown;
497
- };
498
- content?: never;
499
- };
500
- 404: components["responses"]["NotFound"];
501
- 429: components["responses"]["RateLimited"];
502
- };
503
- };
504
- delete?: never;
505
- options?: never;
506
- head?: never;
507
- patch?: never;
508
- trace?: never;
509
- };
510
- "/spaces/{spaceId}/cubes/{cubeId}/wake": {
511
- parameters: {
512
- query?: never;
513
- header?: never;
514
- path?: never;
515
- cookie?: never;
516
- };
517
- get?: never;
518
- put?: never;
519
- /** Start a stopped Cube */
520
- post: {
521
- parameters: {
522
- query?: never;
523
- header?: never;
524
- path: {
525
- spaceId: string;
526
- cubeId: string;
527
- };
528
- cookie?: never;
529
- };
530
- requestBody?: never;
531
- responses: {
532
- /** @description Start enqueued */
533
- 200: {
534
- headers: {
535
- [name: string]: unknown;
536
- };
537
- content?: never;
538
- };
539
- 404: components["responses"]["NotFound"];
540
- 429: components["responses"]["RateLimited"];
541
- };
542
- };
543
- delete?: never;
544
- options?: never;
545
- head?: never;
546
- patch?: never;
547
- trace?: never;
548
- };
549
- "/spaces/{spaceId}/cubes/{cubeId}/restart": {
550
- parameters: {
551
- query?: never;
552
- header?: never;
553
- path?: never;
554
- cookie?: never;
555
- };
556
- get?: never;
557
- put?: never;
558
- /**
559
- * Restart a running Cube
560
- * @description Cold-restarts the Cube: the hypervisor process is stopped and relaunched, so the Cube boots against the host's current kernel. This is how a Cube picks up a refreshed guest kernel after a platform image update — a `reboot` issued inside the Cube cannot do it, because the kernel is supplied externally by the host. Disk state is preserved; only the kernel changes. Cube must be `running` (a stopped Cube already picks up the latest kernel when started). Concurrent restarts of the same Cube are rejected with 409 rather than queued twice.
561
- */
562
- post: {
563
- parameters: {
564
- query?: never;
565
- header?: never;
566
- path: {
567
- spaceId: string;
568
- cubeId: string;
569
- };
570
- cookie?: never;
571
- };
572
- requestBody?: never;
573
- responses: {
574
- /** @description Restart enqueued */
575
- 200: {
576
- headers: {
577
- [name: string]: unknown;
578
- };
579
- content?: never;
580
- };
581
- 404: components["responses"]["NotFound"];
582
- /** @description Cube is not running, or a restart is already in progress */
583
- 409: {
584
- headers: {
585
- [name: string]: unknown;
586
- };
587
- content?: never;
588
- };
589
- 429: components["responses"]["RateLimited"];
590
- };
591
- };
592
- delete?: never;
593
- options?: never;
594
- head?: never;
595
- patch?: never;
596
- trace?: never;
597
- };
598
- "/spaces/{spaceId}/cubes/{cubeId}/ssh-port": {
599
- parameters: {
600
- query?: never;
601
- header?: never;
602
- path?: never;
603
- cookie?: never;
604
- };
605
- get?: never;
606
- /**
607
- * Change a Cube's SSH port
608
- * @description Sets the port INSIDE the Cube that SSH is forwarded to — NOT the host port you connect to. The host port is allocated by Krova and is unchanged by this call. Pointing this at a port nothing is listening on inside the Cube will make SSH unreachable; the default is 22. The change is applied atomically (the old port mapping is replaced).
609
- */
610
- put: {
611
- parameters: {
612
- query?: never;
613
- header?: never;
614
- path: {
615
- spaceId: string;
616
- cubeId: string;
617
- };
618
- cookie?: never;
619
- };
620
- requestBody: {
621
- content: {
622
- "application/json": {
623
- /** @description The port inside the Cube that sshd listens on (default 22). This is the Cube side of the mapping, not the host port. */
624
- cubePort: number;
625
- };
626
- };
627
- };
628
- responses: {
629
- /** @description SSH port updated */
630
- 200: {
631
- headers: {
632
- [name: string]: unknown;
633
- };
634
- content?: never;
635
- };
636
- 400: components["responses"]["BadRequest"];
637
- 404: components["responses"]["NotFound"];
638
- 429: components["responses"]["RateLimited"];
639
- };
640
- };
641
- post?: never;
642
- delete?: never;
643
- options?: never;
644
- head?: never;
645
- patch?: never;
646
- trace?: never;
647
- };
648
- "/spaces/{spaceId}/cubes/{cubeId}/ssh": {
649
- parameters: {
650
- query?: never;
651
- header?: never;
652
- path?: never;
653
- cookie?: never;
654
- };
655
- /**
656
- * Get a Cube's SSH connection info
657
- * @description Host (server public IPv4), host SSH port, login user, and the Cube's captured SSH host public keys. **Use `user` rather than assuming a username** — it is `ubuntu` or `debian` on Cubes created from images that ship a default user, and `root` on Cubes created before that change or imported from a rootfs without one. `hostKeys` is empty only until the reachability cron makes its first capture; clients fall back to trust-on-first-use until then, and pin strictly afterwards.
658
- */
659
- get: {
660
- parameters: {
661
- query?: never;
662
- header?: never;
663
- path: {
664
- spaceId: string;
665
- cubeId: string;
666
- };
667
- cookie?: never;
668
- };
669
- requestBody?: never;
670
- responses: {
671
- /** @description SSH connection info */
672
- 200: {
673
- headers: {
674
- [name: string]: unknown;
675
- };
676
- content: {
677
- "application/json": components["schemas"]["CubeSshInfo"];
678
- };
679
- };
680
- 404: components["responses"]["NotFound"];
681
- };
682
- };
683
- put?: never;
684
- post?: never;
685
- delete?: never;
686
- options?: never;
687
- head?: never;
688
- patch?: never;
689
- trace?: never;
690
- };
691
- "/spaces/{spaceId}/cubes/{cubeId}/domains": {
692
- parameters: {
693
- query?: never;
694
- header?: never;
695
- path?: never;
696
- cookie?: never;
697
- };
698
- /** List custom domains attached to a Cube */
699
- get: {
700
- parameters: {
701
- query?: never;
702
- header?: never;
703
- path: {
704
- spaceId: string;
705
- cubeId: string;
706
- };
707
- cookie?: never;
708
- };
709
- requestBody?: never;
710
- responses: {
711
- /** @description Domain list */
712
- 200: {
713
- headers: {
714
- [name: string]: unknown;
715
- };
716
- content: {
717
- "application/json": {
718
- domains: components["schemas"]["Domain"][];
719
- };
720
- };
721
- };
722
- };
723
- };
724
- put?: never;
725
- /**
726
- * Attach a custom domain to a Cube
727
- * @description Attaches a domain and optionally configures any per-domain proxy settings at the same time. Settings can also be changed later via PATCH.
728
- */
729
- post: {
730
- parameters: {
731
- query?: never;
732
- header?: {
733
- /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
734
- "Idempotency-Key"?: string;
735
- };
736
- path: {
737
- spaceId: string;
738
- cubeId: string;
739
- };
740
- cookie?: never;
741
- };
742
- requestBody: {
743
- content: {
744
- "application/json": {
745
- /** @description The hostname to attach, e.g. app.example.com */
746
- domain: string;
747
- /** @description Cube port the domain proxies to. */
748
- port: number;
749
- /**
750
- * @description enforced = proxy sets platform security headers (HSTS, X-Frame-Options, …); app_managed = the app's own headers pass through. Default enforced.
751
- * @enum {string}
752
- */
753
- securityHeadersMode?: "enforced" | "app_managed";
754
- /** @description Seconds the app may take to send response headers (streaming unaffected). Default 60. */
755
- responseHeaderTimeoutSecs?: number;
756
- /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
757
- responseHeaderOverrides?: {
758
- set?: {
759
- [key: string]: string;
760
- };
761
- remove?: string[];
762
- } | null;
763
- /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
764
- requestHeaderOverrides?: {
765
- set?: {
766
- [key: string]: string;
767
- };
768
- remove?: string[];
769
- } | null;
770
- /** @description Max request body size (MB). Null = unlimited (default). */
771
- maxRequestBodyMb?: number | null;
772
- /** @description Per-domain CORS policy, applied at the edge. Null (default) = CORS disabled and no Access-Control-* header is emitted anywhere. When set, the proxy answers OPTIONS preflight itself (204, the cube is never involved) and adds the headers to normal AND error responses, so a cross-origin request to a failing or sleeping cube is never CORS-masked. */
773
- corsConfig?: {
774
- /** @description Exact scheme://host[:port] origins (no path, query or trailing slash), or the single-element wildcard ["*"]. "*" and allowCredentials are mutually exclusive. */
775
- allowedOrigins: string[];
776
- /** @description Allowed methods. Omitted = GET, POST, PUT, PATCH, DELETE, OPTIONS. */
777
- allowedMethods?: string[];
778
- /** @description Allowed request headers. Omitted/empty = echo the preflight's Access-Control-Request-Headers. */
779
- allowedHeaders?: string[];
780
- /** @description Response headers exposed to JS. Omitted/empty = none. */
781
- exposedHeaders?: string[];
782
- /** @description Send Access-Control-Allow-Credentials: true. Rejected together with the "*" origin. */
783
- allowCredentials?: boolean;
784
- /** @description Preflight cache TTL. Default 600; 86400 is Chromium's hard cap. */
785
- maxAgeSeconds?: number;
786
- } | null;
787
- /**
788
- * @description Scheme the edge speaks to the CUBE on the backend hop. http (default) = cleartext. https = the cube terminates TLS itself (a control panel holding its own certificate, or an app listening on HTTPS) and answers plain HTTP with a redirect, so it cannot be reached over cleartext at all. Visitors are on HTTPS either way. The dial port is derived: https on the default port 80 connects on 443; a deliberate custom port is honoured exactly. Verified against the cube before it is applied — if the domain does not serve, the route is left on http.
789
- * @enum {string}
790
- */
791
- originScheme?: "http" | "https";
792
- /** @description Edge gzip/zstd compression. Default false (domains behind a CDN are already compressed there). */
793
- responseCompression?: boolean;
794
- /** @description Visitor IP/CIDR allow-list (v4+v6). Non-empty ⇒ only these reach the app. Null/empty = open. */
795
- ipAllowList?: string[] | null;
796
- /** @description Visitor IP/CIDR deny-list (v4+v6) → 403. Null/empty = none. */
797
- ipDenyList?: string[] | null;
798
- /** @description HTTP Basic Auth username. Null/empty clears Basic Auth. Setting it requires basicAuthPassword. */
799
- basicAuthUser?: string | null;
800
- /** @description Plaintext Basic Auth password — bcrypt-hashed server-side, never stored or returned. Required when setting basicAuthUser. */
801
- basicAuthPassword?: string;
802
- };
803
- };
804
- };
805
- responses: {
806
- /** @description Domain attached */
807
- 201: {
808
- headers: {
809
- [name: string]: unknown;
810
- };
811
- content: {
812
- "application/json": {
813
- domain: components["schemas"]["Domain"];
814
- records: components["schemas"]["DnsRecord"][];
815
- };
816
- };
817
- };
818
- 400: components["responses"]["BadRequest"];
819
- 429: components["responses"]["RateLimited"];
820
- };
821
- };
822
- delete?: never;
823
- options?: never;
824
- head?: never;
825
- patch?: never;
826
- trace?: never;
827
- };
828
- "/spaces/{spaceId}/cubes/{cubeId}/domains/{mappingId}/records": {
829
- parameters: {
830
- query?: never;
831
- header?: never;
832
- path?: never;
833
- cookie?: never;
834
- };
835
- /**
836
- * DNS records this domain needs, with their live status
837
- * @description Every record required for the domain to work, each checked against live DNS. Poll this after publishing them.
838
- *
839
- * `state` is per record: `found`, `missing` (not published yet — the expected state before you add it, never an error), `mismatch` (something else is there), or `unknown` (we could not check — never a statement about your DNS). `summary.complete` is true only when every record is `found`.
840
- *
841
- * A wildcard needs three records; an exact host needs one. Each call performs live DNS lookups and is rate limited.
842
- */
843
- get: {
844
- parameters: {
845
- query?: never;
846
- header?: never;
847
- path: {
848
- spaceId: string;
849
- cubeId: string;
850
- mappingId: string;
851
- };
852
- cookie?: never;
853
- };
854
- requestBody?: never;
855
- responses: {
856
- /** @description Required records with live status */
857
- 200: {
858
- headers: {
859
- [name: string]: unknown;
860
- };
861
- content: {
862
- "application/json": {
863
- domain: string;
864
- isWildcard: boolean;
865
- records: components["schemas"]["DnsRecordStatus"][];
866
- summary: {
867
- found: number;
868
- total: number;
869
- complete: boolean;
870
- };
871
- /** Format: date-time */
872
- checkedAt: string;
873
- };
874
- };
875
- };
876
- 404: components["responses"]["NotFound"];
877
- 429: components["responses"]["RateLimited"];
878
- };
879
- };
880
- put?: never;
881
- post?: never;
882
- delete?: never;
883
- options?: never;
884
- head?: never;
885
- patch?: never;
886
- trace?: never;
887
- };
888
- "/spaces/{spaceId}/cubes/{cubeId}/domains/{mappingId}": {
889
- parameters: {
890
- query?: never;
891
- header?: never;
892
- path?: never;
893
- cookie?: never;
894
- };
895
- get?: never;
896
- put?: never;
897
- post?: never;
898
- /** Detach a custom domain */
899
- delete: {
900
- parameters: {
901
- query?: never;
902
- header?: never;
903
- path: {
904
- spaceId: string;
905
- cubeId: string;
906
- mappingId: string;
907
- };
908
- cookie?: never;
909
- };
910
- requestBody?: never;
911
- responses: {
912
- /** @description Detached */
913
- 200: {
914
- headers: {
915
- [name: string]: unknown;
916
- };
917
- content: {
918
- "application/json": {
919
- success: boolean;
920
- };
921
- };
922
- };
923
- 404: components["responses"]["NotFound"];
924
- };
925
- };
926
- options?: never;
927
- head?: never;
928
- /**
929
- * Update a custom domain's proxy settings
930
- * @description Partial update — only the fields you send change; omitted fields are left as-is. The Basic Auth password is write-only and bcrypt-hashed server-side.
931
- */
932
- patch: {
933
- parameters: {
934
- query?: never;
935
- header?: never;
936
- path: {
937
- spaceId: string;
938
- cubeId: string;
939
- mappingId: string;
940
- };
941
- cookie?: never;
942
- };
943
- requestBody: {
944
- content: {
945
- "application/json": {
946
- /**
947
- * @description enforced = proxy sets platform security headers (HSTS, X-Frame-Options, …); app_managed = the app's own headers pass through. Default enforced.
948
- * @enum {string}
949
- */
950
- securityHeadersMode?: "enforced" | "app_managed";
951
- /** @description Seconds the app may take to send response headers (streaming unaffected). Default 60. */
952
- responseHeaderTimeoutSecs?: number;
953
- /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
954
- responseHeaderOverrides?: {
955
- set?: {
956
- [key: string]: string;
957
- };
958
- remove?: string[];
959
- } | null;
960
- /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
961
- requestHeaderOverrides?: {
962
- set?: {
963
- [key: string]: string;
964
- };
965
- remove?: string[];
966
- } | null;
967
- /** @description Max request body size (MB). Null = unlimited (default). */
968
- maxRequestBodyMb?: number | null;
969
- /** @description Per-domain CORS policy, applied at the edge. Null (default) = CORS disabled and no Access-Control-* header is emitted anywhere. When set, the proxy answers OPTIONS preflight itself (204, the cube is never involved) and adds the headers to normal AND error responses, so a cross-origin request to a failing or sleeping cube is never CORS-masked. */
970
- corsConfig?: {
971
- /** @description Exact scheme://host[:port] origins (no path, query or trailing slash), or the single-element wildcard ["*"]. "*" and allowCredentials are mutually exclusive. */
972
- allowedOrigins: string[];
973
- /** @description Allowed methods. Omitted = GET, POST, PUT, PATCH, DELETE, OPTIONS. */
974
- allowedMethods?: string[];
975
- /** @description Allowed request headers. Omitted/empty = echo the preflight's Access-Control-Request-Headers. */
976
- allowedHeaders?: string[];
977
- /** @description Response headers exposed to JS. Omitted/empty = none. */
978
- exposedHeaders?: string[];
979
- /** @description Send Access-Control-Allow-Credentials: true. Rejected together with the "*" origin. */
980
- allowCredentials?: boolean;
981
- /** @description Preflight cache TTL. Default 600; 86400 is Chromium's hard cap. */
982
- maxAgeSeconds?: number;
983
- } | null;
984
- /**
985
- * @description Scheme the edge speaks to the CUBE on the backend hop. http (default) = cleartext. https = the cube terminates TLS itself (a control panel holding its own certificate, or an app listening on HTTPS) and answers plain HTTP with a redirect, so it cannot be reached over cleartext at all. Visitors are on HTTPS either way. The dial port is derived: https on the default port 80 connects on 443; a deliberate custom port is honoured exactly. Verified against the cube before it is applied — if the domain does not serve, the route is left on http.
986
- * @enum {string}
987
- */
988
- originScheme?: "http" | "https";
989
- /** @description Edge gzip/zstd compression. Default false (domains behind a CDN are already compressed there). */
990
- responseCompression?: boolean;
991
- /** @description Visitor IP/CIDR allow-list (v4+v6). Non-empty ⇒ only these reach the app. Null/empty = open. */
992
- ipAllowList?: string[] | null;
993
- /** @description Visitor IP/CIDR deny-list (v4+v6) → 403. Null/empty = none. */
994
- ipDenyList?: string[] | null;
995
- /** @description HTTP Basic Auth username. Null/empty clears Basic Auth. Setting it requires basicAuthPassword. */
996
- basicAuthUser?: string | null;
997
- /** @description Plaintext Basic Auth password — bcrypt-hashed server-side, never stored or returned. Required when setting basicAuthUser. */
998
- basicAuthPassword?: string;
999
- };
1000
- };
1001
- };
1002
- responses: {
1003
- /** @description Settings updated */
1004
- 200: {
1005
- headers: {
1006
- [name: string]: unknown;
1007
- };
1008
- content: {
1009
- "application/json": {
1010
- domain: components["schemas"]["Domain"];
1011
- };
1012
- };
1013
- };
1014
- 400: components["responses"]["BadRequest"];
1015
- 404: components["responses"]["NotFound"];
1016
- 429: components["responses"]["RateLimited"];
1017
- };
1018
- };
1019
- trace?: never;
1020
- };
1021
- "/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings": {
1022
- parameters: {
1023
- query?: never;
1024
- header?: never;
1025
- path?: never;
1026
- cookie?: never;
1027
- };
1028
- /** List TCP port forwards for a Cube */
1029
- get: {
1030
- parameters: {
1031
- query?: never;
1032
- header?: never;
1033
- path: {
1034
- spaceId: string;
1035
- cubeId: string;
1036
- };
1037
- cookie?: never;
1038
- };
1039
- requestBody?: never;
1040
- responses: {
1041
- /** @description TCP mapping list */
1042
- 200: {
1043
- headers: {
1044
- [name: string]: unknown;
1045
- };
1046
- content: {
1047
- "application/json": {
1048
- tcpMappings: components["schemas"]["TcpMapping"][];
1049
- };
1050
- };
1051
- };
1052
- };
1053
- };
1054
- put?: never;
1055
- /** Create a TCP port forward */
1056
- post: {
1057
- parameters: {
1058
- query?: never;
1059
- header?: {
1060
- /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
1061
- "Idempotency-Key"?: string;
1062
- };
1063
- path: {
1064
- spaceId: string;
1065
- cubeId: string;
1066
- };
1067
- cookie?: never;
1068
- };
1069
- requestBody: {
1070
- content: {
1071
- "application/json": {
1072
- cubePort: number;
1073
- whitelistIps?: string[];
1074
- };
1075
- };
1076
- };
1077
- responses: {
1078
- /** @description Mapping created */
1079
- 201: {
1080
- headers: {
1081
- [name: string]: unknown;
1082
- };
1083
- content: {
1084
- "application/json": {
1085
- tcpMapping: components["schemas"]["TcpMapping"];
1086
- };
1087
- };
1088
- };
1089
- 400: components["responses"]["BadRequest"];
1090
- 429: components["responses"]["RateLimited"];
1091
- };
1092
- };
1093
- delete?: never;
1094
- options?: never;
1095
- head?: never;
1096
- patch?: never;
1097
- trace?: never;
1098
- };
1099
- "/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings/{mappingId}": {
1100
- parameters: {
1101
- query?: never;
1102
- header?: never;
1103
- path?: never;
1104
- cookie?: never;
1105
- };
1106
- get?: never;
1107
- put?: never;
1108
- post?: never;
1109
- /** Delete a TCP port forward */
1110
- delete: {
1111
- parameters: {
1112
- query?: never;
1113
- header?: never;
1114
- path: {
1115
- spaceId: string;
1116
- cubeId: string;
1117
- mappingId: string;
1118
- };
1119
- cookie?: never;
1120
- };
1121
- requestBody?: never;
1122
- responses: {
1123
- /** @description Deleted */
1124
- 200: {
1125
- headers: {
1126
- [name: string]: unknown;
1127
- };
1128
- content: {
1129
- "application/json": {
1130
- success: boolean;
1131
- };
1132
- };
1133
- };
1134
- 404: components["responses"]["NotFound"];
1135
- };
1136
- };
1137
- options?: never;
1138
- head?: never;
1139
- patch?: never;
1140
- trace?: never;
1141
- };
1142
- "/spaces/{spaceId}/cubes/{cubeId}/snapshots": {
1143
- parameters: {
1144
- query?: never;
1145
- header?: never;
1146
- path?: never;
1147
- cookie?: never;
1148
- };
1149
- /** List snapshots for a Cube */
1150
- get: {
1151
- parameters: {
1152
- query?: never;
1153
- header?: never;
1154
- path: {
1155
- spaceId: string;
1156
- cubeId: string;
1157
- };
1158
- cookie?: never;
1159
- };
1160
- requestBody?: never;
1161
- responses: {
1162
- /** @description Snapshot list */
1163
- 200: {
1164
- headers: {
1165
- [name: string]: unknown;
1166
- };
1167
- content: {
1168
- "application/json": {
1169
- snapshots: components["schemas"]["Snapshot"][];
1170
- };
1171
- };
1172
- };
1173
- };
1174
- };
1175
- put?: never;
1176
- /** Create a snapshot */
1177
- post: {
1178
- parameters: {
1179
- query?: never;
1180
- header?: {
1181
- /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
1182
- "Idempotency-Key"?: string;
1183
- };
1184
- path: {
1185
- spaceId: string;
1186
- cubeId: string;
1187
- };
1188
- cookie?: never;
1189
- };
1190
- requestBody?: {
1191
- content: {
1192
- "application/json": {
1193
- name?: string;
1194
- };
1195
- };
1196
- };
1197
- responses: {
1198
- /** @description Snapshot enqueued */
1199
- 201: {
1200
- headers: {
1201
- [name: string]: unknown;
1202
- };
1203
- content: {
1204
- "application/json": {
1205
- snapshot: components["schemas"]["Snapshot"];
1206
- };
1207
- };
1208
- };
1209
- 429: components["responses"]["RateLimited"];
1210
- };
1211
- };
1212
- delete?: never;
1213
- options?: never;
1214
- head?: never;
1215
- patch?: never;
1216
- trace?: never;
1217
- };
1218
- "/spaces/{spaceId}/cubes/{cubeId}/snapshots/{snapshotId}": {
1219
- parameters: {
1220
- query?: never;
1221
- header?: never;
1222
- path?: never;
1223
- cookie?: never;
1224
- };
1225
- get?: never;
1226
- put?: never;
1227
- post?: never;
1228
- /** Delete a snapshot */
1229
- delete: {
1230
- parameters: {
1231
- query?: never;
1232
- header?: never;
1233
- path: {
1234
- spaceId: string;
1235
- cubeId: string;
1236
- snapshotId: string;
1237
- };
1238
- cookie?: never;
1239
- };
1240
- requestBody?: never;
1241
- responses: {
1242
- /** @description Deleted */
1243
- 200: {
1244
- headers: {
1245
- [name: string]: unknown;
1246
- };
1247
- content: {
1248
- "application/json": {
1249
- success: boolean;
1250
- };
1251
- };
1252
- };
1253
- 404: components["responses"]["NotFound"];
1254
- };
1255
- };
1256
- options?: never;
1257
- head?: never;
1258
- patch?: never;
1259
- trace?: never;
1260
- };
1261
- "/spaces/{spaceId}/cubes/{cubeId}/restore": {
1262
- parameters: {
1263
- query?: never;
1264
- header?: never;
1265
- path?: never;
1266
- cookie?: never;
1267
- };
1268
- get?: never;
1269
- put?: never;
1270
- /** Restore a Cube from a snapshot */
1271
- post: {
1272
- parameters: {
1273
- query?: never;
1274
- header?: never;
1275
- path: {
1276
- spaceId: string;
1277
- cubeId: string;
1278
- };
1279
- cookie?: never;
1280
- };
1281
- requestBody: {
1282
- content: {
1283
- "application/json": {
1284
- snapshotId: string;
1285
- };
1286
- };
1287
- };
1288
- responses: {
1289
- /** @description Restore enqueued */
1290
- 200: {
1291
- headers: {
1292
- [name: string]: unknown;
1293
- };
1294
- content: {
1295
- "application/json": {
1296
- success: boolean;
1297
- };
1298
- };
1299
- };
1300
- 404: components["responses"]["NotFound"];
1301
- };
1302
- };
1303
- delete?: never;
1304
- options?: never;
1305
- head?: never;
1306
- patch?: never;
1307
- trace?: never;
1308
- };
1309
- "/spaces/{spaceId}/backups/{backupId}/download": {
1310
- parameters: {
1311
- query?: never;
1312
- header?: never;
1313
- path?: never;
1314
- cookie?: never;
1315
- };
1316
- /** Generate a presigned download URL for a backup .cube archive */
1317
- get: {
1318
- parameters: {
1319
- query?: never;
1320
- header?: never;
1321
- path: {
1322
- spaceId: string;
1323
- backupId: string;
1324
- };
1325
- cookie?: never;
1326
- };
1327
- requestBody?: never;
1328
- responses: {
1329
- /** @description Presigned URL valid for 15 minutes */
1330
- 200: {
1331
- headers: {
1332
- [name: string]: unknown;
1333
- };
1334
- content: {
1335
- "application/json": {
1336
- url?: string;
1337
- filename?: string;
1338
- sizeBytes?: number | null;
1339
- /** Format: date-time */
1340
- expiresAt?: string;
1341
- };
1342
- };
1343
- };
1344
- 404: components["responses"]["NotFound"];
1345
- /** @description Backup is not in 'complete' status */
1346
- 409: {
1347
- headers: {
1348
- [name: string]: unknown;
1349
- };
1350
- content?: never;
1351
- };
1352
- };
1353
- };
1354
- put?: never;
1355
- post?: never;
1356
- delete?: never;
1357
- options?: never;
1358
- head?: never;
1359
- patch?: never;
1360
- trace?: never;
1361
- };
1362
- "/spaces/{spaceId}/cubes/imports": {
1363
- parameters: {
1364
- query?: never;
1365
- header?: never;
1366
- path?: never;
1367
- cookie?: never;
1368
- };
1369
- get?: never;
1370
- put?: never;
1371
- /** Initiate a .cube archive import (browser-side multipart upload) */
1372
- post: {
1373
- parameters: {
1374
- query?: never;
1375
- header?: never;
1376
- path: {
1377
- spaceId: string;
1378
- };
1379
- cookie?: never;
1380
- };
1381
- requestBody: {
1382
- content: {
1383
- "application/json": {
1384
- name: string;
1385
- fileSizeBytes: number;
1386
- /**
1387
- * @description What to do with SSH access on the imported rootfs. `replace` (default) writes `sshPublicKey` to the login user's authorized_keys and requires `sshPublicKey` to be set. `keep` leaves the image's own authorized_keys and sshd configuration completely untouched — nothing is written — so you must already hold a private key that the image accepts, or you will not be able to log in.
1388
- * @default replace
1389
- * @enum {string}
1390
- */
1391
- sshKeyMode?: "replace" | "keep";
1392
- /** @description Public key to install when `sshKeyMode` is `replace`. Written to the login user's `~/.ssh/authorized_keys` — which user that is comes from the imported rootfs itself, so an image without a Krova default user keeps logging in as root. Ignored when `sshKeyMode` is `keep`. */
1393
- sshPublicKey?: string | null;
1394
- region?: string | null;
1395
- vcpusOverride?: number | null;
1396
- ramMbOverride?: number | null;
1397
- diskGbOverride?: number | null;
1398
- userData?: string | null;
1399
- expectedConfig?: {
1400
- vcpus?: number;
1401
- ramMb?: number;
1402
- diskLimitGb?: number;
1403
- } | null;
1404
- };
1405
- };
1406
- };
1407
- responses: {
1408
- /** @description Import initiated; returns presigned part URLs */
1409
- 201: {
1410
- headers: {
1411
- [name: string]: unknown;
1412
- };
1413
- content: {
1414
- "application/json": {
1415
- importId?: string;
1416
- uploadId?: string;
1417
- key?: string;
1418
- chunkSizeBytes?: number;
1419
- parts?: {
1420
- partNumber?: number;
1421
- url?: string;
1422
- }[];
1423
- /** Format: date-time */
1424
- expiresAt?: string;
1425
- };
1426
- };
1427
- };
1428
- /** @description Invalid input */
1429
- 400: {
1430
- headers: {
1431
- [name: string]: unknown;
1432
- };
1433
- content?: never;
1434
- };
1435
- /** @description Plan limit exceeded */
1436
- 403: {
1437
- headers: {
1438
- [name: string]: unknown;
1439
- };
1440
- content?: never;
1441
- };
1442
- /** @description No active storage backend */
1443
- 503: {
1444
- headers: {
1445
- [name: string]: unknown;
1446
- };
1447
- content?: never;
1448
- };
1449
- };
1450
- };
1451
- delete?: never;
1452
- options?: never;
1453
- head?: never;
1454
- patch?: never;
1455
- trace?: never;
1456
- };
1457
- "/spaces/{spaceId}/cubes/imports/{importId}": {
1458
- parameters: {
1459
- query?: never;
1460
- header?: never;
1461
- path?: never;
1462
- cookie?: never;
1463
- };
1464
- /** Get the current state of an import */
1465
- get: {
1466
- parameters: {
1467
- query?: never;
1468
- header?: never;
1469
- path: {
1470
- spaceId: string;
1471
- importId: string;
1472
- };
1473
- cookie?: never;
1474
- };
1475
- requestBody?: never;
1476
- responses: {
1477
- /** @description Current import state */
1478
- 200: {
1479
- headers: {
1480
- [name: string]: unknown;
1481
- };
1482
- content: {
1483
- "application/json": {
1484
- import?: {
1485
- id?: string;
1486
- name?: string;
1487
- /** @enum {string} */
1488
- status?: "uploading" | "finalizing" | "provisioning" | "complete" | "failed" | "expired";
1489
- cubeId?: string | null;
1490
- error?: string | null;
1491
- createdAt?: string;
1492
- updatedAt?: string;
1493
- completedAt?: string | null;
1494
- };
1495
- };
1496
- };
1497
- };
1498
- 404: components["responses"]["NotFound"];
1499
- };
1500
- };
1501
- put?: never;
1502
- post?: never;
1503
- /** Cancel an in-flight upload (only allowed in 'uploading' state) */
1504
- delete: {
1505
- parameters: {
1506
- query?: never;
1507
- header?: never;
1508
- path: {
1509
- spaceId: string;
1510
- importId: string;
1511
- };
1512
- cookie?: never;
1513
- };
1514
- requestBody?: never;
1515
- responses: {
1516
- /** @description Cancelled */
1517
- 200: {
1518
- headers: {
1519
- [name: string]: unknown;
1520
- };
1521
- content: {
1522
- "application/json": {
1523
- success: boolean;
1524
- };
1525
- };
1526
- };
1527
- 404: components["responses"]["NotFound"];
1528
- /** @description Cannot cancel an import past the 'uploading' state */
1529
- 409: {
1530
- headers: {
1531
- [name: string]: unknown;
1532
- };
1533
- content?: never;
1534
- };
1535
- };
1536
- };
1537
- options?: never;
1538
- head?: never;
1539
- patch?: never;
1540
- trace?: never;
1541
- };
1542
- "/spaces/{spaceId}/cubes/imports/{importId}/complete": {
1543
- parameters: {
1544
- query?: never;
1545
- header?: never;
1546
- path?: never;
1547
- cookie?: never;
1548
- };
1549
- get?: never;
1550
- put?: never;
1551
- /** Finalize a .cube import: complete multipart upload + create cube row + enqueue provisioning */
1552
- post: {
1553
- parameters: {
1554
- query?: never;
1555
- header?: never;
1556
- path: {
1557
- spaceId: string;
1558
- importId: string;
1559
- };
1560
- cookie?: never;
1561
- };
1562
- requestBody: {
1563
- content: {
1564
- "application/json": {
1565
- parts: {
1566
- partNumber: number;
1567
- etag: string;
1568
- }[];
1569
- config: {
1570
- vcpus: number;
1571
- ramMb: number;
1572
- diskLimitGb: number;
1573
- imageId: string;
1574
- userData?: string | null;
1575
- };
1576
- };
1577
- };
1578
- };
1579
- responses: {
1580
- /** @description Provisioning enqueued */
1581
- 200: {
1582
- headers: {
1583
- [name: string]: unknown;
1584
- };
1585
- content: {
1586
- "application/json": {
1587
- importId?: string;
1588
- cubeId?: string;
1589
- /** @enum {string} */
1590
- status?: "provisioning";
1591
- };
1592
- };
1593
- };
1594
- /** @description Invalid input */
1595
- 400: {
1596
- headers: {
1597
- [name: string]: unknown;
1598
- };
1599
- content?: never;
1600
- };
1601
- /** @description Plan limit exceeded */
1602
- 403: {
1603
- headers: {
1604
- [name: string]: unknown;
1605
- };
1606
- content?: never;
1607
- };
1608
- /** @description Import not in 'uploading' state */
1609
- 409: {
1610
- headers: {
1611
- [name: string]: unknown;
1612
- };
1613
- content?: never;
1614
- };
1615
- /** @description S3 finalization failed */
1616
- 502: {
1617
- headers: {
1618
- [name: string]: unknown;
1619
- };
1620
- content?: never;
1621
- };
1622
- /** @description Storage backend unavailable */
1623
- 503: {
1624
- headers: {
1625
- [name: string]: unknown;
1626
- };
1627
- content?: never;
1628
- };
1629
- };
1630
- };
1631
- delete?: never;
1632
- options?: never;
1633
- head?: never;
1634
- patch?: never;
1635
- trace?: never;
1636
- };
1637
- "/spaces/{spaceId}/webhooks": {
1638
- parameters: {
1639
- query?: never;
1640
- header?: never;
1641
- path?: never;
1642
- cookie?: never;
1643
- };
1644
- /** List webhook endpoints */
1645
- get: {
1646
- parameters: {
1647
- query?: never;
1648
- header?: never;
1649
- path: {
1650
- spaceId: string;
1651
- };
1652
- cookie?: never;
1653
- };
1654
- requestBody?: never;
1655
- responses: {
1656
- /** @description Webhook list */
1657
- 200: {
1658
- headers: {
1659
- [name: string]: unknown;
1660
- };
1661
- content?: never;
1662
- };
1663
- };
1664
- };
1665
- put?: never;
1666
- /** Create a webhook endpoint (signing secret returned once) */
1667
- post: {
1668
- parameters: {
1669
- query?: never;
1670
- header?: never;
1671
- path: {
1672
- spaceId: string;
1673
- };
1674
- cookie?: never;
1675
- };
1676
- requestBody: {
1677
- content: {
1678
- "application/json": {
1679
- /** Format: uri */
1680
- url: string;
1681
- events: ("cube.created" | "cube.running" | "cube.stopped" | "cube.error" | "cube.deleted" | "cube.cold_restarted" | "cube.transfer.started" | "cube.transfer.completed" | "cube.transfer.failed" | "cube.resize.started" | "cube.resize.completed" | "cube.resize.failed" | "resource.alert.memory" | "resource.alert.cpu" | "resource.alert.disk" | "domain.alert.error_4xx" | "domain.alert.error_5xx" | "snapshot.created" | "snapshot.restored" | "snapshot.deleted" | "snapshot.pinned" | "snapshot.promoted_to_backup" | "snapshot.exported" | "backup.created" | "backup.deleted" | "backup.redeployed" | "domain.added" | "domain.active" | "domain.removed" | "tcp_mapping.added" | "tcp_mapping.removed" | "tcp_mapping.updated" | "hosting.provisioned" | "hosting.suspended" | "hosting.unsuspended" | "hosting.deleted" | "hosting.plan_changed" | "hosting.renewed" | "hosting.cancellation_scheduled" | "hosting.suspended_for_non_payment" | "hosting.deleted_after_recovery" | "member.invited" | "member.joined" | "member.removed" | "member.role_changed")[];
1682
- };
1683
- };
1684
- };
1685
- responses: {
1686
- /** @description Webhook created (response includes secret) */
1687
- 201: {
1688
- headers: {
1689
- [name: string]: unknown;
1690
- };
1691
- content?: never;
1692
- };
1693
- 400: components["responses"]["BadRequest"];
1694
- 429: components["responses"]["RateLimited"];
1695
- };
1696
- };
1697
- delete?: never;
1698
- options?: never;
1699
- head?: never;
1700
- patch?: never;
1701
- trace?: never;
1702
- };
1703
- "/spaces/{spaceId}/webhooks/{endpointId}": {
1704
- parameters: {
1705
- query?: never;
1706
- header?: never;
1707
- path?: never;
1708
- cookie?: never;
1709
- };
1710
- /** Get a webhook (no secret) */
1711
- get: {
1712
- parameters: {
1713
- query?: never;
1714
- header?: never;
1715
- path: {
1716
- spaceId: string;
1717
- endpointId: string;
1718
- };
1719
- cookie?: never;
1720
- };
1721
- requestBody?: never;
1722
- responses: {
1723
- /** @description Webhook */
1724
- 200: {
1725
- headers: {
1726
- [name: string]: unknown;
1727
- };
1728
- content?: never;
1729
- };
1730
- };
1731
- };
1732
- put?: never;
1733
- post?: never;
1734
- /** Delete a webhook (cascades deliveries) */
1735
- delete: {
1736
- parameters: {
1737
- query?: never;
1738
- header?: never;
1739
- path: {
1740
- spaceId: string;
1741
- endpointId: string;
1742
- };
1743
- cookie?: never;
1744
- };
1745
- requestBody?: never;
1746
- responses: {
1747
- /** @description Deleted */
1748
- 200: {
1749
- headers: {
1750
- [name: string]: unknown;
1751
- };
1752
- content?: never;
1753
- };
1754
- 429: components["responses"]["RateLimited"];
1755
- };
1756
- };
1757
- options?: never;
1758
- head?: never;
1759
- patch?: never;
1760
- trace?: never;
1761
- };
1762
- "/spaces/{spaceId}/webhooks/{endpointId}/deliveries": {
1763
- parameters: {
1764
- query?: never;
1765
- header?: never;
1766
- path?: never;
1767
- cookie?: never;
1768
- };
1769
- /** Last 30 days of webhook delivery history (max 100) */
1770
- get: {
1771
- parameters: {
1772
- query?: {
1773
- limit?: number;
1774
- };
1775
- header?: never;
1776
- path: {
1777
- spaceId: string;
1778
- endpointId: string;
1779
- };
1780
- cookie?: never;
1781
- };
1782
- requestBody?: never;
1783
- responses: {
1784
- /** @description Delivery list */
1785
- 200: {
1786
- headers: {
1787
- [name: string]: unknown;
1788
- };
1789
- content?: never;
1790
- };
8
+ "/regions": {
9
+ parameters: {
10
+ query?: never;
11
+ header?: never;
12
+ path?: never;
13
+ cookie?: never;
14
+ };
15
+ /** List regions with available capacity */
16
+ get: {
17
+ parameters: {
18
+ query?: never;
19
+ header?: never;
20
+ path?: never;
21
+ cookie?: never;
22
+ };
23
+ requestBody?: never;
24
+ responses: {
25
+ /** @description Region list */
26
+ 200: {
27
+ headers: {
28
+ [name: string]: unknown;
29
+ };
30
+ content: {
31
+ "application/json": {
32
+ regions: components["schemas"]["Region"][];
33
+ };
34
+ };
35
+ };
36
+ };
37
+ };
38
+ put?: never;
39
+ post?: never;
40
+ delete?: never;
41
+ options?: never;
42
+ head?: never;
43
+ patch?: never;
44
+ trace?: never;
45
+ };
46
+ "/images": {
47
+ parameters: {
48
+ query?: never;
49
+ header?: never;
50
+ path?: never;
51
+ cookie?: never;
52
+ };
53
+ /** List available OS images */
54
+ get: {
55
+ parameters: {
56
+ query?: never;
57
+ header?: never;
58
+ path?: never;
59
+ cookie?: never;
60
+ };
61
+ requestBody?: never;
62
+ responses: {
63
+ /** @description Image list */
64
+ 200: {
65
+ headers: {
66
+ [name: string]: unknown;
67
+ };
68
+ content: {
69
+ "application/json": {
70
+ images: components["schemas"]["Image"][];
71
+ };
72
+ };
73
+ };
74
+ };
75
+ };
76
+ put?: never;
77
+ post?: never;
78
+ delete?: never;
79
+ options?: never;
80
+ head?: never;
81
+ patch?: never;
82
+ trace?: never;
83
+ };
84
+ "/pricing": {
85
+ parameters: {
86
+ query?: never;
87
+ header?: never;
88
+ path?: never;
89
+ cookie?: never;
90
+ };
91
+ /** Per-resource hourly rates and volume pricing tiers */
92
+ get: {
93
+ parameters: {
94
+ query?: never;
95
+ header?: never;
96
+ path?: never;
97
+ cookie?: never;
98
+ };
99
+ requestBody?: never;
100
+ responses: {
101
+ /** @description Pricing data */
102
+ 200: {
103
+ headers: {
104
+ [name: string]: unknown;
105
+ };
106
+ content: {
107
+ "application/json": {
108
+ currency: string;
109
+ rates: {
110
+ vcpuPerHour: number;
111
+ ramGbPerHour: number;
112
+ diskGbPerHour: number;
113
+ };
114
+ tiers: components["schemas"]["PricingTier"][];
115
+ note: string;
1791
116
  };
117
+ };
1792
118
  };
1793
- put?: never;
1794
- post?: never;
1795
- delete?: never;
1796
- options?: never;
1797
- head?: never;
1798
- patch?: never;
1799
- trace?: never;
119
+ };
1800
120
  };
1801
- }
1802
- interface components {
1803
- schemas: {
1804
- Space: {
1805
- id: string;
1806
- name: string;
1807
- tier: string;
1808
- /** Format: date-time */
1809
- createdAt: string;
1810
- };
1811
- CubeSshInfo: {
1812
- host: string | null;
1813
- port: number;
1814
- user: string;
1815
- hostKeys: {
1816
- type: string;
1817
- key: string;
1818
- }[];
1819
- };
1820
- Cube: {
1821
- id: string;
121
+ put?: never;
122
+ post?: never;
123
+ delete?: never;
124
+ options?: never;
125
+ head?: never;
126
+ patch?: never;
127
+ trace?: never;
128
+ };
129
+ "/auth/cli/start": {
130
+ parameters: {
131
+ query?: never;
132
+ header?: never;
133
+ path?: never;
134
+ cookie?: never;
135
+ };
136
+ get?: never;
137
+ put?: never;
138
+ /**
139
+ * Begin a CLI device-authorization login (RFC 8628)
140
+ * @description Public, unauthenticated. Mints a device code (returned once) and a short human user code, and returns the verification URIs the user opens in a browser to approve. The CLI then polls /auth/cli/poll. Rate-limited per client IP.
141
+ */
142
+ post: {
143
+ parameters: {
144
+ query?: never;
145
+ header?: never;
146
+ path?: never;
147
+ cookie?: never;
148
+ };
149
+ requestBody?: never;
150
+ responses: {
151
+ /** @description Device-authorization request created */
152
+ 200: {
153
+ headers: {
154
+ [name: string]: unknown;
155
+ };
156
+ content: {
157
+ "application/json": {
158
+ /** @description High-entropy code the CLI keeps secret and presents on each poll. Only its hash is stored server-side. */
159
+ deviceCode: string;
160
+ /** @description Short human-readable code (KROVA-XXXX-XXXX) the user confirms in the browser. */
161
+ userCode: string;
162
+ /**
163
+ * Format: uri
164
+ * @description Browser URL where the user approves.
165
+ */
166
+ verificationUri: string;
167
+ /**
168
+ * Format: uri
169
+ * @description verificationUri with the user code pre-filled.
170
+ */
171
+ verificationUriComplete: string;
172
+ /** @description Seconds to wait between polls. */
173
+ interval: number;
174
+ /** @description Seconds until the device code expires (~600). */
175
+ expiresIn: number;
176
+ };
177
+ };
178
+ };
179
+ 429: components["responses"]["RateLimited"];
180
+ /** @description Could not allocate a login code; retry */
181
+ 503: {
182
+ headers: {
183
+ [name: string]: unknown;
184
+ };
185
+ content?: never;
186
+ };
187
+ };
188
+ };
189
+ delete?: never;
190
+ options?: never;
191
+ head?: never;
192
+ patch?: never;
193
+ trace?: never;
194
+ };
195
+ "/auth/cli/poll": {
196
+ parameters: {
197
+ query?: never;
198
+ header?: never;
199
+ path?: never;
200
+ cookie?: never;
201
+ };
202
+ get?: never;
203
+ put?: never;
204
+ /**
205
+ * Poll for CLI device-authorization approval (RFC 8628)
206
+ * @description Public, unauthenticated. The CLI submits its deviceCode until the user approves or denies. On approval a real API key is minted ONCE, scoped to the approved Space and the approving user's membership, and returned a single time. Rate-limited per client IP.
207
+ */
208
+ post: {
209
+ parameters: {
210
+ query?: never;
211
+ header?: never;
212
+ path?: never;
213
+ cookie?: never;
214
+ };
215
+ requestBody: {
216
+ content: {
217
+ "application/json": {
218
+ /** @description The device code from /auth/cli/start. */
219
+ deviceCode: string;
220
+ };
221
+ };
222
+ };
223
+ responses: {
224
+ /** @description Approved — API key minted (returned once) */
225
+ 200: {
226
+ headers: {
227
+ [name: string]: unknown;
228
+ };
229
+ content: {
230
+ "application/json": {
231
+ /** @description The full API key. Shown once and never returned again — store it securely. */
232
+ apiKey: string;
233
+ /** @description The Space the key is scoped to. */
234
+ spaceId: string;
235
+ };
236
+ };
237
+ };
238
+ 400: components["responses"]["BadRequest"];
239
+ /** @description The user denied the login request */
240
+ 403: {
241
+ headers: {
242
+ [name: string]: unknown;
243
+ };
244
+ content?: never;
245
+ };
246
+ /** @description The device code expired, was already consumed, or is unknown */
247
+ 410: {
248
+ headers: {
249
+ [name: string]: unknown;
250
+ };
251
+ content?: never;
252
+ };
253
+ /** @description Authorization still pending — keep polling at the given interval */
254
+ 428: {
255
+ headers: {
256
+ [name: string]: unknown;
257
+ };
258
+ content?: never;
259
+ };
260
+ 429: components["responses"]["RateLimited"];
261
+ };
262
+ };
263
+ delete?: never;
264
+ options?: never;
265
+ head?: never;
266
+ patch?: never;
267
+ trace?: never;
268
+ };
269
+ "/space": {
270
+ parameters: {
271
+ query?: never;
272
+ header?: never;
273
+ path?: never;
274
+ cookie?: never;
275
+ };
276
+ /**
277
+ * Resolve the space this API key is scoped to
278
+ * @description Returns the single space the API key belongs to. Lets a client auto-resolve the space id from the key alone (no spaceId in the URL).
279
+ */
280
+ get: {
281
+ parameters: {
282
+ query?: never;
283
+ header?: never;
284
+ path?: never;
285
+ cookie?: never;
286
+ };
287
+ requestBody?: never;
288
+ responses: {
289
+ /** @description The key's space */
290
+ 200: {
291
+ headers: {
292
+ [name: string]: unknown;
293
+ };
294
+ content: {
295
+ "application/json": components["schemas"]["Space"];
296
+ };
297
+ };
298
+ 401: components["responses"]["Unauthorized"];
299
+ 404: components["responses"]["NotFound"];
300
+ };
301
+ };
302
+ put?: never;
303
+ post?: never;
304
+ delete?: never;
305
+ options?: never;
306
+ head?: never;
307
+ patch?: never;
308
+ trace?: never;
309
+ };
310
+ "/spaces/{spaceId}/cubes": {
311
+ parameters: {
312
+ query?: never;
313
+ header?: never;
314
+ path?: never;
315
+ cookie?: never;
316
+ };
317
+ /** List Cubes in a Space */
318
+ get: {
319
+ parameters: {
320
+ query?: never;
321
+ header?: never;
322
+ path: {
323
+ spaceId: string;
324
+ };
325
+ cookie?: never;
326
+ };
327
+ requestBody?: never;
328
+ responses: {
329
+ /** @description Paginated Cube list */
330
+ 200: {
331
+ headers: {
332
+ [name: string]: unknown;
333
+ };
334
+ content: {
335
+ "application/json": {
336
+ cubes: components["schemas"]["Cube"][];
337
+ pagination: components["schemas"]["Pagination"];
338
+ };
339
+ };
340
+ };
341
+ 401: components["responses"]["Unauthorized"];
342
+ 403: components["responses"]["Forbidden"];
343
+ };
344
+ };
345
+ put?: never;
346
+ /** Create a Cube */
347
+ post: {
348
+ parameters: {
349
+ query?: never;
350
+ header?: {
351
+ /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
352
+ "Idempotency-Key"?: string;
353
+ };
354
+ path: {
355
+ spaceId: string;
356
+ };
357
+ cookie?: never;
358
+ };
359
+ requestBody: {
360
+ content: {
361
+ "application/json": {
1822
362
  name: string;
1823
- /** @enum {string} */
1824
- state: "pending" | "booting" | "running" | "stopped" | "stopping" | "error" | "deleted";
1825
- publicIpv4: string | null;
363
+ image: string;
1826
364
  resources: {
1827
- vcpu: number;
1828
- ramGb: number;
1829
- diskGb: number;
365
+ vcpu: number;
366
+ ramGb: number;
367
+ diskGb: number;
368
+ };
369
+ /** @description SSH public key written to the Cube login user's authorized_keys at boot (~/.ssh/authorized_keys for the ubuntu or debian user; /root/.ssh/authorized_keys on Cubes created before the default-user change). GET /cubes/{cubeId}/ssh reports the login user for a given Cube. Must start with ssh-ed25519, ssh-rsa, ecdsa-sha2-*, ssh-dss, or sk-*@openssh.com. */
370
+ sshPublicKey: string;
371
+ /** @description Region slug from /v1/regions (optional). */
372
+ region?: string;
373
+ /** @description cloud-init script (max 16 KB, optional). */
374
+ userData?: string;
375
+ };
376
+ };
377
+ };
378
+ responses: {
379
+ /** @description Cube created */
380
+ 201: {
381
+ headers: {
382
+ [name: string]: unknown;
383
+ };
384
+ content: {
385
+ "application/json": {
386
+ cube?: components["schemas"]["Cube"];
387
+ };
388
+ };
389
+ };
390
+ 400: components["responses"]["BadRequest"];
391
+ 401: components["responses"]["Unauthorized"];
392
+ 403: components["responses"]["Forbidden"];
393
+ 429: components["responses"]["RateLimited"];
394
+ };
395
+ };
396
+ delete?: never;
397
+ options?: never;
398
+ head?: never;
399
+ patch?: never;
400
+ trace?: never;
401
+ };
402
+ "/spaces/{spaceId}/cubes/{cubeId}": {
403
+ parameters: {
404
+ query?: never;
405
+ header?: never;
406
+ path?: never;
407
+ cookie?: never;
408
+ };
409
+ /** Get a Cube */
410
+ get: {
411
+ parameters: {
412
+ query?: never;
413
+ header?: never;
414
+ path: {
415
+ spaceId: string;
416
+ cubeId: string;
417
+ };
418
+ cookie?: never;
419
+ };
420
+ requestBody?: never;
421
+ responses: {
422
+ /** @description Cube */
423
+ 200: {
424
+ headers: {
425
+ [name: string]: unknown;
426
+ };
427
+ content: {
428
+ "application/json": {
429
+ cube: components["schemas"]["Cube"];
430
+ };
431
+ };
432
+ };
433
+ 404: components["responses"]["NotFound"];
434
+ };
435
+ };
436
+ put?: never;
437
+ post?: never;
438
+ /** Delete a Cube (asynchronous) */
439
+ delete: {
440
+ parameters: {
441
+ query?: never;
442
+ header?: never;
443
+ path: {
444
+ spaceId: string;
445
+ cubeId: string;
446
+ };
447
+ cookie?: never;
448
+ };
449
+ requestBody?: never;
450
+ responses: {
451
+ /** @description Deletion enqueued */
452
+ 200: {
453
+ headers: {
454
+ [name: string]: unknown;
455
+ };
456
+ content: {
457
+ "application/json": {
458
+ success: boolean;
459
+ };
460
+ };
461
+ };
462
+ 404: components["responses"]["NotFound"];
463
+ 429: components["responses"]["RateLimited"];
464
+ };
465
+ };
466
+ options?: never;
467
+ head?: never;
468
+ patch?: never;
469
+ trace?: never;
470
+ };
471
+ "/spaces/{spaceId}/cubes/{cubeId}/power-off": {
472
+ parameters: {
473
+ query?: never;
474
+ header?: never;
475
+ path?: never;
476
+ cookie?: never;
477
+ };
478
+ get?: never;
479
+ put?: never;
480
+ /** Power off a running Cube */
481
+ post: {
482
+ parameters: {
483
+ query?: never;
484
+ header?: never;
485
+ path: {
486
+ spaceId: string;
487
+ cubeId: string;
488
+ };
489
+ cookie?: never;
490
+ };
491
+ requestBody?: never;
492
+ responses: {
493
+ /** @description Power off enqueued */
494
+ 200: {
495
+ headers: {
496
+ [name: string]: unknown;
497
+ };
498
+ content?: never;
499
+ };
500
+ 404: components["responses"]["NotFound"];
501
+ 429: components["responses"]["RateLimited"];
502
+ };
503
+ };
504
+ delete?: never;
505
+ options?: never;
506
+ head?: never;
507
+ patch?: never;
508
+ trace?: never;
509
+ };
510
+ "/spaces/{spaceId}/cubes/{cubeId}/wake": {
511
+ parameters: {
512
+ query?: never;
513
+ header?: never;
514
+ path?: never;
515
+ cookie?: never;
516
+ };
517
+ get?: never;
518
+ put?: never;
519
+ /** Start a stopped Cube */
520
+ post: {
521
+ parameters: {
522
+ query?: never;
523
+ header?: never;
524
+ path: {
525
+ spaceId: string;
526
+ cubeId: string;
527
+ };
528
+ cookie?: never;
529
+ };
530
+ requestBody?: never;
531
+ responses: {
532
+ /** @description Start enqueued */
533
+ 200: {
534
+ headers: {
535
+ [name: string]: unknown;
536
+ };
537
+ content?: never;
538
+ };
539
+ 404: components["responses"]["NotFound"];
540
+ 429: components["responses"]["RateLimited"];
541
+ };
542
+ };
543
+ delete?: never;
544
+ options?: never;
545
+ head?: never;
546
+ patch?: never;
547
+ trace?: never;
548
+ };
549
+ "/spaces/{spaceId}/cubes/{cubeId}/restart": {
550
+ parameters: {
551
+ query?: never;
552
+ header?: never;
553
+ path?: never;
554
+ cookie?: never;
555
+ };
556
+ get?: never;
557
+ put?: never;
558
+ /**
559
+ * Restart a running Cube
560
+ * @description Cold-restarts the Cube: the hypervisor process is stopped and relaunched, so the Cube boots against the host's current kernel. This is how a Cube picks up a refreshed guest kernel after a platform image update — a `reboot` issued inside the Cube cannot do it, because the kernel is supplied externally by the host. Disk state is preserved; only the kernel changes. Cube must be `running` (a stopped Cube already picks up the latest kernel when started). Concurrent restarts of the same Cube are rejected with 409 rather than queued twice.
561
+ */
562
+ post: {
563
+ parameters: {
564
+ query?: never;
565
+ header?: never;
566
+ path: {
567
+ spaceId: string;
568
+ cubeId: string;
569
+ };
570
+ cookie?: never;
571
+ };
572
+ requestBody?: never;
573
+ responses: {
574
+ /** @description Restart enqueued */
575
+ 200: {
576
+ headers: {
577
+ [name: string]: unknown;
578
+ };
579
+ content?: never;
580
+ };
581
+ 404: components["responses"]["NotFound"];
582
+ /** @description Cube is not running, or a restart is already in progress */
583
+ 409: {
584
+ headers: {
585
+ [name: string]: unknown;
586
+ };
587
+ content?: never;
588
+ };
589
+ 429: components["responses"]["RateLimited"];
590
+ };
591
+ };
592
+ delete?: never;
593
+ options?: never;
594
+ head?: never;
595
+ patch?: never;
596
+ trace?: never;
597
+ };
598
+ "/spaces/{spaceId}/cubes/{cubeId}/ssh-port": {
599
+ parameters: {
600
+ query?: never;
601
+ header?: never;
602
+ path?: never;
603
+ cookie?: never;
604
+ };
605
+ get?: never;
606
+ /**
607
+ * Change a Cube's SSH port
608
+ * @description Sets the port INSIDE the Cube that SSH is forwarded to — NOT the host port you connect to. The host port is allocated by Krova and is unchanged by this call. Pointing this at a port nothing is listening on inside the Cube will make SSH unreachable; the default is 22. The change is applied atomically (the old port mapping is replaced).
609
+ */
610
+ put: {
611
+ parameters: {
612
+ query?: never;
613
+ header?: never;
614
+ path: {
615
+ spaceId: string;
616
+ cubeId: string;
617
+ };
618
+ cookie?: never;
619
+ };
620
+ requestBody: {
621
+ content: {
622
+ "application/json": {
623
+ /** @description The port inside the Cube that sshd listens on (default 22). This is the Cube side of the mapping, not the host port. */
624
+ cubePort: number;
625
+ };
626
+ };
627
+ };
628
+ responses: {
629
+ /** @description SSH port updated */
630
+ 200: {
631
+ headers: {
632
+ [name: string]: unknown;
633
+ };
634
+ content?: never;
635
+ };
636
+ 400: components["responses"]["BadRequest"];
637
+ 404: components["responses"]["NotFound"];
638
+ 429: components["responses"]["RateLimited"];
639
+ };
640
+ };
641
+ post?: never;
642
+ delete?: never;
643
+ options?: never;
644
+ head?: never;
645
+ patch?: never;
646
+ trace?: never;
647
+ };
648
+ "/spaces/{spaceId}/cubes/{cubeId}/ssh": {
649
+ parameters: {
650
+ query?: never;
651
+ header?: never;
652
+ path?: never;
653
+ cookie?: never;
654
+ };
655
+ /**
656
+ * Get a Cube's SSH connection info
657
+ * @description Host (server public IPv4), host SSH port, login user, and the Cube's captured SSH host public keys. **Use `user` rather than assuming a username** — it is `ubuntu` or `debian` on Cubes created from images that ship a default user, and `root` on Cubes created before that change or imported from a rootfs without one. `hostKeys` is empty only until the reachability cron makes its first capture; clients fall back to trust-on-first-use until then, and pin strictly afterwards.
658
+ */
659
+ get: {
660
+ parameters: {
661
+ query?: never;
662
+ header?: never;
663
+ path: {
664
+ spaceId: string;
665
+ cubeId: string;
666
+ };
667
+ cookie?: never;
668
+ };
669
+ requestBody?: never;
670
+ responses: {
671
+ /** @description SSH connection info */
672
+ 200: {
673
+ headers: {
674
+ [name: string]: unknown;
675
+ };
676
+ content: {
677
+ "application/json": components["schemas"]["CubeSshInfo"];
678
+ };
679
+ };
680
+ 404: components["responses"]["NotFound"];
681
+ };
682
+ };
683
+ put?: never;
684
+ post?: never;
685
+ delete?: never;
686
+ options?: never;
687
+ head?: never;
688
+ patch?: never;
689
+ trace?: never;
690
+ };
691
+ "/spaces/{spaceId}/cubes/{cubeId}/domains": {
692
+ parameters: {
693
+ query?: never;
694
+ header?: never;
695
+ path?: never;
696
+ cookie?: never;
697
+ };
698
+ /** List custom domains attached to a Cube */
699
+ get: {
700
+ parameters: {
701
+ query?: never;
702
+ header?: never;
703
+ path: {
704
+ spaceId: string;
705
+ cubeId: string;
706
+ };
707
+ cookie?: never;
708
+ };
709
+ requestBody?: never;
710
+ responses: {
711
+ /** @description Domain list */
712
+ 200: {
713
+ headers: {
714
+ [name: string]: unknown;
715
+ };
716
+ content: {
717
+ "application/json": {
718
+ domains: components["schemas"]["Domain"][];
719
+ };
720
+ };
721
+ };
722
+ };
723
+ };
724
+ put?: never;
725
+ /**
726
+ * Attach a custom domain to a Cube
727
+ * @description Attaches a domain and optionally configures any per-domain proxy settings at the same time. Settings can also be changed later via PATCH.
728
+ */
729
+ post: {
730
+ parameters: {
731
+ query?: never;
732
+ header?: {
733
+ /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
734
+ "Idempotency-Key"?: string;
735
+ };
736
+ path: {
737
+ spaceId: string;
738
+ cubeId: string;
739
+ };
740
+ cookie?: never;
741
+ };
742
+ requestBody: {
743
+ content: {
744
+ "application/json": {
745
+ /** @description The hostname to attach, e.g. app.example.com */
746
+ domain: string;
747
+ /** @description Cube port the domain proxies to. */
748
+ port: number;
749
+ /**
750
+ * @description enforced = proxy sets platform security headers (HSTS, X-Frame-Options, …); app_managed = the app's own headers pass through. Default enforced.
751
+ * @enum {string}
752
+ */
753
+ securityHeadersMode?: "enforced" | "app_managed";
754
+ /** @description Seconds the app may take to send response headers (streaming unaffected). Default 60. */
755
+ responseHeaderTimeoutSecs?: number;
756
+ /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
757
+ responseHeaderOverrides?: {
758
+ set?: {
759
+ [key: string]: string;
760
+ };
761
+ remove?: string[];
762
+ } | null;
763
+ /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
764
+ requestHeaderOverrides?: {
765
+ set?: {
766
+ [key: string]: string;
767
+ };
768
+ remove?: string[];
769
+ } | null;
770
+ /** @description Max request body size (MB). Null = unlimited (default). */
771
+ maxRequestBodyMb?: number | null;
772
+ /** @description Per-domain CORS policy, applied at the edge. Null (default) = CORS disabled and no Access-Control-* header is emitted anywhere. When set, the proxy answers OPTIONS preflight itself (204, the cube is never involved) and adds the headers to normal AND error responses, so a cross-origin request to a failing or sleeping cube is never CORS-masked. */
773
+ corsConfig?: {
774
+ /** @description Exact scheme://host[:port] origins (no path, query or trailing slash), or the single-element wildcard ["*"]. "*" and allowCredentials are mutually exclusive. */
775
+ allowedOrigins: string[];
776
+ /** @description Allowed methods. Omitted = GET, POST, PUT, PATCH, DELETE, OPTIONS. */
777
+ allowedMethods?: string[];
778
+ /** @description Allowed request headers. Omitted/empty = echo the preflight's Access-Control-Request-Headers. */
779
+ allowedHeaders?: string[];
780
+ /** @description Response headers exposed to JS. Omitted/empty = none. */
781
+ exposedHeaders?: string[];
782
+ /** @description Send Access-Control-Allow-Credentials: true. Rejected together with the "*" origin. */
783
+ allowCredentials?: boolean;
784
+ /** @description Preflight cache TTL. Default 600; 86400 is Chromium's hard cap. */
785
+ maxAgeSeconds?: number;
786
+ } | null;
787
+ /**
788
+ * @description Scheme the edge speaks to the CUBE on the backend hop. http (default) = cleartext. https = the cube terminates TLS itself (a control panel holding its own certificate, or an app listening on HTTPS) and answers plain HTTP with a redirect, so it cannot be reached over cleartext at all. Visitors are on HTTPS either way. The dial port is derived: https on the default port 80 connects on 443; a deliberate custom port is honoured exactly. Verified against the cube before it is applied — if the domain does not serve, the route is left on http.
789
+ * @enum {string}
790
+ */
791
+ originScheme?: "http" | "https";
792
+ /** @description Edge gzip/zstd compression. Default false (domains behind a CDN are already compressed there). */
793
+ responseCompression?: boolean;
794
+ /** @description Visitor IP/CIDR allow-list (v4+v6). Non-empty ⇒ only these reach the app. Null/empty = open. */
795
+ ipAllowList?: string[] | null;
796
+ /** @description Visitor IP/CIDR deny-list (v4+v6) → 403. Null/empty = none. */
797
+ ipDenyList?: string[] | null;
798
+ /** @description HTTP Basic Auth username. Null/empty clears Basic Auth. Setting it requires basicAuthPassword. */
799
+ basicAuthUser?: string | null;
800
+ /** @description Plaintext Basic Auth password — bcrypt-hashed server-side, never stored or returned. Required when setting basicAuthUser. */
801
+ basicAuthPassword?: string;
802
+ };
803
+ };
804
+ };
805
+ responses: {
806
+ /** @description Domain attached */
807
+ 201: {
808
+ headers: {
809
+ [name: string]: unknown;
810
+ };
811
+ content: {
812
+ "application/json": {
813
+ domain: components["schemas"]["Domain"];
814
+ records: components["schemas"]["DnsRecord"][];
815
+ };
816
+ };
817
+ };
818
+ 400: components["responses"]["BadRequest"];
819
+ 429: components["responses"]["RateLimited"];
820
+ };
821
+ };
822
+ delete?: never;
823
+ options?: never;
824
+ head?: never;
825
+ patch?: never;
826
+ trace?: never;
827
+ };
828
+ "/spaces/{spaceId}/cubes/{cubeId}/domains/{mappingId}/records": {
829
+ parameters: {
830
+ query?: never;
831
+ header?: never;
832
+ path?: never;
833
+ cookie?: never;
834
+ };
835
+ /**
836
+ * DNS records this domain needs, with their live status
837
+ * @description Every record required for the domain to work, each checked against live DNS. Poll this after publishing them.
838
+ *
839
+ * `state` is per record: `found`, `missing` (not published yet — the expected state before you add it, never an error), `mismatch` (something else is there), or `unknown` (we could not check — never a statement about your DNS). `summary.complete` is true only when every record is `found`.
840
+ *
841
+ * A wildcard needs three records; an exact host needs one. Each call performs live DNS lookups and is rate limited.
842
+ */
843
+ get: {
844
+ parameters: {
845
+ query?: never;
846
+ header?: never;
847
+ path: {
848
+ spaceId: string;
849
+ cubeId: string;
850
+ mappingId: string;
851
+ };
852
+ cookie?: never;
853
+ };
854
+ requestBody?: never;
855
+ responses: {
856
+ /** @description Required records with live status */
857
+ 200: {
858
+ headers: {
859
+ [name: string]: unknown;
860
+ };
861
+ content: {
862
+ "application/json": {
863
+ domain: string;
864
+ isWildcard: boolean;
865
+ records: components["schemas"]["DnsRecordStatus"][];
866
+ summary: {
867
+ found: number;
868
+ total: number;
869
+ complete: boolean;
870
+ };
871
+ /** Format: date-time */
872
+ checkedAt: string;
1830
873
  };
1831
- image: string;
1832
- sshUser: string;
1833
- costPerHour: number;
1834
- /** Format: date-time */
1835
- createdAt: string;
1836
- /** Format: date-time */
1837
- updatedAt: string;
1838
- };
1839
- Pagination: {
1840
- page: number;
1841
- limit: number;
1842
- total: number;
1843
- totalPages: number;
1844
- };
1845
- Region: {
1846
- id: string;
1847
- name: string;
1848
- slug: string;
874
+ };
1849
875
  };
1850
- Image: {
1851
- id: string;
1852
- name: string;
1853
- version: string;
1854
- description: string;
1855
- defaultUser: string;
1856
- };
1857
- PricingTier: {
1858
- minVcpus: number;
1859
- maxVcpus: number | null;
1860
- multiplier: number;
1861
- label: string;
1862
- };
1863
- DnsRecord: {
1864
- /** @enum {string} */
1865
- id: "ownership" | "routing" | "certificate";
1866
- /** @enum {string} */
1867
- type: "CNAME" | "TXT" | "A";
1868
- host: string;
1869
- value: string;
1870
- /** @enum {string} */
1871
- purpose: "ownership" | "routing" | "certificate";
1872
- note?: string | null;
1873
- mustBeGrey: boolean;
1874
- proxyOk: boolean;
1875
- };
1876
- DnsRecordStatus: {
1877
- id: string;
1878
- /** @enum {string} */
1879
- type: "CNAME" | "TXT" | "A";
1880
- host: string;
1881
- value: string;
1882
- purpose: string;
1883
- note?: string | null;
1884
- mustBeGrey?: boolean;
1885
- proxyOk?: boolean;
1886
- /** @enum {string} */
1887
- state: "found" | "missing" | "mismatch" | "unknown";
1888
- detail: string;
1889
- observed?: string[] | null;
1890
- };
1891
- Domain: {
1892
- id: string;
1893
- cubeId: string;
1894
- domain: string;
1895
- port: number | null;
1896
- status: string;
1897
- ingressStatus: string | null;
1898
- /** @enum {string} */
1899
- securityHeadersMode: "enforced" | "app_managed";
1900
- responseHeaderTimeoutSecs: number;
876
+ 404: components["responses"]["NotFound"];
877
+ 429: components["responses"]["RateLimited"];
878
+ };
879
+ };
880
+ put?: never;
881
+ post?: never;
882
+ delete?: never;
883
+ options?: never;
884
+ head?: never;
885
+ patch?: never;
886
+ trace?: never;
887
+ };
888
+ "/spaces/{spaceId}/cubes/{cubeId}/domains/{mappingId}": {
889
+ parameters: {
890
+ query?: never;
891
+ header?: never;
892
+ path?: never;
893
+ cookie?: never;
894
+ };
895
+ get?: never;
896
+ put?: never;
897
+ post?: never;
898
+ /** Detach a custom domain */
899
+ delete: {
900
+ parameters: {
901
+ query?: never;
902
+ header?: never;
903
+ path: {
904
+ spaceId: string;
905
+ cubeId: string;
906
+ mappingId: string;
907
+ };
908
+ cookie?: never;
909
+ };
910
+ requestBody?: never;
911
+ responses: {
912
+ /** @description Detached */
913
+ 200: {
914
+ headers: {
915
+ [name: string]: unknown;
916
+ };
917
+ content: {
918
+ "application/json": {
919
+ success: boolean;
920
+ };
921
+ };
922
+ };
923
+ 404: components["responses"]["NotFound"];
924
+ };
925
+ };
926
+ options?: never;
927
+ head?: never;
928
+ /**
929
+ * Update a custom domain's proxy settings
930
+ * @description Partial update — only the fields you send change; omitted fields are left as-is. The Basic Auth password is write-only and bcrypt-hashed server-side.
931
+ */
932
+ patch: {
933
+ parameters: {
934
+ query?: never;
935
+ header?: never;
936
+ path: {
937
+ spaceId: string;
938
+ cubeId: string;
939
+ mappingId: string;
940
+ };
941
+ cookie?: never;
942
+ };
943
+ requestBody: {
944
+ content: {
945
+ "application/json": {
946
+ /**
947
+ * @description enforced = proxy sets platform security headers (HSTS, X-Frame-Options, …); app_managed = the app's own headers pass through. Default enforced.
948
+ * @enum {string}
949
+ */
950
+ securityHeadersMode?: "enforced" | "app_managed";
951
+ /** @description Seconds the app may take to send response headers (streaming unaffected). Default 60. */
952
+ responseHeaderTimeoutSecs?: number;
1901
953
  /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
1902
- responseHeaderOverrides: {
1903
- set?: {
1904
- [key: string]: string;
1905
- };
1906
- remove?: string[];
954
+ responseHeaderOverrides?: {
955
+ set?: {
956
+ [key: string]: string;
957
+ };
958
+ remove?: string[];
1907
959
  } | null;
1908
960
  /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
1909
- requestHeaderOverrides: {
1910
- set?: {
1911
- [key: string]: string;
1912
- };
1913
- remove?: string[];
961
+ requestHeaderOverrides?: {
962
+ set?: {
963
+ [key: string]: string;
964
+ };
965
+ remove?: string[];
966
+ } | null;
967
+ /** @description Max request body size (MB). Null = unlimited (default). */
968
+ maxRequestBodyMb?: number | null;
969
+ /** @description Per-domain CORS policy, applied at the edge. Null (default) = CORS disabled and no Access-Control-* header is emitted anywhere. When set, the proxy answers OPTIONS preflight itself (204, the cube is never involved) and adds the headers to normal AND error responses, so a cross-origin request to a failing or sleeping cube is never CORS-masked. */
970
+ corsConfig?: {
971
+ /** @description Exact scheme://host[:port] origins (no path, query or trailing slash), or the single-element wildcard ["*"]. "*" and allowCredentials are mutually exclusive. */
972
+ allowedOrigins: string[];
973
+ /** @description Allowed methods. Omitted = GET, POST, PUT, PATCH, DELETE, OPTIONS. */
974
+ allowedMethods?: string[];
975
+ /** @description Allowed request headers. Omitted/empty = echo the preflight's Access-Control-Request-Headers. */
976
+ allowedHeaders?: string[];
977
+ /** @description Response headers exposed to JS. Omitted/empty = none. */
978
+ exposedHeaders?: string[];
979
+ /** @description Send Access-Control-Allow-Credentials: true. Rejected together with the "*" origin. */
980
+ allowCredentials?: boolean;
981
+ /** @description Preflight cache TTL. Default 600; 86400 is Chromium's hard cap. */
982
+ maxAgeSeconds?: number;
1914
983
  } | null;
1915
- maxRequestBodyMb: number | null;
1916
- responseCompression: boolean;
1917
- ipAllowList: string[] | null;
1918
- ipDenyList: string[] | null;
1919
- basicAuthUser: string | null;
1920
- basicAuthEnabled: boolean;
1921
- corsConfig: Record<string, never> | null;
1922
- isWildcard: boolean;
1923
- /** @enum {string|null} */
1924
- wildcardCertState: "pending_delegation" | "issuing" | "ready" | "failed" | null;
1925
- acmeDelegationTarget: string | null;
1926
- /** Format: date-time */
1927
- createdAt: string;
1928
- /** Format: date-time */
1929
- updatedAt: string;
1930
- };
1931
- TcpMapping: {
1932
- id: string;
1933
- cubeId: string;
984
+ /**
985
+ * @description Scheme the edge speaks to the CUBE on the backend hop. http (default) = cleartext. https = the cube terminates TLS itself (a control panel holding its own certificate, or an app listening on HTTPS) and answers plain HTTP with a redirect, so it cannot be reached over cleartext at all. Visitors are on HTTPS either way. The dial port is derived: https on the default port 80 connects on 443; a deliberate custom port is honoured exactly. Verified against the cube before it is applied — if the domain does not serve, the route is left on http.
986
+ * @enum {string}
987
+ */
988
+ originScheme?: "http" | "https";
989
+ /** @description Edge gzip/zstd compression. Default false (domains behind a CDN are already compressed there). */
990
+ responseCompression?: boolean;
991
+ /** @description Visitor IP/CIDR allow-list (v4+v6). Non-empty ⇒ only these reach the app. Null/empty = open. */
992
+ ipAllowList?: string[] | null;
993
+ /** @description Visitor IP/CIDR deny-list (v4+v6) 403. Null/empty = none. */
994
+ ipDenyList?: string[] | null;
995
+ /** @description HTTP Basic Auth username. Null/empty clears Basic Auth. Setting it requires basicAuthPassword. */
996
+ basicAuthUser?: string | null;
997
+ /** @description Plaintext Basic Auth password — bcrypt-hashed server-side, never stored or returned. Required when setting basicAuthUser. */
998
+ basicAuthPassword?: string;
999
+ };
1000
+ };
1001
+ };
1002
+ responses: {
1003
+ /** @description Settings updated */
1004
+ 200: {
1005
+ headers: {
1006
+ [name: string]: unknown;
1007
+ };
1008
+ content: {
1009
+ "application/json": {
1010
+ domain: components["schemas"]["Domain"];
1011
+ };
1012
+ };
1013
+ };
1014
+ 400: components["responses"]["BadRequest"];
1015
+ 404: components["responses"]["NotFound"];
1016
+ 429: components["responses"]["RateLimited"];
1017
+ };
1018
+ };
1019
+ trace?: never;
1020
+ };
1021
+ "/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings": {
1022
+ parameters: {
1023
+ query?: never;
1024
+ header?: never;
1025
+ path?: never;
1026
+ cookie?: never;
1027
+ };
1028
+ /** List TCP port forwards for a Cube */
1029
+ get: {
1030
+ parameters: {
1031
+ query?: never;
1032
+ header?: never;
1033
+ path: {
1034
+ spaceId: string;
1035
+ cubeId: string;
1036
+ };
1037
+ cookie?: never;
1038
+ };
1039
+ requestBody?: never;
1040
+ responses: {
1041
+ /** @description TCP mapping list */
1042
+ 200: {
1043
+ headers: {
1044
+ [name: string]: unknown;
1045
+ };
1046
+ content: {
1047
+ "application/json": {
1048
+ tcpMappings: components["schemas"]["TcpMapping"][];
1049
+ };
1050
+ };
1051
+ };
1052
+ };
1053
+ };
1054
+ put?: never;
1055
+ /** Create a TCP port forward */
1056
+ post: {
1057
+ parameters: {
1058
+ query?: never;
1059
+ header?: {
1060
+ /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
1061
+ "Idempotency-Key"?: string;
1062
+ };
1063
+ path: {
1064
+ spaceId: string;
1065
+ cubeId: string;
1066
+ };
1067
+ cookie?: never;
1068
+ };
1069
+ requestBody: {
1070
+ content: {
1071
+ "application/json": {
1934
1072
  cubePort: number;
1935
- hostPort: number;
1936
- label: string | null;
1937
- status: string;
1938
- isSsh: boolean;
1939
- /** Format: date-time */
1940
- createdAt: string;
1941
- /** Format: date-time */
1942
- updatedAt: string;
1943
- whitelistedIps: {
1944
- id: string;
1945
- cidr: string;
1946
- }[];
1947
- };
1948
- Snapshot: {
1949
- id: string;
1950
- cubeId: string;
1073
+ whitelistIps?: string[];
1074
+ };
1075
+ };
1076
+ };
1077
+ responses: {
1078
+ /** @description Mapping created */
1079
+ 201: {
1080
+ headers: {
1081
+ [name: string]: unknown;
1082
+ };
1083
+ content: {
1084
+ "application/json": {
1085
+ tcpMapping: components["schemas"]["TcpMapping"];
1086
+ };
1087
+ };
1088
+ };
1089
+ 400: components["responses"]["BadRequest"];
1090
+ 429: components["responses"]["RateLimited"];
1091
+ };
1092
+ };
1093
+ delete?: never;
1094
+ options?: never;
1095
+ head?: never;
1096
+ patch?: never;
1097
+ trace?: never;
1098
+ };
1099
+ "/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings/{mappingId}": {
1100
+ parameters: {
1101
+ query?: never;
1102
+ header?: never;
1103
+ path?: never;
1104
+ cookie?: never;
1105
+ };
1106
+ get?: never;
1107
+ put?: never;
1108
+ post?: never;
1109
+ /** Delete a TCP port forward */
1110
+ delete: {
1111
+ parameters: {
1112
+ query?: never;
1113
+ header?: never;
1114
+ path: {
1115
+ spaceId: string;
1116
+ cubeId: string;
1117
+ mappingId: string;
1118
+ };
1119
+ cookie?: never;
1120
+ };
1121
+ requestBody?: never;
1122
+ responses: {
1123
+ /** @description Deleted */
1124
+ 200: {
1125
+ headers: {
1126
+ [name: string]: unknown;
1127
+ };
1128
+ content: {
1129
+ "application/json": {
1130
+ success: boolean;
1131
+ };
1132
+ };
1133
+ };
1134
+ 404: components["responses"]["NotFound"];
1135
+ };
1136
+ };
1137
+ options?: never;
1138
+ head?: never;
1139
+ patch?: never;
1140
+ trace?: never;
1141
+ };
1142
+ "/spaces/{spaceId}/cubes/{cubeId}/snapshots": {
1143
+ parameters: {
1144
+ query?: never;
1145
+ header?: never;
1146
+ path?: never;
1147
+ cookie?: never;
1148
+ };
1149
+ /** List snapshots for a Cube */
1150
+ get: {
1151
+ parameters: {
1152
+ query?: never;
1153
+ header?: never;
1154
+ path: {
1155
+ spaceId: string;
1156
+ cubeId: string;
1157
+ };
1158
+ cookie?: never;
1159
+ };
1160
+ requestBody?: never;
1161
+ responses: {
1162
+ /** @description Snapshot list */
1163
+ 200: {
1164
+ headers: {
1165
+ [name: string]: unknown;
1166
+ };
1167
+ content: {
1168
+ "application/json": {
1169
+ snapshots: components["schemas"]["Snapshot"][];
1170
+ };
1171
+ };
1172
+ };
1173
+ };
1174
+ };
1175
+ put?: never;
1176
+ /** Create a snapshot */
1177
+ post: {
1178
+ parameters: {
1179
+ query?: never;
1180
+ header?: {
1181
+ /** @description Optional unique key (max 255 chars). Replays return the original response and add header Idempotency-Replayed: true. Scoped per space; expires after 24h. */
1182
+ "Idempotency-Key"?: string;
1183
+ };
1184
+ path: {
1185
+ spaceId: string;
1186
+ cubeId: string;
1187
+ };
1188
+ cookie?: never;
1189
+ };
1190
+ requestBody?: {
1191
+ content: {
1192
+ "application/json": {
1193
+ name?: string;
1194
+ };
1195
+ };
1196
+ };
1197
+ responses: {
1198
+ /** @description Snapshot enqueued */
1199
+ 201: {
1200
+ headers: {
1201
+ [name: string]: unknown;
1202
+ };
1203
+ content: {
1204
+ "application/json": {
1205
+ snapshot: components["schemas"]["Snapshot"];
1206
+ };
1207
+ };
1208
+ };
1209
+ 429: components["responses"]["RateLimited"];
1210
+ };
1211
+ };
1212
+ delete?: never;
1213
+ options?: never;
1214
+ head?: never;
1215
+ patch?: never;
1216
+ trace?: never;
1217
+ };
1218
+ "/spaces/{spaceId}/cubes/{cubeId}/snapshots/{snapshotId}": {
1219
+ parameters: {
1220
+ query?: never;
1221
+ header?: never;
1222
+ path?: never;
1223
+ cookie?: never;
1224
+ };
1225
+ get?: never;
1226
+ put?: never;
1227
+ post?: never;
1228
+ /** Delete a snapshot */
1229
+ delete: {
1230
+ parameters: {
1231
+ query?: never;
1232
+ header?: never;
1233
+ path: {
1234
+ spaceId: string;
1235
+ cubeId: string;
1236
+ snapshotId: string;
1237
+ };
1238
+ cookie?: never;
1239
+ };
1240
+ requestBody?: never;
1241
+ responses: {
1242
+ /** @description Deleted */
1243
+ 200: {
1244
+ headers: {
1245
+ [name: string]: unknown;
1246
+ };
1247
+ content: {
1248
+ "application/json": {
1249
+ success: boolean;
1250
+ };
1251
+ };
1252
+ };
1253
+ 404: components["responses"]["NotFound"];
1254
+ };
1255
+ };
1256
+ options?: never;
1257
+ head?: never;
1258
+ patch?: never;
1259
+ trace?: never;
1260
+ };
1261
+ "/spaces/{spaceId}/cubes/{cubeId}/restore": {
1262
+ parameters: {
1263
+ query?: never;
1264
+ header?: never;
1265
+ path?: never;
1266
+ cookie?: never;
1267
+ };
1268
+ get?: never;
1269
+ put?: never;
1270
+ /** Restore a Cube from a snapshot */
1271
+ post: {
1272
+ parameters: {
1273
+ query?: never;
1274
+ header?: never;
1275
+ path: {
1276
+ spaceId: string;
1277
+ cubeId: string;
1278
+ };
1279
+ cookie?: never;
1280
+ };
1281
+ requestBody: {
1282
+ content: {
1283
+ "application/json": {
1284
+ snapshotId: string;
1285
+ };
1286
+ };
1287
+ };
1288
+ responses: {
1289
+ /** @description Restore enqueued */
1290
+ 200: {
1291
+ headers: {
1292
+ [name: string]: unknown;
1293
+ };
1294
+ content: {
1295
+ "application/json": {
1296
+ success: boolean;
1297
+ };
1298
+ };
1299
+ };
1300
+ 404: components["responses"]["NotFound"];
1301
+ };
1302
+ };
1303
+ delete?: never;
1304
+ options?: never;
1305
+ head?: never;
1306
+ patch?: never;
1307
+ trace?: never;
1308
+ };
1309
+ "/spaces/{spaceId}/backups/{backupId}/download": {
1310
+ parameters: {
1311
+ query?: never;
1312
+ header?: never;
1313
+ path?: never;
1314
+ cookie?: never;
1315
+ };
1316
+ /** Generate a presigned download URL for a backup .cube archive */
1317
+ get: {
1318
+ parameters: {
1319
+ query?: never;
1320
+ header?: never;
1321
+ path: {
1322
+ spaceId: string;
1323
+ backupId: string;
1324
+ };
1325
+ cookie?: never;
1326
+ };
1327
+ requestBody?: never;
1328
+ responses: {
1329
+ /** @description Presigned URL valid for 15 minutes */
1330
+ 200: {
1331
+ headers: {
1332
+ [name: string]: unknown;
1333
+ };
1334
+ content: {
1335
+ "application/json": {
1336
+ url?: string;
1337
+ filename?: string;
1338
+ sizeBytes?: number | null;
1339
+ /** Format: date-time */
1340
+ expiresAt?: string;
1341
+ };
1342
+ };
1343
+ };
1344
+ 404: components["responses"]["NotFound"];
1345
+ /** @description Backup is not in 'complete' status */
1346
+ 409: {
1347
+ headers: {
1348
+ [name: string]: unknown;
1349
+ };
1350
+ content?: never;
1351
+ };
1352
+ };
1353
+ };
1354
+ put?: never;
1355
+ post?: never;
1356
+ delete?: never;
1357
+ options?: never;
1358
+ head?: never;
1359
+ patch?: never;
1360
+ trace?: never;
1361
+ };
1362
+ "/spaces/{spaceId}/cubes/imports": {
1363
+ parameters: {
1364
+ query?: never;
1365
+ header?: never;
1366
+ path?: never;
1367
+ cookie?: never;
1368
+ };
1369
+ get?: never;
1370
+ put?: never;
1371
+ /** Initiate a .cube archive import (browser-side multipart upload) */
1372
+ post: {
1373
+ parameters: {
1374
+ query?: never;
1375
+ header?: never;
1376
+ path: {
1377
+ spaceId: string;
1378
+ };
1379
+ cookie?: never;
1380
+ };
1381
+ requestBody: {
1382
+ content: {
1383
+ "application/json": {
1951
1384
  name: string;
1952
- sizeBytes: number | null;
1953
- status: string;
1954
- kind: string;
1955
- /** Format: date-time */
1956
- createdAt: string;
1957
- };
1958
- Webhook: {
1959
- id: string;
1385
+ fileSizeBytes: number;
1386
+ /**
1387
+ * @description What to do with SSH access on the imported rootfs. `replace` (default) writes `sshPublicKey` to the login user's authorized_keys and requires `sshPublicKey` to be set. `keep` leaves the image's own authorized_keys and sshd configuration completely untouched — nothing is written — so you must already hold a private key that the image accepts, or you will not be able to log in.
1388
+ * @default replace
1389
+ * @enum {string}
1390
+ */
1391
+ sshKeyMode?: "replace" | "keep";
1392
+ /** @description Public key to install when `sshKeyMode` is `replace`. Written to the login user's `~/.ssh/authorized_keys` — which user that is comes from the imported rootfs itself, so an image without a Krova default user keeps logging in as root. Ignored when `sshKeyMode` is `keep`. */
1393
+ sshPublicKey?: string | null;
1394
+ region?: string | null;
1395
+ vcpusOverride?: number | null;
1396
+ ramMbOverride?: number | null;
1397
+ diskGbOverride?: number | null;
1398
+ userData?: string | null;
1399
+ expectedConfig?: {
1400
+ vcpus?: number;
1401
+ ramMb?: number;
1402
+ diskLimitGb?: number;
1403
+ } | null;
1404
+ };
1405
+ };
1406
+ };
1407
+ responses: {
1408
+ /** @description Import initiated; returns presigned part URLs */
1409
+ 201: {
1410
+ headers: {
1411
+ [name: string]: unknown;
1412
+ };
1413
+ content: {
1414
+ "application/json": {
1415
+ importId?: string;
1416
+ uploadId?: string;
1417
+ key?: string;
1418
+ chunkSizeBytes?: number;
1419
+ parts?: {
1420
+ partNumber?: number;
1421
+ url?: string;
1422
+ }[];
1423
+ /** Format: date-time */
1424
+ expiresAt?: string;
1425
+ };
1426
+ };
1427
+ };
1428
+ /** @description Invalid input */
1429
+ 400: {
1430
+ headers: {
1431
+ [name: string]: unknown;
1432
+ };
1433
+ content?: never;
1434
+ };
1435
+ /** @description Plan limit exceeded */
1436
+ 403: {
1437
+ headers: {
1438
+ [name: string]: unknown;
1439
+ };
1440
+ content?: never;
1441
+ };
1442
+ /** @description No active storage backend */
1443
+ 503: {
1444
+ headers: {
1445
+ [name: string]: unknown;
1446
+ };
1447
+ content?: never;
1448
+ };
1449
+ };
1450
+ };
1451
+ delete?: never;
1452
+ options?: never;
1453
+ head?: never;
1454
+ patch?: never;
1455
+ trace?: never;
1456
+ };
1457
+ "/spaces/{spaceId}/cubes/imports/{importId}": {
1458
+ parameters: {
1459
+ query?: never;
1460
+ header?: never;
1461
+ path?: never;
1462
+ cookie?: never;
1463
+ };
1464
+ /** Get the current state of an import */
1465
+ get: {
1466
+ parameters: {
1467
+ query?: never;
1468
+ header?: never;
1469
+ path: {
1470
+ spaceId: string;
1471
+ importId: string;
1472
+ };
1473
+ cookie?: never;
1474
+ };
1475
+ requestBody?: never;
1476
+ responses: {
1477
+ /** @description Current import state */
1478
+ 200: {
1479
+ headers: {
1480
+ [name: string]: unknown;
1481
+ };
1482
+ content: {
1483
+ "application/json": {
1484
+ import?: {
1485
+ id?: string;
1486
+ name?: string;
1487
+ /** @enum {string} */
1488
+ status?: "uploading" | "finalizing" | "provisioning" | "complete" | "failed" | "expired";
1489
+ cubeId?: string | null;
1490
+ error?: string | null;
1491
+ createdAt?: string;
1492
+ updatedAt?: string;
1493
+ completedAt?: string | null;
1494
+ };
1495
+ };
1496
+ };
1497
+ };
1498
+ 404: components["responses"]["NotFound"];
1499
+ };
1500
+ };
1501
+ put?: never;
1502
+ post?: never;
1503
+ /** Cancel an in-flight upload (only allowed in 'uploading' state) */
1504
+ delete: {
1505
+ parameters: {
1506
+ query?: never;
1507
+ header?: never;
1508
+ path: {
1509
+ spaceId: string;
1510
+ importId: string;
1511
+ };
1512
+ cookie?: never;
1513
+ };
1514
+ requestBody?: never;
1515
+ responses: {
1516
+ /** @description Cancelled */
1517
+ 200: {
1518
+ headers: {
1519
+ [name: string]: unknown;
1520
+ };
1521
+ content: {
1522
+ "application/json": {
1523
+ success: boolean;
1524
+ };
1525
+ };
1526
+ };
1527
+ 404: components["responses"]["NotFound"];
1528
+ /** @description Cannot cancel an import past the 'uploading' state */
1529
+ 409: {
1530
+ headers: {
1531
+ [name: string]: unknown;
1532
+ };
1533
+ content?: never;
1534
+ };
1535
+ };
1536
+ };
1537
+ options?: never;
1538
+ head?: never;
1539
+ patch?: never;
1540
+ trace?: never;
1541
+ };
1542
+ "/spaces/{spaceId}/cubes/imports/{importId}/complete": {
1543
+ parameters: {
1544
+ query?: never;
1545
+ header?: never;
1546
+ path?: never;
1547
+ cookie?: never;
1548
+ };
1549
+ get?: never;
1550
+ put?: never;
1551
+ /** Finalize a .cube import: complete multipart upload + create cube row + enqueue provisioning */
1552
+ post: {
1553
+ parameters: {
1554
+ query?: never;
1555
+ header?: never;
1556
+ path: {
1557
+ spaceId: string;
1558
+ importId: string;
1559
+ };
1560
+ cookie?: never;
1561
+ };
1562
+ requestBody: {
1563
+ content: {
1564
+ "application/json": {
1565
+ parts: {
1566
+ partNumber: number;
1567
+ etag: string;
1568
+ }[];
1569
+ config: {
1570
+ vcpus: number;
1571
+ ramMb: number;
1572
+ diskLimitGb: number;
1573
+ imageId: string;
1574
+ userData?: string | null;
1575
+ };
1576
+ };
1577
+ };
1578
+ };
1579
+ responses: {
1580
+ /** @description Provisioning enqueued */
1581
+ 200: {
1582
+ headers: {
1583
+ [name: string]: unknown;
1584
+ };
1585
+ content: {
1586
+ "application/json": {
1587
+ importId?: string;
1588
+ cubeId?: string;
1589
+ /** @enum {string} */
1590
+ status?: "provisioning";
1591
+ };
1592
+ };
1593
+ };
1594
+ /** @description Invalid input */
1595
+ 400: {
1596
+ headers: {
1597
+ [name: string]: unknown;
1598
+ };
1599
+ content?: never;
1600
+ };
1601
+ /** @description Plan limit exceeded */
1602
+ 403: {
1603
+ headers: {
1604
+ [name: string]: unknown;
1605
+ };
1606
+ content?: never;
1607
+ };
1608
+ /** @description Import not in 'uploading' state */
1609
+ 409: {
1610
+ headers: {
1611
+ [name: string]: unknown;
1612
+ };
1613
+ content?: never;
1614
+ };
1615
+ /** @description S3 finalization failed */
1616
+ 502: {
1617
+ headers: {
1618
+ [name: string]: unknown;
1619
+ };
1620
+ content?: never;
1621
+ };
1622
+ /** @description Storage backend unavailable */
1623
+ 503: {
1624
+ headers: {
1625
+ [name: string]: unknown;
1626
+ };
1627
+ content?: never;
1628
+ };
1629
+ };
1630
+ };
1631
+ delete?: never;
1632
+ options?: never;
1633
+ head?: never;
1634
+ patch?: never;
1635
+ trace?: never;
1636
+ };
1637
+ "/spaces/{spaceId}/webhooks": {
1638
+ parameters: {
1639
+ query?: never;
1640
+ header?: never;
1641
+ path?: never;
1642
+ cookie?: never;
1643
+ };
1644
+ /** List webhook endpoints */
1645
+ get: {
1646
+ parameters: {
1647
+ query?: never;
1648
+ header?: never;
1649
+ path: {
1650
+ spaceId: string;
1651
+ };
1652
+ cookie?: never;
1653
+ };
1654
+ requestBody?: never;
1655
+ responses: {
1656
+ /** @description Webhook list */
1657
+ 200: {
1658
+ headers: {
1659
+ [name: string]: unknown;
1660
+ };
1661
+ content?: never;
1662
+ };
1663
+ };
1664
+ };
1665
+ put?: never;
1666
+ /** Create a webhook endpoint (signing secret returned once) */
1667
+ post: {
1668
+ parameters: {
1669
+ query?: never;
1670
+ header?: never;
1671
+ path: {
1672
+ spaceId: string;
1673
+ };
1674
+ cookie?: never;
1675
+ };
1676
+ requestBody: {
1677
+ content: {
1678
+ "application/json": {
1960
1679
  /** Format: uri */
1961
1680
  url: string;
1962
- events: string[];
1963
- enabled: boolean;
1964
- /** Format: date-time */
1965
- createdAt: string;
1966
- /** Format: date-time */
1967
- updatedAt: string;
1968
- };
1969
- WebhookDelivery: {
1970
- id: string;
1971
- event: string;
1972
- /** @enum {string} */
1973
- status: "pending" | "delivered" | "failed";
1974
- attempts: number;
1975
- /** Format: date-time */
1976
- lastAttemptAt: string | null;
1977
- responseStatus: number | null;
1978
- /** Format: date-time */
1979
- createdAt: string;
1980
- };
1981
- Error: {
1982
- error: string;
1983
- };
1984
- };
1985
- responses: {
1986
- /** @description Bad request */
1987
- BadRequest: {
1988
- headers: {
1989
- [name: string]: unknown;
1990
- };
1991
- content: {
1992
- "application/json": components["schemas"]["Error"];
1993
- };
1994
- };
1995
- /** @description Missing or invalid API key */
1996
- Unauthorized: {
1997
- headers: {
1998
- [name: string]: unknown;
1999
- };
2000
- content: {
2001
- "application/json": components["schemas"]["Error"];
2002
- };
2003
- };
2004
- /** @description Authenticated but lacks the required permission */
2005
- Forbidden: {
2006
- headers: {
2007
- [name: string]: unknown;
2008
- };
2009
- content: {
2010
- "application/json": components["schemas"]["Error"];
2011
- };
2012
- };
2013
- /** @description Resource not found */
2014
- NotFound: {
2015
- headers: {
2016
- [name: string]: unknown;
2017
- };
2018
- content: {
2019
- "application/json": components["schemas"]["Error"];
2020
- };
2021
- };
2022
- /** @description Rate limit exceeded (10 mutations / 60s) */
2023
- RateLimited: {
2024
- headers: {
2025
- [name: string]: unknown;
2026
- };
2027
- content: {
2028
- "application/json": components["schemas"]["Error"];
2029
- };
2030
- };
1681
+ events: ("cube.created" | "cube.running" | "cube.stopped" | "cube.error" | "cube.deleted" | "cube.cold_restarted" | "cube.transfer.started" | "cube.transfer.completed" | "cube.transfer.failed" | "cube.resize.started" | "cube.resize.completed" | "cube.resize.failed" | "resource.alert.memory" | "resource.alert.cpu" | "resource.alert.disk" | "domain.alert.error_4xx" | "domain.alert.error_5xx" | "snapshot.created" | "snapshot.restored" | "snapshot.deleted" | "snapshot.pinned" | "snapshot.promoted_to_backup" | "snapshot.exported" | "backup.created" | "backup.deleted" | "backup.redeployed" | "domain.added" | "domain.active" | "domain.removed" | "tcp_mapping.added" | "tcp_mapping.removed" | "tcp_mapping.updated" | "hosting.provisioned" | "hosting.suspended" | "hosting.unsuspended" | "hosting.deleted" | "hosting.plan_changed" | "hosting.renewed" | "hosting.cancellation_scheduled" | "hosting.suspended_for_non_payment" | "hosting.deleted_after_recovery" | "member.invited" | "member.joined" | "member.removed" | "member.role_changed")[];
1682
+ };
1683
+ };
1684
+ };
1685
+ responses: {
1686
+ /** @description Webhook created (response includes secret) */
1687
+ 201: {
1688
+ headers: {
1689
+ [name: string]: unknown;
1690
+ };
1691
+ content?: never;
1692
+ };
1693
+ 400: components["responses"]["BadRequest"];
1694
+ 429: components["responses"]["RateLimited"];
1695
+ };
1696
+ };
1697
+ delete?: never;
1698
+ options?: never;
1699
+ head?: never;
1700
+ patch?: never;
1701
+ trace?: never;
1702
+ };
1703
+ "/spaces/{spaceId}/webhooks/{endpointId}": {
1704
+ parameters: {
1705
+ query?: never;
1706
+ header?: never;
1707
+ path?: never;
1708
+ cookie?: never;
1709
+ };
1710
+ /** Get a webhook (no secret) */
1711
+ get: {
1712
+ parameters: {
1713
+ query?: never;
1714
+ header?: never;
1715
+ path: {
1716
+ spaceId: string;
1717
+ endpointId: string;
1718
+ };
1719
+ cookie?: never;
1720
+ };
1721
+ requestBody?: never;
1722
+ responses: {
1723
+ /** @description Webhook */
1724
+ 200: {
1725
+ headers: {
1726
+ [name: string]: unknown;
1727
+ };
1728
+ content?: never;
1729
+ };
1730
+ };
1731
+ };
1732
+ put?: never;
1733
+ post?: never;
1734
+ /** Delete a webhook (cascades deliveries) */
1735
+ delete: {
1736
+ parameters: {
1737
+ query?: never;
1738
+ header?: never;
1739
+ path: {
1740
+ spaceId: string;
1741
+ endpointId: string;
1742
+ };
1743
+ cookie?: never;
1744
+ };
1745
+ requestBody?: never;
1746
+ responses: {
1747
+ /** @description Deleted */
1748
+ 200: {
1749
+ headers: {
1750
+ [name: string]: unknown;
1751
+ };
1752
+ content?: never;
1753
+ };
1754
+ 429: components["responses"]["RateLimited"];
1755
+ };
1756
+ };
1757
+ options?: never;
1758
+ head?: never;
1759
+ patch?: never;
1760
+ trace?: never;
1761
+ };
1762
+ "/spaces/{spaceId}/webhooks/{endpointId}/deliveries": {
1763
+ parameters: {
1764
+ query?: never;
1765
+ header?: never;
1766
+ path?: never;
1767
+ cookie?: never;
2031
1768
  };
2032
- parameters: never;
2033
- requestBodies: never;
2034
- headers: never;
2035
- pathItems: never;
1769
+ /** Last 30 days of webhook delivery history (max 100) */
1770
+ get: {
1771
+ parameters: {
1772
+ query?: {
1773
+ limit?: number;
1774
+ };
1775
+ header?: never;
1776
+ path: {
1777
+ spaceId: string;
1778
+ endpointId: string;
1779
+ };
1780
+ cookie?: never;
1781
+ };
1782
+ requestBody?: never;
1783
+ responses: {
1784
+ /** @description Delivery list */
1785
+ 200: {
1786
+ headers: {
1787
+ [name: string]: unknown;
1788
+ };
1789
+ content?: never;
1790
+ };
1791
+ };
1792
+ };
1793
+ put?: never;
1794
+ post?: never;
1795
+ delete?: never;
1796
+ options?: never;
1797
+ head?: never;
1798
+ patch?: never;
1799
+ trace?: never;
1800
+ };
2036
1801
  }
2037
-
1802
+ interface components {
1803
+ schemas: {
1804
+ Space: {
1805
+ id: string;
1806
+ name: string;
1807
+ tier: string;
1808
+ /** Format: date-time */
1809
+ createdAt: string;
1810
+ };
1811
+ CubeSshInfo: {
1812
+ host: string | null;
1813
+ port: number;
1814
+ user: string;
1815
+ hostKeys: {
1816
+ type: string;
1817
+ key: string;
1818
+ }[];
1819
+ };
1820
+ Cube: {
1821
+ id: string;
1822
+ name: string;
1823
+ /** @enum {string} */
1824
+ state: "pending" | "booting" | "running" | "stopped" | "stopping" | "error" | "deleted";
1825
+ publicIpv4: string | null;
1826
+ resources: {
1827
+ vcpu: number;
1828
+ ramGb: number;
1829
+ diskGb: number;
1830
+ };
1831
+ image: string;
1832
+ sshUser: string;
1833
+ costPerHour: number;
1834
+ /** Format: date-time */
1835
+ createdAt: string;
1836
+ /** Format: date-time */
1837
+ updatedAt: string;
1838
+ };
1839
+ Pagination: {
1840
+ page: number;
1841
+ limit: number;
1842
+ total: number;
1843
+ totalPages: number;
1844
+ };
1845
+ Region: {
1846
+ id: string;
1847
+ name: string;
1848
+ slug: string;
1849
+ };
1850
+ Image: {
1851
+ id: string;
1852
+ name: string;
1853
+ version: string;
1854
+ description: string;
1855
+ defaultUser: string;
1856
+ };
1857
+ PricingTier: {
1858
+ minVcpus: number;
1859
+ maxVcpus: number | null;
1860
+ multiplier: number;
1861
+ label: string;
1862
+ };
1863
+ DnsRecord: {
1864
+ /** @enum {string} */
1865
+ id: "ownership" | "routing" | "certificate";
1866
+ /** @enum {string} */
1867
+ type: "CNAME" | "TXT" | "A";
1868
+ host: string;
1869
+ value: string;
1870
+ /** @enum {string} */
1871
+ purpose: "ownership" | "routing" | "certificate";
1872
+ note?: string | null;
1873
+ mustBeGrey: boolean;
1874
+ proxyOk: boolean;
1875
+ };
1876
+ DnsRecordStatus: {
1877
+ id: string;
1878
+ /** @enum {string} */
1879
+ type: "CNAME" | "TXT" | "A";
1880
+ host: string;
1881
+ value: string;
1882
+ purpose: string;
1883
+ note?: string | null;
1884
+ mustBeGrey?: boolean;
1885
+ proxyOk?: boolean;
1886
+ /** @enum {string} */
1887
+ state: "found" | "missing" | "mismatch" | "unknown";
1888
+ detail: string;
1889
+ observed?: string[] | null;
1890
+ };
1891
+ Domain: {
1892
+ id: string;
1893
+ cubeId: string;
1894
+ domain: string;
1895
+ port: number | null;
1896
+ status: string;
1897
+ ingressStatus: string | null;
1898
+ /** @enum {string} */
1899
+ securityHeadersMode: "enforced" | "app_managed";
1900
+ responseHeaderTimeoutSecs: number;
1901
+ /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
1902
+ responseHeaderOverrides: {
1903
+ set?: {
1904
+ [key: string]: string;
1905
+ };
1906
+ remove?: string[];
1907
+ } | null;
1908
+ /** @description Header rewrites: `set` adds/overwrites, `remove` deletes. Null clears all. */
1909
+ requestHeaderOverrides: {
1910
+ set?: {
1911
+ [key: string]: string;
1912
+ };
1913
+ remove?: string[];
1914
+ } | null;
1915
+ maxRequestBodyMb: number | null;
1916
+ responseCompression: boolean;
1917
+ ipAllowList: string[] | null;
1918
+ ipDenyList: string[] | null;
1919
+ basicAuthUser: string | null;
1920
+ basicAuthEnabled: boolean;
1921
+ corsConfig: Record<string, never> | null;
1922
+ isWildcard: boolean;
1923
+ /** @enum {string|null} */
1924
+ wildcardCertState: "pending_delegation" | "issuing" | "ready" | "failed" | null;
1925
+ acmeDelegationTarget: string | null;
1926
+ /** Format: date-time */
1927
+ createdAt: string;
1928
+ /** Format: date-time */
1929
+ updatedAt: string;
1930
+ };
1931
+ TcpMapping: {
1932
+ id: string;
1933
+ cubeId: string;
1934
+ cubePort: number;
1935
+ hostPort: number;
1936
+ label: string | null;
1937
+ status: string;
1938
+ isSsh: boolean;
1939
+ /** Format: date-time */
1940
+ createdAt: string;
1941
+ /** Format: date-time */
1942
+ updatedAt: string;
1943
+ whitelistedIps: {
1944
+ id: string;
1945
+ cidr: string;
1946
+ }[];
1947
+ };
1948
+ Snapshot: {
1949
+ id: string;
1950
+ cubeId: string;
1951
+ name: string;
1952
+ sizeBytes: number | null;
1953
+ status: string;
1954
+ kind: string;
1955
+ /** Format: date-time */
1956
+ createdAt: string;
1957
+ };
1958
+ Webhook: {
1959
+ id: string;
1960
+ /** Format: uri */
1961
+ url: string;
1962
+ events: string[];
1963
+ enabled: boolean;
1964
+ /** Format: date-time */
1965
+ createdAt: string;
1966
+ /** Format: date-time */
1967
+ updatedAt: string;
1968
+ };
1969
+ WebhookDelivery: {
1970
+ id: string;
1971
+ event: string;
1972
+ /** @enum {string} */
1973
+ status: "pending" | "delivered" | "failed";
1974
+ attempts: number;
1975
+ /** Format: date-time */
1976
+ lastAttemptAt: string | null;
1977
+ responseStatus: number | null;
1978
+ /** Format: date-time */
1979
+ createdAt: string;
1980
+ };
1981
+ Error: {
1982
+ error: string;
1983
+ };
1984
+ };
1985
+ responses: {
1986
+ /** @description Bad request */
1987
+ BadRequest: {
1988
+ headers: {
1989
+ [name: string]: unknown;
1990
+ };
1991
+ content: {
1992
+ "application/json": components["schemas"]["Error"];
1993
+ };
1994
+ };
1995
+ /** @description Missing or invalid API key */
1996
+ Unauthorized: {
1997
+ headers: {
1998
+ [name: string]: unknown;
1999
+ };
2000
+ content: {
2001
+ "application/json": components["schemas"]["Error"];
2002
+ };
2003
+ };
2004
+ /** @description Authenticated but lacks the required permission */
2005
+ Forbidden: {
2006
+ headers: {
2007
+ [name: string]: unknown;
2008
+ };
2009
+ content: {
2010
+ "application/json": components["schemas"]["Error"];
2011
+ };
2012
+ };
2013
+ /** @description Resource not found */
2014
+ NotFound: {
2015
+ headers: {
2016
+ [name: string]: unknown;
2017
+ };
2018
+ content: {
2019
+ "application/json": components["schemas"]["Error"];
2020
+ };
2021
+ };
2022
+ /** @description Rate limit exceeded (10 mutations / 60s) */
2023
+ RateLimited: {
2024
+ headers: {
2025
+ [name: string]: unknown;
2026
+ };
2027
+ content: {
2028
+ "application/json": components["schemas"]["Error"];
2029
+ };
2030
+ };
2031
+ };
2032
+ parameters: never;
2033
+ requestBodies: never;
2034
+ headers: never;
2035
+ pathItems: never;
2036
+ }
2037
+ //#endregion
2038
+ //#region src/client.d.ts
2038
2039
  /** The Cube resource, as defined in the Krova Cloud OpenAPI spec. */
2039
2040
  type Cube = components["schemas"]["Cube"];
2040
2041
  /** A region with available capacity (from the catalog). */
@@ -2095,27 +2096,27 @@ declare const DEFAULT_BASE_URL = "https://krova.cloud/api/v1";
2095
2096
  */
2096
2097
  type AuthScheme = "x-api-key" | "bearer";
2097
2098
  interface KrovaClientOptions {
2098
- /**
2099
- * Your Krova Cloud API key (a `kro_...` token). Keys are scoped per Space
2100
- * and inherit the permissions of the membership that created them.
2101
- */
2102
- apiKey: string;
2103
- /** Override the API base URL. Defaults to {@link DEFAULT_BASE_URL}. */
2104
- baseUrl?: string;
2105
- /**
2106
- * Auth header scheme. Defaults to `"x-api-key"` (the spec's scheme).
2107
- */
2108
- authScheme?: AuthScheme;
2109
- /**
2110
- * Max automatic retries on retryable statuses (429, 503).
2111
- * Defaults to 2. Set to 0 to disable retries.
2112
- */
2113
- maxRetries?: number;
2114
- /**
2115
- * A custom `fetch` implementation (e.g. for tests or a proxy). Defaults to
2116
- * the global `fetch`.
2117
- */
2118
- fetch?: typeof fetch;
2099
+ /**
2100
+ * Your Krova Cloud API key (a `kro_...` token). Keys are scoped per Space
2101
+ * and inherit the permissions of the membership that created them.
2102
+ */
2103
+ apiKey: string;
2104
+ /** Override the API base URL. Defaults to {@link DEFAULT_BASE_URL}. */
2105
+ baseUrl?: string;
2106
+ /**
2107
+ * Auth header scheme. Defaults to `"x-api-key"` (the spec's scheme).
2108
+ */
2109
+ authScheme?: AuthScheme;
2110
+ /**
2111
+ * Max automatic retries on retryable statuses (429, 503).
2112
+ * Defaults to 2. Set to 0 to disable retries.
2113
+ */
2114
+ maxRetries?: number;
2115
+ /**
2116
+ * A custom `fetch` implementation (e.g. for tests or a proxy). Defaults to
2117
+ * the global `fetch`.
2118
+ */
2119
+ fetch?: typeof fetch;
2119
2120
  }
2120
2121
  /**
2121
2122
  * A typed client for the Krova Cloud API.
@@ -2127,283 +2128,284 @@ interface KrovaClientOptions {
2127
2128
  * ```
2128
2129
  */
2129
2130
  declare class KrovaClient {
2131
+ /**
2132
+ * The underlying openapi-fetch client — a fully typed escape hatch to every
2133
+ * path in the spec. Returns `{ data, error, response }` and never throws.
2134
+ *
2135
+ * @example
2136
+ * ```ts
2137
+ * const { data, error } = await krova.raw.GET(
2138
+ * "/spaces/{spaceId}/cubes/{cubeId}",
2139
+ * { params: { path: { spaceId, cubeId } } },
2140
+ * );
2141
+ * ```
2142
+ */
2143
+ readonly raw: Client<paths>;
2144
+ /** The resolved base URL in use. */
2145
+ readonly baseUrl: string;
2146
+ constructor(options: KrovaClientOptions);
2147
+ readonly cubes: {
2148
+ /** List Cubes in a Space, with pagination metadata. */
2149
+ list: (spaceId: string) => Promise<{
2150
+ cubes: {
2151
+ id: string;
2152
+ name: string;
2153
+ state: "pending" | "booting" | "running" | "stopped" | "stopping" | "error" | "deleted";
2154
+ publicIpv4: string | null;
2155
+ resources: {
2156
+ vcpu: number;
2157
+ ramGb: number;
2158
+ diskGb: number;
2159
+ };
2160
+ image: string;
2161
+ sshUser: string;
2162
+ costPerHour: number;
2163
+ createdAt: string;
2164
+ updatedAt: string;
2165
+ }[];
2166
+ pagination: {
2167
+ page: number;
2168
+ limit: number;
2169
+ total: number;
2170
+ totalPages: number;
2171
+ };
2172
+ }>;
2130
2173
  /**
2131
- * The underlying openapi-fetch client — a fully typed escape hatch to every
2132
- * path in the spec. Returns `{ data, error, response }` and never throws.
2174
+ * Create a Cube. Returns the created {@link Cube}.
2133
2175
  *
2134
- * @example
2135
- * ```ts
2136
- * const { data, error } = await krova.raw.GET(
2137
- * "/spaces/{spaceId}/cubes/{cubeId}",
2138
- * { params: { path: { spaceId, cubeId } } },
2139
- * );
2140
- * ```
2176
+ * @param spaceId Target Space id.
2177
+ * @param body Cube spec — `{ name, image, resources, sshPublicKey, ... }`.
2178
+ * @param opts Optional `idempotencyKey` (max 255 chars, scoped per space).
2141
2179
  */
2142
- readonly raw: Client<paths>;
2143
- /** The resolved base URL in use. */
2144
- readonly baseUrl: string;
2145
- constructor(options: KrovaClientOptions);
2146
- readonly cubes: {
2147
- /** List Cubes in a Space, with pagination metadata. */
2148
- list: (spaceId: string) => Promise<{
2149
- cubes: {
2150
- id: string;
2151
- name: string;
2152
- state: "pending" | "booting" | "running" | "stopped" | "stopping" | "error" | "deleted";
2153
- publicIpv4: string | null;
2154
- resources: {
2155
- vcpu: number;
2156
- ramGb: number;
2157
- diskGb: number;
2158
- };
2159
- image: string;
2160
- sshUser: string;
2161
- costPerHour: number;
2162
- createdAt: string;
2163
- updatedAt: string;
2164
- }[];
2165
- pagination: {
2166
- page: number;
2167
- limit: number;
2168
- total: number;
2169
- totalPages: number;
2170
- };
2171
- }>;
2172
- /**
2173
- * Create a Cube. Returns the created {@link Cube}.
2174
- *
2175
- * @param spaceId Target Space id.
2176
- * @param body Cube spec — `{ name, image, resources, sshPublicKey, ... }`.
2177
- * @param opts Optional `idempotencyKey` (max 255 chars, scoped per space).
2178
- */
2179
- create: (spaceId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes"]["post"]["requestBody"]>["content"]["application/json"], opts?: {
2180
- idempotencyKey?: string;
2181
- }) => Promise<Cube>;
2182
- /** Get a single Cube. Returns the {@link Cube}. */
2183
- get: (spaceId: string, cubeId: string) => Promise<Cube>;
2184
- /**
2185
- * Update the IN-CUBE port that SSH is forwarded to.
2186
- *
2187
- * `cubePort` is the port **inside** the Cube that sshd listens on — NOT the
2188
- * host port you connect to. The host port is allocated by Krova and is not
2189
- * changed by this call. Pointing this at a port nothing is listening on
2190
- * inside the Cube will silently make SSH unreachable; the default is 22.
2191
- *
2192
- * The Krova Cloud API exposes no general Cube-mutation endpoint; the only
2193
- * mutable Cube field over the API is this port, via
2194
- * `PUT /spaces/{spaceId}/cubes/{cubeId}/ssh-port`. This helper maps to that
2195
- * endpoint. (Compute resize / rename are not part of the public API.)
2196
- */
2197
- update: (spaceId: string, cubeId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/{cubeId}/ssh-port"]["put"]["requestBody"]>["content"]["application/json"]) => Promise<unknown>;
2198
- /** Delete a Cube (asynchronous — deletion is enqueued). */
2199
- delete: (spaceId: string, cubeId: string) => Promise<{
2200
- success: boolean;
2201
- }>;
2202
- /** Power off a running Cube (asynchronous — power-off is enqueued). The Cube
2203
- * becomes `stopped` (its host RAM is freed); start it again with `wake`. */
2204
- powerOff: (spaceId: string, cubeId: string) => Promise<unknown>;
2205
- /** Start a stopped Cube (asynchronous — start is enqueued). */
2206
- /**
2207
- * Restart a Cube (COLD restart).
2208
- *
2209
- * The hypervisor process is stopped and relaunched, so the Cube boots
2210
- * against the host's current kernel. This is the only way a Cube picks up a
2211
- * refreshed guest kernel after a platform image update — a `reboot` issued
2212
- * INSIDE the Cube cannot do it, because Firecracker treats a guest reboot as
2213
- * a shutdown and the kernel is supplied externally by the host.
2214
- *
2215
- * Disk state is preserved; only the kernel changes. The Cube must be
2216
- * `running`. Concurrent restarts of the same Cube are rejected (409) rather
2217
- * than queued twice.
2218
- */
2219
- restart: (spaceId: string, cubeId: string) => Promise<unknown>;
2220
- wake: (spaceId: string, cubeId: string) => Promise<unknown>;
2221
- /**
2222
- * Get a Cube's SSH connection info — host, port, login user, and (when
2223
- * available) the pinned host public keys for strict host-key verification.
2224
- */
2225
- ssh: (spaceId: string, cubeId: string) => Promise<CubeSshInfo>;
2226
- /**
2227
- * Restore a Cube's disk from one of its {@link Snapshot}s (asynchronous —
2228
- * the restore is enqueued). The Cube's current disk is replaced.
2229
- */
2230
- restore: (spaceId: string, cubeId: string, snapshotId: string) => Promise<{
2231
- success: boolean;
2232
- }>;
2233
- };
2180
+ create: (spaceId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes"]["post"]["requestBody"]>["content"]["application/json"], opts?: {
2181
+ idempotencyKey?: string;
2182
+ }) => Promise<Cube>;
2183
+ /** Get a single Cube. Returns the {@link Cube}. */
2184
+ get: (spaceId: string, cubeId: string) => Promise<Cube>;
2234
2185
  /**
2235
- * Resolve the {@link Space} this API key is scoped to — so you don't have to
2236
- * hardcode a `spaceId`. Handy right after constructing the client:
2186
+ * Update the IN-CUBE port that SSH is forwarded to.
2237
2187
  *
2238
- * @example
2239
- * ```ts
2240
- * const space = await krova.getSpace();
2241
- * const cubes = await krova.cubes.list(space.id);
2242
- * ```
2188
+ * `cubePort` is the port **inside** the Cube that sshd listens on — NOT the
2189
+ * host port you connect to. The host port is allocated by Krova and is not
2190
+ * changed by this call. Pointing this at a port nothing is listening on
2191
+ * inside the Cube will silently make SSH unreachable; the default is 22.
2192
+ *
2193
+ * The Krova Cloud API exposes no general Cube-mutation endpoint; the only
2194
+ * mutable Cube field over the API is this port, via
2195
+ * `PUT /spaces/{spaceId}/cubes/{cubeId}/ssh-port`. This helper maps to that
2196
+ * endpoint. (Compute resize / rename are not part of the public API.)
2243
2197
  */
2244
- getSpace(): Promise<Space>;
2245
- readonly domains: {
2246
- /** List the custom domains attached to a Cube. */
2247
- list: (spaceId: string, cubeId: string) => Promise<Domain[]>;
2248
- /**
2249
- * Attach a custom domain to a Cube. `domain` + `port` are required.
2250
- *
2251
- * Returns the domain AND the DNS records you must publish for it to work —
2252
- * so you can create them in the same run, without a second call and without
2253
- * hard-coding record shapes. A wildcard needs three; an exact host needs one.
2254
- *
2255
- * ⛔ BREAKING in 0.4.0: this used to resolve to `Domain`. It now resolves to
2256
- * `{ domain, records }`, because for a wildcard two of the three records
2257
- * (the ownership TXT and the `_acme-challenge` delegation) were not
2258
- * derivable from anything the SDK returned an integration had to read
2259
- * them out of the docs and hope they still matched the server.
2260
- */
2261
- create: (spaceId: string, cubeId: string, body: CreateDomainInput) => Promise<{
2262
- domain: Domain;
2263
- records: DnsRecord[];
2264
- }>;
2265
- /**
2266
- * The DNS records a domain needs, each checked against live DNS.
2267
- *
2268
- * Poll this after publishing them: `summary.complete` turns true only once
2269
- * every record is `found`. Each call performs real DNS lookups and is rate
2270
- * limited, so poll on an interval rather than in a tight loop.
2271
- */
2272
- records: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2273
- domain: string;
2274
- isWildcard: boolean;
2275
- records: DnsRecordStatus[];
2276
- summary: {
2277
- found: number;
2278
- total: number;
2279
- complete: boolean;
2280
- };
2281
- checkedAt: string;
2282
- }>;
2283
- /** Update a domain's per-domain proxy settings. */
2284
- update: (spaceId: string, cubeId: string, mappingId: string, body: UpdateDomainInput) => Promise<Domain>;
2285
- /** Detach a custom domain from a Cube. */
2286
- delete: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2287
- success: boolean;
2288
- }>;
2289
- };
2290
- readonly snapshots: {
2291
- /** List a Cube's snapshots. */
2292
- list: (spaceId: string, cubeId: string) => Promise<Snapshot[]>;
2293
- /** Create a snapshot of a Cube's disk (asynchronous — enqueued). */
2294
- create: (spaceId: string, cubeId: string, body?: {
2295
- name?: string;
2296
- }) => Promise<Snapshot>;
2297
- /** Delete a snapshot. */
2298
- delete: (spaceId: string, cubeId: string, snapshotId: string) => Promise<{
2299
- success: boolean;
2300
- }>;
2301
- };
2302
- readonly tcpMappings: {
2303
- /** List a Cube's TCP port mappings. */
2304
- list: (spaceId: string, cubeId: string) => Promise<TcpMapping[]>;
2305
- /**
2306
- * Create a TCP port mapping exposing a Cube port on the host. `cubePort` is
2307
- * required; `whitelistIps` optionally restricts who can reach it.
2308
- */
2309
- create: (spaceId: string, cubeId: string, body: CreateTcpMappingInput) => Promise<TcpMapping>;
2310
- /** Delete a TCP port mapping. */
2311
- delete: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2312
- success: boolean;
2313
- }>;
2314
- };
2315
- readonly imports: {
2316
- /**
2317
- * Start importing a `.cube` archive into a new Cube. Returns the multipart
2318
- * upload target (`importId`, `uploadId`, presigned `parts`, …). Upload the
2319
- * archive to those URLs, then call {@link imports.complete}.
2320
- */
2321
- create: (spaceId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/imports"]["post"]["requestBody"]>["content"]["application/json"]) => Promise<{
2322
- importId?: string | undefined;
2323
- uploadId?: string | undefined;
2324
- key?: string | undefined;
2325
- chunkSizeBytes?: number | undefined;
2326
- parts?: {
2327
- partNumber?: number | undefined;
2328
- url?: string | undefined;
2329
- }[] | undefined;
2330
- expiresAt?: string | undefined;
2331
- } | undefined>;
2332
- /** Get an in-progress or completed import by id. */
2333
- get: (spaceId: string, importId: string) => Promise<{
2334
- import?: {
2335
- id?: string | undefined;
2336
- name?: string | undefined;
2337
- status?: "uploading" | "finalizing" | "provisioning" | "complete" | "failed" | "expired" | undefined;
2338
- cubeId?: string | null | undefined;
2339
- error?: string | null | undefined;
2340
- createdAt?: string | undefined;
2341
- updatedAt?: string | undefined;
2342
- completedAt?: string | null | undefined;
2343
- } | undefined;
2344
- }>;
2345
- /**
2346
- * Finish an import after the archive has been uploaded — provisions the
2347
- * Cube. Pass the uploaded `parts` (partNumber + etag) and the resolved
2348
- * `config`.
2349
- */
2350
- complete: (spaceId: string, importId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/imports/{importId}/complete"]["post"]["requestBody"]>["content"]["application/json"]) => Promise<{
2351
- importId?: string | undefined;
2352
- cubeId?: string | undefined;
2353
- status?: "provisioning" | undefined;
2354
- } | undefined>;
2355
- /** Cancel an in-progress import. */
2356
- cancel: (spaceId: string, importId: string) => Promise<{
2357
- success: boolean;
2358
- } | undefined>;
2359
- };
2360
- readonly backups: {
2361
- /** Get a time-limited download URL for a backup `.cube` archive. */
2362
- download: (spaceId: string, backupId: string) => Promise<{
2363
- url?: string | undefined;
2364
- filename?: string | undefined;
2365
- sizeBytes?: number | null | undefined;
2366
- expiresAt?: string | undefined;
2367
- } | undefined>;
2368
- };
2369
- readonly catalog: {
2370
- /** List regions with available capacity. */
2371
- regions: () => Promise<{
2372
- regions: {
2373
- id: string;
2374
- name: string;
2375
- slug: string;
2376
- }[];
2377
- }>;
2378
- /** List available OS images. */
2379
- images: () => Promise<{
2380
- images: {
2381
- id: string;
2382
- name: string;
2383
- version: string;
2384
- description: string;
2385
- defaultUser: string;
2386
- }[];
2387
- }>;
2388
- /** Per-resource hourly rates and volume pricing tiers. */
2389
- pricing: () => Promise<{
2390
- currency: string;
2391
- rates: {
2392
- vcpuPerHour: number;
2393
- ramGbPerHour: number;
2394
- diskGbPerHour: number;
2395
- };
2396
- tiers: {
2397
- minVcpus: number;
2398
- maxVcpus: number | null;
2399
- multiplier: number;
2400
- label: string;
2401
- }[];
2402
- note: string;
2403
- }>;
2404
- };
2198
+ update: (spaceId: string, cubeId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/{cubeId}/ssh-port"]["put"]["requestBody"]>["content"]["application/json"]) => Promise<unknown>;
2199
+ /** Delete a Cube (asynchronous — deletion is enqueued). */
2200
+ delete: (spaceId: string, cubeId: string) => Promise<{
2201
+ success: boolean;
2202
+ }>;
2203
+ /** Power off a running Cube (asynchronous power-off is enqueued). The Cube
2204
+ * becomes `stopped` (its host RAM is freed); start it again with `wake`. */
2205
+ powerOff: (spaceId: string, cubeId: string) => Promise<unknown>;
2206
+ /** Start a stopped Cube (asynchronous start is enqueued). */
2207
+ /**
2208
+ * Restart a Cube (COLD restart).
2209
+ *
2210
+ * The hypervisor process is stopped and relaunched, so the Cube boots
2211
+ * against the host's current kernel. This is the only way a Cube picks up a
2212
+ * refreshed guest kernel after a platform image update a `reboot` issued
2213
+ * INSIDE the Cube cannot do it, because Firecracker treats a guest reboot as
2214
+ * a shutdown and the kernel is supplied externally by the host.
2215
+ *
2216
+ * Disk state is preserved; only the kernel changes. The Cube must be
2217
+ * `running`. Concurrent restarts of the same Cube are rejected (409) rather
2218
+ * than queued twice.
2219
+ */
2220
+ restart: (spaceId: string, cubeId: string) => Promise<unknown>;
2221
+ wake: (spaceId: string, cubeId: string) => Promise<unknown>;
2222
+ /**
2223
+ * Get a Cube's SSH connection info host, port, login user, and (when
2224
+ * available) the pinned host public keys for strict host-key verification.
2225
+ */
2226
+ ssh: (spaceId: string, cubeId: string) => Promise<CubeSshInfo>;
2227
+ /**
2228
+ * Restore a Cube's disk from one of its {@link Snapshot}s (asynchronous —
2229
+ * the restore is enqueued). The Cube's current disk is replaced.
2230
+ */
2231
+ restore: (spaceId: string, cubeId: string, snapshotId: string) => Promise<{
2232
+ success: boolean;
2233
+ }>;
2234
+ };
2235
+ /**
2236
+ * Resolve the {@link Space} this API key is scoped to — so you don't have to
2237
+ * hardcode a `spaceId`. Handy right after constructing the client:
2238
+ *
2239
+ * @example
2240
+ * ```ts
2241
+ * const space = await krova.getSpace();
2242
+ * const cubes = await krova.cubes.list(space.id);
2243
+ * ```
2244
+ */
2245
+ getSpace(): Promise<Space>;
2246
+ readonly domains: {
2247
+ /** List the custom domains attached to a Cube. */
2248
+ list: (spaceId: string, cubeId: string) => Promise<Domain[]>;
2249
+ /**
2250
+ * Attach a custom domain to a Cube. `domain` + `port` are required.
2251
+ *
2252
+ * Returns the domain AND the DNS records you must publish for it to work —
2253
+ * so you can create them in the same run, without a second call and without
2254
+ * hard-coding record shapes. A wildcard needs three; an exact host needs one.
2255
+ *
2256
+ * ⛔ BREAKING in 0.4.0: this used to resolve to `Domain`. It now resolves to
2257
+ * `{ domain, records }`, because for a wildcard two of the three records
2258
+ * (the ownership TXT and the `_acme-challenge` delegation) were not
2259
+ * derivable from anything the SDK returned — an integration had to read
2260
+ * them out of the docs and hope they still matched the server.
2261
+ */
2262
+ create: (spaceId: string, cubeId: string, body: CreateDomainInput) => Promise<{
2263
+ domain: Domain;
2264
+ records: DnsRecord[];
2265
+ }>;
2266
+ /**
2267
+ * The DNS records a domain needs, each checked against live DNS.
2268
+ *
2269
+ * Poll this after publishing them: `summary.complete` turns true only once
2270
+ * every record is `found`. Each call performs real DNS lookups and is rate
2271
+ * limited, so poll on an interval rather than in a tight loop.
2272
+ */
2273
+ records: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2274
+ domain: string;
2275
+ isWildcard: boolean;
2276
+ records: DnsRecordStatus[];
2277
+ summary: {
2278
+ found: number;
2279
+ total: number;
2280
+ complete: boolean;
2281
+ };
2282
+ checkedAt: string;
2283
+ }>;
2284
+ /** Update a domain's per-domain proxy settings. */
2285
+ update: (spaceId: string, cubeId: string, mappingId: string, body: UpdateDomainInput) => Promise<Domain>;
2286
+ /** Detach a custom domain from a Cube. */
2287
+ delete: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2288
+ success: boolean;
2289
+ }>;
2290
+ };
2291
+ readonly snapshots: {
2292
+ /** List a Cube's snapshots. */
2293
+ list: (spaceId: string, cubeId: string) => Promise<Snapshot[]>;
2294
+ /** Create a snapshot of a Cube's disk (asynchronous — enqueued). */
2295
+ create: (spaceId: string, cubeId: string, body?: {
2296
+ name?: string;
2297
+ }) => Promise<Snapshot>;
2298
+ /** Delete a snapshot. */
2299
+ delete: (spaceId: string, cubeId: string, snapshotId: string) => Promise<{
2300
+ success: boolean;
2301
+ }>;
2302
+ };
2303
+ readonly tcpMappings: {
2304
+ /** List a Cube's TCP port mappings. */
2305
+ list: (spaceId: string, cubeId: string) => Promise<TcpMapping[]>;
2306
+ /**
2307
+ * Create a TCP port mapping exposing a Cube port on the host. `cubePort` is
2308
+ * required; `whitelistIps` optionally restricts who can reach it.
2309
+ */
2310
+ create: (spaceId: string, cubeId: string, body: CreateTcpMappingInput) => Promise<TcpMapping>;
2311
+ /** Delete a TCP port mapping. */
2312
+ delete: (spaceId: string, cubeId: string, mappingId: string) => Promise<{
2313
+ success: boolean;
2314
+ }>;
2315
+ };
2316
+ readonly imports: {
2317
+ /**
2318
+ * Start importing a `.cube` archive into a new Cube. Returns the multipart
2319
+ * upload target (`importId`, `uploadId`, presigned `parts`, …). Upload the
2320
+ * archive to those URLs, then call {@link imports.complete}.
2321
+ */
2322
+ create: (spaceId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/imports"]["post"]["requestBody"]>["content"]["application/json"]) => Promise<{
2323
+ importId?: string;
2324
+ uploadId?: string;
2325
+ key?: string;
2326
+ chunkSizeBytes?: number;
2327
+ parts?: {
2328
+ partNumber?: number;
2329
+ url?: string;
2330
+ }[] | undefined;
2331
+ expiresAt?: string;
2332
+ } | undefined>;
2333
+ /** Get an in-progress or completed import by id. */
2334
+ get: (spaceId: string, importId: string) => Promise<{
2335
+ import?: {
2336
+ id?: string;
2337
+ name?: string;
2338
+ status?: "uploading" | "finalizing" | "provisioning" | "complete" | "failed" | "expired";
2339
+ cubeId?: string | null;
2340
+ error?: string | null;
2341
+ createdAt?: string;
2342
+ updatedAt?: string;
2343
+ completedAt?: string | null;
2344
+ } | undefined;
2345
+ }>;
2346
+ /**
2347
+ * Finish an import after the archive has been uploaded — provisions the
2348
+ * Cube. Pass the uploaded `parts` (partNumber + etag) and the resolved
2349
+ * `config`.
2350
+ */
2351
+ complete: (spaceId: string, importId: string, body: NonNullable<paths["/spaces/{spaceId}/cubes/imports/{importId}/complete"]["post"]["requestBody"]>["content"]["application/json"]) => Promise<{
2352
+ importId?: string;
2353
+ cubeId?: string;
2354
+ status?: "provisioning";
2355
+ } | undefined>;
2356
+ /** Cancel an in-progress import. */
2357
+ cancel: (spaceId: string, importId: string) => Promise<{
2358
+ success: boolean;
2359
+ } | undefined>;
2360
+ };
2361
+ readonly backups: {
2362
+ /** Get a time-limited download URL for a backup `.cube` archive. */
2363
+ download: (spaceId: string, backupId: string) => Promise<{
2364
+ url?: string;
2365
+ filename?: string;
2366
+ sizeBytes?: number | null;
2367
+ expiresAt?: string;
2368
+ } | undefined>;
2369
+ };
2370
+ readonly catalog: {
2371
+ /** List regions with available capacity. */
2372
+ regions: () => Promise<{
2373
+ regions: {
2374
+ id: string;
2375
+ name: string;
2376
+ slug: string;
2377
+ }[];
2378
+ }>;
2379
+ /** List available OS images. */
2380
+ images: () => Promise<{
2381
+ images: {
2382
+ id: string;
2383
+ name: string;
2384
+ version: string;
2385
+ description: string;
2386
+ defaultUser: string;
2387
+ }[];
2388
+ }>;
2389
+ /** Per-resource hourly rates and volume pricing tiers. */
2390
+ pricing: () => Promise<{
2391
+ currency: string;
2392
+ rates: {
2393
+ vcpuPerHour: number;
2394
+ ramGbPerHour: number;
2395
+ diskGbPerHour: number;
2396
+ };
2397
+ tiers: {
2398
+ minVcpus: number;
2399
+ maxVcpus: number | null;
2400
+ multiplier: number;
2401
+ label: string;
2402
+ }[];
2403
+ note: string;
2404
+ }>;
2405
+ };
2405
2406
  }
2406
-
2407
+ //#endregion
2408
+ //#region src/error.d.ts
2407
2409
  /**
2408
2410
  * The error body shape returned by the Krova Cloud API.
2409
2411
  *
@@ -2412,8 +2414,8 @@ declare class KrovaClient {
2412
2414
  * we keep the type open.
2413
2415
  */
2414
2416
  interface KrovaErrorBody {
2415
- error?: string;
2416
- [key: string]: unknown;
2417
+ error?: string;
2418
+ [key: string]: unknown;
2417
2419
  }
2418
2420
  /**
2419
2421
  * Error thrown by the ergonomic {@link KrovaClient} helpers when the API
@@ -2424,34 +2426,35 @@ interface KrovaErrorBody {
2424
2426
  * so callers can `try/catch`.
2425
2427
  */
2426
2428
  declare class KrovaError extends Error {
2427
- /** HTTP status code of the failing response. */
2428
- readonly status: number;
2429
- /**
2430
- * A machine-readable error code, when the API surfaces one via the
2431
- * `X-Error-Code` response header. The documented error body only carries a
2432
- * human-readable `error` string, so this is best-effort.
2433
- */
2434
- readonly code?: string;
2435
- /**
2436
- * The request id from the `X-Request-Id` response header, when present.
2437
- * Useful when contacting Krova Cloud support about a specific failure.
2438
- */
2439
- readonly requestId?: string;
2440
- /** The parsed JSON error body, when the response had one. */
2441
- readonly body?: KrovaErrorBody;
2442
- /** The raw `Response` object, for callers that need headers/url/etc. */
2443
- readonly response?: Response;
2444
- constructor(message: string, init: {
2445
- status: number;
2446
- code?: string;
2447
- requestId?: string;
2448
- body?: KrovaErrorBody;
2449
- response?: Response;
2450
- });
2429
+ /** HTTP status code of the failing response. */
2430
+ readonly status: number;
2431
+ /**
2432
+ * A machine-readable error code, when the API surfaces one via the
2433
+ * `X-Error-Code` response header. The documented error body only carries a
2434
+ * human-readable `error` string, so this is best-effort.
2435
+ */
2436
+ readonly code?: string;
2437
+ /**
2438
+ * The request id from the `X-Request-Id` response header, when present.
2439
+ * Useful when contacting Krova Cloud support about a specific failure.
2440
+ */
2441
+ readonly requestId?: string;
2442
+ /** The parsed JSON error body, when the response had one. */
2443
+ readonly body?: KrovaErrorBody;
2444
+ /** The raw `Response` object, for callers that need headers/url/etc. */
2445
+ readonly response?: Response;
2446
+ constructor(message: string, init: {
2447
+ status: number;
2448
+ code?: string;
2449
+ requestId?: string;
2450
+ body?: KrovaErrorBody;
2451
+ response?: Response;
2452
+ });
2451
2453
  }
2452
2454
  /**
2453
2455
  * Build a {@link KrovaError} from a failing response + parsed error body.
2454
2456
  */
2455
2457
  declare function krovaErrorFrom(response: Response, body: KrovaErrorBody | undefined): KrovaError;
2456
-
2458
+ //#endregion
2457
2459
  export { type AuthScheme, type CreateDomainInput, type CreateTcpMappingInput, type Cube, type CubeSshInfo, DEFAULT_BASE_URL, type Domain, type Image, KrovaClient, type KrovaClientOptions, KrovaError, type KrovaErrorBody, type Pagination, type PricingTier, type Region, type Snapshot, type Space, type TcpMapping, type UpdateDomainInput, type components, krovaErrorFrom, type paths };
2460
+ //# sourceMappingURL=index.d.ts.map