@spacefast/common 0.0.11 → 0.0.13

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.
Files changed (160) hide show
  1. package/dist/agents/connect-targets.d.ts +4 -4
  2. package/dist/agents/connect-targets.js +3 -3
  3. package/dist/agents/private-key-oauth.d.ts +37 -0
  4. package/dist/agents/private-key-oauth.js +158 -0
  5. package/dist/config/domains.js +1 -1
  6. package/dist/config/index.d.ts +1 -0
  7. package/dist/config/index.js +1 -0
  8. package/dist/config/postgres-budget.d.ts +126 -0
  9. package/dist/config/postgres-budget.js +135 -0
  10. package/dist/config/postgres-budget.json +50 -0
  11. package/dist/contracts/access.d.ts +386 -1183
  12. package/dist/contracts/access.js +240 -1018
  13. package/dist/contracts/activity.d.ts +1 -1
  14. package/dist/contracts/activity.js +11 -19
  15. package/dist/contracts/api-keys.d.ts +69 -45
  16. package/dist/contracts/api-keys.js +3 -0
  17. package/dist/contracts/archives.d.ts +9 -10
  18. package/dist/contracts/archives.js +4 -6
  19. package/dist/contracts/builds.d.ts +8 -8
  20. package/dist/contracts/builds.js +28 -48
  21. package/dist/contracts/channels.js +1 -2
  22. package/dist/contracts/comments.d.ts +102 -93
  23. package/dist/contracts/comments.js +121 -63
  24. package/dist/contracts/common.d.ts +4 -3
  25. package/dist/contracts/common.js +2 -0
  26. package/dist/contracts/countries.js +2 -7
  27. package/dist/contracts/data-source-routes.d.ts +20 -0
  28. package/dist/contracts/data-source-routes.js +15 -0
  29. package/dist/contracts/deployments.d.ts +3 -3
  30. package/dist/contracts/device-auth.d.ts +21 -15
  31. package/dist/contracts/docs.d.ts +5 -5
  32. package/dist/contracts/domains.d.ts +261 -1330
  33. package/dist/contracts/domains.js +39 -301
  34. package/dist/contracts/email-preferences.d.ts +50 -0
  35. package/dist/contracts/email-preferences.js +44 -0
  36. package/dist/contracts/enums.d.ts +3 -5
  37. package/dist/contracts/enums.js +3 -8
  38. package/dist/contracts/error-code-meta.d.ts +99 -33
  39. package/dist/contracts/error-code-meta.js +36 -9
  40. package/dist/contracts/error-codes.d.ts +1 -1
  41. package/dist/contracts/error-codes.js +28 -11
  42. package/dist/contracts/execution.d.ts +212 -0
  43. package/dist/contracts/execution.js +288 -0
  44. package/dist/contracts/feature-lifecycle.d.ts +498 -2
  45. package/dist/contracts/feature-lifecycle.js +539 -2
  46. package/dist/contracts/features.d.ts +184 -74
  47. package/dist/contracts/features.js +4 -303
  48. package/dist/contracts/functions.d.ts +729 -0
  49. package/dist/contracts/functions.js +485 -0
  50. package/dist/contracts/git.d.ts +1 -1
  51. package/dist/contracts/grants.d.ts +1158 -0
  52. package/dist/contracts/grants.js +696 -0
  53. package/dist/contracts/ids.d.ts +6 -5
  54. package/dist/contracts/ids.js +6 -5
  55. package/dist/contracts/internal.d.ts +3 -3
  56. package/dist/contracts/mcp.d.ts +12 -12
  57. package/dist/contracts/me.js +1 -1
  58. package/dist/contracts/mounts.d.ts +142 -0
  59. package/dist/contracts/mounts.js +56 -0
  60. package/dist/contracts/oauth-resources.d.ts +5 -5
  61. package/dist/contracts/oauth-resources.js +2 -0
  62. package/dist/contracts/operations.d.ts +4 -4
  63. package/dist/contracts/pages.d.ts +6 -14
  64. package/dist/contracts/pages.js +11 -23
  65. package/dist/contracts/plan-policy.d.ts +2 -9
  66. package/dist/contracts/plan-policy.js +1 -4
  67. package/dist/contracts/platform.d.ts +80 -32
  68. package/dist/contracts/platform.js +59 -12
  69. package/dist/contracts/push-new.d.ts +26 -2
  70. package/dist/contracts/push-new.js +8 -0
  71. package/dist/contracts/quotas.d.ts +0 -1
  72. package/dist/contracts/quotas.js +0 -5
  73. package/dist/contracts/repository-connections.d.ts +1 -1
  74. package/dist/contracts/resources.d.ts +21 -85
  75. package/dist/contracts/resources.js +17 -47
  76. package/dist/contracts/runtime-api.d.ts +799 -192
  77. package/dist/contracts/runtime-api.js +231 -100
  78. package/dist/contracts/runtime-app.d.ts +138 -0
  79. package/dist/contracts/runtime-app.js +21 -0
  80. package/dist/contracts/sf-config-v1.d.ts +5 -0
  81. package/dist/contracts/sf-config-v1.js +1 -1
  82. package/dist/contracts/sites.d.ts +17 -12
  83. package/dist/contracts/sites.js +30 -12
  84. package/dist/contracts/space-config.d.ts +46 -117
  85. package/dist/contracts/space-config.js +323 -25
  86. package/dist/contracts/spaces.d.ts +392 -256
  87. package/dist/contracts/spaces.js +163 -83
  88. package/dist/contracts/superadmin-emails.d.ts +27 -3
  89. package/dist/contracts/superadmin-emails.js +10 -15
  90. package/dist/contracts/superadmin-runtime.d.ts +2 -2
  91. package/dist/contracts/superadmin-spaces.d.ts +19 -142
  92. package/dist/contracts/superadmin-spaces.js +7 -0
  93. package/dist/contracts/tags.d.ts +66 -36
  94. package/dist/contracts/tags.js +195 -11
  95. package/dist/contracts/teams.d.ts +9 -9
  96. package/dist/contracts/transfers.d.ts +1 -2
  97. package/dist/contracts/variables.d.ts +4 -4
  98. package/dist/contracts/variables.js +4 -3
  99. package/dist/contracts/webhooks.d.ts +2 -2
  100. package/dist/contracts/zero.d.ts +437 -193
  101. package/dist/contracts/zero.js +149 -158
  102. package/dist/dashboard-paths/index.d.ts +3 -3
  103. package/dist/dashboard-paths/index.js +1 -0
  104. package/dist/docs/agent-prose.js +10 -8
  105. package/dist/docs/agent-setup.d.ts +6 -4
  106. package/dist/docs/agent-setup.js +26 -16
  107. package/dist/docs/agent-solutions.js +1 -1
  108. package/dist/docs/catalog.d.ts +35 -37
  109. package/dist/docs/catalog.js +36 -38
  110. package/dist/docs/error-docs.js +108 -44
  111. package/dist/utils/asset-fingerprint.d.ts +11 -0
  112. package/dist/utils/asset-fingerprint.js +46 -0
  113. package/dist/utils/auth-redirect.d.ts +1 -3
  114. package/dist/utils/auth-redirect.js +1 -21
  115. package/dist/utils/build-settings.d.ts +2 -0
  116. package/dist/utils/build-settings.js +61 -9
  117. package/dist/utils/credential-policy.d.ts +1 -1
  118. package/dist/utils/credential-policy.js +4 -0
  119. package/dist/utils/dns-instructions.d.ts +29 -0
  120. package/dist/utils/dns-instructions.js +78 -0
  121. package/dist/utils/domain-diagnostics.d.ts +29 -0
  122. package/dist/utils/domain-diagnostics.js +63 -0
  123. package/dist/utils/egress-policy.fixtures.json +51 -0
  124. package/dist/utils/grants.d.ts +53 -0
  125. package/dist/utils/grants.js +160 -0
  126. package/dist/utils/id-hints.d.ts +1 -0
  127. package/dist/utils/id-hints.js +55 -13
  128. package/dist/utils/local-space-state.js +1 -0
  129. package/dist/utils/page-colors.d.ts +50 -0
  130. package/dist/utils/page-colors.js +167 -0
  131. package/dist/utils/page-fonts.d.ts +2 -0
  132. package/dist/utils/page-fonts.js +4 -0
  133. package/dist/utils/pages.d.ts +19 -6
  134. package/dist/utils/pages.js +122 -49
  135. package/dist/utils/production-runtime.d.ts +18 -0
  136. package/dist/utils/production-runtime.js +28 -0
  137. package/dist/utils/publish-policy.d.ts +34 -4
  138. package/dist/utils/publish-policy.js +132 -61
  139. package/dist/utils/query-keys.d.ts +7 -13
  140. package/dist/utils/query-keys.js +12 -18
  141. package/dist/utils/source-archive-policy.d.ts +2 -0
  142. package/dist/utils/source-archive-policy.js +2 -0
  143. package/dist/utils/space-config.d.ts +5 -1
  144. package/dist/utils/space-config.js +35 -0
  145. package/dist/utils/static-runtime-policy.d.ts +5 -0
  146. package/dist/utils/static-runtime-policy.fixtures.json +57 -0
  147. package/dist/utils/static-runtime-policy.js +54 -10
  148. package/dist/utils/upload-session.d.ts +3 -0
  149. package/dist/utils/upload-session.js +31 -0
  150. package/package.json +6 -4
  151. package/dist/contracts/annotations.d.ts +0 -327
  152. package/dist/contracts/annotations.js +0 -235
  153. package/dist/contracts/generated-feature-launch-entries.d.ts +0 -2
  154. package/dist/contracts/generated-feature-launch-entries.js +0 -518
  155. package/dist/contracts/publishes.d.ts +0 -135
  156. package/dist/contracts/publishes.js +0 -162
  157. package/dist/utils/access-match.d.ts +0 -39
  158. package/dist/utils/access-match.js +0 -296
  159. package/dist/utils/sf-config-v1.d.ts +0 -2
  160. package/dist/utils/sf-config-v1.js +0 -542
