@spacefast/common 0.0.24 → 0.2.1

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 (320) hide show
  1. package/brand-assets/LICENSE-Haskoy.txt +93 -0
  2. package/brand-assets/haskoy-latin-variable.woff2 +0 -0
  3. package/brand-assets/spacefast-favicon.svg +4 -4
  4. package/brand-assets/spacefast-sf-full-bleed.svg +3 -3
  5. package/brand-assets/spacefast-wordmark.svg +2 -4
  6. package/dist/agents/connect-targets.d.ts +6 -146
  7. package/dist/agents/connect-targets.js +63 -295
  8. package/dist/agents/private-key-oauth.d.ts +31 -2
  9. package/dist/agents/private-key-oauth.js +166 -92
  10. package/dist/agents/registry/core.d.ts +292 -0
  11. package/dist/agents/registry/core.js +1388 -0
  12. package/dist/agents/registry/deeplink-probes.d.ts +23 -0
  13. package/dist/agents/registry/deeplink-probes.js +18 -0
  14. package/dist/agents/registry/node.d.ts +56 -0
  15. package/dist/agents/registry/node.js +339 -0
  16. package/dist/brand-assets-build.js +3 -6
  17. package/dist/brand-assets.d.ts +5 -15
  18. package/dist/brand-assets.js +12 -14
  19. package/dist/brand.d.ts +17 -0
  20. package/dist/brand.js +24 -4
  21. package/dist/config/domains.d.ts +79 -12
  22. package/dist/config/domains.js +128 -29
  23. package/dist/config/index.js +1 -2
  24. package/dist/contracts/abuse.js +9 -24
  25. package/dist/contracts/access-profiles.d.ts +86 -0
  26. package/dist/contracts/access-profiles.js +89 -0
  27. package/dist/contracts/access.d.ts +24 -30
  28. package/dist/contracts/access.js +33 -64
  29. package/dist/contracts/activity.d.ts +18 -1
  30. package/dist/contracts/activity.js +72 -26
  31. package/dist/contracts/analytics.js +8 -10
  32. package/dist/contracts/api-keys.d.ts +77 -52
  33. package/dist/contracts/api-keys.js +44 -24
  34. package/dist/contracts/application-journal.d.ts +216 -0
  35. package/dist/contracts/application-journal.js +167 -0
  36. package/dist/contracts/auth.d.ts +90 -17
  37. package/dist/contracts/auth.js +86 -17
  38. package/dist/contracts/beta.d.ts +9 -4
  39. package/dist/contracts/beta.js +20 -16
  40. package/dist/contracts/billing.d.ts +2 -1
  41. package/dist/contracts/billing.js +37 -11
  42. package/dist/contracts/bootstrap.d.ts +791 -0
  43. package/dist/contracts/bootstrap.js +51 -0
  44. package/dist/contracts/builds.d.ts +209 -18
  45. package/dist/contracts/builds.js +93 -27
  46. package/dist/contracts/channels.d.ts +43 -0
  47. package/dist/contracts/channels.js +25 -9
  48. package/dist/contracts/cli.d.ts +7 -0
  49. package/dist/contracts/cli.js +6 -0
  50. package/dist/contracts/collab-public.d.ts +1 -1
  51. package/dist/contracts/collab-public.js +5 -8
  52. package/dist/contracts/comments.d.ts +44 -34
  53. package/dist/contracts/comments.js +107 -77
  54. package/dist/contracts/commerce.d.ts +165 -0
  55. package/dist/contracts/commerce.js +146 -0
  56. package/dist/contracts/common.d.ts +3 -3
  57. package/dist/contracts/common.js +20 -31
  58. package/dist/contracts/content-contract-verification.d.ts +521 -0
  59. package/dist/contracts/content-contract-verification.js +320 -0
  60. package/dist/contracts/content-platform-fixture.d.ts +1278 -0
  61. package/dist/contracts/content-platform-fixture.js +44 -0
  62. package/dist/contracts/content-program.d.ts +994 -0
  63. package/dist/contracts/content-program.js +658 -0
  64. package/dist/contracts/content-sync.d.ts +290 -0
  65. package/dist/contracts/content-sync.js +167 -0
  66. package/dist/contracts/content.d.ts +432 -0
  67. package/dist/contracts/content.js +303 -0
  68. package/dist/contracts/continuation.d.ts +17 -1
  69. package/dist/contracts/continuation.js +23 -23
  70. package/dist/contracts/countries.js +3 -4
  71. package/dist/contracts/crons.d.ts +52 -0
  72. package/dist/contracts/crons.js +60 -0
  73. package/dist/contracts/dashboard-prefs.d.ts +56 -0
  74. package/dist/contracts/dashboard-prefs.js +51 -0
  75. package/dist/contracts/device-auth.d.ts +234 -37
  76. package/dist/contracts/device-auth.js +267 -53
  77. package/dist/contracts/docs.d.ts +1 -5
  78. package/dist/contracts/docs.js +7 -15
  79. package/dist/contracts/domains.d.ts +501 -93
  80. package/dist/contracts/domains.js +193 -55
  81. package/dist/contracts/email-preferences.d.ts +3 -3
  82. package/dist/contracts/email-preferences.js +6 -7
  83. package/dist/contracts/enums.d.ts +27 -26
  84. package/dist/contracts/enums.js +68 -61
  85. package/dist/contracts/error-code-meta.d.ts +283 -7
  86. package/dist/contracts/error-code-meta.js +97 -5
  87. package/dist/contracts/error-codes.d.ts +5 -5
  88. package/dist/contracts/error-codes.js +82 -17
  89. package/dist/contracts/events.d.ts +100 -20
  90. package/dist/contracts/events.js +107 -20
  91. package/dist/contracts/execution.d.ts +48 -64
  92. package/dist/contracts/execution.js +52 -62
  93. package/dist/contracts/feature-lifecycle.d.ts +73 -27
  94. package/dist/contracts/feature-lifecycle.js +86 -26
  95. package/dist/contracts/features.d.ts +68 -19
  96. package/dist/contracts/features.js +42 -41
  97. package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
  98. package/dist/contracts/frame-session.d.ts +192 -0
  99. package/dist/contracts/frame-session.js +164 -0
  100. package/dist/contracts/functions.d.ts +338 -164
  101. package/dist/contracts/functions.js +367 -198
  102. package/dist/contracts/git.d.ts +27 -33
  103. package/dist/contracts/git.js +10 -11
  104. package/dist/contracts/grant-copy.d.ts +43 -0
  105. package/dist/contracts/grant-copy.js +44 -0
  106. package/dist/contracts/grants.d.ts +62 -54
  107. package/dist/contracts/grants.js +124 -23
  108. package/dist/contracts/ids.d.ts +4 -1
  109. package/dist/contracts/ids.js +6 -3
  110. package/dist/contracts/internal.d.ts +8 -18
  111. package/dist/contracts/internal.js +13 -14
  112. package/dist/contracts/mcp.d.ts +28 -0
  113. package/dist/contracts/mcp.js +28 -0
  114. package/dist/contracts/me.d.ts +6 -1
  115. package/dist/contracts/me.js +12 -6
  116. package/dist/contracts/notifications.d.ts +27 -29
  117. package/dist/contracts/notifications.js +9 -4
  118. package/dist/contracts/oauth-resources.d.ts +112 -10
  119. package/dist/contracts/oauth-resources.js +116 -11
  120. package/dist/contracts/oauth-scope-actions.d.ts +90 -0
  121. package/dist/contracts/oauth-scope-actions.js +126 -0
  122. package/dist/contracts/operations.d.ts +27 -4
  123. package/dist/contracts/operations.js +12 -6
  124. package/dist/contracts/pages.d.ts +31 -7
  125. package/dist/contracts/pages.js +22 -5
  126. package/dist/contracts/partner-notifications.d.ts +3 -0
  127. package/dist/contracts/partner-notifications.js +65 -0
  128. package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
  129. package/dist/contracts/{platform.js → partner.js} +27 -40
  130. package/dist/contracts/plan-policy.js +1 -1
  131. package/dist/contracts/principal-assertion.d.ts +43 -0
  132. package/dist/contracts/principal-assertion.js +67 -0
  133. package/dist/contracts/principals.d.ts +73 -0
  134. package/dist/contracts/principals.js +59 -0
  135. package/dist/contracts/privacy.d.ts +11 -0
  136. package/dist/contracts/privacy.js +17 -0
  137. package/dist/contracts/problem-document.js +3 -4
  138. package/dist/contracts/publish-archive.d.ts +269 -161
  139. package/dist/contracts/publish-archive.js +11 -1
  140. package/dist/contracts/push-new.d.ts +8 -8
  141. package/dist/contracts/quotas.js +5 -5
  142. package/dist/contracts/realtime.d.ts +52 -0
  143. package/dist/contracts/realtime.js +54 -0
  144. package/dist/contracts/repository-connections.d.ts +44 -31
  145. package/dist/contracts/repository-connections.js +17 -5
  146. package/dist/contracts/resources.d.ts +105 -14
  147. package/dist/contracts/resources.js +150 -26
  148. package/dist/contracts/route-inventory.d.ts +358 -0
  149. package/dist/contracts/route-inventory.js +141 -0
  150. package/dist/contracts/runtime-api.d.ts +206 -82
  151. package/dist/contracts/runtime-api.js +131 -70
  152. package/dist/contracts/runtime-app.d.ts +13 -23
  153. package/dist/contracts/runtime-app.js +39 -24
  154. package/dist/contracts/runtime-components.d.ts +143 -0
  155. package/dist/contracts/runtime-components.js +199 -0
  156. package/dist/contracts/runtime-db.d.ts +49 -23
  157. package/dist/contracts/runtime-db.js +87 -22
  158. package/dist/contracts/runtime-purge.d.ts +8 -0
  159. package/dist/contracts/runtime-purge.js +5 -0
  160. package/dist/contracts/runtime-services.d.ts +43 -75
  161. package/dist/contracts/runtime-services.js +29 -49
  162. package/dist/contracts/runtime-storage.d.ts +15 -14
  163. package/dist/contracts/runtime-storage.js +30 -14
  164. package/dist/contracts/sf-config-v1.d.ts +48 -14
  165. package/dist/contracts/slugs.js +13 -4
  166. package/dist/contracts/space-config.d.ts +283 -19
  167. package/dist/contracts/space-config.js +430 -80
  168. package/dist/contracts/spaces.d.ts +376 -290
  169. package/dist/contracts/spaces.js +200 -135
  170. package/dist/contracts/superadmin-activity.d.ts +3 -43
  171. package/dist/contracts/superadmin-activity.js +6 -30
  172. package/dist/contracts/superadmin-emails.d.ts +1 -0
  173. package/dist/contracts/superadmin-emails.js +17 -1
  174. package/dist/contracts/superadmin-runtime.d.ts +199 -0
  175. package/dist/contracts/superadmin-runtime.js +141 -0
  176. package/dist/contracts/superadmin-search.d.ts +22 -2
  177. package/dist/contracts/superadmin-search.js +14 -6
  178. package/dist/contracts/superadmin-spaces.d.ts +438 -189
  179. package/dist/contracts/superadmin-spaces.js +131 -25
  180. package/dist/contracts/superadmin-teams.d.ts +5 -2
  181. package/dist/contracts/superadmin-teams.js +1 -2
  182. package/dist/contracts/superadmin-tenants.d.ts +627 -12
  183. package/dist/contracts/superadmin-tenants.js +32 -13
  184. package/dist/contracts/superadmin.d.ts +232 -37
  185. package/dist/contracts/superadmin.js +106 -22
  186. package/dist/contracts/tags.d.ts +85 -58
  187. package/dist/contracts/tags.js +47 -37
  188. package/dist/contracts/teams.d.ts +86 -26
  189. package/dist/contracts/teams.js +90 -31
  190. package/dist/contracts/tenants.d.ts +135 -0
  191. package/dist/contracts/tenants.js +120 -0
  192. package/dist/contracts/test-triggers.d.ts +70 -0
  193. package/dist/contracts/test-triggers.js +116 -0
  194. package/dist/contracts/theme-json.js +3 -8
  195. package/dist/contracts/transfers.d.ts +1 -0
  196. package/dist/contracts/transfers.js +3 -2
  197. package/dist/contracts/usage.d.ts +209 -0
  198. package/dist/contracts/usage.js +124 -12
  199. package/dist/contracts/variables.d.ts +2 -2
  200. package/dist/contracts/variables.js +9 -13
  201. package/dist/contracts/webhooks.d.ts +13 -5
  202. package/dist/contracts/webhooks.js +3 -1
  203. package/dist/contracts/zero.d.ts +72 -81
  204. package/dist/contracts/zero.js +80 -78
  205. package/dist/dashboard-paths/index.d.ts +24 -21
  206. package/dist/dashboard-paths/index.js +35 -47
  207. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
  208. package/dist/dashboard-paths/route-reservations.generated.js +36 -0
  209. package/dist/docs/agent-arrival.d.ts +92 -0
  210. package/dist/docs/agent-arrival.js +227 -0
  211. package/dist/docs/agent-output-policy.d.ts +6 -0
  212. package/dist/docs/agent-output-policy.js +22 -0
  213. package/dist/docs/agent-prose.d.ts +12 -18
  214. package/dist/docs/agent-prose.js +73 -51
  215. package/dist/docs/agent-setup.d.ts +72 -41
  216. package/dist/docs/agent-setup.js +339 -436
  217. package/dist/docs/catalog.d.ts +153 -95
  218. package/dist/docs/catalog.js +163 -48
  219. package/dist/docs/error-docs.d.ts +2098 -1
  220. package/dist/docs/error-docs.js +421 -144
  221. package/dist/docs/index-build.d.ts +0 -1
  222. package/dist/docs/index-build.js +2 -3
  223. package/dist/docs/page-context-prompt.d.ts +77 -0
  224. package/dist/docs/page-context-prompt.js +131 -0
  225. package/dist/docs/reference-urls.d.ts +46 -0
  226. package/dist/docs/reference-urls.js +79 -0
  227. package/dist/docs/search.d.ts +6 -8
  228. package/dist/docs/search.js +10 -13
  229. package/dist/docs/skill-distribution.d.ts +4 -1
  230. package/dist/docs/skill-distribution.js +10 -5
  231. package/dist/docs/skills.d.ts +120 -120
  232. package/dist/docs/skills.js +121 -73
  233. package/dist/docs/start-prompts.d.ts +45 -0
  234. package/dist/docs/start-prompts.js +62 -0
  235. package/dist/domain-exploration.js +9 -13
  236. package/dist/og-template.d.ts +56 -0
  237. package/dist/og-template.js +56 -0
  238. package/dist/slug-policy/index.js +5 -11
  239. package/dist/test-helpers/fetch-stub.js +1 -0
  240. package/dist/utils/browser-credential.d.ts +13 -6
  241. package/dist/utils/browser-credential.js +14 -7
  242. package/dist/utils/build-settings.d.ts +21 -1
  243. package/dist/utils/build-settings.js +133 -15
  244. package/dist/utils/canonical-json.d.ts +3 -5
  245. package/dist/utils/canonical-json.js +4 -5
  246. package/dist/utils/cast-transport.d.ts +5 -17
  247. package/dist/utils/cast-transport.js +6 -19
  248. package/dist/utils/claim-token.js +1 -2
  249. package/dist/utils/comment-avatars.js +4 -6
  250. package/dist/utils/concurrency.js +3 -3
  251. package/dist/utils/content-type.d.ts +7 -6
  252. package/dist/utils/content-type.js +73 -51
  253. package/dist/utils/credential-policy.d.ts +50 -6
  254. package/dist/utils/credential-policy.js +126 -59
  255. package/dist/utils/dns-instructions.js +9 -9
  256. package/dist/utils/egress-policy.fixtures.json +1 -1
  257. package/dist/utils/error-code.js +1 -0
  258. package/dist/utils/generate-space-name.d.ts +3 -8
  259. package/dist/utils/generate-space-name.js +3 -8
  260. package/dist/utils/grant-decision.fixtures.json +2 -2
  261. package/dist/utils/grants.d.ts +0 -1
  262. package/dist/utils/grants.js +7 -8
  263. package/dist/utils/gravatar.d.ts +2 -4
  264. package/dist/utils/gravatar.js +6 -12
  265. package/dist/utils/id-hints.js +14 -23
  266. package/dist/utils/idempotency.d.ts +3 -3
  267. package/dist/utils/idempotency.js +6 -7
  268. package/dist/utils/local-space-state.d.ts +23 -26
  269. package/dist/utils/local-space-state.js +46 -46
  270. package/dist/utils/oauth-signed-query.d.ts +3 -5
  271. package/dist/utils/oauth-signed-query.js +6 -9
  272. package/dist/utils/one-shot-replay.d.ts +7 -6
  273. package/dist/utils/one-shot-replay.js +3 -5
  274. package/dist/utils/page-colors.d.ts +15 -19
  275. package/dist/utils/page-colors.js +23 -45
  276. package/dist/utils/page-fonts.d.ts +1 -1
  277. package/dist/utils/page-fonts.js +8 -20
  278. package/dist/utils/page-preview.d.ts +0 -1
  279. package/dist/utils/page-preview.js +0 -1
  280. package/dist/utils/pages.d.ts +33 -3
  281. package/dist/utils/pages.js +83 -30
  282. package/dist/utils/privacy-regions.d.ts +19 -0
  283. package/dist/utils/privacy-regions.js +91 -0
  284. package/dist/utils/publish-form-data.d.ts +4 -5
  285. package/dist/utils/publish-form-data.js +2 -3
  286. package/dist/utils/publish-policy.d.ts +11 -17
  287. package/dist/utils/publish-policy.fixtures.json +11 -5
  288. package/dist/utils/publish-policy.js +65 -110
  289. package/dist/utils/query-client.d.ts +2 -0
  290. package/dist/utils/query-client.js +10 -1
  291. package/dist/utils/runtime-paths.d.ts +4 -4
  292. package/dist/utils/runtime-paths.js +6 -8
  293. package/dist/utils/runtime-upload.d.ts +9 -0
  294. package/dist/utils/runtime-upload.js +12 -0
  295. package/dist/utils/secure-local-file.d.ts +3 -3
  296. package/dist/utils/secure-local-file.js +23 -40
  297. package/dist/utils/space-config.d.ts +12 -15
  298. package/dist/utils/space-config.js +13 -16
  299. package/dist/utils/static-runtime-policy.d.ts +10 -7
  300. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  301. package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
  302. package/dist/utils/static-runtime-policy.generated.js +70 -0
  303. package/dist/utils/static-runtime-policy.js +31 -132
  304. package/dist/utils/storage-policy.js +1 -2
  305. package/dist/utils/upload-session.d.ts +4 -1
  306. package/dist/utils/upload-session.js +41 -19
  307. package/dist/utils/version-path.js +11 -19
  308. package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
  309. package/dist/utils/wpcom-auth-redirects.js +1 -4
  310. package/dist/vocabulary.d.ts +13 -13
  311. package/dist/vocabulary.js +52 -27
  312. package/package.json +15 -18
  313. package/dist/agents/client-registry.d.ts +0 -22
  314. package/dist/agents/client-registry.js +0 -41
  315. package/dist/docs/agent-handoff-document.d.ts +0 -15
  316. package/dist/docs/agent-handoff-document.js +0 -180
  317. package/dist/docs/agent-solutions.d.ts +0 -110
  318. package/dist/docs/agent-solutions.js +0 -183
  319. package/dist/utils/query-keys.d.ts +0 -84
  320. package/dist/utils/query-keys.js +0 -108
