@spacefast/common 0.0.12 → 0.0.17

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 (189) hide show
  1. package/dist/agents/client-registry.d.ts +22 -0
  2. package/dist/agents/client-registry.js +41 -0
  3. package/dist/agents/connect-targets.d.ts +51 -6
  4. package/dist/agents/connect-targets.js +93 -28
  5. package/dist/brand.d.ts +0 -11
  6. package/dist/brand.js +0 -20
  7. package/dist/config/domains.d.ts +15 -6
  8. package/dist/config/domains.js +24 -10
  9. package/dist/config/postgres-budget.d.ts +3 -0
  10. package/dist/config/postgres-budget.js +6 -1
  11. package/dist/config/postgres-budget.json +2 -1
  12. package/dist/contracts/abuse.js +1 -1
  13. package/dist/contracts/access.d.ts +486 -1196
  14. package/dist/contracts/access.js +323 -1054
  15. package/dist/contracts/activity.d.ts +1 -1
  16. package/dist/contracts/activity.js +11 -15
  17. package/dist/contracts/api-keys.d.ts +16 -0
  18. package/dist/contracts/api-keys.js +11 -9
  19. package/dist/contracts/archives.d.ts +1 -2
  20. package/dist/contracts/archives.js +15 -17
  21. package/dist/contracts/beta.js +1 -1
  22. package/dist/contracts/builds.js +14 -14
  23. package/dist/contracts/channels.js +2 -2
  24. package/dist/contracts/comments.d.ts +143 -99
  25. package/dist/contracts/comments.js +194 -79
  26. package/dist/contracts/common.d.ts +12 -12
  27. package/dist/contracts/common.js +33 -30
  28. package/dist/contracts/continuation.js +5 -5
  29. package/dist/contracts/countries.js +2 -7
  30. package/dist/contracts/data-source-routes.d.ts +20 -0
  31. package/dist/contracts/data-source-routes.js +15 -0
  32. package/dist/contracts/device-auth.d.ts +13 -9
  33. package/dist/contracts/device-auth.js +12 -12
  34. package/dist/contracts/docs.d.ts +10 -10
  35. package/dist/contracts/domains.js +39 -33
  36. package/dist/contracts/enums.d.ts +4 -14
  37. package/dist/contracts/enums.js +3 -10
  38. package/dist/contracts/error-code-meta.d.ts +122 -56
  39. package/dist/contracts/error-code-meta.js +43 -19
  40. package/dist/contracts/error-codes.d.ts +7 -4
  41. package/dist/contracts/error-codes.js +48 -24
  42. package/dist/contracts/events.d.ts +22 -15
  43. package/dist/contracts/events.js +33 -5
  44. package/dist/contracts/execution.d.ts +238 -0
  45. package/dist/contracts/execution.js +309 -0
  46. package/dist/contracts/feature-lifecycle.d.ts +39 -188
  47. package/dist/contracts/feature-lifecycle.js +52 -196
  48. package/dist/contracts/features.d.ts +13 -115
  49. package/dist/contracts/features.js +5 -35
  50. package/dist/contracts/functions.d.ts +597 -0
  51. package/dist/contracts/functions.js +475 -0
  52. package/dist/contracts/grants.d.ts +1175 -0
  53. package/dist/contracts/grants.js +783 -0
  54. package/dist/contracts/ids.d.ts +7 -5
  55. package/dist/contracts/ids.js +7 -7
  56. package/dist/contracts/internal.js +2 -2
  57. package/dist/contracts/mcp.d.ts +17 -556
  58. package/dist/contracts/mcp.js +9 -103
  59. package/dist/contracts/me.js +3 -4
  60. package/dist/contracts/notifications.d.ts +108 -0
  61. package/dist/contracts/notifications.js +54 -0
  62. package/dist/contracts/oauth-resources.d.ts +22 -5
  63. package/dist/contracts/oauth-resources.js +23 -2
  64. package/dist/contracts/operations.d.ts +0 -48
  65. package/dist/contracts/operations.js +0 -19
  66. package/dist/contracts/pages.d.ts +10 -14
  67. package/dist/contracts/pages.js +17 -21
  68. package/dist/contracts/plan-policy.d.ts +1 -8
  69. package/dist/contracts/plan-policy.js +1 -4
  70. package/dist/contracts/platform.d.ts +78 -30
  71. package/dist/contracts/platform.js +69 -20
  72. package/dist/contracts/problem-document.d.ts +14 -0
  73. package/dist/contracts/problem-document.js +35 -0
  74. package/dist/contracts/push-new.d.ts +41 -2
  75. package/dist/contracts/push-new.js +4 -0
  76. package/dist/contracts/quotas.d.ts +0 -1
  77. package/dist/contracts/quotas.js +0 -5
  78. package/dist/contracts/repository-connections.d.ts +1 -1
  79. package/dist/contracts/resources.d.ts +16 -71
  80. package/dist/contracts/resources.js +13 -16
  81. package/dist/contracts/runtime-api.d.ts +666 -303
  82. package/dist/contracts/runtime-api.js +272 -113
  83. package/dist/contracts/runtime-app.d.ts +168 -0
  84. package/dist/contracts/runtime-app.js +42 -0
  85. package/dist/contracts/runtime-db.d.ts +424 -0
  86. package/dist/contracts/runtime-db.js +108 -0
  87. package/dist/contracts/runtime-storage.d.ts +120 -0
  88. package/dist/contracts/runtime-storage.js +40 -0
  89. package/dist/contracts/sf-config-v1.d.ts +54 -1
  90. package/dist/contracts/sf-config-v1.js +2 -2
  91. package/dist/contracts/sites.d.ts +6 -0
  92. package/dist/contracts/sites.js +30 -11
  93. package/dist/contracts/space-config.d.ts +91 -121
  94. package/dist/contracts/space-config.js +464 -42
  95. package/dist/contracts/spaces.d.ts +300 -171
  96. package/dist/contracts/spaces.js +128 -98
  97. package/dist/contracts/superadmin-emails.d.ts +2 -2
  98. package/dist/contracts/superadmin-spaces.d.ts +26 -130
  99. package/dist/contracts/superadmin-spaces.js +22 -0
  100. package/dist/contracts/superadmin-tenants.js +4 -4
  101. package/dist/contracts/superadmin.d.ts +4 -0
  102. package/dist/contracts/superadmin.js +14 -1
  103. package/dist/contracts/tags.d.ts +6 -6
  104. package/dist/contracts/tags.js +1 -1
  105. package/dist/contracts/teams.d.ts +9 -9
  106. package/dist/contracts/teams.js +25 -16
  107. package/dist/contracts/theme-json.js +1 -1
  108. package/dist/contracts/transfers.d.ts +0 -1
  109. package/dist/contracts/transfers.js +4 -4
  110. package/dist/contracts/variables.js +3 -3
  111. package/dist/contracts/zero.d.ts +384 -596
  112. package/dist/contracts/zero.js +167 -299
  113. package/dist/dashboard-paths/index.d.ts +18 -3
  114. package/dist/dashboard-paths/index.js +19 -0
  115. package/dist/docs/agent-handoff-document.d.ts +2 -2
  116. package/dist/docs/agent-handoff-document.js +8 -7
  117. package/dist/docs/agent-prose.d.ts +22 -3
  118. package/dist/docs/agent-prose.js +227 -55
  119. package/dist/docs/agent-setup.d.ts +14 -11
  120. package/dist/docs/agent-setup.js +289 -61
  121. package/dist/docs/agent-solutions.d.ts +6 -6
  122. package/dist/docs/agent-solutions.js +24 -22
  123. package/dist/docs/catalog.d.ts +53 -98
  124. package/dist/docs/catalog.js +90 -117
  125. package/dist/docs/error-docs.js +304 -236
  126. package/dist/docs/skill-distribution.d.ts +2 -0
  127. package/dist/docs/skill-distribution.js +7 -4
  128. package/dist/docs/skills.d.ts +546 -0
  129. package/dist/docs/skills.js +340 -0
  130. package/dist/utils/auth-redirect.d.ts +1 -3
  131. package/dist/utils/auth-redirect.js +1 -21
  132. package/dist/utils/browser-credential.d.ts +19 -0
  133. package/dist/utils/browser-credential.js +62 -0
  134. package/dist/utils/build-settings.d.ts +2 -0
  135. package/dist/utils/build-settings.js +61 -9
  136. package/dist/utils/comment-avatars.d.ts +7 -0
  137. package/dist/utils/comment-avatars.js +42 -0
  138. package/dist/utils/content-type.d.ts +3 -3
  139. package/dist/utils/content-type.js +38 -61
  140. package/dist/utils/credential-policy.d.ts +1 -1
  141. package/dist/utils/credential-policy.js +4 -0
  142. package/dist/utils/domain-diagnostics.d.ts +5 -5
  143. package/dist/utils/domain-diagnostics.js +21 -10
  144. package/dist/utils/egress-policy.fixtures.json +1 -1
  145. package/dist/utils/grants.d.ts +53 -0
  146. package/dist/utils/grants.js +160 -0
  147. package/dist/utils/local-space-state.d.ts +78 -4
  148. package/dist/utils/local-space-state.js +384 -82
  149. package/dist/utils/one-shot-replay.d.ts +14 -0
  150. package/dist/utils/one-shot-replay.js +21 -0
  151. package/dist/utils/page-preview.d.ts +7 -0
  152. package/dist/utils/page-preview.js +9 -0
  153. package/dist/utils/pages.d.ts +2 -5
  154. package/dist/utils/pages.js +64 -33
  155. package/dist/utils/publish-form-data.d.ts +22 -0
  156. package/dist/utils/publish-form-data.js +26 -0
  157. package/dist/utils/publish-policy.d.ts +34 -4
  158. package/dist/utils/publish-policy.js +149 -62
  159. package/dist/utils/query-keys.d.ts +8 -10
  160. package/dist/utils/query-keys.js +14 -10
  161. package/dist/utils/runtime-paths.d.ts +3 -0
  162. package/dist/utils/runtime-paths.js +7 -0
  163. package/dist/utils/secure-local-file.d.ts +73 -0
  164. package/dist/utils/secure-local-file.js +1373 -0
  165. package/dist/utils/space-config.d.ts +17 -4
  166. package/dist/utils/space-config.js +151 -8
  167. package/dist/utils/static-runtime-policy.d.ts +5 -0
  168. package/dist/utils/static-runtime-policy.js +54 -10
  169. package/dist/utils/storage-policy.d.ts +20 -0
  170. package/dist/utils/storage-policy.fixtures.json +174 -0
  171. package/dist/utils/storage-policy.js +193 -0
  172. package/dist/utils/upload-session.d.ts +15 -1
  173. package/dist/utils/upload-session.js +68 -2
  174. package/dist/utils/version-file-browser.d.ts +13 -0
  175. package/dist/utils/version-file-browser.js +59 -0
  176. package/package.json +20 -1
  177. package/dist/contracts/mounts.d.ts +0 -142
  178. package/dist/contracts/mounts.js +0 -56
  179. package/dist/utils/access-grant.d.ts +0 -14
  180. package/dist/utils/access-grant.js +0 -88
  181. package/dist/utils/access-match.d.ts +0 -46
  182. package/dist/utils/access-match.fixtures.json +0 -513
  183. package/dist/utils/access-match.js +0 -312
  184. package/dist/utils/access-verdict.fixtures.json +0 -421
  185. package/dist/utils/asset-fingerprint.d.ts +0 -53
  186. package/dist/utils/asset-fingerprint.js +0 -574
  187. package/dist/utils/sf-config-v1.d.ts +0 -2
  188. package/dist/utils/sf-config-v1.fixtures.json +0 -9
  189. package/dist/utils/sf-config-v1.js +0 -551