@@ -1,32 +1,29 @@
1
1
  import { z } from "zod";
2
+ import { SPACE_SLUG_MAX_LENGTH } from "../slug-policy/index.js";
3
+ import { openHandoffSchema } from "./access.js";
2
4
  import { AsyncOperationSchema, baseDiagnosticSchema, CursorPaginationSchema, cursorListQuerySchema, } from "./common.js";
3
5
  import { versionStatus, spaceStatus } from "./enums.js";
6
+ import { runtimeKindSchema } from "./execution.js";
4
7
  import { conventionFilesSchema, uploadInstructionsSchema, manifestFileSchema } from "./internal.js";
5
- import { ChannelPointerSchema, VersionSchema, PublishSourceSchema, SpaceSchema, spaceSettingsDigestSchema, } from "./resources.js";
8
+ import { VersionSchema, PublishSourceSchema, SpaceSchema, spaceSettingsDigestSchema, } from "./resources.js";
9
+ import { runtimeAppSchema } from "./runtime-app.js";
6
10
  import { spaceConfigSchema, spacePlacementConfigSchema } from "./space-config.js";
7
11
  import { principalIdSchema } from "./transfers.js";
8
- import { zeroRuntimeKindSchema } from "./zero.js";
9
- export const AnonymousSpaceAccessSchema = z.object({
10
- claimToken: z
12
+ export const spaceClaimReceiptSchema = z.object({
13
+ token: z
11
14
  .string()
12
- .nullable()
15
+ .min(1)
13
16
  .describe("One-time, space-scoped credential returned only at anonymous space creation. Save it immediately — it is never shown again and is required to publish and manage the space until it is claimed."),
14
- claimUrl: z
17
+ url: z
15
18
  .string()
16
- .nullable()
19
+ .url()
17
20
  .describe("Browser-only claim link in `/claim#nonce` form. The fragment is a human handoff capability; API clients use the claim token as bearer auth for publish/update/status/exchange."),
18
- expiresAt: z
19
- .string()
20
- .datetime()
21
- .nullable()
22
- .describe("When the unclaimed space expires if nobody publishes to it or claims it."),
23
- warning: z
24
- .string()
25
- .describe("Human-readable notice explaining that the space is anonymous and will expire unless claimed."),
21
+ expiresAt: z.string().datetime(),
26
22
  });
27
23
  export const SpaceCreateResponseSchema = z.object({
28
24
  space: SpaceSchema,
29
- anonymousAccess: AnonymousSpaceAccessSchema.optional(),
25
+ open: openHandoffSchema,
26
+ claim: spaceClaimReceiptSchema.optional(),
30
27
  });
31
28
  // Stored per-version diagnostic surfaced on the space diagnostics feed: the shared
32
29
  // Diagnostic shape (contracts/common.ts) plus persistence identity.
@@ -70,6 +67,12 @@ export const spaceCreateSchema = z
70
67
  export const spacePatchSchema = z
71
68
  .object({
72
69
  title: z.string().min(1).max(255).optional(),
70
+ slug: z
71
+ .string()
72
+ .min(2)
73
+ .max(SPACE_SLUG_MAX_LENGTH)
74
+ .optional()
75
+ .describe("Renames the space and its managed view.fast hostname. Send slug by itself. Previously managed hostnames keep a temporary, path- and query-preserving 307 redirect to the current hostname; immutable version URLs do not change."),
73
76
  config: spaceConfigSchema
74
77
  .nullable()
75
78
  .optional()
@@ -87,21 +90,16 @@ export const spacePatchSchema = z
87
90
  .boolean()
88
91
  .optional()
89
92
  .describe("Hide the live production site from search engines. Applies only to claimed spaces' live hostnames; preview and version hostnames are always noindex."),
90
- password: z
91
- .string()
92
- .min(1)
93
- .max(255)
94
- .nullable()
95
- .optional()
96
- .describe("Sets (string) or removes (null) space password protection."),
97
93
  })
98
- // Strict so an unknown field (notably `slug`) is rejected with a validation
99
- // error rather than silently stripped. Slug rename is a deliberately
100
- // post-flip surface (its dormant reserve/commit core + retained-hostname 308
101
- // serving land with the slug-rename activation card); accepting-and-dropping
102
- // `slug` here would be a silent no-op, so the live PATCH must refuse it.
103
94
  .strict()
104
95
  .superRefine((value, ctx) => {
96
+ if (value.slug !== undefined && Object.keys(value).some((key) => key !== "slug")) {
97
+ ctx.addIssue({
98
+ code: z.ZodIssueCode.custom,
99
+ message: "slug must be updated in a separate request.",
100
+ path: ["slug"],
101
+ });
102
+ }
105
103
  if (value.force === true && value.baseSettingsDigest === undefined) {
106
104
  ctx.addIssue({
107
105
  code: z.ZodIssueCode.custom,
@@ -166,6 +164,24 @@ export const anonymousClaimSpacePreviewSchema = z.object({
166
164
  liveUrl: z.string().nullable(),
167
165
  createdAt: z.string().datetime().nullable(),
168
166
  });
167
+ export const anonymousClaimSharingSummarySchema = z.object({
168
+ people: z.array(z.object({
169
+ id: z.string(),
170
+ displayName: z.string(),
171
+ status: z.enum(["pending", "accepted"]),
172
+ grants: z.array(z.object({
173
+ scope: z.string().startsWith("/"),
174
+ role: z.enum(["viewer", "commenter", "editor"]),
175
+ })),
176
+ })),
177
+ links: z.array(z.object({
178
+ id: z.string(),
179
+ name: z.string(),
180
+ landingPath: z.string().startsWith("/"),
181
+ scopes: z.array(z.string().startsWith("/")),
182
+ expiresAt: z.string().datetime().nullable(),
183
+ })),
184
+ });
169
185
  export const anonymousClaimResponseSchema = z.object({
170
186
  state: z.enum(["unclaimed", "claimed"]),
171
187
  action: z.enum(["claimed", "login_required", "team_required", "confirm_assign"]),
@@ -185,6 +201,7 @@ export const anonymousClaimResponseSchema = z.object({
185
201
  })
186
202
  .describe("Server-authoritative continuation eligibility and claim result."),
187
203
  teams: z.array(anonymousClaimTeamSchema).optional(),
204
+ sharing: anonymousClaimSharingSummarySchema,
188
205
  });
189
206
  export const anonymousClaimStatusResponseSchema = z.object({
190
207
  publish: z.object({
@@ -228,6 +245,20 @@ export const anonymousClaimExchangeResponseSchema = z.object({
228
245
  teamId: z.string(),
229
246
  }),
230
247
  });
248
+ export const anonymousClaimRotateSchema = z.object({
249
+ spaceId: z.string().min(1),
250
+ });
251
+ export const anonymousClaimRotateResponseSchema = z.object({
252
+ spaceId: z.string(),
253
+ claimToken: z
254
+ .string()
255
+ .describe("Replacement claim token. Shown exactly once; store it before leaving this response."),
256
+ claimNonce: z
257
+ .string()
258
+ .describe("Replacement browser claim nonce embedded in claimUrl. Shown exactly once."),
259
+ claimUrl: z.string().url(),
260
+ expiresAt: z.string().datetime(),
261
+ });
231
262
  export const spaceClaimReminderSchema = z.object({
232
263
  email: z
233
264
  .string()
@@ -238,6 +269,30 @@ export const spaceClaimReminderSchema = z.object({
238
269
  export const spaceClaimReminderResponseSchema = z.object({
239
270
  accepted: z.literal(true),
240
271
  });
272
+ // Shared by spaceVersionCreateSchema and publishRequestSchema: both accept the
273
+ // same manifest-mutation fields and enforce the same "requires a declared
274
+ // files manifest / snapshot mode" rules on them.
275
+ const manifestMutationFieldsSchema = {
276
+ deletePaths: z
277
+ .array(z.string().min(1))
278
+ .default([])
279
+ .describe("Explicit paths to remove when publishMode is additive. Omitted paths are retained; only paths listed here are deleted."),
280
+ immutableAssetPrefixes: z
281
+ .array(z.string().min(2))
282
+ .optional()
283
+ .describe("Publisher-owned directory prefixes whose declared files are immutable generation assets. Snapshot publishes retain the current generation's matching files for exactly one subsequent generation."),
284
+ };
285
+ function refineManifestMutationRules(value, ctx) {
286
+ if (value.immutableAssetPrefixes !== undefined) {
287
+ if (value.publishMode !== "snapshot") {
288
+ ctx.addIssue({
289
+ code: z.ZodIssueCode.custom,
290
+ message: "immutableAssetPrefixes requires snapshot publish mode.",
291
+ path: ["immutableAssetPrefixes"],
292
+ });
293
+ }
294
+ }
295
+ }
241
296
  export const spaceVersionCreateSchema = z
242
297
  .object({
243
298
  source: PublishSourceSchema.optional().describe('Publish provenance recorded on the version; defaults to {kind: "direct_upload"}.'),
@@ -257,24 +312,16 @@ export const spaceVersionCreateSchema = z
257
312
  conventionFiles: conventionFilesSchema
258
313
  .optional()
259
314
  .describe("Routing convention contents used when deciding whether this publish is unchanged. The same values are supplied again when the version is finalized."),
315
+ finalize: z
316
+ .object({ channel: z.literal("live").nullable().optional() })
317
+ .optional()
318
+ .describe("Finalize intent for a declared upload. When every declared file lands, the version finalizes itself; the explicit finalize call remains available for recovery and replay."),
260
319
  files: z
261
320
  .array(manifestFileSchema)
262
- .optional()
263
- .describe("Full desired file manifest. For first deploys, send path/size/contentType without hashes so upload can begin immediately. For updates, include sha256 to let the server skip unchanged files. Omit entirely for an open session: the upload token then authorizes any policy-valid path within plan caps and finalize derives the manifest from what was uploaded."),
264
- deletePaths: z
265
- .array(z.string().min(1))
266
- .default([])
267
- .describe("Explicit paths to remove when publishMode is additive. Omitted paths are retained; only paths listed here are deleted."),
321
+ .describe("Full desired file manifest. For first deploys, send path/size/contentType without hashes so upload can begin immediately. For updates, include sha256 to let the server skip unchanged files."),
322
+ ...manifestMutationFieldsSchema,
268
323
  })
269
- .superRefine((value, ctx) => {
270
- if (value.files === undefined && value.deletePaths.length > 0) {
271
- ctx.addIssue({
272
- code: z.ZodIssueCode.custom,
273
- message: "deletePaths requires a declared files manifest.",
274
- path: ["deletePaths"],
275
- });
276
- }
277
- });
324
+ .superRefine(refineManifestMutationRules);
278
325
  export const spaceVersionListSchema = z.object({
279
326
  data: z.array(VersionSchema),
280
327
  pagination: CursorPaginationSchema,
@@ -442,7 +489,6 @@ export const spaceVersionComputedRoutingSummarySchema = z.object({
442
489
  headerRuleCount: z.number().int().nonnegative(),
443
490
  staticRedirectCount: z.number().int().nonnegative(),
444
491
  dynamicRedirectCount: z.number().int().nonnegative(),
445
- basicAuthRuleCount: z.number().int().nonnegative(),
446
492
  proxyRuleCount: z.number().int().nonnegative(),
447
493
  }),
448
494
  diagnostics: z.array(spaceVersionRoutingDiagnosticSchema),
@@ -467,16 +513,31 @@ export const spaceVersionFileDiffEntrySchema = z.object({
467
513
  format: z.literal("unified"),
468
514
  content: z.string(),
469
515
  truncated: z.boolean(),
516
+ truncationReason: z.literal("patch_byte_limit").nullable(),
470
517
  })
471
518
  .nullable(),
519
+ patchOmission: z
520
+ .enum(["input_too_large", "not_previewable", "content_unavailable", "patch_budget_exhausted"])
521
+ .nullable(),
472
522
  });
473
- export const spaceVersionFileDiffQuerySchema = z.object({
523
+ export const spaceVersionFileDiffQuerySchema = cursorListQuerySchema.extend({
474
524
  baseVersionId: z.string().optional(),
475
525
  });
476
526
  export const spaceVersionFileDiffResponseSchema = z.object({
477
527
  versionId: z.string(),
478
528
  baseVersionId: z.string().nullable(),
479
529
  files: z.array(spaceVersionFileDiffEntrySchema),
530
+ pagination: CursorPaginationSchema,
531
+ limits: z.object({
532
+ maxFiles: z.number().int().positive(),
533
+ maxInputBytes: z.number().int().positive(),
534
+ maxPatchBytes: z.number().int().positive(),
535
+ readConcurrency: z.number().int().positive(),
536
+ }),
537
+ usage: z.object({
538
+ inputBytes: z.number().int().nonnegative(),
539
+ patchBytes: z.number().int().nonnegative(),
540
+ }),
480
541
  });
481
542
  // Upload state is inferable (internal-docs/platform.md L2216): `upload` present means bytes are
482
543
  // still needed (then finalize); `versionId` null means the manifest matched and nothing changed.
@@ -502,13 +563,21 @@ export const publishRequestSchema = z
502
563
  principal: principalRefInputSchema.optional(),
503
564
  files: z
504
565
  .array(manifestFileSchema)
505
- .optional()
506
- .describe("Desired file manifest for a declared publish session. Clients upload returned paths, then finalize. Omit for inline one-shot and open-session publishes."),
507
- deletePaths: z
508
- .array(z.string().min(1))
509
- .default([])
510
- .describe("Explicit paths to remove when publishMode is additive. Omitted paths are retained; only paths listed here are deleted."),
566
+ .describe("Desired file manifest for a declared publish session. Clients upload returned paths, then finalize."),
567
+ ...manifestMutationFieldsSchema,
511
568
  source: PublishSourceSchema.optional().describe('Publish provenance recorded on the version; defaults to {kind: "direct_upload"}.'),
569
+ // Same fields, same bounds as spaceVersionCreateSchema: a publish that ran
570
+ // a build carries its transcript and provenance whichever door it enters
571
+ // by, so the first version of a space is not poorer than its second.
572
+ sourceMetadata: z
573
+ .record(z.string(), z.unknown())
574
+ .optional()
575
+ .describe("Additional control-plane-only provenance for build/deploy read models."),
576
+ buildLog: z
577
+ .string()
578
+ .max(64_000)
579
+ .optional()
580
+ .describe("Bounded build transcript for deploys that ran a local build before publishing."),
512
581
  publishMode: z
513
582
  .enum(["additive", "snapshot"])
514
583
  .default("additive")
@@ -531,9 +600,7 @@ export const publishRequestSchema = z
531
600
  dataLocation: z.string().min(1).optional(),
532
601
  })
533
602
  .optional(),
534
- config: spaceConfigSchema
535
- .optional()
536
- .describe("SpaceConfig overlay to store on the space (sf.jsonc contents)."),
603
+ config: spaceConfigSchema.optional().describe("SpaceConfig overlay to store on the space."),
537
604
  })
538
605
  .superRefine((value, ctx) => {
539
606
  if (value.teamId && value.principal?.type === "team" && value.teamId !== value.principal.id) {
@@ -543,13 +610,7 @@ export const publishRequestSchema = z
543
610
  path: ["principal", "id"],
544
611
  });
545
612
  }
546
- if (value.files === undefined && value.deletePaths.length > 0) {
547
- ctx.addIssue({
548
- code: z.ZodIssueCode.custom,
549
- message: "deletePaths requires a declared files manifest.",
550
- path: ["deletePaths"],
551
- });
552
- }
613
+ refineManifestMutationRules(value, ctx);
553
614
  });
554
615
  export const publishUploadReceiptSchema = z.object({
555
616
  ...uploadInstructionsSchema.shape,
@@ -569,21 +630,47 @@ export const publishReceiptVersionSchema = z.object({
569
630
  number: z.number().int().positive().nullable().optional(),
570
631
  manifestHash: z.string().nullable(),
571
632
  });
633
+ // Liveness is never a version status — it is the channel pointer, reported
634
+ // here. "Ready and live" (activated), "ready but outraced" (superseded), and
635
+ // "ready by design" (unpromoted) are three different receipts.
636
+ export const publishActivationSchema = z.object({
637
+ channel: z
638
+ .enum(["live"])
639
+ .nullable()
640
+ .describe("Channel this publish targeted. null = ready version without promotion."),
641
+ outcome: z
642
+ .enum(["activated", "unpromoted", "superseded", "pending"])
643
+ .describe("activated: the live pointer moved to this version. unpromoted: ready with channel null, by request. superseded: ready, but a newer publish holds the live pointer. pending: not settled yet."),
644
+ currentLiveVersionId: z
645
+ .string()
646
+ .nullable()
647
+ .describe("The version currently serving live traffic, or null when the space has none."),
648
+ });
649
+ // The receipt's normative next step: the deterministic projection of
650
+ // (version status, activation outcome, pending bytes, operation state). An
651
+ // agent drives the whole lifecycle by branching on `action` alone.
652
+ export const publishNextSchema = z.object({
653
+ action: z
654
+ .enum(["done", "upload", "finalize", "poll"])
655
+ .describe("done: stop, this request's intent is settled. upload: PUT the upload targets, then follow the finalize link. finalize: all bytes are present, POST url to commit. poll: server-side work in flight, GET url after retryAfter seconds."),
656
+ url: z.string().optional().describe("The endpoint the action applies to."),
657
+ retryAfter: z
658
+ .number()
659
+ .int()
660
+ .positive()
661
+ .optional()
662
+ .describe("Polling cadence in seconds; present only when action is poll."),
663
+ hint: z.string().max(140).describe("One plain sentence for an agent mid-loop."),
664
+ });
572
665
  export const publishReceiptSchema = z.object({
573
666
  space: publishReceiptSpaceSchema,
667
+ open: openHandoffSchema.optional(),
574
668
  version: publishReceiptVersionSchema,
669
+ activation: publishActivationSchema,
670
+ next: publishNextSchema,
575
671
  operation: AsyncOperationSchema.optional().describe("Background finalize operation when publish work continues asynchronously."),
576
- // Paste-ready one-liner (URL + claim nudge) so agents propagate consistent
577
- // claim copy into transcripts (internal-docs/platform.md M1a "share blurb").
578
- shareBlurb: z.string(),
579
672
  upload: publishUploadReceiptSchema.optional(),
580
- claim: z
581
- .object({
582
- token: z.string().optional(),
583
- url: z.string(),
584
- expiresAt: z.string().datetime(),
585
- })
586
- .optional(),
673
+ claim: spaceClaimReceiptSchema.optional(),
587
674
  diagnostics: z
588
675
  .array(baseDiagnosticSchema)
589
676
  .optional()
@@ -665,23 +752,17 @@ export const spaceRuntimeStatusSchema = z.object({
665
752
  .describe("Live space URL. Flips to the latest version after a successful publish to `live`."),
666
753
  runtimeState: spaceStatus.describe("Space operation-lifecycle status."),
667
754
  liveVersionStatus: versionStatus.nullable(),
668
- liveRuntimeKind: zeroRuntimeKindSchema
755
+ liveRuntimeKind: runtimeKindSchema
669
756
  .nullable()
670
757
  .describe("Runtime kind declared by the live version, if any."),
671
758
  pendingVersionStatus: versionStatus.nullable(),
672
759
  operation: AsyncOperationSchema.nullable(),
673
- });
674
- // Channel listing entry: the channel name plus its spec ChannelPointer.
675
- export const spaceChannelSchema = z.object({
676
- name: z.string().describe('Channel name; "live" is the default channel.'),
677
- pointer: ChannelPointerSchema,
678
- });
679
- export const spaceChannelListResponseSchema = z.object({
680
- data: z.array(spaceChannelSchema),
681
- pagination: CursorPaginationSchema,
760
+ app: runtimeAppSchema
761
+ .nullable()
762
+ .describe("What the live version runs: its Zero capsule or Functions worker, discriminated by `runtimeKind`. Null for a static space, and null for callers whose credential does not carry `versions:read` — describing an app is a read of the version's contents, not of the space's serving state."),
682
763
  });
683
764
  export const spaceApplyChangeBaseSchema = z.object({
684
- kind: z.enum(["variable", "routing", "password", "settings"]),
765
+ kind: z.enum(["variable", "routing", "access", "settings"]),
685
766
  name: z.string(),
686
767
  label: z.string(),
687
768
  });
@@ -690,7 +771,6 @@ export const spaceApplyChangeSchema = spaceApplyChangeBaseSchema.extend({
690
771
  id: z.string(),
691
772
  sourceSurface: z.string(),
692
773
  applyMode: spaceApplyModeSchema,
693
- changesetId: z.string().optional(),
694
774
  before: z.record(z.string(), z.unknown()).nullable().optional(),
695
775
  after: z.record(z.string(), z.unknown()).nullable().optional(),
696
776
  metadata: z.record(z.string(), z.unknown()).optional(),
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- export declare const superadminEmailStatusValues: readonly ["all", "scheduled", "sent", "delivered", "bounced", "dropped", "complained", "opened", "clicked", "failed"];
2
+ export declare const superadminEmailStatusValues: readonly ["all", "scheduled", "sent", "suppressed", "delivered", "bounced", "dropped", "complained", "opened", "clicked", "failed"];
3
3
  export declare const superadminEmailCategoryValues: readonly ["transactional", "announcements", "offers", "system", "invites"];
4
4
  export declare const superadminEmailListQuerySchema: z.ZodObject<{
5
5
  limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
@@ -7,11 +7,12 @@ export declare const superadminEmailListQuerySchema: z.ZodObject<{
7
7
  status: z.ZodDefault<z.ZodEnum<{
8
8
  all: "all";
9
9
  failed: "failed";
10
- delivered: "delivered";
11
- dropped: "dropped";
12
10
  scheduled: "scheduled";
11
+ delivered: "delivered";
13
12
  sent: "sent";
13
+ suppressed: "suppressed";
14
14
  bounced: "bounced";
15
+ dropped: "dropped";
15
16
  complained: "complained";
16
17
  opened: "opened";
17
18
  clicked: "clicked";
@@ -49,6 +50,12 @@ export declare const superadminEmailSendSchema: z.ZodObject<{
49
50
  offers: "offers";
50
51
  invites: "invites";
51
52
  }>>;
53
+ preferenceTopic: z.ZodEnum<{
54
+ system: "system";
55
+ announcements: "announcements";
56
+ offers: "offers";
57
+ invites: "invites";
58
+ }>;
52
59
  type: z.ZodDefault<z.ZodString>;
53
60
  props: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
54
61
  sendAt: z.ZodOptional<z.ZodString>;
@@ -92,6 +99,13 @@ export declare const SuperadminEmailSchema: z.ZodObject<{
92
99
  type: z.ZodString;
93
100
  template: z.ZodString;
94
101
  category: z.ZodString;
102
+ preferenceTopic: z.ZodNullable<z.ZodEnum<{
103
+ system: "system";
104
+ announcements: "announcements";
105
+ offers: "offers";
106
+ invites: "invites";
107
+ }>>;
108
+ essentialAuth: z.ZodBoolean;
95
109
  props: z.ZodRecord<z.ZodString, z.ZodUnknown>;
96
110
  options: z.ZodRecord<z.ZodString, z.ZodUnknown>;
97
111
  metadata: z.ZodNullable<z.ZodObject<{
@@ -125,6 +139,7 @@ export declare const SuperadminEmailSchema: z.ZodObject<{
125
139
  fakeOpenedAt: z.ZodNullable<z.ZodString>;
126
140
  combinedOpenedAt: z.ZodNullable<z.ZodString>;
127
141
  unsubscribedAt: z.ZodNullable<z.ZodString>;
142
+ suppressedAt: z.ZodNullable<z.ZodString>;
128
143
  failedAt: z.ZodNullable<z.ZodString>;
129
144
  createdAt: z.ZodString;
130
145
  updatedAt: z.ZodString;
@@ -148,6 +163,13 @@ export declare const SuperadminEmailListSchema: z.ZodObject<{
148
163
  type: z.ZodString;
149
164
  template: z.ZodString;
150
165
  category: z.ZodString;
166
+ preferenceTopic: z.ZodNullable<z.ZodEnum<{
167
+ system: "system";
168
+ announcements: "announcements";
169
+ offers: "offers";
170
+ invites: "invites";
171
+ }>>;
172
+ essentialAuth: z.ZodBoolean;
151
173
  props: z.ZodRecord<z.ZodString, z.ZodUnknown>;
152
174
  options: z.ZodRecord<z.ZodString, z.ZodUnknown>;
153
175
  metadata: z.ZodNullable<z.ZodObject<{
@@ -181,6 +203,7 @@ export declare const SuperadminEmailListSchema: z.ZodObject<{
181
203
  fakeOpenedAt: z.ZodNullable<z.ZodString>;
182
204
  combinedOpenedAt: z.ZodNullable<z.ZodString>;
183
205
  unsubscribedAt: z.ZodNullable<z.ZodString>;
206
+ suppressedAt: z.ZodNullable<z.ZodString>;
184
207
  failedAt: z.ZodNullable<z.ZodString>;
185
208
  createdAt: z.ZodString;
186
209
  updatedAt: z.ZodString;
@@ -203,6 +226,7 @@ export declare const SuperadminEmailSendResultSchema: z.ZodObject<{
203
226
  error: "error";
204
227
  scheduled: "scheduled";
205
228
  sent: "sent";
229
+ suppressed: "suppressed";
206
230
  }>;
207
231
  error: z.ZodOptional<z.ZodString>;
208
232
  }, z.core.$strip>>;
@@ -1,10 +1,12 @@
1
1
  import { z } from "zod";
2
2
  import { makeOffsetListSchema } from "./common.js";
3
+ import { emailCategoryValues, emailPreferenceTopicValues } from "./email-preferences.js";
3
4
  import { superadminPaginationSchema } from "./superadmin.js";
4
5
  export const superadminEmailStatusValues = [
5
6
  "all",
6
7
  "scheduled",
7
8
  "sent",
9
+ "suppressed",
8
10
  "delivered",
9
11
  "bounced",
10
12
  "dropped",
@@ -13,20 +15,9 @@ export const superadminEmailStatusValues = [
13
15
  "clicked",
14
16
  "failed",
15
17
  ];
16
- // "invites" is the invite/request sending stream (access-plan X-25): mail
17
- // carrying sender-authored content to arbitrary non-user addresses is
18
- // attacker-adjacent, so it is categorized apart from transactional mail —
19
- // burned reputation on the invite stream must never take down password
20
- // resets. Stream-level isolation at the provider (a separate SES
21
- // configuration set / sending identity) is an infra follow-up; the category
22
- // is the seam it keys off.
23
- export const superadminEmailCategoryValues = [
24
- "transactional",
25
- "announcements",
26
- "offers",
27
- "system",
28
- "invites",
29
- ];
18
+ // Delivery category is provider-facing telemetry/routing. Recipient control is
19
+ // modeled independently by preferenceTopic; essential auth has no topic.
20
+ export const superadminEmailCategoryValues = emailCategoryValues;
30
21
  export const superadminEmailListQuerySchema = z.object({
31
22
  limit: z.coerce.number().int().min(1).max(100).default(25),
32
23
  offset: z.coerce.number().int().min(0).default(0),
@@ -44,6 +35,7 @@ export const superadminEmailSendSchema = z.object({
44
35
  html: z.string().optional(),
45
36
  template: z.string().trim().min(1).default("generic-message"),
46
37
  category: z.enum(superadminEmailCategoryValues).default("transactional"),
38
+ preferenceTopic: z.enum(emailPreferenceTopicValues),
47
39
  type: z.string().trim().min(1).default("generic-message"),
48
40
  props: z.record(z.string(), z.unknown()).default({}),
49
41
  sendAt: z.string().datetime().optional(),
@@ -90,6 +82,8 @@ export const SuperadminEmailSchema = z.object({
90
82
  type: z.string(),
91
83
  template: z.string(),
92
84
  category: z.string(),
85
+ preferenceTopic: z.enum(emailPreferenceTopicValues).nullable(),
86
+ essentialAuth: z.boolean(),
93
87
  props: z.record(z.string(), z.unknown()),
94
88
  options: z.record(z.string(), z.unknown()),
95
89
  metadata: SuperadminEmailMetadataSchema.nullable(),
@@ -104,6 +98,7 @@ export const SuperadminEmailSchema = z.object({
104
98
  fakeOpenedAt: z.string().datetime().nullable(),
105
99
  combinedOpenedAt: z.string().datetime().nullable(),
106
100
  unsubscribedAt: z.string().datetime().nullable(),
101
+ suppressedAt: z.string().datetime().nullable(),
107
102
  failedAt: z.string().datetime().nullable(),
108
103
  createdAt: z.string().datetime(),
109
104
  updatedAt: z.string().datetime(),
@@ -114,7 +109,7 @@ export const SuperadminEmailSendResultSchema = z.object({
114
109
  id: z.string(),
115
110
  userId: z.string().nullable().optional(),
116
111
  email: z.string().optional(),
117
- status: z.enum(["sent", "scheduled", "error"]),
112
+ status: z.enum(["sent", "scheduled", "suppressed", "error"]),
118
113
  error: z.string().optional(),
119
114
  })),
120
115
  });
@@ -8,8 +8,8 @@ export declare const superadminEdgePurgeSchema: z.ZodObject<{
8
8
  uris: z.ZodNullable<z.ZodArray<z.ZodString>>;
9
9
  status: z.ZodEnum<{
10
10
  pending: "pending";
11
- purged: "purged";
12
11
  superseded: "superseded";
12
+ purged: "purged";
13
13
  }>;
14
14
  executedAt: z.ZodNullable<z.ZodString>;
15
15
  createdAt: z.ZodString;
@@ -17,8 +17,8 @@ export declare const superadminEdgePurgeSchema: z.ZodObject<{
17
17
  export declare const superadminEdgePurgeListQuerySchema: z.ZodObject<{
18
18
  status: z.ZodOptional<z.ZodEnum<{
19
19
  pending: "pending";
20
- purged: "purged";
21
20
  superseded: "superseded";
21
+ purged: "purged";
22
22
  }>>;
23
23
  providerSiteId: z.ZodOptional<z.ZodString>;
24
24
  hostname: z.ZodOptional<z.ZodString>;