unfazed 0.0.1 → 0.2.0

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.
@@ -0,0 +1,1303 @@
1
+ scalar File
2
+ scalar JSON
3
+
4
+ type Function {
5
+ id: ID!
6
+ name: String!
7
+ filename: String!
8
+ sizeBytes: Int!
9
+ sha256: String!
10
+ createdAt: String!
11
+ bundled: Boolean!
12
+ }
13
+
14
+ enum DeploymentKind {
15
+ STATIC
16
+ SERVICE
17
+ "A persistent always-on Linux VM with a per-workspace data disk (docs/agent-box.md)."
18
+ BOX
19
+ }
20
+
21
+ enum DeploymentStatus {
22
+ BUILDING
23
+ READY
24
+ FAILED
25
+ }
26
+
27
+ enum ServiceMode {
28
+ "Default. Sleeps and cold-starts a VM on the first request, then parks it after a short idle period — cheap and right for most services. Use on_demand + cronSchedule for periodic work."
29
+ ON_DEMAND
30
+ "Keeps a supervised VM running 24/7 (resource-expensive). Reserve for services that must stay warm (low first-request latency), do background work between requests, or run a frequent cron."
31
+ ALWAYS_ON
32
+ }
33
+
34
+ enum ServiceRuntime {
35
+ "Default. Bundles a TypeScript/JavaScript entry (server.ts) into a Bun HTTP server."
36
+ BUN
37
+ "Compiles a Go module (go.mod) into a static binary that starts its own HTTP server on $PORT."
38
+ GO
39
+ }
40
+
41
+ enum DeploymentEventType {
42
+ UNKNOWN
43
+ DEPLOYMENT_CREATED
44
+ DEPLOYMENT_PROMOTION_REJECTED
45
+ DEPLOYMENT_ROLLED_BACK
46
+ SERVICE_BUILD_FAILED
47
+ SERVICE_BUILD_SUCCEEDED
48
+ SERVICE_BOOT_FAILED
49
+ SERVICE_HEALTH_PROBE_FAILED
50
+ SERVICE_PROXY_ERROR
51
+ SERVICE_SUPERVISOR_STARTED
52
+ SERVICE_RESTART_REQUESTED
53
+ SERVICE_VM_START_FAILED
54
+ SERVICE_STOP_REQUESTED
55
+ SERVICE_SUPERVISOR_STOPPED
56
+ SERVICE_WATCHDOG_PROBE_FAILED
57
+ SERVICE_WATCHDOG_RESTART
58
+ SERVICE_VM_STARTED
59
+ SERVICE_VM_STOPPED
60
+ SERVICE_CRON_TRIGGERED
61
+ }
62
+
63
+ enum DeploymentEventSeverity {
64
+ INFO
65
+ WARN
66
+ ERROR
67
+ }
68
+
69
+ type Workspace {
70
+ id: ID!
71
+ name: String!
72
+ "Who owns this source. The listing includes the sources of agents the caller claimed, so this is how a client tells its own from an agent's: it matches one of whoami.linkedAgents[].agentID for the latter. Operations that require a DIRECTLY owned source — alias adoption targets — must filter on it."
73
+ ownerId: ID!
74
+ "The owner-defined project this app is grouped under (dashboard organization only); null when ungrouped."
75
+ projectId: ID
76
+ gitSource: GitSource
77
+ createdAt: String!
78
+ updatedAt: String!
79
+ }
80
+
81
+ "A project groups an owner's apps under a human-chosen name. Purely a dashboard organization layer: it does not affect app URLs or aliases, and is never exposed to agents."
82
+ type Project {
83
+ id: ID!
84
+ name: String!
85
+ "The owning identity (github:<login>); the dashboard uses it to tell own projects from team-shared ones."
86
+ owner: String!
87
+ createdAt: String!
88
+ updatedAt: String!
89
+ }
90
+
91
+ input CreateProjectInput {
92
+ name: String!
93
+ }
94
+
95
+ input RenameProjectInput {
96
+ id: ID!
97
+ name: String!
98
+ }
99
+
100
+ input DeleteProjectInput {
101
+ id: ID!
102
+ }
103
+
104
+ input AssignWorkspaceToProjectInput {
105
+ workspaceID: ID!
106
+ "Target project; pass null or omit to ungroup the workspace."
107
+ projectId: ID
108
+ }
109
+
110
+ type ProjectPayload {
111
+ project: Project!
112
+ }
113
+
114
+ "A team: a named audience SELECTED projects are shared with (docs/teams.md). Membership alone shows nothing — members see exactly the projects shared with the team, their apps, and those apps' integrations (still running on the app owner's connections)."
115
+ type Team {
116
+ id: ID!
117
+ name: String!
118
+ createdAt: String!
119
+ "The caller's role on this team: owner or member."
120
+ viewerRole: String!
121
+ members: [TeamMember!]!
122
+ "Pending invitations; they grant nothing until accepted."
123
+ invites: [TeamInvite!]!
124
+ "Projects shared with this team."
125
+ projects: [TeamSharedProject!]!
126
+ "Recent membership events, oldest first — who invited/removed/joined/shared, the audit-trail seed."
127
+ events: [TeamEvent!]!
128
+ }
129
+
130
+ type TeamSharedProject {
131
+ projectID: ID!
132
+ name: String!
133
+ sharedBy: String!
134
+ sharedByName: String!
135
+ }
136
+
137
+ type TeamMember {
138
+ userID: String!
139
+ "Bare github login for display."
140
+ name: String!
141
+ role: String!
142
+ addedAt: String!
143
+ }
144
+
145
+ type TeamInvite {
146
+ userID: String!
147
+ name: String!
148
+ invitedBy: String!
149
+ invitedByName: String!
150
+ invitedAt: String!
151
+ }
152
+
153
+ type TeamEvent {
154
+ at: String!
155
+ actor: String!
156
+ actorName: String!
157
+ "created | renamed | invited | invite_cancelled | invite_declined | joined | member_removed | member_left"
158
+ action: String!
159
+ subject: String
160
+ subjectName: String
161
+ }
162
+
163
+ "A pending invite addressed to the caller."
164
+ type TeamInviteForMe {
165
+ teamID: ID!
166
+ teamName: String!
167
+ invitedBy: String!
168
+ invitedByName: String!
169
+ invitedAt: String!
170
+ }
171
+
172
+ input CreateTeamInput {
173
+ name: String!
174
+ }
175
+
176
+ input RenameTeamInput {
177
+ id: ID!
178
+ name: String!
179
+ }
180
+
181
+ input TeamIDInput {
182
+ teamID: ID!
183
+ }
184
+
185
+ input TeamInviteInput {
186
+ teamID: ID!
187
+ "GitHub login to invite, with or without a leading @."
188
+ login: String!
189
+ }
190
+
191
+ input TeamMemberInput {
192
+ teamID: ID!
193
+ userID: String!
194
+ }
195
+
196
+ input TeamProjectInput {
197
+ teamID: ID!
198
+ projectID: ID!
199
+ }
200
+
201
+ type TeamPayload {
202
+ team: Team!
203
+ }
204
+
205
+ "A BYO custom domain attached to an app's alias. The edge issues its TLS cert (Let's Encrypt) once active; requests to the domain serve the app."
206
+ type CustomDomain {
207
+ domain: String!
208
+ alias: String!
209
+ "True once the platform allows the edge to issue a cert and route the domain."
210
+ active: Boolean!
211
+ createdAt: String!
212
+ }
213
+
214
+ "A public key that may authenticate to the box SSH gateway. Public keys are not secrets, so the fingerprint and type are shown in full."
215
+ type SSHKey {
216
+ "OpenSSH SHA-256 fingerprint (the string ssh-keygen -lf prints). Also the id used to remove the key."
217
+ id: ID!
218
+ "Key algorithm, e.g. ssh-ed25519."
219
+ type: String!
220
+ "Trailing comment from the authorized_keys line, usually user@host."
221
+ comment: String
222
+ "Where the key came from: \"github\" when imported from the account's published GitHub keys, null when the user added it."
223
+ source: String
224
+ createdAt: String!
225
+ }
226
+
227
+ input AddSSHKeyInput {
228
+ "One authorized_keys line: \"<type> <base64> [comment]\". Never a private key."
229
+ publicKey: String!
230
+ }
231
+
232
+ input RemoveSSHKeyInput {
233
+ "Fingerprint from the sshKeys query."
234
+ id: ID!
235
+ }
236
+
237
+ input AddCustomDomainInput {
238
+ "The app alias the domain should serve."
239
+ alias: String!
240
+ domain: String!
241
+ }
242
+
243
+ input RemoveCustomDomainInput {
244
+ domain: String!
245
+ }
246
+
247
+ type GitSource {
248
+ provider: String!
249
+ repo: String!
250
+ branch: String!
251
+ repoURL: String!
252
+ autoDeploy: Boolean!
253
+ "The alias a push/webhook (or syncRepo) auto-deploys to. Empty means no fixed target."
254
+ deployAlias: String
255
+ subdir: String
256
+ lastImportedCommit: String
257
+ lastImportedAt: String
258
+ lastImportStatus: String!
259
+ lastImportError: String
260
+ webhookURL: String
261
+ webhookSecret: String
262
+ "When set, the auto-deploy webhook has been registered on the GitHub repo (RFC3339)."
263
+ webhookInstalledAt: String
264
+ }
265
+
266
+ type GitHubTokenStatus {
267
+ configured: Boolean!
268
+ updatedAt: String
269
+ }
270
+
271
+ type GitHubRepository {
272
+ owner: String!
273
+ name: String!
274
+ nameWithOwner: String!
275
+ private: Boolean!
276
+ defaultBranch: String!
277
+ url: String!
278
+ connectedWorkspaceID: ID
279
+ connectedWorkspaceName: String
280
+ }
281
+
282
+ type GitHubBranch {
283
+ name: String!
284
+ commit: String!
285
+ }
286
+
287
+ type WorkspaceFile {
288
+ path: String!
289
+ sizeBytes: Int!
290
+ size: String!
291
+ sha256: String!
292
+ updatedAt: String!
293
+ }
294
+
295
+ type WorkspaceFileContent {
296
+ file: WorkspaceFile!
297
+ text: String!
298
+ offset: Int!
299
+ limit: Int!
300
+ totalBytes: Int!
301
+ truncated: Boolean!
302
+ nextOffset: Int
303
+ }
304
+
305
+ type WorkspaceEnvVar {
306
+ name: String!
307
+ value: String
308
+ secret: Boolean!
309
+ "Canonical app alias for an app-scoped desired env view; null for workspace defaults."
310
+ alias: String
311
+ "True when the app currently follows the workspace default for this name."
312
+ inherited: Boolean!
313
+ "True when REMOVE explicitly blocks this name for the app, including integration enrichment."
314
+ masked: Boolean!
315
+ updatedAt: String!
316
+ }
317
+
318
+ "One app alias's configured override set and its share of the workspace-wide env budget."
319
+ type AppEnvScope {
320
+ alias: String!
321
+ "App-scoped non-secret overrides."
322
+ overrides: Int!
323
+ "App-scoped encrypted secrets. Values are never exposed."
324
+ secrets: Int!
325
+ "Explicit REMOVE masks."
326
+ masks: Int!
327
+ "Bytes this scope charges against the workspace env size limit."
328
+ bytes: Int!
329
+ """
330
+ ACTIVE — a deployment carries this alias, or a git source redeploys it.
331
+ PENDING — the alias has never been deployed; this is config staged for an app
332
+ that has not shipped yet, which is the normal order, so it is NOT junk.
333
+ ORPHANED — the alias was deployed once and no longer is: the only status
334
+ that is safe to clear without asking. Every status consumes the shared budget.
335
+ """
336
+ status: String!
337
+ "Newest timestamp across the scope's entries."
338
+ updatedAt: String!
339
+ }
340
+
341
+ type Deployment {
342
+ id: ID!
343
+ workspaceID: ID!
344
+ kind: DeploymentKind!
345
+ "SERVICE runtime (BUN or GO); null for STATIC."
346
+ runtime: ServiceRuntime
347
+ alias: String
348
+ serviceMode: ServiceMode!
349
+ healthPath: String
350
+ cronSchedule: String
351
+ cronPath: String
352
+ url: String!
353
+ "Immutable by-id URL (/d/<id>/), stable across alias repoints. Safe to hit before promoting — use it to verify a deploy before it owns the public alias."
354
+ previewUrl: String!
355
+ "Ready-to-run SSH command for a BOX (e.g. \"ssh myboxs@ssh.unfazed.dev\"). Null for other kinds and when the gateway is not configured."
356
+ sshCommand: String
357
+ "Whether this deployment currently holds its alias (serves the public alias URL)."
358
+ aliasHeld: Boolean!
359
+ "Opaque alias-generation token. For rollback, pass the current holder's value as expectedCurrentAliasRevision together with its id; do not interpret it."
360
+ aliasRevision: String!
361
+ status: DeploymentStatus!
362
+ error: String
363
+ filesCount: Int!
364
+ sizeBytes: Int!
365
+ size: String!
366
+ spaMode: Boolean!
367
+ gitRepo: String
368
+ gitCommit: String
369
+ createdAt: String!
370
+ """
371
+ The runtime target serving this exact current deployment: an enrolled worker
372
+ or the control plane. Null for historical releases and residual legacy
373
+ placements, which must be migrated rather than presented as normal workers.
374
+ """
375
+ worker: DeploymentWorker
376
+ }
377
+
378
+ "The authoritative runtime target assigned to a current deployment."
379
+ type DeploymentWorker {
380
+ id: String!
381
+ "Stable human-readable worker name."
382
+ name: String!
383
+ "Region advertised by the worker; null when the assignment has no durable region metadata."
384
+ region: String
385
+ }
386
+
387
+ type DeploymentEvent {
388
+ id: ID!
389
+ deploymentID: ID!
390
+ type: DeploymentEventType!
391
+ rawType: String!
392
+ severity: DeploymentEventSeverity!
393
+ message: String!
394
+ vmID: String
395
+ metadata: JSON
396
+ createdAt: String!
397
+ }
398
+
399
+ type ServiceRuntimeStatus {
400
+ deploymentID: ID!
401
+ alias: String
402
+ serviceMode: ServiceMode!
403
+ running: Boolean!
404
+ health: String!
405
+ vmID: String
406
+ inFlight: Int!
407
+ alwaysOn: Boolean!
408
+ "The VM's RAM ceiling in MiB; guest processes exceeding it are OOM-killed."
409
+ memSizeMiB: Int!
410
+ startedAt: String
411
+ lastUsedAt: String
412
+ lastStoppedAt: String
413
+ restartCount: Int!
414
+ lastError: String
415
+ }
416
+
417
+ type ServiceRuntimeLogs {
418
+ deploymentID: ID!
419
+ stdout: String!
420
+ stderr: String!
421
+ truncated: Boolean!
422
+ stdoutBytes: Int!
423
+ stderrBytes: Int!
424
+ tailBytes: Int!
425
+ }
426
+
427
+ type AppStateValue {
428
+ found: Boolean!
429
+ value: String
430
+ encoding: String
431
+ }
432
+
433
+ type AppStateKeys {
434
+ keys: [String!]!
435
+ count: Int!
436
+ }
437
+
438
+ type DeleteResultPayload {
439
+ ok: Boolean!
440
+ }
441
+
442
+ "An available integration type (e.g. postgres, redis). Managed integrations need no connection; BYO ones declare the control or backend fields they connect with."
443
+ type IntegrationKind {
444
+ available: Boolean!
445
+ kind: String!
446
+ label: String!
447
+ iconURL: String
448
+ # who supplies the backend: "platform" (unfazed runs it) or "user" (BYO)
449
+ provenance: String!
450
+ # how the owner connects: "none" (no connection), "fields" (a form), "link" (an auth flow)
451
+ connectMethod: String!
452
+ fields: [IntegrationField!]!
453
+ manifestVersion: Int!
454
+ description: String!
455
+ capabilities: [String!]!
456
+ policies: [IntegrationCapabilityPolicy!]!
457
+ supportedModes: [String!]!
458
+ "Safe isolation mode selected when bindIntegration omits mode; null for providers without app runtime."
459
+ defaultMode: String
460
+ runtime: IntegrationRuntime!
461
+ surfaces: [IntegrationSurface!]!
462
+ }
463
+ type IntegrationSurface {
464
+ id: String!
465
+ spec: JSON!
466
+ }
467
+ type IntegrationCapabilityPolicy {
468
+ capability: String!
469
+ allowedScopes: [String!]!
470
+ defaultActivation: String!
471
+ replacesLegacyFeed: Boolean!
472
+ }
473
+ type IntegrationRuntime {
474
+ revision: String!
475
+ env: [IntegrationRuntimeEnv!]!
476
+ usage: String!
477
+ }
478
+ type IntegrationRuntimeEnv {
479
+ name: String!
480
+ description: String!
481
+ secret: Boolean!
482
+ }
483
+ type IntegrationField {
484
+ name: String!
485
+ label: String!
486
+ secret: Boolean!
487
+ required: Boolean!
488
+ }
489
+ "A connected backend or provisioner (the owner's BYO instance). Only non-secret fields are returned; secrets are sealed and never exposed or injected unless the provider explicitly declares passthrough mode."
490
+ type IntegrationConnection {
491
+ id: ID!
492
+ kind: String!
493
+ name: String!
494
+ "The owning identity; members see it on granted connections to know whose credentials they are borrowing."
495
+ owner: String!
496
+ fields: [IntegrationFieldValue!]!
497
+ configuredFields: [String!]!
498
+ validationStatus: String!
499
+ validatedAt: String
500
+ "Shared projects this connection is currently granted into (owner's own view; empty for borrowed projections)."
501
+ grantedProjectIDs: [ID!]!
502
+ createdAt: String!
503
+ updatedAt: String!
504
+ }
505
+ type IntegrationFieldValue {
506
+ name: String!
507
+ value: String!
508
+ }
509
+ "A backend bound to ONE app (by workspace + alias). Scoped bindings own a durable per-app resource and credential; their control connection is never returned."
510
+ type IntegrationBinding {
511
+ id: ID!
512
+ kind: String!
513
+ connectionID: ID
514
+ workspaceID: ID!
515
+ alias: String!
516
+ mode: String
517
+ "What the binding carries: null/empty = runtime env or events (the legacy default), \"publish\" = external static hosting."
518
+ capability: String
519
+ "The published site's public URL (publish bindings only)."
520
+ siteUrl: String
521
+ "The user-chosen custom hostname attached to the published site, when one is."
522
+ siteDomain: String
523
+ "Durable lifecycle state: provisioning, active, detached, or revoked (the connection grant was withdrawn — the next deploy refuses until the binding is removed or replaced). Legacy rows project as active."
524
+ status: String!
525
+ "Set when the binding rides a GRANTED connection: the lender's identity. The lender can always see and sever such bindings."
526
+ connectionOwner: String
527
+ }
528
+ type IntegrationConnectionPayload {
529
+ connection: IntegrationConnection!
530
+ }
531
+ type IntegrationBindingPayload {
532
+ binding: IntegrationBinding!
533
+ "One-time command (curl) that prints THIS binding's freshly minted credentials as .env lines, exactly once. Present only in the bind response for credential-carrying bindings; it can never be re-issued — only its hash is stored."
534
+ revealCommand: String
535
+ "RFC3339 time the unused reveal stops working."
536
+ revealExpiresAt: String
537
+ }
538
+ "Account-level non-secret event routing. Credential/runtime grants never use this type."
539
+ type IntegrationSubscription {
540
+ id: ID!
541
+ kind: String!
542
+ connectionID: ID
543
+ capability: String!
544
+ scope: String!
545
+ enabled: Boolean!
546
+ createdAt: String!
547
+ updatedAt: String!
548
+ }
549
+ input SendFeedbackInput {
550
+ message: String!
551
+ "Optional name of the screen/operation where the friction occurred."
552
+ context: String
553
+ }
554
+ type SendFeedbackPayload {
555
+ id: ID!
556
+ createdAt: String!
557
+ }
558
+ input ConnectionGrantInput {
559
+ connectionID: ID!
560
+ projectID: ID!
561
+ }
562
+ input SetIntegrationSubscriptionInput {
563
+ id: ID!
564
+ enabled: Boolean!
565
+ }
566
+ "Where one effective capability is configured for this app. Values and credentials are never exposed."
567
+ type EffectiveIntegrationSource {
568
+ scope: String!
569
+ id: ID
570
+ inherited: Boolean!
571
+ }
572
+ type EffectiveIntegrationCapability {
573
+ name: String!
574
+ source: EffectiveIntegrationSource!
575
+ configured: Boolean!
576
+ requiresRedeploy: Boolean!
577
+ applied: Boolean!
578
+ appliedDeploymentID: ID
579
+ appliedEnvNames: [String!]!
580
+ shadowedEnvNames: [String!]!
581
+ "The published site's public URL (publish capability only), present from bind time."
582
+ siteUrl: String
583
+ }
584
+ "Secret-free integration configuration that will apply to this app's next deploy or event."
585
+ type EffectiveIntegration {
586
+ kind: String!
587
+ manifest: IntegrationKind!
588
+ connection: IntegrationConnection
589
+ capabilities: [EffectiveIntegrationCapability!]!
590
+ }
591
+ type IntegrationLinkPayload {
592
+ # URL to send the owner to in order to authorize a link integration (e.g. a
593
+ # Telegram deeplink). The connection is completed by the provider's webhook.
594
+ url: String!
595
+ }
596
+ input IntegrationFieldValueInput {
597
+ name: String!
598
+ value: String!
599
+ }
600
+ input ConnectIntegrationInput {
601
+ kind: String!
602
+ name: String!
603
+ fields: [IntegrationFieldValueInput!]!
604
+ }
605
+ input BindIntegrationInput {
606
+ kind: String!
607
+ connectionID: ID
608
+ workspaceID: ID!
609
+ alias: String!
610
+ "Optional provider-supported isolation mode. Omit to use the provider's safe default (scoped for Postgres)."
611
+ mode: String
612
+ }
613
+ input IntegrationIDInput {
614
+ id: ID!
615
+ }
616
+ input PublishDomainInput {
617
+ bindingID: ID!
618
+ hostname: String!
619
+ }
620
+ type PublishDomainProbe {
621
+ supported: Boolean!
622
+ reason: String
623
+ }
624
+
625
+ type FunctionPage {
626
+ items: [Function!]!
627
+ total: Int!
628
+ limit: Int!
629
+ offset: Int!
630
+ hasMore: Boolean!
631
+ nextOffset: Int
632
+ }
633
+
634
+ type WorkspacePage {
635
+ items: [Workspace!]!
636
+ total: Int!
637
+ limit: Int!
638
+ offset: Int!
639
+ hasMore: Boolean!
640
+ nextOffset: Int
641
+ }
642
+
643
+ type WorkspaceFilePage {
644
+ items: [WorkspaceFile!]!
645
+ total: Int!
646
+ limit: Int!
647
+ offset: Int!
648
+ hasMore: Boolean!
649
+ nextOffset: Int
650
+ }
651
+
652
+ type WorkspaceEnvPage {
653
+ items: [WorkspaceEnvVar!]!
654
+ total: Int!
655
+ limit: Int!
656
+ offset: Int!
657
+ hasMore: Boolean!
658
+ nextOffset: Int
659
+ format: String!
660
+ }
661
+
662
+ type DeploymentPage {
663
+ items: [Deployment!]!
664
+ total: Int!
665
+ limit: Int!
666
+ offset: Int!
667
+ hasMore: Boolean!
668
+ nextOffset: Int
669
+ }
670
+
671
+ type DeploymentEventPage {
672
+ items: [DeploymentEvent!]!
673
+ total: Int!
674
+ limit: Int!
675
+ offset: Int!
676
+ hasMore: Boolean!
677
+ nextOffset: Int
678
+ format: String!
679
+ }
680
+
681
+ type Invocation {
682
+ id: ID!
683
+ functionID: ID!
684
+ ok: Boolean!
685
+ result: JSON
686
+ stdout: String!
687
+ stderr: String!
688
+ error: String
689
+ exitCode: Int!
690
+ durationMs: Int!
691
+ vmID: String
692
+ }
693
+
694
+ enum CurrentActorKind {
695
+ "The operator of this Unfazed instance, authenticated with the owner token. Full access, no free-tier limits."
696
+ OWNER
697
+ "An automated caller using a self-registered bearer token. Subject to free-tier usage/resource limits; a user can claim it to link it to their account."
698
+ AGENT
699
+ "A human signed in via GitHub OAuth, who manages their linked agents and apps."
700
+ USER
701
+ }
702
+
703
+ type CurrentActorUsage {
704
+ month: String!
705
+ requests: Int!
706
+ limit: Int!
707
+ }
708
+
709
+ type CurrentActorResources {
710
+ workspaces: Int!
711
+ workspaceLimit: Int!
712
+ services: Int!
713
+ serviceLimit: Int!
714
+ }
715
+
716
+ type CurrentActorUser {
717
+ kind: CurrentActorKind!
718
+ userID: String!
719
+ name: String!
720
+ }
721
+
722
+ type CurrentActorAgent {
723
+ agentID: String!
724
+ name: String!
725
+ claimed: Boolean!
726
+ claimedBy: String
727
+ claimedAt: String
728
+ "Deployments owned by this linked agent. Resolved lazily — only fetched when selected."
729
+ deployments: [Deployment!]!
730
+ }
731
+
732
+ type CurrentActor {
733
+ kind: CurrentActorKind!
734
+ userID: String!
735
+ name: String!
736
+ clientID: String
737
+ agentID: String
738
+ agentName: String
739
+ claimed: Boolean!
740
+ claimedBy: String
741
+ scopes: [String!]!
742
+ resource: String
743
+ expiresAt: String
744
+ usage: CurrentActorUsage
745
+ resources: CurrentActorResources
746
+ user: CurrentActorUser
747
+ agent: CurrentActorAgent
748
+ linkedAgents: [CurrentActorAgent!]!
749
+ }
750
+
751
+ type Query {
752
+ whoami: CurrentActor!
753
+ functions: [Function!]!
754
+ functionsPage(input: PageInput): FunctionPage!
755
+ function(id: ID!): Function
756
+ "Sources visible to the current account: directly owned plus those of linked claimed agents for a user; own for an agent; all for the operator. The same scope as deployments, so an agent's apps can be grouped into the caller's projects."
757
+ workspaces: [Workspace!]!
758
+ "Paginated sources visible to the current account, with the same ownership scope as workspaces."
759
+ workspacesPage(input: PageInput): WorkspacePage!
760
+ workspace(id: ID!): Workspace
761
+ "The signed-in owner's projects (dashboard grouping), oldest first."
762
+ projects: [Project!]!
763
+ "Teams the caller belongs to (owner or member), oldest first."
764
+ myTeams: [Team!]!
765
+ "Pending team invites addressed to the caller."
766
+ myTeamInvites: [TeamInviteForMe!]!
767
+ "The signed-in owner's BYO custom domains, oldest first."
768
+ customDomains: [CustomDomain!]!
769
+ "The signed-in account's SSH public keys — the keys that may open its boxes."
770
+ sshKeys: [SSHKey!]!
771
+ "Integration types available to connect (postgres, redis, …)."
772
+ availableIntegrations: [IntegrationKind!]!
773
+ "The signed-in owner's connected backends."
774
+ integrationConnections: [IntegrationConnection!]!
775
+ "Value-free projections of connections granted into a shared project the caller participates in — the bind picker's third section."
776
+ projectSharedConnections(projectID: ID!): [IntegrationConnection!]!
777
+ "The signed-in owner's app bindings (which app uses which backend)."
778
+ integrationBindings: [IntegrationBinding!]!
779
+ "Account-level event subscriptions, including disabled state."
780
+ integrationSubscriptions: [IntegrationSubscription!]!
781
+ "Secret-free configuration effective for this app's next deploy or lifecycle event."
782
+ effectiveIntegrations(workspaceID: ID!, alias: String!): [EffectiveIntegration!]!
783
+ "Whether the publish binding's connection can attach custom domains right now (a live probe against the provider). reason is set when it cannot — e.g. the API token lacks zone permissions."
784
+ publishDomainProbe(bindingID: ID!): PublishDomainProbe!
785
+ workspaceFiles(workspaceID: ID!): [WorkspaceFile!]!
786
+ workspaceFilesPage(input: ListWorkspaceFilesInput!): WorkspaceFilePage!
787
+ readWorkspaceFile(input: ReadWorkspaceFileInput!): WorkspaceFileContent
788
+ workspaceEnv(workspaceID: ID!): [WorkspaceEnvVar!]!
789
+ workspaceEnvPage(input: ListWorkspaceEnvInput!): WorkspaceEnvPage!
790
+ "Configured desired env for one monorepo app alias: overrides, inherited workspace defaults, and explicit REMOVE masks. Integration bindings and runtime env names are discovered separately; credential values are never exposed."
791
+ appEnv(workspaceID: ID!, alias: String!): [WorkspaceEnvVar!]!
792
+ "Paginated configured desired env for one monorepo app alias. Integration bindings and runtime env names are discovered separately; credential values are never exposed."
793
+ appEnvPage(input: ListAppEnvInput!): WorkspaceEnvPage!
794
+ "Every configured app scope in the workspace with what it costs against the shared env budget. App scopes are otherwise reachable only by exact alias, so this is how an orphaned one — a scope no deployment claims any more — becomes visible."
795
+ appEnvScopes(workspaceID: ID!): [AppEnvScope!]!
796
+ "Deployments visible to the current account: directly owned plus linked claimed-agent deployments for a user; own deployments for an agent; all deployments for the operator."
797
+ deployments: [Deployment!]!
798
+ "Paginated deployments visible to the current account, with the same ownership scope as deployments."
799
+ deploymentsPage(input: ListDeploymentsInput): DeploymentPage!
800
+ "Deployments owned by one of your linked (claimed) agents; the operator may query any agent."
801
+ agentDeployments(agentID: ID!): [Deployment!]!
802
+ deployment(id: ID!): Deployment
803
+ "The alias holder visible to the current account. A human who claimed the holder's agent may use its id and aliasRevision as the compare-and-swap tuple for adoptDeploymentAlias."
804
+ deploymentByAlias(alias: String!): Deployment
805
+ "An alias's terminal history, newest first: the current holder, retained READY snapshots, and FAILED promotion attempts. Only READY non-current entries are rollback targets."
806
+ deploymentReleases(alias: String!): [Deployment!]!
807
+ deploymentEvents(deploymentID: ID!, limit: Int): [DeploymentEvent!]!
808
+ deploymentEventsPage(input: ListDeploymentEventsInput!): DeploymentEventPage!
809
+ serviceStatus(deploymentID: ID!): ServiceRuntimeStatus!
810
+ serviceLogs(deploymentID: ID!, tailBytes: Int): ServiceRuntimeLogs!
811
+ appState(alias: String!, key: String!): AppStateValue!
812
+ appStateKeys(alias: String!): AppStateKeys!
813
+ githubToken: GitHubTokenStatus!
814
+ githubRepositories: [GitHubRepository!]!
815
+ githubBranches(repo: String!): [GitHubBranch!]!
816
+ }
817
+
818
+ type Mutation {
819
+ registerFunction(input: RegisterFunctionInput!): Function!
820
+ invokeFunction(input: InvokeFunctionInput!): Invocation!
821
+ createWorkspace(input: CreateWorkspaceInput!): CreateWorkspacePayload!
822
+ "Rename an app (its workspace). Does not change its alias or public URL."
823
+ renameWorkspace(input: RenameWorkspaceInput!): Workspace!
824
+ "Create an empty project to group apps under (dashboard only)."
825
+ createProject(input: CreateProjectInput!): ProjectPayload!
826
+ "Rename a project."
827
+ renameProject(input: RenameProjectInput!): ProjectPayload!
828
+ "Delete a project; its apps are detached (ungrouped), never deleted."
829
+ deleteProject(input: DeleteProjectInput!): DeleteResultPayload!
830
+ "Group a workspace under a project (same owner), or ungroup it when projectId is null."
831
+ assignWorkspaceToProject(input: AssignWorkspaceToProjectInput!): Workspace!
832
+ "Create a team owned by the caller (one owned team per user)."
833
+ createTeam(input: CreateTeamInput!): TeamPayload!
834
+ "Rename a team (team owner only)."
835
+ renameTeam(input: RenameTeamInput!): TeamPayload!
836
+ "Delete a team; resources are untouched, members just stop seeing each other's (team owner only)."
837
+ deleteTeam(input: TeamIDInput!): DeleteResultPayload!
838
+ "Invite a github login to the team (team owner only)."
839
+ inviteTeamMember(input: TeamInviteInput!): TeamPayload!
840
+ "Withdraw a pending invite (team owner only)."
841
+ cancelTeamInvite(input: TeamMemberInput!): TeamPayload!
842
+ "Accept the caller's pending invite; joining is two-way visibility."
843
+ acceptTeamInvite(input: TeamIDInput!): TeamPayload!
844
+ "Decline the caller's pending invite."
845
+ declineTeamInvite(input: TeamIDInput!): DeleteResultPayload!
846
+ "Remove a member (team owner only; the owner deletes the team instead)."
847
+ removeTeamMember(input: TeamMemberInput!): TeamPayload!
848
+ "Leave a team (members only; the owner deletes the team instead)."
849
+ leaveTeam(input: TeamIDInput!): DeleteResultPayload!
850
+ "Share one of the caller's projects with a team they belong to."
851
+ shareProjectWithTeam(input: TeamProjectInput!): TeamPayload!
852
+ "Withdraw a share (project owner or team owner)."
853
+ unshareProjectFromTeam(input: TeamProjectInput!): TeamPayload!
854
+ "Connect a BYO backend or provisioner (Postgres/Redis/…); provider-declared secret fields are sealed and never returned."
855
+ connectIntegration(input: ConnectIntegrationInput!): IntegrationConnectionPayload!
856
+ "Start the link flow for a link integration (e.g. Telegram); returns a URL to open."
857
+ startIntegrationLink(kind: String!): IntegrationLinkPayload!
858
+ "Delete a connected backend by id. Active bindings must be unbound first; detached bindings retain it until rollback/provider cleanup completes."
859
+ deleteIntegrationConnection(input: IntegrationIDInput!): DeleteResultPayload!
860
+ "Bind a backend to ONE app. Scoped providers first create a distinct per-app resource and credential; the app receives only that credential on its next deploy."
861
+ bindIntegration(input: BindIntegrationInput!): IntegrationBindingPayload!
862
+ "Attach a custom hostname (a zone already in the connected account) to a publish binding's site. Replaces the previously attached hostname, if any."
863
+ setPublishDomain(input: PublishDomainInput!): IntegrationBindingPayload!
864
+ "Detach the publish binding's custom hostname. The site stays reachable at its provider URL."
865
+ removePublishDomain(input: IntegrationIDInput!): IntegrationBindingPayload!
866
+ """
867
+ Share the RIGHT TO BIND a connection into a shared project. The values stay
868
+ in the owner's account, but an app owner who binds it can effectively read
869
+ them at runtime (env cannot be hidden from the code that receives it) —
870
+ revoking a grant is therefore NOT rotation.
871
+ """
872
+ grantConnectionToProject(input: ConnectionGrantInput!): IntegrationConnectionPayload!
873
+ """
874
+ Report a platform friction point or bug to the operator — from the surface
875
+ where it happened. Free-form; one short message with what you expected and
876
+ what happened instead is enough.
877
+ """
878
+ sendFeedback(input: SendFeedbackInput!): SendFeedbackPayload!
879
+ "Withdraw a grant. Dependent bindings by other accounts flip to revoked and their next deploy fails loudly; running releases keep the env they booted with."
880
+ revokeConnectionGrant(input: ConnectionGrantInput!): IntegrationConnectionPayload!
881
+ "Detach a binding by id. New deploys omit it; rollback credentials are retained until no immutable deployment references the binding, then revoked."
882
+ unbindIntegration(input: IntegrationIDInput!): DeleteResultPayload!
883
+ "Enable or disable an account-level integration event subscription."
884
+ setIntegrationSubscription(input: SetIntegrationSubscriptionInput!): IntegrationSubscription!
885
+ "Register a public key for the signed-in account so it can SSH into that account's boxes. Adding the same key twice returns the existing record."
886
+ addSSHKey(input: AddSSHKeyInput!): SSHKey!
887
+ "Remove one of the account's SSH public keys. Takes effect on the next connection; live sessions are unaffected."
888
+ removeSSHKey(input: RemoveSSHKeyInput!): DeleteResultPayload!
889
+ "Attach a BYO custom domain to an app's alias (point its DNS at the edge first)."
890
+ addCustomDomain(input: AddCustomDomainInput!): CustomDomain!
891
+ "Detach a custom domain; the app keeps serving on its alias/URL."
892
+ removeCustomDomain(input: RemoveCustomDomainInput!): DeleteResultPayload!
893
+ writeWorkspaceTextFile(input: WriteWorkspaceTextFileInput!): WorkspaceFilePayload!
894
+ writeWorkspaceBase64File(input: WriteWorkspaceBase64FileInput!): WorkspaceFilePayload!
895
+ uploadWorkspaceFile(input: UploadWorkspaceFileInput!): WorkspaceFilePayload!
896
+ deleteWorkspaceFile(input: DeleteWorkspaceFileInput!): DeleteWorkspaceFilePayload!
897
+ setWorkspaceEnv(input: SetWorkspaceEnvInput!): SetWorkspaceEnvPayload!
898
+ setWorkspaceSecret(input: SetWorkspaceSecretInput!): SetWorkspaceEnvPayload!
899
+ deleteWorkspaceEnv(input: DeleteWorkspaceEnvInput!): DeleteWorkspaceEnvPayload!
900
+ "Override one non-secret env var for a single app alias."
901
+ setAppEnv(input: SetAppEnvInput!): SetWorkspaceEnvPayload!
902
+ "Override one encrypted secret for a single app alias. The value is never returned."
903
+ setAppSecret(input: SetAppSecretInput!): SetWorkspaceEnvPayload!
904
+ "REMOVE an env name for one app, blocking the workspace default and integration enrichment."
905
+ removeAppEnv(input: RemoveAppEnvInput!): DeleteWorkspaceEnvPayload!
906
+ "Clear an app override or REMOVE mask so the app follows workspace/integration defaults again."
907
+ inheritAppEnv(input: InheritAppEnvInput!): DeleteWorkspaceEnvPayload!
908
+ "Drop an app's entire scope — every override, secret, and REMOVE mask — in one call, so it follows workspace/integration defaults again. The bulk form of inheritAppEnv, and the only way a scope is ever removed: deleting a deployment keeps its config, because app secrets cannot be read back and dropping a REMOVE mask would expose a workspace default the app denied."
909
+ clearAppEnv(input: ClearAppEnvInput!): ClearAppEnvPayload!
910
+ createDeployment(input: CreateDeploymentInput!): CreateDeploymentPayload!
911
+ "Build the directly owned target workspace, then atomically transfer an alias held by one of the caller's claimed agents after the replacement is READY. The current holder remains live while the replacement builds. Pass the id and aliasRevision observed through deploymentByAlias; the operation fails if either changed, if the alias has a custom domain or stateful placement, or if it would replace a SERVICE with STATIC."
912
+ adoptDeploymentAlias(input: AdoptDeploymentAliasInput!): CreateDeploymentPayload!
913
+ "Deploy a workspace's CURRENT files, detecting the kind from them (a root server.ts/index.html or an unfazed.json). The recovery path after a failed import: add/fix unfazed.json (or an entry), then deploy — no git re-fetch. Errors with what to add if the files still aren't deployable."
914
+ deployWorkspace(input: DeployWorkspaceInput!): CreateDeploymentPayload!
915
+ "Import and deploy a GitHub repo into a new workspace. Kind/runtime are detected from the repo root (server.ts/go.mod+main.go -> SERVICE, index.html -> STATIC) unless a root unfazed.json overrides it. For a monorepo, a root unfazed.json `apps` array deploys SEVERAL apps from one push — each {alias, rootDir} builds that subdirectory as its own app (apps[] is repo config, not an input here; the same applies to syncRepo and webhook pushes). Returns immediately with an IMPORTING status; the fetch+build runs in the background."
916
+ importRepo(input: ImportRepoInput!): ImportRepoPayload!
917
+ "Link a GitHub repo to an EXISTING workspace (one with no source yet) and import it. The workspace keeps its id, env, and secrets. If unfazed.json apps[] omits the supplied/stored current alias, that alias, its current deployment, and its App State are retired."
918
+ connectRepo(input: ConnectRepoInput!): ImportRepoPayload!
919
+ syncRepo(input: SyncRepoInput!): ImportRepoPayload!
920
+ unlinkRepo(input: UnlinkRepoInput!): DeleteResultPayload!
921
+ installRepoWebhook(input: InstallRepoWebhookInput!): ImportRepoPayload!
922
+ setRepoDeployAlias(input: SetRepoDeployAliasInput!): ImportRepoPayload!
923
+ setGitHubToken(input: SetGitHubTokenInput!): GitHubTokenStatus!
924
+ deleteGitHubToken: GitHubTokenStatus!
925
+ restartService(input: ServiceControlInput!): ServiceRuntimeStatus!
926
+ stopService(input: ServiceControlInput!): ServiceRuntimeStatus!
927
+ "Permanently delete a deployment and its files snapshot, stopping a running service VM first. Alias-keyed app state is freed once no other deployment uses the alias; the alias's app-scoped env and secrets are reclaimed on that condition plus two more — the alias really was deployed once, and no git source redeploys it — so deleting a failed first build keeps the env staged for the retry. That reclaim is not reversible: secret values are never returned by the API."
928
+ deleteDeployment(input: DeleteDeploymentInput!): DeleteResultPayload!
929
+ "Roll an alias back to a PRIOR release: atomically repoint it to the given deployment and bring that snapshot back (always_on restarts warm; on_demand cold-starts on the next request). Also reverts to that release's env/secrets snapshot. Pass the id and opaque aliasRevision of the aliasHeld release you observed; the rollback fails if either changed since deploymentReleases."
930
+ rollbackDeployment(input: RollbackDeploymentInput!): Deployment!
931
+ deleteWorkspace(input: DeleteWorkspaceInput!): DeleteResultPayload!
932
+ setAppState(input: SetAppStateInput!): AppStateValue!
933
+ deleteAppState(input: DeleteAppStateInput!): DeleteResultPayload!
934
+ "Rename a linked (claimed) agent. Allowed for the agent's claimer or the operator."
935
+ renameAgent(input: RenameAgentInput!): CurrentActorAgent!
936
+ "Delete a linked (claimed) agent: revoke its token AND delete every workspace and deployment it owns (stopping service VMs). Irreversible."
937
+ deleteAgent(input: DeleteAgentInput!): DeleteResultPayload!
938
+ "Issue a fresh access token for a linked (claimed) agent, keeping its identity so it can still redeploy the aliases it owns. Self-registration cannot do this: it always mints a NEW agent, and the platform refuses to let a different owner near an existing alias. Every previous token of the agent stops working immediately, so write the returned value wherever the agent reads it. The token is returned once and is never retrievable again. Allowed for the agent's claimer or the operator."
939
+ rotateAgentToken(input: RotateAgentTokenInput!): AgentTokenPayload!
940
+ "Issue a one-time code to connect the caller's Telegram to deploy notifications. Returns a t.me deep link to open the bot with the code prefilled; the code expires and is single-use."
941
+ createTelegramLinkCode: TelegramLinkPayload!
942
+ }
943
+
944
+ type TelegramLinkPayload {
945
+ "Open this to start the bot with the code prefilled (t.me/<bot>?start=<code>)."
946
+ deepLink: String!
947
+ "The raw code, in case the deep link can't be used (send the bot: /start <code>)."
948
+ code: String!
949
+ "RFC3339 time the code stops working."
950
+ expiresAt: String!
951
+ "The bot's @username (no @)."
952
+ botUsername: String!
953
+ }
954
+
955
+ input RenameAgentInput {
956
+ agentID: ID!
957
+ name: String!
958
+ }
959
+
960
+ input DeleteAgentInput {
961
+ agentID: ID!
962
+ }
963
+
964
+ input RotateAgentTokenInput {
965
+ agentID: ID!
966
+ }
967
+
968
+ "A newly issued agent credential. Shown once: only its hash is stored."
969
+ type AgentTokenPayload {
970
+ "The agent this token authenticates as — unchanged by rotation."
971
+ agentID: ID!
972
+ "The bearer token. Copy it now; it cannot be read again."
973
+ accessToken: String!
974
+ tokenType: String!
975
+ scopes: [String!]!
976
+ "RFC3339 time the token stops working."
977
+ expiresAt: String!
978
+ }
979
+
980
+ input RegisterFunctionInput {
981
+ name: String!
982
+ file: File!
983
+ packageJSON: File
984
+ bunLock: File
985
+ }
986
+
987
+ input InvokeFunctionInput {
988
+ functionID: ID!
989
+ payload: JSON
990
+ }
991
+
992
+ input PageInput {
993
+ limit: Int
994
+ offset: Int
995
+ order: String
996
+ }
997
+
998
+ input CreateWorkspaceInput {
999
+ name: String!
1000
+ }
1001
+
1002
+ input RenameWorkspaceInput {
1003
+ workspaceID: ID!
1004
+ name: String!
1005
+ }
1006
+
1007
+ type CreateWorkspacePayload {
1008
+ workspace: Workspace!
1009
+ }
1010
+
1011
+ input WriteWorkspaceTextFileInput {
1012
+ workspaceID: ID!
1013
+ path: String!
1014
+ text: String!
1015
+ }
1016
+
1017
+ input WriteWorkspaceBase64FileInput {
1018
+ workspaceID: ID!
1019
+ path: String!
1020
+ contentBase64: String!
1021
+ }
1022
+
1023
+ input UploadWorkspaceFileInput {
1024
+ workspaceID: ID!
1025
+ path: String!
1026
+ file: File!
1027
+ }
1028
+
1029
+ type WorkspaceFilePayload {
1030
+ file: WorkspaceFile!
1031
+ }
1032
+
1033
+ input ReadWorkspaceFileInput {
1034
+ workspaceID: ID!
1035
+ path: String!
1036
+ offset: Int
1037
+ limit: Int
1038
+ }
1039
+
1040
+ input ListWorkspaceFilesInput {
1041
+ workspaceID: ID!
1042
+ limit: Int
1043
+ offset: Int
1044
+ order: String
1045
+ }
1046
+
1047
+ input ListWorkspaceEnvInput {
1048
+ workspaceID: ID!
1049
+ limit: Int
1050
+ offset: Int
1051
+ order: String
1052
+ format: String
1053
+ }
1054
+
1055
+ input ListAppEnvInput {
1056
+ workspaceID: ID!
1057
+ alias: String!
1058
+ limit: Int
1059
+ offset: Int
1060
+ order: String
1061
+ format: String
1062
+ }
1063
+
1064
+ input DeleteWorkspaceFileInput {
1065
+ workspaceID: ID!
1066
+ path: String!
1067
+ }
1068
+
1069
+ type DeleteWorkspaceFilePayload {
1070
+ ok: Boolean!
1071
+ }
1072
+
1073
+ input SetWorkspaceEnvInput {
1074
+ workspaceID: ID!
1075
+ name: String!
1076
+ value: String!
1077
+ }
1078
+
1079
+ input SetWorkspaceSecretInput {
1080
+ workspaceID: ID!
1081
+ name: String!
1082
+ value: String!
1083
+ }
1084
+
1085
+ type SetWorkspaceEnvPayload {
1086
+ env: WorkspaceEnvVar!
1087
+ }
1088
+
1089
+ input DeleteWorkspaceEnvInput {
1090
+ workspaceID: ID!
1091
+ name: String!
1092
+ }
1093
+
1094
+ input SetAppEnvInput {
1095
+ workspaceID: ID!
1096
+ alias: String!
1097
+ name: String!
1098
+ value: String!
1099
+ }
1100
+
1101
+ input SetAppSecretInput {
1102
+ workspaceID: ID!
1103
+ alias: String!
1104
+ name: String!
1105
+ value: String!
1106
+ }
1107
+
1108
+ input RemoveAppEnvInput {
1109
+ workspaceID: ID!
1110
+ alias: String!
1111
+ name: String!
1112
+ }
1113
+
1114
+ input InheritAppEnvInput {
1115
+ workspaceID: ID!
1116
+ alias: String!
1117
+ name: String!
1118
+ }
1119
+
1120
+ input ClearAppEnvInput {
1121
+ workspaceID: ID!
1122
+ alias: String!
1123
+ }
1124
+
1125
+ type ClearAppEnvPayload {
1126
+ "True when the call removed something. Clearing an already-clear scope returns false with removed 0 and is not an error."
1127
+ ok: Boolean!
1128
+ "How many overrides, secrets, and REMOVE masks were dropped."
1129
+ removed: Int!
1130
+ }
1131
+
1132
+ type DeleteWorkspaceEnvPayload {
1133
+ ok: Boolean!
1134
+ }
1135
+
1136
+ """
1137
+ Creates a deployment from the workspace's current files. The build is driven by
1138
+ an optional root unfazed.json: STATIC serves the files as-is unless unfazed.json
1139
+ sets build (a command run in the build VM) + output (publish dir, default "dist"
1140
+ when build is set; output with no build republishes a committed dir like dist/ as
1141
+ is); SERVICE bundles server.ts by default, or the entry set in unfazed.json.
1142
+ install defaults to "bun install" (--frozen-lockfile when a bun lockfile exists).
1143
+ """
1144
+ input CreateDeploymentInput {
1145
+ workspaceID: ID!
1146
+ "STATIC (serve files) or SERVICE (run an HTTP server). Classify it yourself: SERVICE if the workspace has server.ts, a go.mod+main.go, or an unfazed.json entry, else STATIC."
1147
+ kind: DeploymentKind!
1148
+ "SERVICE runtime. Omit to auto-detect (a go.mod+main.go is GO, otherwise BUN). Ignored for STATIC."
1149
+ runtime: ServiceRuntime
1150
+ alias: String
1151
+ "STATIC only: when true, missing paths serve index.html (single-page apps). Ignored for SERVICE."
1152
+ spaMode: Boolean
1153
+ "SERVICE only. Omit for ON_DEMAND (the default — sleeps and cold-starts on first request, right for most services). Set ALWAYS_ON only to keep the VM warm."
1154
+ serviceMode: ServiceMode
1155
+ healthPath: String
1156
+ """
1157
+ Standard 5-field cron spec (minute hour day-of-month month day-of-week). When
1158
+ set, the platform wakes the SERVICE on each tick with a POST to cronPath
1159
+ (default /cron) carrying header X-Unfz-Trigger: cron and a signed
1160
+ X-Unfz-Cron-Token equal to the service's UNFZ_STATE_TOKEN.
1161
+ """
1162
+ cronSchedule: String
1163
+ "Absolute HTTP path the cron tick POSTs to; defaults to /cron when cronSchedule is set."
1164
+ cronPath: String
1165
+ "BOX only: optional VM size. Omit for the platform defaults."
1166
+ boxResources: BoxResourcesInput
1167
+ }
1168
+
1169
+ "A box's requested VM size. Omitted fields use the platform default."
1170
+ input BoxResourcesInput {
1171
+ "RAM in MiB (default 2048, min 512, max 16384)."
1172
+ memMiB: Int
1173
+ "vCPU count (default 2, max 8)."
1174
+ vcpus: Int
1175
+ "Persistent disk in GiB (default 8, max 64). Applies only when the disk is first created; an existing disk keeps its size."
1176
+ diskGiB: Int
1177
+ }
1178
+
1179
+ input AdoptDeploymentAliasInput {
1180
+ alias: String!
1181
+ "The caller's directly owned workspace whose current files will become the replacement."
1182
+ targetWorkspaceID: ID!
1183
+ "The id returned by deploymentByAlias for the current holder. Required compare-and-swap guard."
1184
+ expectedCurrentDeploymentID: ID!
1185
+ "The opaque aliasRevision returned with that holder. Required compare-and-swap guard against same-id ABA."
1186
+ expectedCurrentAliasRevision: String!
1187
+ }
1188
+
1189
+ input DeployWorkspaceInput {
1190
+ workspaceID: ID!
1191
+ "Optional public alias; defaults to the workspace's git deploy alias when it was imported."
1192
+ alias: String
1193
+ "SERVICE only; defaults to the git source's mode, otherwise ON_DEMAND."
1194
+ serviceMode: ServiceMode
1195
+ "STATIC only; overrides the detected SPA fallback."
1196
+ spaMode: Boolean
1197
+ }
1198
+
1199
+ type CreateDeploymentPayload {
1200
+ deployment: Deployment!
1201
+ }
1202
+
1203
+ input ImportRepoInput {
1204
+ repo: String!
1205
+ ref: String
1206
+ alias: String
1207
+ spaMode: Boolean
1208
+ serviceMode: ServiceMode
1209
+ autoDeploy: Boolean
1210
+ force: Boolean
1211
+ }
1212
+
1213
+ input ConnectRepoInput {
1214
+ workspaceID: ID!
1215
+ repo: String!
1216
+ ref: String
1217
+ alias: String
1218
+ spaMode: Boolean
1219
+ serviceMode: ServiceMode
1220
+ autoDeploy: Boolean
1221
+ }
1222
+
1223
+ input SyncRepoInput {
1224
+ workspaceID: ID!
1225
+ force: Boolean
1226
+ }
1227
+
1228
+ input UnlinkRepoInput {
1229
+ workspaceID: ID!
1230
+ }
1231
+
1232
+ input InstallRepoWebhookInput {
1233
+ workspaceID: ID!
1234
+ }
1235
+
1236
+ input SetRepoDeployAliasInput {
1237
+ workspaceID: ID!
1238
+ "The alias future pushes/syncs should deploy to. The deploy-time guard re-checks ownership."
1239
+ alias: String!
1240
+ }
1241
+
1242
+ input SetGitHubTokenInput {
1243
+ token: String!
1244
+ }
1245
+
1246
+ type ImportRepoPayload {
1247
+ workspace: Workspace!
1248
+ deployment: Deployment
1249
+ gitSource: GitSource
1250
+ noop: Boolean!
1251
+ }
1252
+
1253
+ input ListDeploymentsInput {
1254
+ limit: Int
1255
+ offset: Int
1256
+ kind: DeploymentKind
1257
+ alias: String
1258
+ workspaceID: ID
1259
+ order: String
1260
+ }
1261
+
1262
+ input ListDeploymentEventsInput {
1263
+ deploymentID: ID!
1264
+ limit: Int
1265
+ offset: Int
1266
+ order: String
1267
+ format: String
1268
+ }
1269
+
1270
+ input ServiceControlInput {
1271
+ deploymentID: ID!
1272
+ }
1273
+
1274
+ input DeleteDeploymentInput {
1275
+ deploymentID: ID!
1276
+ }
1277
+
1278
+ input RollbackDeploymentInput {
1279
+ "The prior deployment to restore as the alias's live release. Get candidate ids from deploymentReleases."
1280
+ deploymentID: ID!
1281
+ "The id of the aliasHeld release observed in the same deploymentReleases result. Required compare-and-swap guard."
1282
+ expectedCurrentDeploymentID: ID!
1283
+ "The opaque aliasRevision of that aliasHeld release. Required compare-and-swap guard against same-id ABA."
1284
+ expectedCurrentAliasRevision: String!
1285
+ }
1286
+
1287
+ input DeleteWorkspaceInput {
1288
+ workspaceID: ID!
1289
+ "Also delete every deployment snapshotted from the workspace (stopping service VMs) instead of refusing while any exist."
1290
+ withDeployments: Boolean
1291
+ }
1292
+
1293
+ input SetAppStateInput {
1294
+ alias: String!
1295
+ key: String!
1296
+ value: String!
1297
+ encoding: String
1298
+ }
1299
+
1300
+ input DeleteAppStateInput {
1301
+ alias: String!
1302
+ key: String!
1303
+ }