@@ -1,8 +1,24 @@
1
1
  import { z } from "zod";
2
- import { dataEnvelope } from "./common.js";
2
+ import { appRoutePathSchema, EXECUTION_ENV_MAX_KEYS, executionBundleSchema, executionCapabilitiesSchema, executionEnvNameSchema, executionIdentifierSchema, executionInspectPolicySchema, executionLogEntrySchema, executionLogListQuerySchema, executionLogListResponseSchema, executionSha256Schema, executionStaticFileSchema, httpMethodSchema, LAKEBED_SERVER_ENV_FILE, PLATFORM_ROUTE_PREFIX, runtimeRealtimeModeSchema, SERVER_ENV_FILE, } from "./execution.js";
3
+ /**
4
+ * Spacefast Zero: capsules — schema, queries, mutations and endpoints that run
5
+ * together inside one parent-owned transaction — executed by the native runner
6
+ * on a dedicated wp.cloud site, against that site's own MySQL.
7
+ *
8
+ * The transaction is what makes this a separate product rather than a
9
+ * placement option for `./functions.js`. A capsule handler's semantics depend
10
+ * on the transaction wrapped around it, and an isolate reaching the database
11
+ * over a relay cannot offer one. See `endpointIsPortable` in `./execution.js`
12
+ * for the narrow surface both products can host.
13
+ */
3
14
  export const ZERO_SOURCE_METADATA_KEY = "statticZero";
