@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,11 +1,12 @@
1
1
  // Error reference content (internal-docs/platform.md "Global API Conventions"):
2
- // every error envelope `docsUrl` points at `https://spacefast.com/docs/errors/{code}`,
2
+ // every problem document `type` points at `https://spacefast.com/docs/errors/{code}`,
3
3
  // and those pages are GENERATED from this table — one entry per member of
4
4
  // `ERROR_CODES`, asserted complete by the conformance suite so links never rot
5
5
  // and pages never go missing. apps/www renders the HTML pages and writes the
6
6
  // `.md` twins from the same entries.
7
7
  import { BRAND } from "../brand.js";
8
- import { errorDocsUrl } from "../contracts/error-codes.js";
8
+ import { serviceOrigin } from "../config/domains.js";
9
+ import { errorDocsUrl, errorTitle, PROBLEM_CONTENT_TYPE, } from "../contracts/error-codes.js";
9
10
  // Restore upgrade-oriented recovery copy here when paid plan checkout is live.
10
11
  export const ERROR_DOCS = {
11
12
  abuse_report_invalid_transition: {
@@ -30,15 +31,15 @@ export const ERROR_DOCS = {
30
31
  },
31
32
  agent_handoff_declined: {
32
33
  summary: "The app-private agent handoff cannot be redeemed.",
33
- fix: "Ask the user to create a fresh handoff for this Space and client, then redeem that new link once.",
34
+ fix: "Ask the user to create a fresh handoff for this space and client, then redeem that new link once.",
34
35
  },
35
36
  agent_handoff_limit_reached: {
36
- summary: "This user already has the maximum number of pending handoffs for the Space.",
37
- fix: "Redeem or revoke an existing pending handoff for the Space before creating another.",
37
+ summary: "This user already has the maximum number of pending handoffs for the space.",
38
+ fix: "Redeem or revoke an existing pending handoff for the space before creating another.",
38
39
  },
39
40
  agent_handoff_origin_unsupported: {
40
41
  summary: "The dashboard origin this deployment is configured with cannot mint canonical agent handoff links.",
41
- fix: "Point SPACEFAST_DASHBOARD_URL at a valid HTTP(S) origin; if you cannot change it, contact support.",
42
+ fix: "Point SPACEFAST_DASHBOARD_URL at a valid HTTP(S) origin. If you cannot change it, contact support.",
42
43
  },
43
44
  ambiguous_space_slug: {
44
45
  summary: "The slug matches spaces in more than one of your teams, so it cannot be resolved.",
@@ -46,11 +47,11 @@ export const ERROR_DOCS = {
46
47
  },
47
48
  anonymous_expired: {
48
49
  summary: "This anonymous space expired before it was claimed.",
49
- fix: "Publish a fresh space and share its claim link right away this time. If you meant to update a space that is still live, check .spacefast/ (or your saved receipt) for its spaceId and publish to that with its credential instead of creating a new space.",
50
+ fix: "Publish a fresh space and share its claim link right away this time. If you meant to update a live space, check .spacefast/ (or your saved receipt) for its spaceId. Publish to that space with its credential instead of creating a new space.",
50
51
  },
51
52
  anonymous_pool_unavailable: {
52
53
  summary: "No pooled capacity is available for anonymous publishes right now.",
53
- fix: "Retry shortly; capacity replenishes automatically.",
54
+ fix: "Retry shortly. Capacity replenishes automatically.",
54
55
  },
55
56
  anonymous_publish_rate_limited: {
56
57
  summary: "Too many anonymous publishes came from this network in a short window.",
@@ -61,8 +62,8 @@ export const ERROR_DOCS = {
61
62
  fix: "Log in to publish into an authenticated space, or claim/delete an existing anonymous space before creating another.",
62
63
  },
63
64
  api_key_scope_underivable: {
64
- summary: "A concrete access policy could not be derived from the requested scope and permissions.",
65
- fix: "Point scope at a resource you can already reach (an existing space owned by a team) and request permissions your credential already has.",
65
+ summary: "A concrete access policy cannot be derived from the requested scope and permissions.",
66
+ fix: "Point scope at a resource you can already reach (an existing space owned by a team). Request only permissions your credential already has.",
66
67
  },
67
68
  archive_body_required: {
68
69
  summary: "This request must carry an archive body but none was provided.",
@@ -77,12 +78,12 @@ export const ERROR_DOCS = {
77
78
  fix: "Pass the code returned by the authorization step.",
78
79
  },
79
80
  authorization_pending: {
80
- summary: "The device login has not been approved yet.",
81
+ summary: "The device login is not approved yet.",
81
82
  fix: "Keep polling at the advised interval until the user approves the request.",
82
83
  },
83
84
  billing_receipt_invalid: {
84
- summary: "The store receipt or notification could not be verified with the payment provider.",
85
- fix: "Re-check the transaction id or purchase token and retry; contact support if it persists.",
85
+ summary: "The store receipt or notification cannot be verified with the payment provider.",
86
+ fix: "Re-check the transaction id or purchase token and retry. Contact support if it persists.",
86
87
  },
87
88
  billing_receipt_not_bound_to_team: {
88
89
  summary: "The store purchase was made under a different account token than this team's.",
@@ -101,7 +102,7 @@ export const ERROR_DOCS = {
101
102
  fix: "Check the product id against the store catalog returned by the billing endpoints.",
102
103
  },
103
104
  build_command_missing: {
104
- summary: "A build or install command could not be found during the build run.",
105
+ summary: "A build or install command cannot be found during the build run.",
105
106
  fix: "Check the command spelling and ensure its tool is declared in package.json or available in the build image.",
106
107
  },
107
108
  build_execution_unavailable: {
@@ -118,10 +119,10 @@ export const ERROR_DOCS = {
118
119
  },
119
120
  build_no_index_html: {
120
121
  summary: "The build produced output but no index.html at the site root.",
121
- fix: "Make sure your build writes an index.html to the output directory, or point the output directory at the folder that contains it.",
122
+ fix: "Ensure your build writes an index.html to the output directory. Otherwise point the output directory at the folder that contains index.html.",
122
123
  },
123
124
  build_not_created: {
124
- summary: "The build could not be created.",
125
+ summary: "The build cannot be created.",
125
126
  fix: "Verify the build request payload and retry.",
126
127
  },
127
128
  build_oom: {
@@ -146,7 +147,7 @@ export const ERROR_DOCS = {
146
147
  },
147
148
  channel_name_reserved: {
148
149
  summary: "The channel name collides with a reserved hostname suffix and cannot be used.",
149
- fix: "Choose a different channel name; v-prefixed numeric names and ver- prefixes are reserved.",
150
+ fix: "Choose a different channel name. V-prefixed numeric names and ver- prefixes are reserved.",
150
151
  },
151
152
  channel_pointer_moved: {
152
153
  summary: "The channel was promoted to a different version since you read it.",
@@ -173,13 +174,17 @@ export const ERROR_DOCS = {
173
174
  fix: "Upgrade the CLI to the latest release and retry.",
174
175
  },
175
176
  comment_screenshot_rate_limited: {
176
- summary: "Too many anonymous comment screenshot uploads were attempted.",
177
+ summary: "Too many comment screenshot uploads were attempted.",
177
178
  fix: "Wait for the one-minute window to reset, then retry the screenshot upload.",
178
179
  },
179
180
  config_file_too_large: {
180
181
  summary: "The sf.jsonc configuration file exceeds the maximum size.",
181
182
  fix: "Keep the configuration file under the documented size limit (256 KB).",
182
183
  },
184
+ config_functions_key_removed: {
185
+ summary: "The sf.jsonc configuration still uses the removed top-level functions key.",
186
+ fix: 'Replace the functions block with a runtime block: set runtime.kind to "functions" and move entry, compatibilityDate, and database under it.',
187
+ },
183
188
  config_invalid: {
184
189
  summary: "The space configuration failed validation.",
185
190
  fix: "Fix the reported fields against the published schema at /schemas/sf.json.",
@@ -188,20 +193,32 @@ export const ERROR_DOCS = {
188
193
  summary: "A meta field in the space configuration exceeds its maximum length.",
189
194
  fix: "Shorten the meta title, description, or other reported field.",
190
195
  },
196
+ config_name_too_long: {
197
+ summary: "The name in the space configuration exceeds its maximum length.",
198
+ fix: "Shorten the name in sf.jsonc to 255 characters or fewer.",
199
+ },
200
+ config_runtime_entry_missing: {
201
+ summary: "The declared runtime has no entry module to compile.",
202
+ fix: "Name the entry in sf.jsonc: runtime.entry for functions, runtime.server and runtime.client for zero. Remove the runtime block to publish static files instead.",
203
+ },
204
+ config_runtime_invalid_kind: {
205
+ summary: "The runtime block in the space configuration declares an unknown kind.",
206
+ fix: 'Set runtime.kind to "zero" or "functions" in sf.jsonc.',
207
+ },
191
208
  config_templates_over_limit: {
192
209
  summary: "The configuration declares more template files than the plan allows.",
193
210
  fix: "Reduce the number of template entries in sf.jsonc. Still stuck? POST /v1/feedback with the error code and request id.",
194
211
  },
195
212
  continuation_unavailable: {
196
- summary: "This claim token can no longer be exchanged for an access token.",
197
- fix: "If the space is claimed, ask its owner for an access token (dashboard: Account → Access tokens). If it is still unclaimed, keep using the claim token as bearer auth instead of exchanging it. Still stuck? POST /v1/feedback with the error code and request id.",
213
+ summary: "This claim token can no longer be exchanged for an API key.",
214
+ fix: "If the space is claimed, ask its owner for an API key (dashboard: Account → API keys). If it is still unclaimed, keep using the claim token as bearer auth instead of exchanging it. Still stuck? POST /v1/feedback with the error code and request id.",
198
215
  },
199
216
  continuation_used: {
200
- summary: "This claim token was already exchanged for a durable access token.",
201
- fix: "Authenticate with the exchanged access token (check .spacefast/state.json or wherever it was saved). If it was lost, ask the space owner to mint a new access token.",
217
+ summary: "This claim token was already exchanged for a durable API key.",
218
+ fix: "Authenticate with the exchanged API key (check .spacefast/state.json or wherever it was saved). If it was lost, ask the space owner to create a new API key.",
202
219
  },
203
220
  credential_expired: {
204
- summary: "The credential used for this request has expired.",
221
+ summary: "The credential used for this request is expired.",
205
222
  fix: "Create a new API key or sign in again.",
206
223
  },
207
224
  credential_not_yet_valid: {
@@ -218,7 +235,7 @@ export const ERROR_DOCS = {
218
235
  },
219
236
  csam_blocked: {
220
237
  summary: "The content was blocked because it matched known child sexual abuse material.",
221
- fix: "This action is final and reported as required by law; do not retry.",
238
+ fix: "This action is final and reported as required by law. Do not retry.",
222
239
  },
223
240
  csam_policy_floor: {
224
241
  summary: "CSAM enforcement policy cannot be set below the mandatory account-suspend floor.",
@@ -232,6 +249,10 @@ export const ERROR_DOCS = {
232
249
  summary: "This request tried to change data location through an immutable path.",
233
250
  fix: "Data location is fixed when the space is created and cannot be changed afterwards. Create a new space in the region you want.",
234
251
  },
252
+ db_not_available: {
253
+ summary: "The live version has no database to read.",
254
+ fix: 'Publish a Zero app, or declare `"database": true` under `runtime` in sf.jsonc for a Functions app.',
255
+ },
235
256
  device_authorization_failed: {
236
257
  summary: "The device login request failed and cannot be completed.",
237
258
  fix: "Start a new device login flow.",
@@ -249,7 +270,7 @@ export const ERROR_DOCS = {
249
270
  fix: "Follow the capability rule in the error details and submit only the compatible fields.",
250
271
  },
251
272
  dns_import_partial_visibility: {
252
- summary: "The DNS import could not see the full zone, so importing would lose records.",
273
+ summary: "The DNS import cannot see the full zone, so importing would lose records.",
253
274
  fix: "Verify delegation and retry once the full zone is visible.",
254
275
  },
255
276
  dns_provider_auth_expired: {
@@ -281,7 +302,7 @@ export const ERROR_DOCS = {
281
302
  fix: "Use the provider workflow template or primary-domain action for this provider-managed zone.",
282
303
  },
283
304
  dns_provider_credentials_expired: {
284
- summary: "The DNS provider credentials have expired or were revoked.",
305
+ summary: "The DNS provider credentials are expired or revoked.",
285
306
  fix: "Reconnect the provider account or replace the API token.",
286
307
  },
287
308
  dns_provider_feature_descriptors: {
@@ -337,8 +358,8 @@ export const ERROR_DOCS = {
337
358
  fix: "Refresh the provider snapshot, review the new diff, and retry the change against the latest record ids.",
338
359
  },
339
360
  dns_provider_snapshot_unavailable: {
340
- summary: `${BRAND.productName} could not cache the latest DNS provider snapshot.`,
341
- fix: "Retry refresh after the cache or provider recovers; do not edit connected-provider records from stale data.",
361
+ summary: `${BRAND.productName} cannot cache the latest DNS provider snapshot.`,
362
+ fix: "Retry refresh after the cache or provider recovers. Do not edit connected-provider records from stale data.",
342
363
  },
343
364
  dns_provider_temporarily_unavailable: {
344
365
  summary: "The DNS provider is rate-limited, degraded, or temporarily unavailable.",
@@ -357,12 +378,12 @@ export const ERROR_DOCS = {
357
378
  fix: "Preview and run the advertised template so provider-specific side effects and receipts are captured.",
358
379
  },
359
380
  dns_provider_zone_not_found: {
360
- summary: "The connected DNS provider zone could not be found.",
381
+ summary: "The connected DNS provider zone cannot be found.",
361
382
  fix: "Refresh the provider account, reattach the zone, or reconnect the provider.",
362
383
  },
363
384
  dns_record_conflicts_with_managed: {
364
385
  summary: `The DNS change conflicts with a record ${BRAND.productName} manages for this domain.`,
365
- fix: "Remove or adjust the conflicting record; managed records cannot be overridden.",
386
+ fix: "Remove or adjust the conflicting record. Managed records cannot be overridden.",
366
387
  },
367
388
  dns_record_managed: {
368
389
  summary: `This DNS record is managed by ${BRAND.productName} and cannot be edited directly.`,
@@ -382,7 +403,7 @@ export const ERROR_DOCS = {
382
403
  },
383
404
  domain_facet_already_managed: {
384
405
  summary: `This facet of the domain is already managed by ${BRAND.productName}.`,
385
- fix: "No action is needed; the facet is already active.",
406
+ fix: "No action is needed. The facet is already active.",
386
407
  },
387
408
  domain_facet_external: {
388
409
  summary: `This facet of the domain is managed outside ${BRAND.productName}.`,
@@ -422,7 +443,7 @@ export const ERROR_DOCS = {
422
443
  },
423
444
  domain_reserved_suffix: {
424
445
  summary: `The hostname is under a ${BRAND.productName}-managed suffix and cannot be added as a domain.`,
425
- fix: `Use a domain you own; ${BRAND.productName} default and management hostnames are assigned automatically.`,
446
+ fix: `Use a domain you own. ${BRAND.productName} assigns default and management hostnames automatically.`,
426
447
  },
427
448
  domain_transfer_active: {
428
449
  summary: "The domain has a transfer in progress, which blocks this operation.",
@@ -449,7 +470,7 @@ export const ERROR_DOCS = {
449
470
  fix: "Adjust the category ranges so each severity is covered by at most one policy.",
450
471
  },
451
472
  expired_token: {
452
- summary: "The token has expired.",
473
+ summary: "The token is expired.",
453
474
  fix: "Request a new token and retry.",
454
475
  },
455
476
  export_archive_not_ready: {
@@ -476,37 +497,29 @@ export const ERROR_DOCS = {
476
497
  summary: "Proxy routes to external upstreams are not available on the Free plan.",
477
498
  fix: "Remove the proxy rules before publishing. Still stuck? POST /v1/feedback with the error code and request id.",
478
499
  },
479
- free_headers_basic_auth_disabled: {
480
- summary: "Basic-Auth via _headers is not available on the Free plan.",
481
- fix: "Use space password protection instead. Still stuck? POST /v1/feedback with the error code and request id.",
482
- },
483
500
  google_play_webhook_identity_not_configured: {
484
501
  summary: "Google Play Pub/Sub push authentication is not configured on this deployment.",
485
502
  fix: "Configure the exact push audience and dedicated Pub/Sub service-account email before enabling RTDN delivery.",
486
503
  },
487
504
  idempotency_conflict_in_progress: {
488
505
  summary: "Another request with the same Idempotency-Key is still in flight.",
489
- fix: "Wait for the original request to finish; its response will be replayed.",
506
+ fix: "Wait for the original request to finish. Its response will be replayed.",
490
507
  },
491
508
  idempotency_key_reused: {
492
509
  summary: "The Idempotency-Key was reused with a different request body.",
493
- fix: "Use a fresh key for new requests; keys bind to one exact request body.",
494
- },
495
- immutable_version_requires_login: {
496
- summary: "This immutable version URL is past its public window and now requires login.",
497
- fix: "Sign in to view it, or promote the version to a channel for public serving.",
510
+ fix: "Use a fresh key for new requests. Keys bind to one exact request body.",
498
511
  },
499
512
  import_archive_not_uploaded: {
500
513
  summary: "The import has no uploaded archive yet.",
501
514
  fix: "Upload the archive to the import's upload target, then finalize.",
502
515
  },
503
516
  import_not_cancelable: {
504
- summary: "The import has progressed past the point where it can be canceled.",
505
- fix: "Wait for the import to finish; completed imports can be deleted as versions.",
517
+ summary: "The import is past the point where it can be canceled.",
518
+ fix: "Wait for the import to finish. Completed imports can be deleted as versions.",
506
519
  },
507
520
  import_not_waiting_for_archive: {
508
521
  summary: "The import is not waiting for an archive upload.",
509
- fix: "Check the import status; the archive step may already be complete.",
522
+ fix: "Check the import status. If the archive step is complete, continue to the next step.",
510
523
  },
511
524
  incumbent_controls_dns: {
512
525
  summary: "Another team controls this domain's DNS, so the operation is blocked.",
@@ -522,7 +535,7 @@ export const ERROR_DOCS = {
522
535
  },
523
536
  internal_error: {
524
537
  summary: "Something went wrong on our side.",
525
- fix: "Retry the request; if it persists, contact support with the requestId.",
538
+ fix: "Retry the request. If it persists, contact support with the requestId.",
526
539
  },
527
540
  invalid_claim_token: {
528
541
  summary: "The claim token is invalid or does not match this space.",
@@ -537,7 +550,7 @@ export const ERROR_DOCS = {
537
550
  fix: "Pick a region from the documented data locations, or use auto.",
538
551
  },
539
552
  invalid_device_code: {
540
- summary: "The device code is invalid or has expired.",
553
+ summary: "The device code is invalid or expired.",
541
554
  fix: "Start a new device login flow.",
542
555
  },
543
556
  invalid_domain: {
@@ -561,11 +574,11 @@ export const ERROR_DOCS = {
561
574
  fix: "Restart the login flow to obtain a new grant.",
562
575
  },
563
576
  invalid_idempotency_key: {
564
- summary: "The Idempotency-Key header is missing, empty, or too long.",
565
- fix: "Send a non-empty Idempotency-Key header of at most 512 characters.",
577
+ summary: "The Idempotency-Key is missing or invalid, or an anonymous publish omitted its secret replay principal.",
578
+ fix: "Send a non-empty Idempotency-Key of at most 255 characters. Credential-free publish retries also need a stable, secret X-Spacefast-Idempotency-Principal containing 64 hexadecimal characters.",
566
579
  },
567
580
  invalid_publish_archive: {
568
- summary: "The uploaded archive could not be read as a valid zip.",
581
+ summary: "The uploaded archive cannot be read as a valid zip.",
569
582
  fix: "Re-create the archive as a standard zip and upload again.",
570
583
  },
571
584
  invalid_publish_path: {
@@ -578,7 +591,7 @@ export const ERROR_DOCS = {
578
591
  },
579
592
  invalid_request: {
580
593
  summary: "The request is malformed.",
581
- fix: "Fix the field referenced by param and details, then retry.",
594
+ fix: "Fix the field referenced by pointer and details, then retry.",
582
595
  },
583
596
  invalid_runtime_event: {
584
597
  summary: "The runtime event payload is not recognized.",
@@ -594,7 +607,7 @@ export const ERROR_DOCS = {
594
607
  },
595
608
  invalid_user_code: {
596
609
  summary: "The user code does not match a pending device login.",
597
- fix: "Enter the code exactly as shown by your CLI; codes expire after a few minutes.",
610
+ fix: "Enter the code exactly as shown by your CLI. Codes expire after a few minutes.",
598
611
  },
599
612
  invalid_version_path: {
600
613
  summary: "A file path in the version is not a valid space path.",
@@ -606,7 +619,7 @@ export const ERROR_DOCS = {
606
619
  },
607
620
  invalid_webhook_payload: {
608
621
  summary: "The webhook configuration payload is malformed.",
609
- fix: "Fix the field referenced by param and retry.",
622
+ fix: "Fix the field referenced by pointer and retry.",
610
623
  },
611
624
  invalid_webhook_signature: {
612
625
  summary: "The webhook signature did not verify.",
@@ -614,7 +627,7 @@ export const ERROR_DOCS = {
614
627
  },
615
628
  invalid_webhook_url: {
616
629
  summary: "The webhook URL is not an allowed public HTTPS endpoint.",
617
- fix: "Use a public HTTPS URL; private networks and link-local addresses are blocked.",
630
+ fix: "Use a public HTTPS URL. Private networks and link-local addresses are blocked.",
618
631
  },
619
632
  invalid_zero_realtime_event: {
620
633
  summary: "The Zero realtime event payload is malformed or scoped to the wrong space.",
@@ -633,7 +646,7 @@ export const ERROR_DOCS = {
633
646
  fix: "Sign in as the invited email, or ask an admin to invite your current address.",
634
647
  },
635
648
  invitation_expired: {
636
- summary: "The invitation has expired and can no longer be accepted.",
649
+ summary: "The invitation is expired and can no longer be accepted.",
637
650
  fix: "Ask a team admin to send a fresh invitation, then accept the new one.",
638
651
  },
639
652
  invitation_not_pending: {
@@ -646,7 +659,7 @@ export const ERROR_DOCS = {
646
659
  },
647
660
  job_not_found: {
648
661
  summary: "The background job was not found.",
649
- fix: "Verify the job id; completed jobs are eventually pruned.",
662
+ fix: "Verify the job id. Completed jobs are eventually pruned.",
650
663
  },
651
664
  job_not_promotable: {
652
665
  summary: "The job cannot be promoted in its current state.",
@@ -678,7 +691,7 @@ export const ERROR_DOCS = {
678
691
  },
679
692
  malware_detected: {
680
693
  summary: "Malware was detected in the uploaded content.",
681
- fix: "Remove the flagged files; contact support if you believe this is a false positive.",
694
+ fix: "Remove the flagged files. Contact support if you believe this is a false positive.",
682
695
  },
683
696
  managed_domain_protected: {
684
697
  summary: "This is a system-managed view.fast hostname and cannot be mutated like a custom domain.",
@@ -686,24 +699,24 @@ export const ERROR_DOCS = {
686
699
  },
687
700
  manifest_body_too_large: {
688
701
  summary: "The upload manifest body exceeds the maximum size.",
689
- fix: "Keep the manifest under 16 MB; split very large publishes into batches.",
702
+ fix: "Keep the manifest under 16 MB. Split very large publishes into batches.",
690
703
  },
691
704
  manifest_duplicate_path: {
692
705
  summary: "The upload manifest declares the same path more than once.",
693
- fix: "Deduplicate paths; comparisons use the canonical (decoded, NFC) form.",
706
+ fix: "Deduplicate paths. Comparisons use the canonical (decoded, NFC) form.",
694
707
  },
695
708
  manifest_too_many_files: {
696
709
  summary: "The upload manifest declares more files than the allowed ceiling.",
697
710
  fix: "Reduce the file count or split content across multiple spaces.",
698
711
  },
699
- mcp_acted_for_team_deleted: {
700
- summary: "This MCP approval or execution run acted only for a team that has since been deleted, so it can no longer be approved, denied, or canceled.",
701
- fix: "Nothing to do — the record is read-only history. Restore the deleted team within its recovery window if you still need to act on it.",
702
- },
703
712
  member_already_exists: {
704
713
  summary: "This user is already a member of the team.",
705
714
  fix: "Update the existing member's role instead of inviting again.",
706
715
  },
716
+ method_not_allowed: {
717
+ summary: "The requested HTTP method is not supported for this endpoint.",
718
+ fix: "Use one of the methods listed in the Allow response header.",
719
+ },
707
720
  missing_route_param: {
708
721
  summary: "A required route parameter is missing from the request path.",
709
722
  fix: "Check the endpoint path in the API reference and include every parameter.",
@@ -712,6 +725,10 @@ export const ERROR_DOCS = {
712
725
  summary: "The selected move target no longer has capacity for the space.",
713
726
  fix: "Retry the move with a different target or after capacity is freed.",
714
727
  },
728
+ name_managed_by_config: {
729
+ summary: "The space name is managed by sf.jsonc while its live version declares one.",
730
+ fix: "Change name in sf.jsonc and publish, or remove name from the file to rename the space through the API.",
731
+ },
715
732
  nameserver_delegation_required: {
716
733
  summary: `This operation requires the domain to be delegated to ${BRAND.productName} nameservers.`,
717
734
  fix: "Update the domain's nameservers at the registrar, then retry once delegation propagates.",
@@ -722,7 +739,7 @@ export const ERROR_DOCS = {
722
739
  },
723
740
  noop_publish: {
724
741
  summary: "The publish matched the live version exactly, so nothing changed.",
725
- fix: "No action needed; the existing live version already serves this content.",
742
+ fix: "No action needed. The existing live version already serves this content.",
726
743
  },
727
744
  not_enrolled: {
728
745
  summary: "This account is not enrolled in the private beta, so the API cannot be used yet.",
@@ -746,7 +763,7 @@ export const ERROR_DOCS = {
746
763
  },
747
764
  plan_grant_already_revoked: {
748
765
  summary: "This plan grant was already revoked.",
749
- fix: "Nothing to do; create a new grant if the team should regain the plan.",
766
+ fix: "Nothing to do. Create a new grant if the team should regain the plan.",
750
767
  },
751
768
  placement_invalid_burstable: {
752
769
  summary: "The placement burstable option was used with an unsupported placement mode.",
@@ -770,15 +787,15 @@ export const ERROR_DOCS = {
770
787
  },
771
788
  provider_error: {
772
789
  summary: "The hosting provider reported an error.",
773
- fix: "Retry; if the error persists, contact support with the requestId.",
790
+ fix: "Retry. If the error persists, contact support with the requestId.",
774
791
  },
775
792
  provider_job_failed: {
776
793
  summary: "A hosting-provider job failed while processing this operation.",
777
- fix: "Retry the operation; if it keeps failing, contact support with the operation id.",
794
+ fix: "Retry the operation. If it keeps failing, contact support with the operation id.",
778
795
  },
779
796
  provider_job_timeout: {
780
797
  summary: "A hosting-provider job timed out while processing this operation.",
781
- fix: "Retry the operation; the provider may be slow right now.",
798
+ fix: "Retry the operation. If the provider is slow right now, wait and retry again.",
782
799
  },
783
800
  provider_runtime_feature_unsupported: {
784
801
  summary: "The hosting provider does not support this runtime feature.",
@@ -790,10 +807,10 @@ export const ERROR_DOCS = {
790
807
  },
791
808
  proxy_upstream_denied: {
792
809
  summary: "The proxy upstream is on a denied network and cannot be used.",
793
- fix: "Proxy only to public HTTPS upstreams; private and internal addresses are blocked.",
810
+ fix: "Proxy only to public HTTPS upstreams. Private and internal addresses are blocked.",
794
811
  },
795
812
  proxy_upstream_unresolved: {
796
- summary: "The proxy upstream hostname could not be resolved.",
813
+ summary: "The proxy upstream hostname cannot be resolved.",
797
814
  fix: "Verify the upstream DNS name resolves publicly, then publish again.",
798
815
  },
799
816
  publish_archive_compression_ratio_exceeded: {
@@ -814,7 +831,7 @@ export const ERROR_DOCS = {
814
831
  },
815
832
  publish_base_changed: {
816
833
  summary: "Someone published new space settings after the base you loaded, so saving would overwrite their change.",
817
- fix: "Reload the latest settings, review the difference, and save again; pass force only to overwrite deliberately.",
834
+ fix: "Reload the latest settings, review the difference, and save again. Pass force only to overwrite deliberately.",
818
835
  },
819
836
  publish_bytes_missing: {
820
837
  summary: "The publish has no complete staged content to materialize.",
@@ -841,12 +858,12 @@ export const ERROR_DOCS = {
841
858
  fix: "Trim the inline payload, or switch to an upload-based publish for larger content.",
842
859
  },
843
860
  publish_not_cancelable: {
844
- summary: "The publish has progressed past the point where it can be canceled.",
861
+ summary: "The publish is past the point where it can be canceled.",
845
862
  fix: "Wait for the publish to finish, then roll back by promoting a previous version if needed.",
846
863
  },
847
864
  publish_path_collision: {
848
- summary: "Two entries in the publish payload normalize to the same path.",
849
- fix: "Remove the duplicate; each path may appear once across files and deletes.",
865
+ summary: "Two different artifacts would serve the same URL after directory-index or clean-URL resolution.",
866
+ fix: "Rename or remove one artifact so every request route has one owner.",
850
867
  },
851
868
  publish_path_invalid: {
852
869
  summary: "A publish path is not a relative, normalized POSIX path.",
@@ -854,7 +871,7 @@ export const ERROR_DOCS = {
854
871
  },
855
872
  publish_setup_failed: {
856
873
  summary: "Provisioning for this publish failed.",
857
- fix: "Retry the publish; if it persists, contact support with the requestId.",
874
+ fix: "Retry the publish. If it persists, contact support with the requestId.",
858
875
  },
859
876
  publish_snapshot_empty: {
860
877
  summary: "An empty snapshot was sent without an explicit base version.",
@@ -862,11 +879,11 @@ export const ERROR_DOCS = {
862
879
  },
863
880
  publish_upload_failed: {
864
881
  summary: "Uploading the publish content failed.",
865
- fix: "Retry the publish; partial uploads are resumable through the upload session.",
882
+ fix: "Retry the publish. Partial uploads are resumable through the upload session.",
866
883
  },
867
884
  publish_verification_failed: {
868
885
  summary: "Post-publish verification did not see the new content serving.",
869
- fix: "Retry; if the space still serves stale content, contact support.",
886
+ fix: "Retry. If the space still serves stale content, contact support.",
870
887
  },
871
888
  queue_not_found: {
872
889
  summary: "The named job queue does not exist.",
@@ -877,13 +894,17 @@ export const ERROR_DOCS = {
877
894
  fix: "Wait for the window in the Retry-After header to pass, then retry.",
878
895
  },
879
896
  registration_expired: {
880
- summary: "The domain registration has expired.",
897
+ summary: "The domain registration is expired.",
881
898
  fix: "Renew the domain at its registrar before retrying.",
882
899
  },
883
900
  registration_expiring: {
884
901
  summary: "The domain registration is about to expire, which blocks this operation.",
885
902
  fix: "Renew the domain first, then retry.",
886
903
  },
904
+ resource_revision_changed: {
905
+ summary: "The resource changed after you loaded it, so the stale write was rejected.",
906
+ fix: "Use the current resource returned in error.details.current, reapply the intended fields, and send its revision as expectedRevision.",
907
+ },
887
908
  routing_rules_over_plan: {
888
909
  summary: "The published _redirects and _headers exceed the plan's routing-rule allowance.",
889
910
  fix: "Reduce the rule count. Still stuck? POST /v1/feedback with the error code and request id.",
@@ -894,12 +915,16 @@ export const ERROR_DOCS = {
894
915
  },
895
916
  runtime_api_not_found: {
896
917
  summary: "The runtime management endpoint was not found.",
897
- fix: "Send the request with the management hostname as the Host header; management routes are not served on public hostnames.",
918
+ fix: "Send the request with the management hostname as the Host header. Management routes are not served on public hostnames.",
898
919
  },
899
920
  runtime_callback_forbidden: {
900
- summary: "The runtime callback could not be authenticated.",
921
+ summary: "The runtime callback cannot be authenticated.",
901
922
  fix: "Verify the callback secret configuration for this runtime.",
902
923
  },
924
+ runtime_dev_unsupported: {
925
+ summary: "`sf dev` cannot run this runtime locally yet.",
926
+ fix: "Run your framework's own dev server (`next dev`, `vite`, …) and publish with `sf publish` when you are ready.",
927
+ },
903
928
  runtime_engine_zip_missing: {
904
929
  summary: "The runtime engine artifact is missing from this deployment.",
905
930
  fix: "Rebuild the control plane so dist/runtime-engine.zip exists.",
@@ -910,30 +935,30 @@ export const ERROR_DOCS = {
910
935
  },
911
936
  runtime_instance_mismatch: {
912
937
  summary: "The request reached a different runtime instance than the one it was issued for.",
913
- fix: "Re-request instructions; the space may have moved to another instance.",
938
+ fix: "Re-request instructions. The space is on another instance now.",
914
939
  },
915
940
  runtime_jti_missing: {
916
941
  summary: "The runtime token is missing its replay-protection id.",
917
- fix: "Mint a fresh runtime token; tokens must carry a jti claim.",
942
+ fix: "Mint a fresh runtime token. Tokens must carry a jti claim.",
918
943
  },
919
944
  runtime_jti_replayed: {
920
- summary: "The runtime token was already used; replays are rejected.",
945
+ summary: "The runtime token was already used. Replays are rejected.",
921
946
  fix: "Mint a fresh runtime token for each request.",
922
947
  },
923
948
  runtime_jwks_key_missing: {
924
949
  summary: "No signing key matching the token's key id was found.",
925
- fix: "Refresh the runtime JWKS; the signing keys may have rotated.",
950
+ fix: "Refresh the runtime JWKS to load the current signing keys.",
926
951
  },
927
- runtime_logs_unavailable: {
928
- summary: "Server logs are not available because Spacefast serves your space as static files.",
929
- fix: "There is no running server process to log. Use the request logs in your dashboard to inspect recent traffic.",
952
+ runtime_kind_mismatch: {
953
+ summary: "This operation is only available for a different runtime kind.",
954
+ fix: "Check `sf runtime status` for what the live version actually runs, then use the surface that runtime supports.",
930
955
  },
931
956
  runtime_management_unavailable: {
932
957
  summary: "The runtime management surface is unavailable for this site.",
933
- fix: "Retry shortly; if the site stays unreachable, contact support.",
958
+ fix: "Retry shortly. If the site stays unreachable, contact support.",
934
959
  },
935
960
  runtime_not_provisioned: {
936
- summary: "The space has not served a published version yet, so it has no runtime data to read.",
961
+ summary: "The space does not serve a published version yet, so it has no runtime data to read.",
937
962
  fix: "Publish a version first. If a publish is already running, wait for it — the operation receipt reports progress.",
938
963
  },
939
964
  runtime_operation_missing: {
@@ -946,14 +971,14 @@ export const ERROR_DOCS = {
946
971
  },
947
972
  runtime_token_bad_signature: {
948
973
  summary: "The runtime token signature did not verify.",
949
- fix: "Mint a fresh token; verify clocks and JWKS freshness if it persists.",
974
+ fix: "Mint a fresh token. Verify clocks and JWKS freshness if it persists.",
950
975
  },
951
976
  runtime_token_expired: {
952
- summary: "The runtime token has expired.",
953
- fix: "Mint a fresh runtime token; step tokens are short-lived by design.",
977
+ summary: "The runtime token is expired.",
978
+ fix: "Mint a fresh runtime token. Step tokens are short-lived by design.",
954
979
  },
955
980
  runtime_token_invalid: {
956
- summary: "The runtime token could not be parsed or validated.",
981
+ summary: "The runtime token cannot be parsed or validated.",
957
982
  fix: "Mint a fresh runtime token.",
958
983
  },
959
984
  runtime_unauthorized: {
@@ -965,28 +990,28 @@ export const ERROR_DOCS = {
965
990
  fix: "Follow the upload instructions returned when the session was created.",
966
991
  },
967
992
  runtime_upload_required: {
968
- summary: "This step requires uploaded content that has not arrived yet.",
993
+ summary: "This step requires uploaded content, but that content is not uploaded yet.",
969
994
  fix: "Complete the uploads for this session, then retry the step.",
970
995
  },
971
996
  scan_pending: {
972
997
  summary: "The content is still being scanned for safety and cannot be served yet.",
973
- fix: "Wait for the scan to finish; serving resumes automatically once it clears.",
998
+ fix: "Wait for the scan to finish. Serving resumes automatically once it clears.",
974
999
  },
975
1000
  secret_variable_in_template: {
976
1001
  summary: "A secret variable was referenced in a template, which is blocked.",
977
- fix: "Templates may only substitute non-secret variables; remove the secret reference.",
1002
+ fix: "Use only non-secret variables in templates. Remove the secret reference.",
1003
+ },
1004
+ service_booting: {
1005
+ summary: "The process that received this request is still starting and cannot serve it yet.",
1006
+ fix: "Wait for the Retry-After window, then send the same request again.",
978
1007
  },
979
1008
  service_signature_invalid: {
980
- summary: "The service request signature could not be verified.",
1009
+ summary: "The service request signature cannot be verified.",
981
1010
  fix: "Sign the exact request method, path, body digest, timestamp, and a fresh nonce.",
982
1011
  },
983
1012
  site_already_deleted: {
984
1013
  summary: "The site was already deleted.",
985
- fix: "No action needed; the site is gone.",
986
- },
987
- site_capacity_exceeded: {
988
- summary: "The site has reached its capacity and cannot take more content.",
989
- fix: "Retry shortly; the platform rebalances spaces onto new sites automatically.",
1014
+ fix: "No action needed. The site is gone.",
990
1015
  },
991
1016
  site_has_live_spaces: {
992
1017
  summary: "The site still has live spaces assigned to it, so it cannot be deleted.",
@@ -1006,11 +1031,11 @@ export const ERROR_DOCS = {
1006
1031
  },
1007
1032
  slow_down: {
1008
1033
  summary: "The device login is being polled faster than the advised interval.",
1009
- fix: "Increase the polling interval; aggressive polling invalidates the flow.",
1034
+ fix: "Increase the polling interval. Aggressive polling invalidates the flow.",
1010
1035
  },
1011
1036
  slug_invalid: {
1012
1037
  summary: "The slug does not meet the structural rules for managed names.",
1013
- fix: "Use lowercase letters, numbers, and single dashes within the allowed length; the error message identifies the failed rule.",
1038
+ fix: "Use lowercase letters, numbers, and single dashes within the allowed length. The error message identifies the failed rule.",
1014
1039
  },
1015
1040
  slug_reserved: {
1016
1041
  summary: "The slug is reserved for infrastructure, product, or impersonation protection.",
@@ -1033,8 +1058,12 @@ export const ERROR_DOCS = {
1033
1058
  fix: "Wait briefly and retry the upload.",
1034
1059
  },
1035
1060
  space_already_claimed: {
1036
- summary: "The space was already claimed; a claim can only succeed once.",
1037
- fix: "If you are the agent that published this space, exchange your claim token once at POST /v1/anonymous-claim/exchange for a durable access token and keep publishing to the same spaceId. Otherwise ask the owner for access — do not publish a duplicate space.",
1061
+ summary: "The space was already claimed. A claim can only succeed once.",
1062
+ fix: "If you published this space, exchange your claim token once at POST /v1/anonymous-claim/exchange. Keep publishing to the same spaceId with that durable API key. Otherwise ask the owner for access — do not publish a duplicate space.",
1063
+ },
1064
+ space_capacity_warming: {
1065
+ summary: "This space is waiting on serving capacity that is being provisioned in the background.",
1066
+ fix: "Wait for the Retry-After window, then send the same publish again. No version was created and no files were uploaded.",
1038
1067
  },
1039
1068
  space_claim_unavailable: {
1040
1069
  summary: "This space cannot be claimed.",
@@ -1042,15 +1071,15 @@ export const ERROR_DOCS = {
1042
1071
  },
1043
1072
  space_claimed_credential_available: {
1044
1073
  summary: "The space was claimed and its owner kept agent publishing enabled; this claim token now works exactly once as an exchange voucher.",
1045
- fix: "POST /v1/anonymous-claim/exchange with this claim token as bearer auth. Save the returned access token (e.g. .spacefast/state.json), then retry the request with it as Authorization: Bearer. Do not publish a new space.",
1074
+ fix: "POST /v1/anonymous-claim/exchange with this claim token as bearer auth. Save the returned API key (e.g. .spacefast/state.json), then retry the request with it as Authorization: Bearer. Do not publish a new space.",
1046
1075
  },
1047
1076
  space_disabled: {
1048
1077
  summary: "The space is disabled and cannot be served or modified.",
1049
- fix: "Check the disabled reason on the space; it explains the path to restore it.",
1078
+ fix: "Check the disabled reason on the space. It explains the path to restore it.",
1050
1079
  },
1051
1080
  space_expired: {
1052
1081
  summary: "The space expired and is no longer served.",
1053
- fix: "If it is within the recovery window, claim or restore it; otherwise publish again.",
1082
+ fix: "If it is within the recovery window, claim or restore it. Otherwise publish again.",
1054
1083
  },
1055
1084
  space_has_active_publish: {
1056
1085
  summary: "The space has a publish in progress, which blocks this operation.",
@@ -1080,6 +1109,10 @@ export const ERROR_DOCS = {
1080
1109
  summary: "The export was produced by an unsupported runtime schema version.",
1081
1110
  fix: "Re-export from a current runtime, or upgrade before exporting.",
1082
1111
  },
1112
+ space_move_would_strand_zero_data: {
1113
+ summary: "The Space runs Zero, whose database and object storage live on the site the Space is placed on. Relocating it would strand that data on the old site, so the move is refused.",
1114
+ fix: "Nothing was moved and no data was lost. Migrating Zero data between sites is not implemented. Contact support if the space genuinely has to be relocated.",
1115
+ },
1083
1116
  space_moving: {
1084
1117
  summary: "The space is moving between sites, which blocks this operation.",
1085
1118
  fix: "Wait for the move to finish, then retry.",
@@ -1090,12 +1123,24 @@ export const ERROR_DOCS = {
1090
1123
  },
1091
1124
  space_not_disabled: {
1092
1125
  summary: "The space is not disabled, so it cannot be restored.",
1093
- fix: "No action needed; the space is already active.",
1126
+ fix: "No action needed. The space is already active.",
1094
1127
  },
1095
1128
  space_not_restorable: {
1096
1129
  summary: "The space is past its recovery window and cannot be restored.",
1097
1130
  fix: "Publish the content to a new space.",
1098
1131
  },
1132
+ space_person_already_member: {
1133
+ summary: "The email already belongs to a member of the space.",
1134
+ fix: "Use the existing member entry instead of sending another invitation.",
1135
+ },
1136
+ space_person_invitation_pending: {
1137
+ summary: "A Person invitation is already pending for this email.",
1138
+ fix: "Resend or update the pending invitation instead of creating another one.",
1139
+ },
1140
+ space_person_self_invite: {
1141
+ summary: "The inviter already belongs to the space.",
1142
+ fix: "Use your existing space access instead of inviting yourself.",
1143
+ },
1099
1144
  space_ref_ambiguous: {
1100
1145
  summary: "The space reference matches more than one accessible space.",
1101
1146
  fix: "Use the spc_ id, or scope the reference with a teamRef.",
@@ -1118,35 +1163,7 @@ export const ERROR_DOCS = {
1118
1163
  },
1119
1164
  static_control_file_not_supported: {
1120
1165
  summary: "This control file is not supported by the static runtime.",
1121
- fix: "Remove the file; see the routing docs for supported convention files.",
1122
- },
1123
- static_mount_path_conflict: {
1124
- summary: "The requested mount path overlaps another static mount on this space.",
1125
- fix: "Choose a path that is not equal to, above, or below an existing mount path.",
1126
- },
1127
- static_mount_source_not_ready: {
1128
- summary: "The website version that owns this mount is not ready.",
1129
- fix: "Wait for the website version to finish finalizing, then retry.",
1130
- },
1131
- static_mount_target_forbidden: {
1132
- summary: "The target space is not an authorized space in the same team.",
1133
- fix: "Choose another space in the source space's team and authenticate with read access to its versions.",
1134
- },
1135
- static_mount_target_in_use: {
1136
- summary: "A static mount dependency blocks changing or deleting this space.",
1137
- fix: "Remove the reported static mount before retrying the operation.",
1138
- },
1139
- static_mount_target_not_live: {
1140
- summary: "The target space does not have a production version to mount.",
1141
- fix: "Publish or promote a ready version on the target space, then retry.",
1142
- },
1143
- static_mount_target_not_ready: {
1144
- summary: "The target production version is not ready for static delivery.",
1145
- fix: "Wait for the target version to finish finalizing, then retry.",
1146
- },
1147
- static_mount_target_not_static: {
1148
- summary: "The target production version contains runtime functions.",
1149
- fix: "Promote a fully static target version or serve the dynamic application without a static mount.",
1166
+ fix: "Remove the file. See the routing docs for supported convention files.",
1150
1167
  },
1151
1168
  static_runtime_control_path_not_supported: {
1152
1169
  summary: "This control path is not supported by the static runtime.",
@@ -1156,33 +1173,73 @@ export const ERROR_DOCS = {
1156
1173
  summary: "This operation only applies to static-runtime spaces.",
1157
1174
  fix: "Target a static-runtime space.",
1158
1175
  },
1176
+ storage_auth_required: {
1177
+ summary: "This storage operation requires an authenticated Zero user.",
1178
+ fix: "Sign in to the hosted Zero app, then retry the storage operation.",
1179
+ },
1159
1180
  storage_bucket_unavailable: {
1160
1181
  summary: "No usable internal storage bucket is configured for this operation.",
1161
1182
  fix: "Check the storage bucket registry and credential environment references, then retry.",
1162
1183
  },
1184
+ storage_content_blocked: {
1185
+ summary: "The object contains executable or active web content that Zero storage does not serve.",
1186
+ fix: "Upload a passive file type without HTML, script, SVG, PHP, or executable bytes.",
1187
+ },
1188
+ storage_delete_forbidden: {
1189
+ summary: "The current Zero user did not upload this object.",
1190
+ fix: "Sign in as the original uploader before deleting the object.",
1191
+ },
1192
+ storage_empty_file: {
1193
+ summary: "The Zero storage upload is empty.",
1194
+ fix: "Upload a file containing at least 1 byte.",
1195
+ },
1196
+ storage_file_too_large: {
1197
+ summary: "The Zero storage object exceeds the 5 MiB file limit.",
1198
+ fix: "Upload a smaller object.",
1199
+ },
1200
+ storage_key_invalid: {
1201
+ summary: "The Zero storage key is malformed.",
1202
+ fix: "Use the public or private object key returned by storage.upload.",
1203
+ },
1204
+ storage_object_not_found: {
1205
+ summary: "The requested Zero storage object does not exist.",
1206
+ fix: "Check the object key or upload the object again.",
1207
+ },
1208
+ storage_quota_already_unlimited: {
1209
+ summary: "The team already has unlimited storage.",
1210
+ fix: "No quota override is needed.",
1211
+ },
1212
+ storage_quota_decrease_not_supported: {
1213
+ summary: "This control cannot reduce a team's storage quota.",
1214
+ fix: "Use a billing or plan change to reduce the quota.",
1215
+ },
1163
1216
  storage_quota_exceeded: {
1164
- summary: "The publish would exceed the plan's storage allowance.",
1165
- fix: "Delete old versions. Still stuck? POST /v1/feedback with the error code and request id.",
1217
+ summary: "The operation would exceed its storage allowance.",
1218
+ fix: "Delete unused Zero objects or old versions, reduce the upload size, then retry.",
1219
+ },
1220
+ storage_unavailable: {
1221
+ summary: "The Zero runtime cannot read or persist object storage.",
1222
+ fix: "Retry on a healthy runtime. Contact support if the failure persists.",
1166
1223
  },
1167
1224
  storage_usage_unavailable: {
1168
- summary: "Storage usage could not be computed right now.",
1225
+ summary: "Storage usage cannot be computed right now.",
1169
1226
  fix: "Retry shortly.",
1170
1227
  },
1171
1228
  stripe_error: {
1172
1229
  summary: "The billing provider reported an error.",
1173
- fix: "Retry; if it persists, check the team's billing settings.",
1230
+ fix: "Retry. If it persists, check the team's billing settings.",
1174
1231
  },
1175
1232
  superseded_by_publish: {
1176
1233
  summary: "A newer publish superseded this operation, so it was skipped.",
1177
- fix: "No action needed; the newer publish already carries the change.",
1234
+ fix: "No action needed. The newer publish already carries the change.",
1178
1235
  },
1179
1236
  takeover_notice_window: {
1180
- summary: "The hostname was recently bound elsewhere; a takeover notice window applies.",
1237
+ summary: "The hostname was recently bound elsewhere. A takeover notice window applies.",
1181
1238
  fix: "Retry after the notice window, or have the current holder release the binding.",
1182
1239
  },
1183
1240
  team_member_quota_exceeded: {
1184
1241
  summary: "Inviting this person would exceed the team's seat limit.",
1185
- fix: "Remove a team member or cancel a pending invitation to free a seat; pending invitations count toward the limit.",
1242
+ fix: "Remove a team member or cancel a pending invitation to free a seat. Pending invitations count toward the limit.",
1186
1243
  },
1187
1244
  team_ref_required: {
1188
1245
  summary: "A team reference is required for this operation.",
@@ -1202,7 +1259,7 @@ export const ERROR_DOCS = {
1202
1259
  },
1203
1260
  event_rate_limited: {
1204
1261
  summary: "Too many event submissions came from this client in a short window.",
1205
- fix: "Drop or batch events; event delivery is best-effort and never required.",
1262
+ fix: "Drop or batch events. Event delivery is best-effort and never required.",
1206
1263
  },
1207
1264
  template_file_too_large: {
1208
1265
  summary: "A template file exceeds the maximum size for substitution.",
@@ -1229,7 +1286,7 @@ export const ERROR_DOCS = {
1229
1286
  fix: "Use a credential issued for this tenant.",
1230
1287
  },
1231
1288
  tenant_past_due: {
1232
- summary: "The tenant is past due; mutations are rejected while serving continues.",
1289
+ summary: "The tenant is past due. Mutations are rejected while serving continues.",
1233
1290
  fix: "Settle the outstanding balance to restore full access.",
1234
1291
  },
1235
1292
  tenant_selection_required: {
@@ -1242,7 +1299,7 @@ export const ERROR_DOCS = {
1242
1299
  },
1243
1300
  theme_value_invalid: {
1244
1301
  summary: "A theme value in the configuration is outside the allowed grammar.",
1245
- fix: "Use allowed CSS values; the offending key is dropped with a warning otherwise.",
1302
+ fix: "Use allowed CSS values. The offending key is dropped with a warning otherwise.",
1246
1303
  },
1247
1304
  transfer_cross_tenant_unsupported: {
1248
1305
  summary: "Spaces cannot be transferred across tenants.",
@@ -1250,15 +1307,15 @@ export const ERROR_DOCS = {
1250
1307
  },
1251
1308
  transfer_move_failed: {
1252
1309
  summary: "The space move backing this transfer failed.",
1253
- fix: "Retry the transfer; if it persists, contact support with the transfer id.",
1310
+ fix: "Retry the transfer. If it persists, contact support with the transfer id.",
1254
1311
  },
1255
1312
  transfer_not_cancelable: {
1256
- summary: "The transfer has progressed past the point where it can be canceled.",
1313
+ summary: "The transfer is past the point where it can be canceled.",
1257
1314
  fix: "Wait for the transfer to finish.",
1258
1315
  },
1259
1316
  transfer_push_failed: {
1260
- summary: "The source runtime could not push the space blobs into the transfer bucket.",
1261
- fix: "Retry the move; if it persists, check the source runtime and bucket configuration.",
1317
+ summary: "The source runtime cannot push the space blobs into the transfer bucket.",
1318
+ fix: "Retry the move. If it persists, check the source runtime and bucket configuration.",
1262
1319
  },
1263
1320
  transfer_source_changed: {
1264
1321
  summary: "The space changed since the transfer was created, so it must be re-confirmed.",
@@ -1269,12 +1326,12 @@ export const ERROR_DOCS = {
1269
1326
  fix: "Pick a different target team or account.",
1270
1327
  },
1271
1328
  transfer_verify_failed: {
1272
- summary: "The target runtime could not verify transferred blob content.",
1273
- fix: "Retry the move; if it persists, check the target runtime and bucket integrity.",
1329
+ summary: "The target runtime cannot verify transferred blob content.",
1330
+ fix: "Retry the move. If it persists, check the target runtime and bucket integrity.",
1274
1331
  },
1275
1332
  unauthorized: {
1276
1333
  summary: "The request carried no valid credential.",
1277
- fix: "Send a bearer access token, use an agent OAuth client, or sign in.",
1334
+ fix: "Send a bearer API key, use an agent OAuth client, or sign in.",
1278
1335
  },
1279
1336
  unsupported_publish_media_type: {
1280
1337
  summary: "The publish content-type is not supported.",
@@ -1290,11 +1347,7 @@ export const ERROR_DOCS = {
1290
1347
  },
1291
1348
  upload_path_not_declared: {
1292
1349
  summary: "An uploaded path was not declared in the version's manifest.",
1293
- fix: "Declare every path up front, or use an open session for incremental uploads.",
1294
- },
1295
- upload_session_cap_exceeded: {
1296
- summary: "The open upload session exceeded its file or byte cap.",
1297
- fix: "Stay within the session caps, or declare a manifest for large publishes.",
1350
+ fix: "Declare every path up front.",
1298
1351
  },
1299
1352
  upload_size_mismatch: {
1300
1353
  summary: "An uploaded file's size does not match the declared size.",
@@ -1306,11 +1359,11 @@ export const ERROR_DOCS = {
1306
1359
  },
1307
1360
  validation_error: {
1308
1361
  summary: "A request field failed validation.",
1309
- fix: "Fix the field referenced by param and details, then retry.",
1362
+ fix: "Fix the field referenced by pointer and details, then retry.",
1310
1363
  },
1311
1364
  variable_cascade_failed: {
1312
1365
  summary: "Republishing spaces after a variable change failed.",
1313
- fix: "Check the operation's diagnostics; live content keeps serving the previous values.",
1366
+ fix: "Check the operation's diagnostics. Live content keeps serving the previous values.",
1314
1367
  },
1315
1368
  verification_required: {
1316
1369
  summary: "Domain verification is required before this operation.",
@@ -1333,7 +1386,7 @@ export const ERROR_DOCS = {
1333
1386
  fix: "Start a new version.",
1334
1387
  },
1335
1388
  version_closed: {
1336
- summary: "The version's upload session is closed; no more files can be added.",
1389
+ summary: "The version's upload session is closed. No more files can be added.",
1337
1390
  fix: "Start a new version for additional changes.",
1338
1391
  },
1339
1392
  version_expired: {
@@ -1362,7 +1415,7 @@ export const ERROR_DOCS = {
1362
1415
  },
1363
1416
  version_in_use: {
1364
1417
  summary: "The version is referenced by one or more channels and cannot be deleted.",
1365
- fix: "Promote another version on those channels first; details lists them.",
1418
+ fix: "Promote another version on those channels first. Details lists them.",
1366
1419
  },
1367
1420
  version_live: {
1368
1421
  summary: "The version is live and cannot be deleted.",
@@ -1374,7 +1427,7 @@ export const ERROR_DOCS = {
1374
1427
  },
1375
1428
  version_not_finalizable: {
1376
1429
  summary: "The version cannot be finalized in its current status.",
1377
- fix: "Only uploaded versions finalize; check the version status.",
1430
+ fix: "Only uploaded versions finalize. Check the version status.",
1378
1431
  },
1379
1432
  version_not_found: {
1380
1433
  summary: "The version was not found.",
@@ -1390,10 +1443,10 @@ export const ERROR_DOCS = {
1390
1443
  },
1391
1444
  version_not_ready: {
1392
1445
  summary: "The version is not ready yet.",
1393
- fix: "Wait for finalize to complete; the operation receipt reports progress.",
1446
+ fix: "Wait for finalize to complete. The operation receipt reports progress.",
1394
1447
  },
1395
1448
  version_quota_exceeded: {
1396
- summary: "The space has reached its version quota.",
1449
+ summary: "The space is at its version quota.",
1397
1450
  fix: "Delete old versions. Still stuck? POST /v1/feedback with the error code and request id.",
1398
1451
  },
1399
1452
  version_total_bytes_exceeded: {
@@ -1414,7 +1467,7 @@ export const ERROR_DOCS = {
1414
1467
  },
1415
1468
  zero_ai_unavailable: {
1416
1469
  summary: "The local Zero AI service is not configured.",
1417
- fix: "Configure an AI handler for zero dev before calling the AI service.",
1470
+ fix: "Configure an AI handler in the project, then restart `sf dev` before calling the AI service.",
1418
1471
  },
1419
1472
  zero_artifact_abi_mismatch: {
1420
1473
  summary: "The Zero endpoint artifact was built for a different runner ABI.",
@@ -1425,15 +1478,15 @@ export const ERROR_DOCS = {
1425
1478
  fix: "Rebuild the Zero project and verify the generated zero endpoint artifacts are uploaded.",
1426
1479
  },
1427
1480
  zero_artifact_malformed: {
1428
- summary: "The Zero endpoint artifact could not be parsed.",
1429
- fix: "Rebuild the Zero project; do not edit generated artifact JSON by hand.",
1481
+ summary: "The Zero endpoint artifact cannot be parsed.",
1482
+ fix: "Rebuild the Zero project. Do not edit generated artifact JSON by hand.",
1430
1483
  },
1431
1484
  zero_artifact_path_invalid: {
1432
1485
  summary: "The Zero endpoint artifact path is invalid.",
1433
1486
  fix: "Rebuild the Zero routes so all artifact paths stay inside the version bundle.",
1434
1487
  },
1435
1488
  zero_artifact_unreadable: {
1436
- summary: "The Zero endpoint artifact could not be read by the runtime.",
1489
+ summary: "The Zero endpoint artifact cannot be read by the runtime.",
1437
1490
  fix: "Verify the version finalized with all generated Zero files present.",
1438
1491
  },
1439
1492
  zero_auth_unavailable: {
@@ -1457,15 +1510,15 @@ export const ERROR_DOCS = {
1457
1510
  fix: "Send a valid blob body within the configured local size limits.",
1458
1511
  },
1459
1512
  zero_bootstrap_encode_failed: {
1460
- summary: "The Zero runner could not encode the JavaScript bootstrap data.",
1461
- fix: "Retry with valid request metadata; report the issue if it persists.",
1513
+ summary: "The Zero runner cannot encode the JavaScript bootstrap data.",
1514
+ fix: "Retry with valid request metadata. Report the issue if it persists.",
1462
1515
  },
1463
1516
  zero_bytecode_hash_mismatch: {
1464
1517
  summary: "The Zero endpoint bytecode hash does not match its artifact metadata.",
1465
1518
  fix: "Rebuild and republish so bytecode and endpoint metadata are from the same build.",
1466
1519
  },
1467
1520
  zero_bytecode_invalid: {
1468
- summary: "The Zero endpoint bytecode could not be loaded by QuickJS.",
1521
+ summary: "The Zero endpoint bytecode cannot be loaded by QuickJS.",
1469
1522
  fix: "Rebuild the project with the current Zero runner and redeploy.",
1470
1523
  },
1471
1524
  zero_bytecode_path_invalid: {
@@ -1473,27 +1526,51 @@ export const ERROR_DOCS = {
1473
1526
  fix: "Rebuild the Zero routes so bytecode paths stay inside the version bundle.",
1474
1527
  },
1475
1528
  zero_bytecode_unreadable: {
1476
- summary: "The Zero endpoint bytecode file could not be read.",
1529
+ summary: "The Zero endpoint bytecode file cannot be read.",
1477
1530
  fix: "Verify the version finalized with the generated bytecode files present.",
1478
1531
  },
1479
1532
  zero_capabilities_encode_failed: {
1480
- summary: "The runtime could not encode the Zero endpoint capabilities.",
1481
- fix: "Rebuild with valid capability metadata; report the failure if it persists.",
1533
+ summary: "The runtime cannot encode the Zero endpoint capabilities.",
1534
+ fix: "Rebuild with valid capability metadata. Report the failure if it persists.",
1482
1535
  },
1483
1536
  zero_client_bundle_not_loaded: {
1484
- summary: "The local Zero dev client bundle has not been generated or loaded.",
1485
- fix: "Restart zero dev or run a fresh local build before loading the client route.",
1537
+ summary: "The local Zero dev client bundle is not generated or loaded.",
1538
+ fix: "Restart `sf dev` or run a fresh local build before loading the client route.",
1486
1539
  },
1487
1540
  zero_db_connect_failed: {
1488
- summary: "The Zero runner could not connect to the configured database.",
1541
+ summary: "The Zero runner cannot connect to the configured database.",
1489
1542
  fix: "Verify DATABASE_URL or the generated MySQL connection variables and retry.",
1490
1543
  },
1491
1544
  zero_db_execute_failed: {
1492
1545
  summary: "A Zero database write failed.",
1493
1546
  fix: "Inspect the mutation, schema, and database logs, then retry after fixing the SQL issue.",
1494
1547
  },
1548
+ zero_db_export_cursor_invalid: {
1549
+ summary: "The local database export cursor is invalid or belongs to another export.",
1550
+ fix: "Start a fresh export and use only cursors returned by that same table and schema.",
1551
+ },
1552
+ zero_db_export_failed: {
1553
+ summary: "The runtime cannot read a database export page.",
1554
+ fix: "Retry the export. If it repeats, inspect the live database and runtime logs.",
1555
+ },
1556
+ zero_db_export_page_too_large: {
1557
+ summary: "One database export page exceeded the 16 MiB response limit.",
1558
+ fix: "Retry with a smaller export page size.",
1559
+ },
1560
+ zero_db_export_query_invalid: {
1561
+ summary: "The local database export request has an invalid table or page size.",
1562
+ fix: "Use a declared table name and a page size within the documented limit.",
1563
+ },
1564
+ zero_db_export_schema_changed: {
1565
+ summary: "The database schema changed while an export was in progress.",
1566
+ fix: "Start a fresh export so every page uses the same schema.",
1567
+ },
1568
+ zero_db_export_schema_unavailable: {
1569
+ summary: "The live capsule has no stable schema hash for a complete export.",
1570
+ fix: "Publish the capsule with a current Zero schema, then start the export again.",
1571
+ },
1495
1572
  zero_db_host_install_failed: {
1496
- summary: "The Zero runner could not install the database host bridge.",
1573
+ summary: "The Zero runner cannot install the database host bridge.",
1497
1574
  fix: "Rebuild with a current runner and report the failure if it repeats.",
1498
1575
  },
1499
1576
  zero_db_operation_invalid: {
@@ -1513,7 +1590,7 @@ export const ERROR_DOCS = {
1513
1590
  fix: "Inspect the query, schema, and database logs, then retry after fixing the SQL issue.",
1514
1591
  },
1515
1592
  zero_db_row_invalid: {
1516
- summary: "A database row could not be converted into a Zero response value.",
1593
+ summary: "A database row cannot be converted into a Zero response value.",
1517
1594
  fix: "Check the table schema and stored values for unsupported data.",
1518
1595
  },
1519
1596
  zero_db_sql_invalid: {
@@ -1529,7 +1606,7 @@ export const ERROR_DOCS = {
1529
1606
  fix: "Rebuild with the current Zero runner and report the failure if it repeats.",
1530
1607
  },
1531
1608
  zero_db_transaction_commit_failed: {
1532
- summary: "The Zero database transaction could not be committed.",
1609
+ summary: "The Zero database transaction cannot be committed.",
1533
1610
  fix: "Retry after checking database connectivity and transaction conflicts.",
1534
1611
  },
1535
1612
  zero_db_transaction_invalid: {
@@ -1541,13 +1618,21 @@ export const ERROR_DOCS = {
1541
1618
  fix: "Rebuild with the current Zero runner and report the failure if it repeats.",
1542
1619
  },
1543
1620
  zero_db_transaction_rollback_failed: {
1544
- summary: "The Zero database transaction could not be rolled back cleanly.",
1621
+ summary: "The Zero database transaction cannot be rolled back cleanly.",
1545
1622
  fix: "Inspect the affected database state before retrying, then report the failure.",
1546
1623
  },
1547
1624
  zero_db_transaction_start_failed: {
1548
- summary: "The Zero database transaction could not be started.",
1625
+ summary: "The Zero database transaction cannot be started.",
1549
1626
  fix: "Check database connectivity and retry the mutation.",
1550
1627
  },
1628
+ zero_db_target_denied: {
1629
+ summary: "The application Zero database target is not a public TCP address.",
1630
+ fix: "Use a public database hostname whose complete DNS answer set contains only public addresses.",
1631
+ },
1632
+ zero_db_tls_required: {
1633
+ summary: "The application Zero database cannot be connected with verified pinned TLS.",
1634
+ fix: "Use the provider-managed database until verified external database TLS is supported.",
1635
+ },
1551
1636
  zero_db_url_invalid: {
1552
1637
  summary: "The Zero database URL is malformed.",
1553
1638
  fix: "Set DATABASE_URL or the generated database variables to a valid MySQL connection URL.",
@@ -1565,7 +1650,7 @@ export const ERROR_DOCS = {
1565
1650
  fix: "Use valid table, limit, and cursor parameters.",
1566
1651
  },
1567
1652
  zero_endpoint_compile_failed: {
1568
- summary: "The runtime could not compile the Zero endpoint bytecode.",
1653
+ summary: "The runtime cannot compile the Zero endpoint bytecode.",
1569
1654
  fix: "Inspect the compile diagnostics, fix the endpoint source, and publish again.",
1570
1655
  },
1571
1656
  zero_endpoint_conflict: {
@@ -1585,7 +1670,7 @@ export const ERROR_DOCS = {
1585
1670
  fix: "Rebuild and republish the Zero project.",
1586
1671
  },
1587
1672
  zero_endpoint_index_malformed: {
1588
- summary: "The Zero endpoint index could not be parsed.",
1673
+ summary: "The Zero endpoint index cannot be parsed.",
1589
1674
  fix: "Rebuild the generated endpoint index and redeploy.",
1590
1675
  },
1591
1676
  zero_endpoint_index_path_invalid: {
@@ -1593,7 +1678,7 @@ export const ERROR_DOCS = {
1593
1678
  fix: "Verify the runtime bundle was finalized with the standard Zero layout.",
1594
1679
  },
1595
1680
  zero_endpoint_index_unreadable: {
1596
- summary: "The Zero endpoint index could not be read.",
1681
+ summary: "The Zero endpoint index cannot be read.",
1597
1682
  fix: "Verify the version finalized with zero/endpoints-index.json present.",
1598
1683
  },
1599
1684
  zero_endpoint_invalid: {
@@ -1621,12 +1706,12 @@ export const ERROR_DOCS = {
1621
1706
  fix: "Upgrade the team to a plan that includes Zero and dedicated runtime, then publish again.",
1622
1707
  },
1623
1708
  zero_envelope_encode_failed: {
1624
- summary: "The PHP bridge could not encode the Zero runner request envelope.",
1625
- fix: "Retry with valid request data; report the issue if it persists.",
1709
+ summary: "The PHP bridge cannot encode the Zero runner request envelope.",
1710
+ fix: "Retry with valid request data. Report the issue if it persists.",
1626
1711
  },
1627
1712
  zero_js_context_init_failed: {
1628
- summary: "The Zero runner could not initialize a QuickJS context.",
1629
- fix: "Retry or rebuild the runner; report persistent runtime initialization failures.",
1713
+ summary: "The Zero runner cannot initialize a QuickJS context.",
1714
+ fix: "Retry or rebuild the runner. Report persistent runtime initialization failures.",
1630
1715
  },
1631
1716
  zero_js_execution_failed: {
1632
1717
  summary: "The Zero endpoint JavaScript threw during execution.",
@@ -1637,7 +1722,7 @@ export const ERROR_DOCS = {
1637
1722
  fix: "Reduce synchronous work or database round trips in the handler.",
1638
1723
  },
1639
1724
  zero_js_globals_failed: {
1640
- summary: "The Zero runner could not install runtime globals for the endpoint.",
1725
+ summary: "The Zero runner cannot install runtime globals for the endpoint.",
1641
1726
  fix: "Rebuild with a current runner and report the failure if it repeats.",
1642
1727
  },
1643
1728
  zero_js_response_malformed: {
@@ -1645,12 +1730,12 @@ export const ERROR_DOCS = {
1645
1730
  fix: "Return a valid Response or supported Zero handler result.",
1646
1731
  },
1647
1732
  zero_js_runtime_init_failed: {
1648
- summary: "The Zero runner could not initialize QuickJS.",
1733
+ summary: "The Zero runner cannot initialize QuickJS.",
1649
1734
  fix: "Retry on a healthy runtime or rebuild the runner binary.",
1650
1735
  },
1651
1736
  zero_log_query_invalid: {
1652
1737
  summary: "The Zero log query parameters are invalid.",
1653
- fix: "Use valid cursor, limit, mutationName, and requestId parameters.",
1738
+ fix: "Use valid cursor, limit, handlerName, and requestId parameters.",
1654
1739
  },
1655
1740
  zero_method_not_allowed: {
1656
1741
  summary: "The request method is not allowed for this Zero endpoint.",
@@ -1693,8 +1778,8 @@ export const ERROR_DOCS = {
1693
1778
  fix: "Send the configured realtime client token by query, header, bearer token, or websocket subprotocol.",
1694
1779
  },
1695
1780
  zero_replay_failed: {
1696
- summary: "The hosted Zero runtime could not fetch realtime replay events.",
1697
- fix: "Retry shortly; check the central realtime and control-plane logs if it persists.",
1781
+ summary: "The hosted Zero runtime cannot fetch realtime replay events.",
1782
+ fix: "Retry shortly. Check the central realtime and control-plane logs if it persists.",
1698
1783
  },
1699
1784
  zero_replay_query_invalid: {
1700
1785
  summary: "The hosted Zero realtime replay query is invalid.",
@@ -1725,7 +1810,7 @@ export const ERROR_DOCS = {
1725
1810
  fix: "Rebuild the generated routes and publish the version again.",
1726
1811
  },
1727
1812
  zero_run_compile_failed: {
1728
- summary: "The runtime could not compile a Zero run handler.",
1813
+ summary: "The runtime cannot compile a Zero run handler.",
1729
1814
  fix: "Inspect the compile diagnostics, fix the run-handler source, and publish again.",
1730
1815
  },
1731
1816
  zero_run_duplicate: {
@@ -1765,19 +1850,19 @@ export const ERROR_DOCS = {
1765
1850
  fix: "Rebuild and redeploy so the PHP bridge and Rust runner versions match.",
1766
1851
  },
1767
1852
  zero_runner_response_encode_failed: {
1768
- summary: "The Zero runner could not encode its response.",
1853
+ summary: "The Zero runner cannot encode its response.",
1769
1854
  fix: "Return JSON-serializable response metadata from the endpoint.",
1770
1855
  },
1771
1856
  zero_runner_stdin_invalid: {
1772
- summary: "The Zero runner could not read its request envelope.",
1773
- fix: "Retry; report the runtime bridge failure if it persists.",
1857
+ summary: "The Zero runner cannot read its request envelope.",
1858
+ fix: "Retry. Report the runtime bridge failure if it persists.",
1774
1859
  },
1775
1860
  zero_runner_stdin_too_large: {
1776
1861
  summary: "The Zero runner request envelope is too large.",
1777
1862
  fix: "Reduce request headers, body size, or route parameters.",
1778
1863
  },
1779
1864
  zero_runner_unavailable: {
1780
- summary: "The Zero runner process could not be started.",
1865
+ summary: "The Zero runner process cannot be started.",
1781
1866
  fix: "Verify the runner binary is installed and executable in the runtime.",
1782
1867
  },
1783
1868
  zero_runs_invalid: {
@@ -1794,27 +1879,7 @@ export const ERROR_DOCS = {
1794
1879
  },
1795
1880
  zero_shopify_unavailable: {
1796
1881
  summary: "The local Zero Shopify service is not configured.",
1797
- fix: "Configure a Shopify handler for zero dev before calling the Shopify service.",
1798
- },
1799
- zero_source_compile_failed: {
1800
- summary: "The Zero endpoint source fallback failed to compile.",
1801
- fix: "Fix the endpoint source and rebuild bytecode.",
1802
- },
1803
- zero_source_hash_mismatch: {
1804
- summary: "The Zero endpoint source hash does not match its artifact metadata.",
1805
- fix: "Rebuild and republish so source and endpoint metadata are from the same build.",
1806
- },
1807
- zero_source_invalid: {
1808
- summary: "The Zero endpoint source is invalid.",
1809
- fix: "Fix the generated endpoint source and rebuild.",
1810
- },
1811
- zero_source_path_invalid: {
1812
- summary: "The Zero endpoint source path is invalid.",
1813
- fix: "Rebuild the Zero routes so source paths stay inside the version bundle.",
1814
- },
1815
- zero_source_unreadable: {
1816
- summary: "The Zero endpoint source file could not be read.",
1817
- fix: "Verify the version finalized with generated source files present.",
1882
+ fix: "Configure a Shopify handler in the project, then restart `sf dev` before calling the Shopify service.",
1818
1883
  },
1819
1884
  wp_cloud_anonymous_pool_required: {
1820
1885
  summary: "This operation requires an anonymous pool site.",
@@ -1864,24 +1929,27 @@ export function errorDocMarkdown(code) {
1864
1929
  "",
1865
1930
  `**How to resolve:** ${doc.fix}`,
1866
1931
  "",
1867
- "## Error envelope",
1932
+ "## Error shape",
1868
1933
  "",
1869
- `Every ${PRODUCT} API error uses one envelope. \`code\` is stable and machine-readable,`,
1870
- "`param` (when present) points at the offending request field, and `details` may carry",
1871
- "structured context. Match on `code`, never on `message`.",
1934
+ `Every ${PRODUCT} API error is an RFC 9457 problem document, served as`,
1935
+ `\`${PROBLEM_CONTENT_TYPE}\`. \`code\` is stable and machine-readable, \`type\` links to`,
1936
+ "this page, `title` is a short label, `status` repeats the HTTP status, and `detail`",
1937
+ "explains this occurrence. `pointer` (when present) is an RFC 6901 JSON Pointer at the",
1938
+ "offending field in the request body, and `details` may carry structured context. Match on",
1939
+ "`code`, never on `detail`.",
1872
1940
  "",
1873
1941
  "```json",
1874
1942
  JSON.stringify({
1875
- error: {
1876
- code,
1877
- message: doc.summary,
1878
- docsUrl: errorDocsUrl(code),
1879
- requestId: "req_4mz0v8qk",
1880
- },
1943
+ type: errorDocsUrl(code),
1944
+ title: errorTitle(code),
1945
+ status: 400,
1946
+ detail: doc.summary,
1947
+ code,
1948
+ requestId: "req_4mz0v8qk",
1881
1949
  }, null, 2),
1882
1950
  "```",
1883
1951
  "",
1884
- `See the full list of error codes in the [error reference](${BRAND.websiteOrigin}/docs/errors).`,
1952
+ `See the full list of error codes in the [error reference](${serviceOrigin("www", "prod")}/docs/errors).`,
1885
1953
  "",
1886
1954
  ].join("\n");
1887
1955
  }