@@ -1,9 +1,11 @@
1
1
  import { z } from "zod";
2
+ import { CONTENT_SNIFF_KINDS } from "../utils/content-type.js";
2
3
  import { accessFenceKindSchema } from "./access.js";
3
4
  import { functionsRuntimeConfigSchema } from "./functions.js";
4
5
  import { grantSchema } from "./grants.js";
5
6
  import { manifestFileSchema } from "./internal.js";
6
7
  import { runtimePagesSchema } from "./pages.js";
8
+ import { runtimePurgeStatusSchema } from "./runtime-purge.js";
7
9
  import { SPACE_CONFIG_CAPS } from "./space-config.js";
8
10
  import { zeroEndpointSchema, zeroRuntimeConfigSchema } from "./zero.js";
9
11
  const hostCanonicalRedirectSchema = z.object({
@@ -37,24 +39,20 @@ const previousVersionIdSchema = z
37
39
  .string()
38
40
  .min(1)
39
41
  .optional()
40
- .describe("The pointer target this activation replaces (diff baseline).");
42
+ .describe("The previous live version used as the catalog diff baseline.");
41
43
  export const runtimePurgeReceiptSchema = z.object({
42
- status: z.enum(["ok", "failed", "pending"]),
44
+ status: runtimePurgeStatusSchema,
43
45
  mode: z.enum(["urls", "domain"]),
44
46
  urls: z.number().int().nonnegative().optional(),
45
47
  });
46
- const runtimeMutationPurgeShape = {
48
+ const runtimeMutationPurgeFields = {
47
49
  purge: runtimePurgeReceiptSchema.optional(),
48
50
  };
49
- export const runtimeSpacePurgeRequestSchema = z.object({
50
- urls: z.array(z.string().startsWith("/")).optional(),
51
- });
52
51
  export const runtimeSpacePurgeResponseSchema = z.object({
53
52
  space_id: z.string().min(1),
54
53
  purge: runtimePurgeReceiptSchema,
55
54
  });
56
- // One bounded page of a version's file catalog the runtime's own answer to
57
- // "which files does this version have". `view=source` is the uploaded,
55
+ // One bounded page of a version's file catalog. `view=source` is the uploaded,
58
56
  // pre-substitution object; `view=served` is the immutable byte a visitor
59
57
  // receives, and `variant_route` marks a channel's substituted bytes within it.
60
58
  export const runtimeVersionFilesResponseSchema = z.object({
@@ -71,20 +69,37 @@ export const runtimeVersionFilesResponseSchema = z.object({
71
69
  })),
72
70
  next_cursor: z.string().min(1).nullable().optional(),
73
71
  });
72
+ export const runtimeRetentionModeSchema = z.enum(["all", "list", "none"]);
74
73
  export const runtimeVersionCreateRequestSchema = z.object({
75
74
  version_id: z.string().min(1).optional(),
76
75
  files: z.array(manifestFileSchema),
77
- // Retention is expressed as "everything from `reusable_version_id`": naming
78
- // the base and NO list is the retain-all signal, which the runtime
79
- // materializes from that version's own catalog at finalize (under the space
80
- // lock). An explicit list is the narrower form it retains exactly these
81
- // paths — and is what a publish that prunes the base uses.
76
+ // Retention is stated, never inferred. `all` carries every path of
77
+ // `reusable_version_id` forward, materialized from the base catalog at
78
+ // finalize under the space lock, which keeps the lazy publish path free of a
79
+ // pre-upload round trip. `list` retains exactly `retained_files`, and an EMPTY
80
+ // list is meaningful: it drops every path the base held. `none` retains
81
+ // nothing.
82
+ //
83
+ // `all` and `list` both require `reusable_version_id`; only `list` may carry
84
+ // `retained_files`. The runtime has no delete list, so deletion IS omission
85
+ // from the retained set.
86
+ retention: runtimeRetentionModeSchema,
82
87
  retained_files: z.array(manifestFileSchema).optional(),
83
88
  reusable_version_id: z.string().min(1).optional(),
84
89
  manifest_hash: z.string().optional(),
85
90
  expires_at: z.string().optional(),
86
91
  metadata: z.record(z.string(), z.unknown()).default({}),
87
92
  });
93
+ export const runtimeStaticZipIngestResponseSchema = z.object({
94
+ space_id: z.string().min(1),
95
+ files: z.array(z.object({
96
+ path: z.string().min(1),
97
+ size: z.number().int().nonnegative(),
98
+ sha256: z.string().regex(/^[a-f0-9]{64}$/),
99
+ sniff: z.enum(CONTENT_SNIFF_KINDS),
100
+ })),
101
+ pin_expires_at: z.string().datetime({ offset: true }),
102
+ });
88
103
  export const runtimeVersionCreateResponseSchema = z.object({
89
104
  space_id: z.string(),
90
105
  version_id: z.string(),
@@ -98,14 +113,26 @@ export const runtimeUploadSessionDescriptorSchema = z.object({
98
113
  expires_at: z.string(),
99
114
  manifest_hash: z.string().optional(),
100
115
  files: z.array(manifestFileSchema),
101
- // Retained files only travel in the authenticated finalize request: they are
102
- // unbounded and unused while accepting a PUT. Omitting them beside a
103
- // `reusable_version_id` is the retain-all signal (see the create request),
104
- // which is also what keeps a lazy session's descriptor inside its JWT budget.
116
+ // Retained files travel only in the authenticated finalize request: they are
117
+ // unbounded and unused while accepting a PUT, which keeps a lazy session's
118
+ // descriptor inside its JWT budget.
119
+ retention: runtimeRetentionModeSchema,
105
120
  retained_files: z.array(manifestFileSchema).optional(),
106
121
  reusable_version_id: z.string().min(1).optional(),
107
122
  metadata: z.record(z.string(), z.unknown()).default({}),
108
123
  });
124
+ /**
125
+ * The retention half of a create-version body or session descriptor.
126
+ * `retained_files` is omitted when empty; with an explicit `retention` that
127
+ * omission means retain nothing beyond what `all` materializes.
128
+ */
129
+ export function runtimeRetentionFields(input) {
130
+ return {
131
+ retention: input.retention,
132
+ ...(input.retainedFiles.length > 0 ? { retained_files: [...input.retainedFiles] } : {}),
133
+ ...(input.reusableVersionId ? { reusable_version_id: input.reusableVersionId } : {}),
134
+ };
135
+ }
109
136
  export const RUNTIME_UPLOAD_SESSION_DESCRIPTOR_MAX_BYTES = 4096;
110
137
  // Hard wire budget for the complete `Authorization: Bearer <jwt>\r\n` line sent
111
138
  // on every PUT. Lazy-session selection measures the signed line and falls back
@@ -198,9 +225,9 @@ export const runtimeAuthorizationProjectionSchema = z
198
225
  // The space-level Comments projection the runtime serves as the whole answer
199
226
  // for `/__spacefast/comments/config`; the runtime adds only per-request fields.
200
227
  const runtimeSdkCommentsSchema = z.object({
201
- // Comments boot on the live/published host.
228
+ // Which hosts Comments boot on: the live/published host, and the immutable
229
+ // version (preview) host.
202
230
  live: z.boolean(),
203
- // ...and on an immutable version (preview) host.
204
231
  preview: z.boolean(),
205
232
  // Null before the Space has ever published.
206
233
  live_url: z.string().url().max(2000).nullable(),
@@ -409,17 +436,17 @@ const runtimeSubstitutionChannelSchema = z.object({
409
436
  export const runtimeVersionFinalizeRequestSchema = z.object({
410
437
  upload_id: z.string().min(1),
411
438
  session: runtimeUploadSessionDescriptorSchema.optional(),
439
+ // Capsule versions finalize and activate in separate calls, but still need
440
+ // the same publish delta as the combined path.
441
+ previous_version_id: previousVersionIdSchema,
412
442
  zero: zeroRuntimeConfigSchema.optional(),
413
443
  // Dispatch configuration for a Functions version. Absent for static versions,
414
- // and absent when no execution host is configured the version then serves
415
- // as pure static content, because this config is what makes the origin
416
- // dispatch at all.
444
+ // and absent when no execution host is configured; this config is what makes
445
+ // the origin dispatch at all.
417
446
  functions: functionsRuntimeConfigSchema.optional(),
418
- // Variable resolution is the control plane's half of substitution and stays
419
- // there: scopes come from its database, secret values are never decrypted for
420
- // it, and `SPACEFAST_*` names are platform-provided. The finalizer owns the
421
- // substitution itself — it has the staged bytes and the config that declares
422
- // which paths are templates, so nothing pre-substituted crosses this wire.
447
+ // The control plane resolves variable scopes; secret values are never
448
+ // decrypted for it. The finalizer performs the substitution itself, so
449
+ // nothing pre-substituted crosses this wire.
423
450
  variable_scopes: z.array(runtimeVariableScopeSchema).optional(),
424
451
  system_variables: z.record(z.string().min(1), z.string()).optional(),
425
452
  // The space's channels, so the finalizer can compile each one's variant files
@@ -444,11 +471,9 @@ export const runtimeVersionFinalizeRequestSchema = z.object({
444
471
  noindexHost: z.boolean().optional(),
445
472
  config: runtimeServingConfigSchema.optional(),
446
473
  // Origins the platform's own browser code loads from, keyed by the CSP
447
- // directive each belongs in. Which origins those are is a control-plane
448
- // decision they come from its environment and are validated against the
449
- // host this version will serve from while the merge itself belongs to
450
- // the finalizer, which is the only side that sees every CSP the version
451
- // sets, in `_headers` and in config rules alike.
474
+ // directive each belongs in. The control plane picks them, validated
475
+ // against the host this version will serve from; the finalizer merges
476
+ // them, because only it sees every CSP the version sets.
452
477
  platform_csp_sources: z
453
478
  .record(z.string().min(1).max(64), z.array(z.string().min(1).max(512)).max(16))
454
479
  .optional(),
@@ -507,9 +532,8 @@ export const runtimeCatalogDeltaSchema = z.object({
507
532
  });
508
533
  // One compiled diagnostic from the finalizer. `path` is the committed file it
509
534
  // points at, carrying `file:line` when the compiler knew a line; `details` is
510
- // what it points at INSIDE that file the variable, the channel, the colliding
511
- // routes — which is the difference between a publish failure you can act on and
512
- // one you can only retry.
535
+ // what it points at INSIDE that file: the variable, the channel, or the
536
+ // colliding routes.
513
537
  export const runtimeCompileDiagnosticSchema = z.object({
514
538
  severity: z.enum(["info", "warning", "error"]),
515
539
  code: z.string().min(1),
@@ -517,6 +541,31 @@ export const runtimeCompileDiagnosticSchema = z.object({
517
541
  path: z.string().optional(),
518
542
  details: z.record(z.string(), z.unknown()).optional(),
519
543
  });
544
+ export const runtimeRouteInventorySchema = z.object({
545
+ format: z.literal("stattic.route-inventory.v1"),
546
+ routes: z.array(z.object({
547
+ id: z.string().regex(/^sha256:[a-f0-9]{64}$/),
548
+ kind: z.enum([
549
+ "redirect",
550
+ "rewrite",
551
+ "proxy",
552
+ "not-found",
553
+ "functions",
554
+ "php-function",
555
+ "zero-control",
556
+ "zero-endpoint",
557
+ ]),
558
+ source: z.string().min(1),
559
+ runtime: z.enum(["routing", "cloudflare-worker", "php", "quick-js"]),
560
+ host: z.string().min(1),
561
+ path: z.string().startsWith("/"),
562
+ methods: z.array(z.string().min(1)).min(1),
563
+ auth: z.literal("inherit"),
564
+ cache: z.literal("shared").optional(),
565
+ destination: z.string().min(1).optional(),
566
+ status: z.number().int().min(200).max(599).optional(),
567
+ })),
568
+ });
520
569
  // What the version's conventions and config compiled TO. The counts are the
521
570
  // control plane's version-row projection; `proxy_rules` is what it overlays the
522
571
  // publishing team's plan onto, because the compiled artifact never bakes a plan
@@ -530,16 +579,41 @@ export const runtimeCompiledRoutingSchema = z.object({
530
579
  .max(1000)
531
580
  .default([]),
532
581
  });
582
+ // What one finalize RUN cost, stage by stage, straight off the native
583
+ // finalizer's envelope, which is why these keys are camelCase while the rest of
584
+ // this receipt is not. `skippedFiles` is the incrementality gauge: it stays 0
585
+ // while every finalize rebuilds everything.
586
+ export const runtimeFinalizeTelemetrySchema = z.object({
587
+ stagedFiles: z.number().int().nonnegative(),
588
+ generatedFiles: z.number().int().nonnegative(),
589
+ decoratedFiles: z.number().int().nonnegative(),
590
+ skippedFiles: z.number().int().nonnegative(),
591
+ stagingMs: z.number().int().nonnegative(),
592
+ templateSubstitutionMs: z.number().int().nonnegative(),
593
+ htmlPipelineMs: z.number().int().nonnegative(),
594
+ // The four stages below ship with the finalizer that splits them out; an
595
+ // engine predating the split reports the coarser stages only.
596
+ conventionsMs: z.number().int().nonnegative().optional(),
597
+ zeroCompileMs: z.number().int().nonnegative().optional(),
598
+ blobInstallMs: z.number().int().nonnegative(),
599
+ listingsMs: z.number().int().nonnegative().optional(),
600
+ responseTablesMs: z.number().int().nonnegative(),
601
+ catalogDeltaMs: z.number().int().nonnegative(),
602
+ artifactsWriteMs: z.number().int().nonnegative().optional(),
603
+ totalMs: z.number().int().nonnegative(),
604
+ });
533
605
  export const runtimeVersionFinalizeResponseSchema = z.object({
534
606
  space_id: z.string(),
535
607
  version_id: z.string(),
536
608
  status: z.literal("ready"),
537
609
  zero_endpoint_count: z.number().int().nonnegative().optional(),
538
- // The finalizer is the one conventions/config compiler, so what it compiled is
539
- // reported back rather than recomputed: the control plane runs no second
540
- // compile pass to learn its own version row.
610
+ // The finalizer is the one conventions/config compiler, so the control plane
611
+ // runs no second compile pass to learn its own version row.
541
612
  diagnostics: z.array(runtimeCompileDiagnosticSchema).default([]),
542
613
  routing: runtimeCompiledRoutingSchema.optional(),
614
+ // Versioned, finalizer-owned route declarations. Optional while runtimes
615
+ // finalized before the inventory ships remain replayable.
616
+ route_inventory: runtimeRouteInventorySchema.optional(),
543
617
  // Provenance for the substitution the finalizer performed: dependency name
544
618
  // (`NAME` or `NAME@channel`) -> SHA-256 of the value it resolved to. This is
545
619
  // what answers "does changing this variable require a republish?".
@@ -556,12 +630,15 @@ export const runtimeVersionFinalizeResponseSchema = z.object({
556
630
  // the catalog at finalize. Null when the version serves no image.
557
631
  preview_image_path: z.string().min(1).nullable().optional(),
558
632
  readiness_target: runtimeReadinessTargetSchema,
633
+ // Absent whenever the runtime answered without finalizing: a replayed or
634
+ // idempotent finalize re-runs no stage and reports no timings.
635
+ telemetry: runtimeFinalizeTelemetrySchema.optional(),
559
636
  activation_event_id: z
560
637
  .string()
561
638
  .min(1)
562
639
  .optional()
563
640
  .describe("Stable route_updated event id when finalize also activated a route."),
564
- ...runtimeMutationPurgeShape,
641
+ ...runtimeMutationPurgeFields,
565
642
  });
566
643
  export const runtimeZeroMigrationsApplyResponseSchema = z.object({
567
644
  space_id: z.string(),
@@ -571,9 +648,10 @@ export const runtimeZeroMigrationsApplyResponseSchema = z.object({
571
648
  export const runtimeRouteUpdateRequestSchema = z.object({
572
649
  version_id: z.string().min(1),
573
650
  config: runtimeRouteConfigSchema.optional(),
574
- // The engine stores this with the route pointer and no-ops the whole PUT — no
575
- // policy store, no journal event, no edge purge when version, digest, and
576
- // hostname intent all match the stored route. Absent = always write.
651
+ // The engine stores this with the route pointer. When version, digest, and
652
+ // hostname intent all match the stored route, the engine no-ops the whole
653
+ // PUT: no policy store, no journal event, no edge purge. Absent = always
654
+ // write.
577
655
  config_digest: z.string().min(1).optional(),
578
656
  // No `changed_paths`: the runtime holds both catalogs and scopes the purge
579
657
  // from `previous_version_id` itself.
@@ -602,12 +680,12 @@ export const runtimeRouteUpdateResponseSchema = z.object({
602
680
  .min(1)
603
681
  .optional()
604
682
  .describe("Stable route_updated event id for this exact route command, including retries."),
605
- ...runtimeMutationPurgeShape,
683
+ ...runtimeMutationPurgeFields,
606
684
  });
607
685
  export const runtimeHostnameIntentUpdateResponseSchema = z.object({
608
686
  space_id: z.string(),
609
687
  route_count: z.number().int().nonnegative(),
610
- ...runtimeMutationPurgeShape,
688
+ ...runtimeMutationPurgeFields,
611
689
  });
612
690
  export const runtimeTombstonesUpdateRequestSchema = z.object({
613
691
  hostnames: runtimeRouteIntentSchema.shape.production_hostnames,
@@ -620,34 +698,13 @@ export const runtimeTombstonesUpdateRequestSchema = z.object({
620
698
  export const runtimeTombstonesUpdateResponseSchema = z.object({
621
699
  space_id: z.string(),
622
700
  tombstone_count: z.number().int().nonnegative(),
623
- ...runtimeMutationPurgeShape,
624
- });
625
- // The control plane computes prunable version ids; the engine stores the list
626
- // and its housekeeping tick prunes trees after re-checking live route pointers.
627
- // An empty list clears the policy.
628
- export const runtimeRetentionPolicyUpdateRequestSchema = z.object({
629
- prunable_version_ids: z.array(z.string()),
630
- });
631
- export const runtimeRetentionPolicyUpdateResponseSchema = z.object({
632
- space_id: z.string(),
633
- prunable_count: z.number().int().nonnegative(),
634
- ...runtimeMutationPurgeShape,
635
- });
636
- export const runtimeSpaceDeleteResponseSchema = z.object({
637
- space_id: z.string(),
638
- status: z.literal("deleted"),
639
- ...runtimeMutationPurgeShape,
701
+ ...runtimeMutationPurgeFields,
640
702
  });
641
703
  export const runtimeVersionDeleteResponseSchema = z.object({
642
704
  space_id: z.string(),
643
705
  version_id: z.string(),
644
706
  status: z.literal("deleted"),
645
- ...runtimeMutationPurgeShape,
646
- });
647
- export const runtimeSpaceRepairResponseSchema = z.object({
648
- space_id: z.string(),
649
- status: z.literal("repaired"),
650
- ...runtimeMutationPurgeShape,
707
+ ...runtimeMutationPurgeFields,
651
708
  });
652
709
  // A pin freezes a set of blob SHAs against the collector for as long as it
653
710
  // lives. `snapshot` pins everything a set of versions plus space storage
@@ -717,7 +774,7 @@ export const runtimeZeroDbImportResponseSchema = z.object({
717
774
  });
718
775
  // Per-space generation state reported by the authed state endpoint. The
719
776
  // reconciliation sweep compares it against control-plane expectations and
720
- // repairs targeted mismatches never a blanket re-sync.
777
+ // repairs targeted mismatches, never a blanket re-sync.
721
778
  export const runtimeSpaceStateSchema = z.object({
722
779
  space_id: z.string().min(1).describe("Space whose runtime route pointers follow."),
723
780
  routes: z
@@ -791,6 +848,10 @@ export const runtimeCallbackEventSchema = z.looseObject({
791
848
  .describe("Runtime management action authorized for the operation."),
792
849
  space_id: z.string().optional().describe("Space the event applies to, when space-scoped."),
793
850
  version_id: z.string().optional().describe("Version the event applies to, when version-scoped."),
851
+ version_ids: z
852
+ .array(z.string().min(1))
853
+ .optional()
854
+ .describe("Exact versions covered by a completed space-scoped runtime operation."),
794
855
  route_name: z.string().optional().describe("Route pointer the event updated, when route-scoped."),
795
856
  hostnames: z
796
857
  .array(z.string().min(1))
@@ -862,7 +923,7 @@ export const runtimeEventsDrainRequestSchema = z
862
923
  });
863
924
  export const runtimeEventsDrainResponseSchema = z.object({
864
925
  // Cursor runtimes keep these at zero. Older engines report their legacy
865
- // delivery counters here while a rolling bundle update is still converging.
926
+ // delivery counters here while a rolling bundle update is still syncing.
866
927
  delivered_count: z.number().int().nonnegative(),
867
928
  failed_count: z.number().int().nonnegative(),
868
929
  expired_count: z.number().int().nonnegative().optional(),
@@ -938,7 +999,7 @@ export const runtimeEngineJobRecordSchema = z.object({
938
999
  export const runtimeEngineJobCreateRequestSchema = z.object({
939
1000
  type: z.string().min(1),
940
1001
  payload: z.record(z.string(), z.unknown()).default({}),
941
- // Unique per (type, space, operation) create is upsert-by-key.
1002
+ // Unique per (type, space, operation). Create is upsert-by-key.
942
1003
  idempotency_key: z.string().min(1),
943
1004
  });
944
1005
  export const runtimeEngineJobResponseSchema = z.object({
@@ -1,20 +1,13 @@
1
1
  import { z } from "zod";
2
2
  /**
3
- * The one answer to "what is running on this space".
3
+ * What is running on this space.
4
4
  *
5
- * One published tree can carry static files, a worker and a capsule at once
6
- * every space owns a site, so what answers a request is a routing decision, not
7
- * a kind the space declared. This is therefore two independent members rather
8
- * than a discriminated union: each is `null` when the live tree carries none of
9
- * that product, and both `null` is the overwhelmingly common answer. A static
10
- * space is not a degenerate app, it is the absence of one.
5
+ * A published tree can carry a worker and a capsule at once, so these are two
6
+ * independent nullable members rather than a discriminated union. Each is
7
+ * `null` when the live tree carries none of that product.
11
8
  *
12
- * When both are present the capsule wins a path conflict it is the one that
13
- * owns the space's database and its transaction.
14
- *
15
- * It lives in its own module because it is the only place that needs to know
16
- * about both products at once. `spaces.ts` imports it to describe runtime
17
- * status; neither `zero.ts` nor `functions.ts` has to learn about the other.
9
+ * When both are present the capsule wins a path conflict: it owns the space's
10
+ * database and its transaction.
18
11
  */
19
12
  export declare const runtimeAppSchema: z.ZodObject<{
20
13
  capsule: z.ZodNullable<z.ZodObject<{
@@ -23,8 +16,8 @@ export declare const runtimeAppSchema: z.ZodObject<{
23
16
  serverRuntime: z.ZodLiteral<"quickjs-rust">;
24
17
  inspect: z.ZodObject<{
25
18
  policy: z.ZodEnum<{
26
- public: "public";
27
19
  private: "private";
20
+ public: "public";
28
21
  }>;
29
22
  }, z.core.$strict>;
30
23
  install: z.ZodObject<{
@@ -36,7 +29,7 @@ export declare const runtimeAppSchema: z.ZodObject<{
36
29
  binary: z.ZodObject<{
37
30
  path: z.ZodLiteral<"__spacefast/zero/bin/stattic-runtime">;
38
31
  compatibilityTarget: z.ZodObject<{
39
- profile: z.ZodLiteral<"wpcloud-linux-x86_64-gnu-v1">;
32
+ profile: z.ZodLiteral<"linux-x86_64-gnu-v1">;
40
33
  os: z.ZodLiteral<"linux">;
41
34
  cpu: z.ZodLiteral<"x86_64">;
42
35
  libc: z.ZodLiteral<"glibc">;
@@ -72,6 +65,8 @@ export declare const runtimeAppSchema: z.ZodObject<{
72
65
  path: z.ZodString;
73
66
  }, z.core.$strict>>>;
74
67
  sockets: z.ZodDefault<z.ZodArray<z.ZodString>>;
68
+ serverBundleSize: z.ZodNullable<z.ZodNumber>;
69
+ clientBundleSize: z.ZodNullable<z.ZodNumber>;
75
70
  migrationCount: z.ZodNumber;
76
71
  schemaHash: z.ZodNullable<z.ZodString>;
77
72
  variables: z.ZodObject<{
@@ -126,6 +121,7 @@ export declare const runtimeAppSchema: z.ZodObject<{
126
121
  gravatar: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
127
122
  spam: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
128
123
  email: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
124
+ content: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
129
125
  }, z.core.$strip>>;
130
126
  executionState: z.ZodEnum<{
131
127
  ready: "ready";
@@ -141,14 +137,7 @@ export declare const runtimeAppSchema: z.ZodObject<{
141
137
  }, z.core.$strict>>;
142
138
  }, z.core.$strict>;
143
139
  export type RuntimeApp = z.infer<typeof runtimeAppSchema>;
144
- /**
145
- * Replay of the invalidation events a live runtime emitted.
146
- *
147
- * The event shape itself is Zero's — it names mutations, changed tables and
148
- * changed queries, which only a capsule has — but the route that serves it is
149
- * the runtime family's, so the page contract lives here beside the rest of the
150
- * unified surface rather than inside one product.
151
- */
140
+ /** Replay of the invalidation events a live runtime emitted, in Zero's event shape. */
152
141
  export declare const runtimeRealtimeEventListQuerySchema: z.ZodObject<{
153
142
  afterEventId: z.ZodOptional<z.ZodString>;
154
143
  limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
@@ -167,6 +156,7 @@ export declare const runtimeRealtimeEventListResponseSchema: z.ZodObject<{
167
156
  schemaHash: z.ZodString;
168
157
  committedAt: z.ZodString;
169
158
  }, z.core.$strict>>;
159
+ nextAfterEventId: z.ZodNullable<z.ZodString>;
170
160
  pagination: z.ZodObject<{
171
161
  nextCursor: z.ZodNullable<z.ZodString>;
172
162
  hasMore: z.ZodBoolean;
@@ -3,21 +3,14 @@ import { CursorPaginationSchema } from "./common.js";
3
3
  import { functionsAppSchema } from "./functions.js";
4
4
  import { zeroAppSchema, zeroRealtimeEventSchema } from "./zero.js";
5
5
  /**
6
- * The one answer to "what is running on this space".
6
+ * What is running on this space.
7
7
  *
8
- * One published tree can carry static files, a worker and a capsule at once
9
- * every space owns a site, so what answers a request is a routing decision, not
10
- * a kind the space declared. This is therefore two independent members rather
11
- * than a discriminated union: each is `null` when the live tree carries none of
12
- * that product, and both `null` is the overwhelmingly common answer. A static
13
- * space is not a degenerate app, it is the absence of one.
8
+ * A published tree can carry a worker and a capsule at once, so these are two
9
+ * independent nullable members rather than a discriminated union. Each is
10
+ * `null` when the live tree carries none of that product.
14
11
  *
15
- * When both are present the capsule wins a path conflict it is the one that
16
- * owns the space's database and its transaction.
17
- *
18
- * It lives in its own module because it is the only place that needs to know
19
- * about both products at once. `spaces.ts` imports it to describe runtime
20
- * status; neither `zero.ts` nor `functions.ts` has to learn about the other.
12
+ * When both are present the capsule wins a path conflict: it owns the space's
13
+ * database and its transaction.
21
14
  */
22
15
  export const runtimeAppSchema = z
23
16
  .object({
@@ -29,23 +22,45 @@ export const runtimeAppSchema = z
29
22
  .describe("The live version's Functions worker, if it carries one."),
30
23
  })
31
24
  .strict();
32
- /**
33
- * Replay of the invalidation events a live runtime emitted.
34
- *
35
- * The event shape itself is Zero's — it names mutations, changed tables and
36
- * changed queries, which only a capsule has — but the route that serves it is
37
- * the runtime family's, so the page contract lives here beside the rest of the
38
- * unified surface rather than inside one product.
39
- */
25
+ /** Replay of the invalidation events a live runtime emitted, in Zero's event shape. */
40
26
  export const runtimeRealtimeEventListQuerySchema = z
41
27
  .object({
42
- afterEventId: z.string().min(1).optional(),
43
- limit: z.coerce.number().int().min(1).max(100).default(50),
28
+ afterEventId: z
29
+ .string()
30
+ .min(1)
31
+ .optional()
32
+ .describe("Walk forward from this event id, exclusive. Omit it to start at the oldest retained event; pass the previous page's `nextAfterEventId` to continue. An id that has aged out of the retention window is rejected."),
33
+ limit: z.coerce
34
+ .number()
35
+ .int()
36
+ .min(1)
37
+ .max(100)
38
+ .default(50)
39
+ .describe("Maximum events to return."),
44
40
  })
45
41
  .strict();
42
+ // Keyset, not the platform's opaque cursor: replay walks forward by event id
43
+ // and an aged-out id is a hard error, so the response names the next
44
+ // `afterEventId` rather than advertising a `pagination` envelope the request
45
+ // has no `cursor` to feed. The legacy `pagination` member below is a temporary
46
+ // back-compat exception, not the canonical shape — see its note.
46
47
  export const runtimeRealtimeEventListResponseSchema = z
47
48
  .object({
48
49
  data: z.array(zeroRealtimeEventSchema),
49
- pagination: CursorPaginationSchema,
50
+ nextAfterEventId: z
51
+ .string()
52
+ .nullable()
53
+ .describe("Event id to pass as `afterEventId` for the next page; null when this page reached the newest retained event."),
54
+ // COMPAT (temporary back-compat, effectively durable): pre-cutover Zero
55
+ // capsule clients are baked per-capsule at build time and cannot be
56
+ // rebuilt (we don't always have capsule source). Those frozen clients page
57
+ // replay by reading `pagination.nextCursor` and never look at
58
+ // `nextAfterEventId`, so the server keeps emitting this legacy envelope
59
+ // alongside the flat field. `nextCursor` carries the exact same
60
+ // continuation value as `nextAfterEventId`, and `hasMore` mirrors it.
61
+ // Remove only once no frozen pre-cutover capsules remain (which may be
62
+ // never); until then this is the sole reason the field survives the
63
+ // cutover.
64
+ pagination: CursorPaginationSchema.describe("Legacy pagination envelope kept only for frozen pre-cutover Zero capsule clients that page by `pagination.nextCursor`. New clients read `nextAfterEventId`; `nextCursor` mirrors it exactly."),
50
65
  })
51
66
  .strict();