4
15
  export const ZERO_RUNTIME_KIND = "zero";
5
- export const ZERO_PLATFORM_ROUTE_PREFIX = "/__spacefast/zero";
16
+ export const ZERO_PLATFORM_ROUTE_PREFIX = `${PLATFORM_ROUTE_PREFIX}/zero`;
17
+ /**
18
+ * Entry paths the Zero scaffold writes into `sf.jsonc#runtime`. They are
19
+ * starting points, not the contract: a capsule's entries are whatever its
20
+ * `runtime.server`/`runtime.client` say, and nothing infers them.
21
+ */
6
22
  export const ZERO_CLIENT_ENTRY = "client/index.tsx";
7
23
  export const ZERO_SERVER_ENTRY = "server/index.ts";
8
24
  export const ZERO_RUNTIME_ROUTE_PATHS = {
@@ -12,125 +28,51 @@ export const ZERO_RUNTIME_ROUTE_PATHS = {
12
28
  db: `${ZERO_PLATFORM_ROUTE_PREFIX}/db`,
13
29
  logs: `${ZERO_PLATFORM_ROUTE_PREFIX}/logs`,
14
30
  run: `${ZERO_PLATFORM_ROUTE_PREFIX}/run`,
15
- authStart: `${ZERO_PLATFORM_ROUTE_PREFIX}/auth/wpcom/start`,
31
+ authStart: `${ZERO_PLATFORM_ROUTE_PREFIX}/auth/gravatar/start`,
16
32
  authSignOut: `${ZERO_PLATFORM_ROUTE_PREFIX}/auth/sign-out`,
17
33
  };
18
34
  export const ZERO_RUNTIME_STORAGE_ROOT = "__spacefast/zero";
19
35
  export const ZERO_RUNTIME_ARTIFACT_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/artifact.json`;
20
36
  export const ZERO_RUNTIME_CONFIG_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/config.json`;
21
- export const ZERO_RUNTIME_BINARY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/bin/stattic-zero-runner`;
37
+ export const ZERO_RUNTIME_BINARY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/bin/stattic-runtime`;
22
38
  export const ZERO_RUNTIME_BINARY_COMPATIBILITY_TARGET = "wpcloud-linux-x86_64-gnu-v1";
23
39
  export const ZERO_RUNTIME_BUNDLE_ROOT = `${ZERO_RUNTIME_STORAGE_ROOT}/bundles`;
24
40
  export const ZERO_RUNTIME_CLIENT_BUNDLE_PATH = `${ZERO_RUNTIME_BUNDLE_ROOT}/client.js`;
25
41
  export const ZERO_RUNTIME_SERVER_BUNDLE_PATH = `${ZERO_RUNTIME_BUNDLE_ROOT}/server.qjs.mjs`;
26
- export const ZERO_SOURCE_ENV_FILE = ".env.zero.server";
27
- export const ZERO_CONFIG_FILE = "zero.json";
28
- export const ZERO_DEPLOY_FILE = ".zero/deploy.json";
29
42
  export const ZERO_RUNTIME_BUNDLE_MAX_BYTES = 786_432;
30
- export const ZERO_ENV_MAX_KEYS = 64;
31
- export const ZERO_ENV_NAME_MAX_BYTES = 128;
32
- export const ZERO_ENV_VALUE_MAX_BYTES = 16 * 1024;
33
- export const ZERO_ENV_TOTAL_VALUE_MAX_BYTES = 64 * 1024;
34
- export const ZERO_ENV_RESERVED_PREFIXES = ["SPACEFAST_", "ZERO_"];
43
+ /**
44
+ * A capsule's compiled server travels as version metadata, not as content, so a
45
+ * server-only change leaves the published app shell byte-identical — and the
46
+ * version intent's manifest comparison would read it as "no changes" and never
47
+ * deploy it. The publish writes this one small file into the version instead:
48
+ * it holds a digest of everything the deploy would install, so any server,
49
+ * schema, or runtime-config change moves the manifest. Same channel a Functions
50
+ * bundle uses (`functionsBundleStoragePath`) — an ordinary manifest entry, no
51
+ * artifact-specific plumbing.
52
+ */
53
+ export const ZERO_RUNTIME_DEPLOY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/deploy.json`;
35
54
  export const ZERO_MANAGED_TABLE_COLUMNS = ["id", "createdAt", "updatedAt"];
55
+ /**
56
+ * Paths the Zero app shell itself answers, on top of the platform-reserved set
57
+ * in `./execution.js`. A capsule cannot claim these because its own client
58
+ * router and auth flow already do.
59
+ */
36
60
  export const ZERO_RESERVED_APP_ROUTE_PATHS = [
37
61
  "/",
38
62
  "/index.html",
39
63
  "/client.js",
40
64
  "/auth/callback",
41
- "/__spacefast",
42
- "/__span",
43
65
  ];
44
- export const ZERO_RESERVED_APP_ROUTE_PREFIXES = ["/auth/", "/__spacefast/", "/__span/"];
45
- export const zeroRuntimeKindSchema = z.enum(["static", "zero", "php", "node", "workers"]);
46
- const zeroNameSchema = z
47
- .string()
48
- .min(1)
49
- .max(128)
50
- .regex(/^[A-Za-z_][A-Za-z0-9_]*$/);
51
- const zeroEnvNameSchema = z
52
- .string()
53
- .min(1)
54
- .max(ZERO_ENV_NAME_MAX_BYTES)
55
- .regex(/^[A-Za-z_][A-Za-z0-9_]*$/)
56
- .refine((name) => !ZERO_ENV_RESERVED_PREFIXES.some((prefix) => name.toUpperCase().startsWith(prefix)), { message: "Zero env variable name uses a reserved prefix." });
57
- function hasWellFormedUnicode(value) {
58
- for (let index = 0; index < value.length; index++) {
59
- const codeUnit = value.charCodeAt(index);
60
- if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
61
- if (index + 1 >= value.length)
62
- return false;
63
- const next = value.charCodeAt(index + 1);
64
- if (next < 0xdc00 || next > 0xdfff)
65
- return false;
66
- index++;
67
- }
68
- else if (codeUnit >= 0xdc00 && codeUnit <= 0xdfff) {
69
- return false;
70
- }
71
- }
72
- return true;
73
- }
74
- function hasNoAsciiControlCharacters(value) {
75
- for (let index = 0; index < value.length; index++) {
76
- const codeUnit = value.charCodeAt(index);
77
- if (codeUnit <= 0x1f || codeUnit === 0x7f)
78
- return false;
79
- }
80
- return true;
81
- }
82
- const zeroRoutePathSchema = z
83
- .string()
84
- .min(1)
85
- .max(2048)
86
- .startsWith("/")
87
- .refine(hasWellFormedUnicode, {
88
- message: "Zero capsule routes must contain well-formed Unicode.",
89
- })
90
- .refine((path) => path.normalize("NFC") === path, {
91
- message: "Zero capsule routes must use NFC-normalized Unicode.",
92
- })
93
- .refine(hasNoAsciiControlCharacters, {
94
- message: "Zero capsule routes must not contain ASCII control characters.",
95
- })
96
- .refine((path) => !path.includes("//") &&
97
- !path.includes("\\") &&
98
- !path.includes("*") &&
99
- !path.includes("?") &&
100
- !path.includes("#") &&
101
- !path.endsWith("/") &&
102
- path
103
- .split("/")
104
- .every((segment, index, segments) => segment !== "." &&
105
- segment !== ".." &&
106
- segment !== ":" &&
107
- (segment !== ":splat" || index === segments.length - 1)), {
108
- message: "Zero capsule routes must be absolute app paths without empty, traversal, unnamed parameter, * wildcard, non-terminal splat, \\, ?, or # segments.",
109
- })
110
- .refine((path) => !ZERO_RESERVED_APP_ROUTE_PATHS.some((reservedPath) => path === reservedPath), {
111
- message: "Zero capsule route is reserved by the Zero app shell.",
112
- })
113
- .refine((path) => !ZERO_RESERVED_APP_ROUTE_PREFIXES.some((reservedPrefix) => path.startsWith(reservedPrefix)), {
114
- message: "Zero capsule route prefix is reserved by the Zero app shell.",
115
- })
116
- .refine((path) => !path.startsWith(ZERO_PLATFORM_ROUTE_PREFIX), {
117
- message: `Zero capsule routes cannot use ${ZERO_PLATFORM_ROUTE_PREFIX}.`,
118
- })
119
- .refine((path) => path !== "/__stattic" && !path.startsWith("/__stattic/"), {
120
- message: "Zero capsule routes cannot use Spacefast private control paths.",
66
+ export const ZERO_RESERVED_APP_ROUTE_PREFIXES = ["/auth/"];
67
+ const zeroNameSchema = executionIdentifierSchema;
68
+ const zeroRoutePathSchema = appRoutePathSchema({
69
+ subject: "Zero capsule routes",
70
+ reservedPaths: ZERO_RESERVED_APP_ROUTE_PATHS,
71
+ reservedPrefixes: ZERO_RESERVED_APP_ROUTE_PREFIXES,
121
72
  });
122
- export const zeroHttpMethodSchema = z.enum([
123
- "GET",
124
- "HEAD",
125
- "POST",
126
- "PUT",
127
- "PATCH",
128
- "DELETE",
129
- "OPTIONS",
130
- ]);
131
73
  export const zeroEndpointSchema = z
132
74
  .object({
133
- method: zeroHttpMethodSchema,
75
+ method: httpMethodSchema,
134
76
  path: zeroRoutePathSchema,
135
77
  })
136
78
  .strict();
@@ -220,53 +162,60 @@ export const zeroTableColumnSchema = z
220
162
  })
221
163
  .strict()
222
164
  .superRefine(zeroDefaultMatchesColumnType);
165
+ export const zeroTableIndexSchema = z
166
+ .object({
167
+ name: zeroNameSchema.refine((name) => name !== "by_creation", {
168
+ message: "by_creation is a built-in Zero index.",
169
+ }),
170
+ fields: z.array(zeroNameSchema).min(1),
171
+ })
172
+ .strict();
223
173
  export const zeroTableSchema = z
224
174
  .object({
225
175
  name: zeroNameSchema,
226
176
  columns: z.array(zeroTableColumnSchema).default([]),
177
+ indexes: z.array(zeroTableIndexSchema).default([]),
227
178
  })
228
- .strict();
179
+ .strict()
180
+ .superRefine((table, context) => {
181
+ const columnNames = new Set(table.columns.map((column) => column.name));
182
+ const indexNames = new Set();
183
+ for (const index of table.indexes) {
184
+ if (indexNames.has(index.name)) {
185
+ context.addIssue({
186
+ code: z.ZodIssueCode.custom,
187
+ message: `Zero table ${table.name} declares duplicate index ${index.name}.`,
188
+ path: ["indexes"],
189
+ });
190
+ }
191
+ indexNames.add(index.name);
192
+ for (const field of index.fields) {
193
+ if (!columnNames.has(field)) {
194
+ context.addIssue({
195
+ code: z.ZodIssueCode.custom,
196
+ message: `Zero index ${table.name}.${index.name} references unknown field ${field}.`,
197
+ path: ["indexes"],
198
+ });
199
+ }
200
+ }
201
+ }
202
+ });
229
203
  export const zeroDatabaseSchema = z.record(z.string(), zeroTableSchema);
230
- const zeroSha256Schema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
231
- const zeroBase64Schema = z
232
- .string()
233
- .regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);
234
- export const zeroRuntimeBundleSchema = z
235
- .object({
236
- path: z
237
- .string()
238
- .min(1)
239
- .startsWith(`${ZERO_RUNTIME_BUNDLE_ROOT}/`)
240
- .refine((bundlePath) => !bundlePath.split("/").includes(".."), {
241
- message: "Zero bundle paths cannot traverse outside the runtime bundle root.",
242
- }),
243
- sha256: zeroSha256Schema,
244
- size: z.number().int().nonnegative().max(ZERO_RUNTIME_BUNDLE_MAX_BYTES),
245
- contentBase64: zeroBase64Schema,
246
- })
247
- .strict();
248
- const zeroPublicStaticPathSchema = z
249
- .string()
250
- .min(1)
251
- .max(2048)
252
- .refine((path) => !path.startsWith("/") && !path.split("/").includes(".."), {
253
- message: "Zero static file paths must be relative and cannot traverse.",
254
- })
255
- .refine((path) => !path.startsWith(ZERO_RUNTIME_STORAGE_ROOT + "/"), {
256
- message: `Zero static files cannot use ${ZERO_RUNTIME_STORAGE_ROOT}.`,
257
- })
258
- .refine((path) => !path.startsWith("_") && !path.startsWith("."), {
259
- message: "Zero static file paths cannot use private root prefixes.",
204
+ const zeroSha256Schema = executionSha256Schema;
205
+ /**
206
+ * Zero's bundles travel inline in the finalize payload — a capsule's compiled
207
+ * client and server fit comfortably under the ceiling, and inlining keeps the
208
+ * whole version one atomic write. Functions bundles do the opposite and land
209
+ * in the content store first; see `functionsBundleRefSchema`.
210
+ */
211
+ export const zeroRuntimeBundleSchema = executionBundleSchema({
212
+ bundleRoot: ZERO_RUNTIME_BUNDLE_ROOT,
213
+ maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
214
+ });
215
+ export const zeroRuntimeStaticFileSchema = executionStaticFileSchema({
216
+ storageRoot: ZERO_RUNTIME_STORAGE_ROOT,
217
+ maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
260
218
  });
261
- export const zeroRuntimeStaticFileSchema = z
262
- .object({
263
- path: zeroPublicStaticPathSchema,
264
- contentType: z.string().min(1).max(255),
265
- sha256: zeroSha256Schema,
266
- size: z.number().int().nonnegative().max(ZERO_RUNTIME_BUNDLE_MAX_BYTES),
267
- contentBase64: zeroBase64Schema,
268
- })
269
- .strict();
270
219
  export const zeroRuntimeRunSourceSchema = z
271
220
  .object({
272
221
  runId: z.string().min(1).max(256),
@@ -275,23 +224,13 @@ export const zeroRuntimeRunSourceSchema = z
275
224
  .min(1)
276
225
  .max(2 * 1024 * 1024),
277
226
  schemaHash: z.string().min(1).max(256).optional(),
278
- capabilities: z
279
- .object({
280
- db: z.boolean().default(false),
281
- fetch: z.boolean().default(false),
282
- auth: z.boolean().default(false),
283
- env: z.boolean().default(false),
284
- realtime: z.boolean().default(false),
285
- logging: z.boolean().default(false),
286
- })
287
- .partial()
288
- .default({}),
227
+ capabilities: executionCapabilitiesSchema,
289
228
  db: z.record(z.string(), z.unknown()).optional(),
290
229
  })
291
230
  .strict();
292
231
  export const zeroRuntimeEndpointSourceSchema = z
293
232
  .object({
294
- method: zeroHttpMethodSchema,
233
+ method: httpMethodSchema,
295
234
  path: zeroRoutePathSchema,
296
235
  endpointId: z.string().min(1).max(256),
297
236
  source: z
@@ -321,10 +260,19 @@ export const zeroMigrationOperationSchema = z.discriminatedUnion("op", [
321
260
  .object({
322
261
  op: z.literal("add_index"),
323
262
  table: zeroNameSchema,
263
+ name: zeroNameSchema,
324
264
  columns: z.array(zeroNameSchema).min(1),
325
265
  unique: z.boolean().default(false),
326
266
  })
327
267
  .strict(),
268
+ z
269
+ .object({
270
+ op: z.literal("drop_index"),
271
+ table: zeroNameSchema,
272
+ name: zeroNameSchema,
273
+ explicit: z.literal("drop"),
274
+ })
275
+ .strict(),
328
276
  z
329
277
  .object({
330
278
  op: z.literal("drop_table"),
@@ -366,16 +314,7 @@ export const zeroMigrationPlanSchema = z
366
314
  operations: z.array(zeroMigrationOperationSchema),
367
315
  })
368
316
  .strict();
369
- const zeroRealtimeCanonicalModeSchema = z.enum(["stattic-central", "spacefast-cast", "local-dev"]);
370
- const zeroRuntimePublicRealtimeCanonicalModeSchema = z.enum([
371
- "stattic-central",
372
- "spacefast-cast",
373
- "local-dev",
374
- "local-websocket",
375
- ]);
376
- export const zeroRealtimeModeSchema = zeroRealtimeCanonicalModeSchema;
377
- export const zeroRuntimePublicRealtimeModeSchema = zeroRuntimePublicRealtimeCanonicalModeSchema;
378
- export const zeroInspectPolicySchema = z.enum(["private", "public"]);
317
+ export const zeroInspectPolicySchema = executionInspectPolicySchema;
379
318
  const zeroRuntimePublicPathSchema = z.string().min(1).startsWith("/");
380
319
  const zeroHttpUrlSchema = z
381
320
  .string()
@@ -393,7 +332,7 @@ const zeroRealtimeUrlSchema = z
393
332
  }, { message: "Realtime URL must use http, https, ws, or wss." });
394
333
  export const zeroRuntimePublicAuthConfigSchema = z
395
334
  .object({
396
- provider: z.literal("wpcom").default("wpcom"),
335
+ provider: z.literal("gravatar").default("gravatar"),
397
336
  signInPath: zeroRuntimePublicPathSchema.nullable().default(null),
398
337
  signInUrl: zeroHttpUrlSchema.nullable().default(null),
399
338
  signOutPath: zeroRuntimePublicPathSchema.nullable().default(null),
@@ -403,7 +342,7 @@ export const zeroRuntimePublicAuthConfigSchema = z
403
342
  .strict();
404
343
  export const zeroRuntimePublicRealtimeConfigSchema = z
405
344
  .object({
406
- mode: zeroRuntimePublicRealtimeModeSchema,
345
+ mode: runtimeRealtimeModeSchema,
407
346
  centralUrl: zeroRealtimeUrlSchema.nullable().default(null),
408
347
  path: zeroRuntimePublicPathSchema.optional(),
409
348
  replayPath: zeroRuntimePublicPathSchema.nullable().optional(),
@@ -411,6 +350,7 @@ export const zeroRuntimePublicRealtimeConfigSchema = z
411
350
  runPath: zeroRuntimePublicPathSchema.nullable().optional(),
412
351
  runUrl: zeroHttpUrlSchema.nullable().optional(),
413
352
  resourceKey: z.string().min(1).max(256).nullable().optional(),
353
+ ticketPath: zeroRuntimePublicPathSchema.nullable().optional(),
414
354
  socketPath: zeroRuntimePublicPathSchema.nullable().optional(),
415
355
  spaceId: z.string().min(1).nullable().optional(),
416
356
  versionId: z.string().min(1).nullable().optional(),
@@ -460,7 +400,7 @@ export const zeroRuntimeInstallProfileSchema = z
460
400
  .strict(),
461
401
  realtime: z
462
402
  .object({
463
- production: z.literal("stattic-central"),
403
+ production: z.literal("central"),
464
404
  local: z.literal("foreground-cli-ws"),
465
405
  })
466
406
  .strict(),
@@ -489,42 +429,23 @@ export const zeroSourceFileSchema = z
489
429
  .strict();
490
430
  export const zeroSourceManifestSchema = z
491
431
  .object({
432
+ // Declared in `sf.jsonc#runtime`, so the manifest records what the author
433
+ // named rather than a layout the builder assumed.
492
434
  entries: z
493
435
  .object({
494
- client: z.literal(ZERO_CLIENT_ENTRY),
495
- server: z.literal(ZERO_SERVER_ENTRY),
436
+ client: z.string().min(1),
437
+ server: z.string().min(1),
496
438
  })
497
439
  .strict(),
498
440
  sourceRoot: z.string().min(1),
499
441
  files: z.array(zeroSourceFileSchema).default([]),
500
442
  env: z
501
443
  .object({
502
- file: z.literal(ZERO_SOURCE_ENV_FILE),
503
- names: z.array(zeroEnvNameSchema).max(ZERO_ENV_MAX_KEYS).default([]),
444
+ file: z.enum([SERVER_ENV_FILE, LAKEBED_SERVER_ENV_FILE]),
445
+ names: z.array(executionEnvNameSchema).max(EXECUTION_ENV_MAX_KEYS).default([]),
504
446
  })
505
447
  .nullable()
506
448
  .default(null),
507
- sourceConfig: z
508
- .object({
509
- configFile: z
510
- .object({
511
- path: z.literal(ZERO_CONFIG_FILE),
512
- appName: z.string().nullable().default(null),
513
- deployId: z.string().nullable().default(null),
514
- name: z.string().nullable().default(null),
515
- title: z.string().nullable().default(null),
516
- })
517
- .nullable()
518
- .default(null),
519
- deployFile: z
520
- .object({
521
- path: z.literal(ZERO_DEPLOY_FILE),
522
- keys: z.array(z.string()).default([]),
523
- })
524
- .nullable()
525
- .default(null),
526
- })
527
- .default({ configFile: null, deployFile: null }),
528
449
  })
529
450
  .strict();
530
451
  export const zeroCapsuleArtifactSchema = z
@@ -544,6 +465,7 @@ export const zeroCapsuleArtifactSchema = z
544
465
  schema: zeroDatabaseSchema.default({}),
545
466
  queries: z.array(zeroNameSchema).default([]),
546
467
  mutations: z.array(zeroNameSchema).default([]),
468
+ actions: z.array(zeroNameSchema).default([]),
547
469
  endpoints: z.array(zeroEndpointSchema).default([]),
548
470
  sockets: z.array(zeroNameSchema).default([]),
549
471
  })
@@ -556,7 +478,7 @@ export const zeroCapsuleArtifactSchema = z
556
478
  .strict(),
557
479
  realtime: z
558
480
  .object({
559
- mode: zeroRealtimeModeSchema,
481
+ mode: runtimeRealtimeModeSchema,
560
482
  mutationEvents: z.boolean().default(true),
561
483
  })
562
484
  .strict(),
@@ -583,7 +505,7 @@ export const zeroRuntimeFinalizePayloadSchema = z
583
505
  .strict(),
584
506
  realtime: z
585
507
  .object({
586
- mode: zeroRealtimeModeSchema,
508
+ mode: runtimeRealtimeModeSchema,
587
509
  centralUrl: zeroRealtimeUrlSchema.nullable().default(null),
588
510
  replayUrl: zeroHttpUrlSchema.nullable().default(null),
589
511
  castResourceKey: z.string().min(1).max(256).nullable().optional(),
@@ -598,7 +520,7 @@ export const zeroRuntimeFinalizePayloadSchema = z
598
520
  .strict(),
599
521
  auth: z
600
522
  .object({
601
- provider: z.literal("wpcom").default("wpcom"),
523
+ provider: z.literal("gravatar").default("gravatar"),
602
524
  signInPath: z.literal(ZERO_RUNTIME_ROUTE_PATHS.authStart).nullable().default(null),
603
525
  signInUrl: zeroHttpUrlSchema.nullable().default(null),
604
526
  signOutPath: z.literal(ZERO_RUNTIME_ROUTE_PATHS.authSignOut).nullable().default(null),
@@ -607,7 +529,7 @@ export const zeroRuntimeFinalizePayloadSchema = z
607
529
  })
608
530
  .strict()
609
531
  .default({
610
- provider: "wpcom",
532
+ provider: "gravatar",
611
533
  signInPath: null,
612
534
  signInUrl: null,
613
535
  signOutPath: null,
@@ -635,6 +557,7 @@ export const zeroRuntimeConfigSchema = zeroRuntimeFinalizePayloadSchema
635
557
  })
636
558
  .extend({
637
559
  variableValues: z.record(z.string(), z.string()).default({}),
560
+ databaseUrlSource: z.enum(["application", "provider"]).default("application"),
638
561
  })
639
562
  .strict();
640
563
  export const zeroDeployMetadataSchema = z
@@ -643,101 +566,61 @@ export const zeroDeployMetadataSchema = z
643
566
  finalize: zeroRuntimeFinalizePayloadSchema,
644
567
  })
645
568
  .strict();
646
- export const zeroInspectResponseSchema = z
569
+ /**
570
+ * What a live Zero capsule is, as the `app` member of a space's runtime status.
571
+ *
572
+ * There is no `versionId` here: this only ever describes the version the status
573
+ * response already names as live, and repeating it would invite the two to
574
+ * disagree. `artifactId` stays because it identifies the built capsule rather
575
+ * than the publish that carries it.
576
+ *
577
+ * Every field is derived from the version's own finalize metadata, which is
578
+ * what makes this safe to answer for a space whose runtime is asleep,
579
+ * mid-move, or failing: nothing here costs a call to the space's origin. It is
580
+ * also why there are no counts of things listed here — a caller that wants
581
+ * `tables.length` can take it — and why the database is not a field: a capsule
582
+ * always owns one, so `runtimeKind: "zero"` already said so.
583
+ */
584
+ export const zeroAppSchema = z
647
585
  .object({
648
- versionId: z.string().min(1).nullable(),
649
- artifactId: z.string().min(1).nullable(),
650
- data: z
586
+ runtimeKind: z.literal(ZERO_RUNTIME_KIND),
587
+ artifactId: z.string().min(1),
588
+ appName: z.string().min(1),
589
+ serverRuntime: z.literal("quickjs-rust"),
590
+ inspect: z
651
591
  .object({
652
- runtimeKind: z.literal(ZERO_RUNTIME_KIND),
653
- appName: z.string().min(1),
654
- serverRuntime: z.literal("quickjs-rust"),
655
- inspect: z
656
- .object({
657
- policy: zeroInspectPolicySchema,
658
- })
659
- .strict(),
660
- install: zeroRuntimeInstallProfileSchema,
661
- tables: z.array(z.string()).default([]),
662
- queries: z.array(z.string()).default([]),
663
- mutations: z.array(z.string()).default([]),
664
- endpoints: z.array(zeroEndpointSchema).default([]),
665
- sockets: z.array(z.string()).default([]),
666
- variables: z
667
- .object({
668
- source: z.literal("stattic-variables"),
669
- names: z.array(z.string()).default([]),
670
- })
671
- .strict(),
672
- realtime: zeroRuntimePublicRealtimeConfigSchema,
592
+ policy: zeroInspectPolicySchema,
673
593
  })
674
- .nullable(),
675
- })
676
- .strict();
677
- export const zeroInspectPublicResponseSchema = dataEnvelope(zeroInspectResponseSchema);
678
- export const zeroDbInspectResponseSchema = z
679
- .object({
680
- versionId: z.string().min(1).nullable(),
681
- artifactId: z.string().min(1).nullable(),
682
- backend: z.literal("wpcloud-mysql").nullable(),
683
- migrationMode: z.enum(["safe", "drop", "rename"]).nullable(),
684
- schemaHash: zeroSha256Schema.nullable(),
685
- tables: z.array(zeroTableSchema).default([]),
686
- migrations: z.array(zeroMigrationOperationSchema).default([]),
687
- })
688
- .strict();
689
- export const zeroDbInspectPublicResponseSchema = dataEnvelope(zeroDbInspectResponseSchema);
690
- export const zeroDbDumpQuerySchema = z
691
- .object({
692
- table: zeroNameSchema.optional(),
693
- limit: z.coerce.number().int().min(1).max(100).default(25),
694
- })
695
- .strict();
696
- export const zeroDbDumpTableSchema = z
697
- .object({
698
- name: zeroNameSchema,
699
- rows: z.array(z.record(z.string(), z.unknown())).default([]),
700
- })
701
- .strict();
702
- export const zeroDbDumpResponseSchema = z
703
- .object({
704
- versionId: z.string().min(1).nullable(),
705
- artifactId: z.string().min(1).nullable(),
594
+ .strict(),
595
+ install: zeroRuntimeInstallProfileSchema,
596
+ tables: z.array(z.string()).default([]),
597
+ queries: z.array(z.string()).default([]),
598
+ mutations: z.array(z.string()).default([]),
599
+ actions: z.array(z.string()).default([]),
600
+ endpoints: z.array(zeroEndpointSchema).default([]),
601
+ sockets: z.array(z.string()).default([]),
602
+ /**
603
+ * Migrations are operations, not names — `create_table`, `add_column` and
604
+ * friends — so a count is the honest summary here. The operations
605
+ * themselves are the database surface's answer (`GET /v1/spaces/{id}/db`).
606
+ */
607
+ migrationCount: z.number().int().nonnegative(),
608
+ /** Digest of the schema the live migration plan settled on, if it ran one. */
706
609
  schemaHash: zeroSha256Schema.nullable(),
707
- tables: z.array(zeroDbDumpTableSchema).default([]),
708
- })
709
- .strict();
710
- export const zeroDbDumpPublicResponseSchema = dataEnvelope(zeroDbDumpResponseSchema);
711
- export const zeroLogListQuerySchema = z
712
- .object({
713
- limit: z.coerce.number().int().min(1).max(100).default(50),
714
- cursor: z.string().min(1).optional(),
715
- requestId: z.string().min(1).optional(),
716
- mutationName: z.string().min(1).optional(),
717
- })
718
- .strict();
719
- export const zeroLogEntrySchema = z
720
- .object({
721
- id: z.string().min(1),
722
- timestamp: z.string().datetime(),
723
- level: z.enum(["debug", "info", "warn", "error"]),
724
- requestId: z.string().min(1).nullable(),
725
- versionId: z.string().min(1).nullable(),
726
- mutationName: z.string().min(1).nullable(),
727
- message: z.string(),
728
- metadata: z.record(z.string(), z.unknown()).default({}),
729
- })
730
- .strict();
731
- export const zeroLogListResponseSchema = z
732
- .object({
733
- data: z.array(zeroLogEntrySchema),
734
- pagination: z
610
+ variables: z
735
611
  .object({
736
- nextCursor: z.string().nullable(),
612
+ source: z.literal("stattic-variables"),
613
+ names: z.array(z.string()).default([]),
737
614
  })
738
615
  .strict(),
616
+ realtime: zeroRuntimePublicRealtimeConfigSchema,
739
617
  })
740
618
  .strict();
619
+ // Both products emit the same log shape; `handlerName` carries the mutation
620
+ // name here and the worker handler name on Functions.
621
+ export const zeroLogListQuerySchema = executionLogListQuerySchema;
622
+ export const zeroLogEntrySchema = executionLogEntrySchema;
623
+ export const zeroLogListResponseSchema = executionLogListResponseSchema;
741
624
  export const zeroRealtimeEventIntakeResponseSchema = z
742
625
  .object({
743
626
  accepted: z.literal(true),
@@ -746,22 +629,6 @@ export const zeroRealtimeEventIntakeResponseSchema = z
746
629
  duplicate: z.boolean().default(false),
747
630
  })
748
631
  .strict();
749
- export const zeroRealtimeEventListQuerySchema = z
750
- .object({
751
- afterEventId: z.string().min(1).optional(),
752
- limit: z.coerce.number().int().min(1).max(100).default(50),
753
- })
754
- .strict();
755
- export const zeroRealtimeEventListResponseSchema = z
756
- .object({
757
- data: z.array(zeroRealtimeEventSchema),
758
- pagination: z
759
- .object({
760
- nextCursor: z.string().min(1).nullable(),
761
- })
762
- .strict(),
763
- })
764
- .strict();
765
632
  export const zeroLocalDevPlanSchema = z
766
633
  .object({
767
634
  runtimeKind: z.literal(ZERO_RUNTIME_KIND),
@@ -792,6 +659,7 @@ export function createZeroCapsuleArtifact(input) {
792
659
  schema: input.schema ?? {},
793
660
  queries: input.queries ?? [],
794
661
  mutations: input.mutations ?? [],
662
+ actions: input.actions ?? [],
795
663
  endpoints: input.endpoints ?? [],
796
664
  sockets: input.sockets ?? [],
797
665
  },
@@ -800,7 +668,7 @@ export function createZeroCapsuleArtifact(input) {
800
668
  migrations: [],
801
669
  },
802
670
  realtime: {
803
- mode: input.realtimeMode ?? "stattic-central",
671
+ mode: input.realtimeMode ?? "central",
804
672
  mutationEvents: true,
805
673
  },
806
674
  limits: {},
@@ -840,7 +708,7 @@ export function createZeroRuntimeInstallProfile(input) {
840
708
  blockIncompatibleRollback: true,
841
709
  },
842
710
  realtime: {
843
- production: "stattic-central",
711
+ production: "central",
844
712
  local: "foreground-cli-ws",
845
713
  },
846
714
  });