@spacefast/common 0.0.24 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/brand-assets/LICENSE-Haskoy.txt +93 -0
  2. package/brand-assets/haskoy-latin-variable.woff2 +0 -0
  3. package/brand-assets/spacefast-favicon.svg +4 -4
  4. package/brand-assets/spacefast-sf-full-bleed.svg +3 -3
  5. package/brand-assets/spacefast-wordmark.svg +2 -4
  6. package/dist/agents/connect-targets.d.ts +6 -146
  7. package/dist/agents/connect-targets.js +63 -295
  8. package/dist/agents/private-key-oauth.d.ts +31 -2
  9. package/dist/agents/private-key-oauth.js +166 -92
  10. package/dist/agents/registry/core.d.ts +292 -0
  11. package/dist/agents/registry/core.js +1388 -0
  12. package/dist/agents/registry/deeplink-probes.d.ts +23 -0
  13. package/dist/agents/registry/deeplink-probes.js +18 -0
  14. package/dist/agents/registry/node.d.ts +56 -0
  15. package/dist/agents/registry/node.js +339 -0
  16. package/dist/brand-assets-build.js +3 -6
  17. package/dist/brand-assets.d.ts +5 -15
  18. package/dist/brand-assets.js +12 -14
  19. package/dist/brand.d.ts +17 -0
  20. package/dist/brand.js +24 -4
  21. package/dist/config/domains.d.ts +79 -12
  22. package/dist/config/domains.js +128 -29
  23. package/dist/config/index.js +1 -2
  24. package/dist/contracts/abuse.js +9 -24
  25. package/dist/contracts/access-profiles.d.ts +86 -0
  26. package/dist/contracts/access-profiles.js +89 -0
  27. package/dist/contracts/access.d.ts +24 -30
  28. package/dist/contracts/access.js +33 -64
  29. package/dist/contracts/activity.d.ts +18 -1
  30. package/dist/contracts/activity.js +72 -26
  31. package/dist/contracts/analytics.js +8 -10
  32. package/dist/contracts/api-keys.d.ts +77 -52
  33. package/dist/contracts/api-keys.js +44 -24
  34. package/dist/contracts/application-journal.d.ts +216 -0
  35. package/dist/contracts/application-journal.js +167 -0
  36. package/dist/contracts/auth.d.ts +90 -17
  37. package/dist/contracts/auth.js +86 -17
  38. package/dist/contracts/beta.d.ts +9 -4
  39. package/dist/contracts/beta.js +20 -16
  40. package/dist/contracts/billing.d.ts +2 -1
  41. package/dist/contracts/billing.js +37 -11
  42. package/dist/contracts/bootstrap.d.ts +791 -0
  43. package/dist/contracts/bootstrap.js +51 -0
  44. package/dist/contracts/builds.d.ts +209 -18
  45. package/dist/contracts/builds.js +93 -27
  46. package/dist/contracts/channels.d.ts +43 -0
  47. package/dist/contracts/channels.js +25 -9
  48. package/dist/contracts/cli.d.ts +7 -0
  49. package/dist/contracts/cli.js +6 -0
  50. package/dist/contracts/collab-public.d.ts +1 -1
  51. package/dist/contracts/collab-public.js +5 -8
  52. package/dist/contracts/comments.d.ts +44 -34
  53. package/dist/contracts/comments.js +107 -77
  54. package/dist/contracts/commerce.d.ts +165 -0
  55. package/dist/contracts/commerce.js +146 -0
  56. package/dist/contracts/common.d.ts +3 -3
  57. package/dist/contracts/common.js +20 -31
  58. package/dist/contracts/content-contract-verification.d.ts +521 -0
  59. package/dist/contracts/content-contract-verification.js +320 -0
  60. package/dist/contracts/content-platform-fixture.d.ts +1278 -0
  61. package/dist/contracts/content-platform-fixture.js +44 -0
  62. package/dist/contracts/content-program.d.ts +994 -0
  63. package/dist/contracts/content-program.js +658 -0
  64. package/dist/contracts/content-sync.d.ts +290 -0
  65. package/dist/contracts/content-sync.js +167 -0
  66. package/dist/contracts/content.d.ts +432 -0
  67. package/dist/contracts/content.js +303 -0
  68. package/dist/contracts/continuation.d.ts +17 -1
  69. package/dist/contracts/continuation.js +23 -23
  70. package/dist/contracts/countries.js +3 -4
  71. package/dist/contracts/crons.d.ts +52 -0
  72. package/dist/contracts/crons.js +60 -0
  73. package/dist/contracts/dashboard-prefs.d.ts +56 -0
  74. package/dist/contracts/dashboard-prefs.js +51 -0
  75. package/dist/contracts/device-auth.d.ts +234 -37
  76. package/dist/contracts/device-auth.js +267 -53
  77. package/dist/contracts/docs.d.ts +1 -5
  78. package/dist/contracts/docs.js +7 -15
  79. package/dist/contracts/domains.d.ts +501 -93
  80. package/dist/contracts/domains.js +193 -55
  81. package/dist/contracts/email-preferences.d.ts +3 -3
  82. package/dist/contracts/email-preferences.js +6 -7
  83. package/dist/contracts/enums.d.ts +27 -26
  84. package/dist/contracts/enums.js +68 -61
  85. package/dist/contracts/error-code-meta.d.ts +283 -7
  86. package/dist/contracts/error-code-meta.js +97 -5
  87. package/dist/contracts/error-codes.d.ts +5 -5
  88. package/dist/contracts/error-codes.js +82 -17
  89. package/dist/contracts/events.d.ts +100 -20
  90. package/dist/contracts/events.js +107 -20
  91. package/dist/contracts/execution.d.ts +48 -64
  92. package/dist/contracts/execution.js +52 -62
  93. package/dist/contracts/feature-lifecycle.d.ts +73 -27
  94. package/dist/contracts/feature-lifecycle.js +86 -26
  95. package/dist/contracts/features.d.ts +68 -19
  96. package/dist/contracts/features.js +42 -41
  97. package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
  98. package/dist/contracts/frame-session.d.ts +192 -0
  99. package/dist/contracts/frame-session.js +164 -0
  100. package/dist/contracts/functions.d.ts +338 -164
  101. package/dist/contracts/functions.js +367 -198
  102. package/dist/contracts/git.d.ts +27 -33
  103. package/dist/contracts/git.js +10 -11
  104. package/dist/contracts/grant-copy.d.ts +43 -0
  105. package/dist/contracts/grant-copy.js +44 -0
  106. package/dist/contracts/grants.d.ts +62 -54
  107. package/dist/contracts/grants.js +124 -23
  108. package/dist/contracts/ids.d.ts +4 -1
  109. package/dist/contracts/ids.js +6 -3
  110. package/dist/contracts/internal.d.ts +8 -18
  111. package/dist/contracts/internal.js +13 -14
  112. package/dist/contracts/mcp.d.ts +28 -0
  113. package/dist/contracts/mcp.js +28 -0
  114. package/dist/contracts/me.d.ts +6 -1
  115. package/dist/contracts/me.js +12 -6
  116. package/dist/contracts/notifications.d.ts +27 -29
  117. package/dist/contracts/notifications.js +9 -4
  118. package/dist/contracts/oauth-resources.d.ts +112 -10
  119. package/dist/contracts/oauth-resources.js +116 -11
  120. package/dist/contracts/oauth-scope-actions.d.ts +90 -0
  121. package/dist/contracts/oauth-scope-actions.js +126 -0
  122. package/dist/contracts/operations.d.ts +27 -4
  123. package/dist/contracts/operations.js +12 -6
  124. package/dist/contracts/pages.d.ts +31 -7
  125. package/dist/contracts/pages.js +22 -5
  126. package/dist/contracts/partner-notifications.d.ts +3 -0
  127. package/dist/contracts/partner-notifications.js +65 -0
  128. package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
  129. package/dist/contracts/{platform.js → partner.js} +27 -40
  130. package/dist/contracts/plan-policy.js +1 -1
  131. package/dist/contracts/principal-assertion.d.ts +43 -0
  132. package/dist/contracts/principal-assertion.js +67 -0
  133. package/dist/contracts/principals.d.ts +73 -0
  134. package/dist/contracts/principals.js +59 -0
  135. package/dist/contracts/privacy.d.ts +11 -0
  136. package/dist/contracts/privacy.js +17 -0
  137. package/dist/contracts/problem-document.js +3 -4
  138. package/dist/contracts/publish-archive.d.ts +269 -161
  139. package/dist/contracts/publish-archive.js +11 -1
  140. package/dist/contracts/push-new.d.ts +8 -8
  141. package/dist/contracts/quotas.js +5 -5
  142. package/dist/contracts/realtime.d.ts +52 -0
  143. package/dist/contracts/realtime.js +54 -0
  144. package/dist/contracts/repository-connections.d.ts +44 -31
  145. package/dist/contracts/repository-connections.js +17 -5
  146. package/dist/contracts/resources.d.ts +105 -14
  147. package/dist/contracts/resources.js +150 -26
  148. package/dist/contracts/route-inventory.d.ts +358 -0
  149. package/dist/contracts/route-inventory.js +141 -0
  150. package/dist/contracts/runtime-api.d.ts +206 -82
  151. package/dist/contracts/runtime-api.js +131 -70
  152. package/dist/contracts/runtime-app.d.ts +13 -23
  153. package/dist/contracts/runtime-app.js +39 -24
  154. package/dist/contracts/runtime-components.d.ts +143 -0
  155. package/dist/contracts/runtime-components.js +199 -0
  156. package/dist/contracts/runtime-db.d.ts +49 -23
  157. package/dist/contracts/runtime-db.js +87 -22
  158. package/dist/contracts/runtime-purge.d.ts +8 -0
  159. package/dist/contracts/runtime-purge.js +5 -0
  160. package/dist/contracts/runtime-services.d.ts +43 -75
  161. package/dist/contracts/runtime-services.js +29 -49
  162. package/dist/contracts/runtime-storage.d.ts +15 -14
  163. package/dist/contracts/runtime-storage.js +30 -14
  164. package/dist/contracts/sf-config-v1.d.ts +48 -14
  165. package/dist/contracts/slugs.js +13 -4
  166. package/dist/contracts/space-config.d.ts +283 -19
  167. package/dist/contracts/space-config.js +430 -80
  168. package/dist/contracts/spaces.d.ts +376 -290
  169. package/dist/contracts/spaces.js +200 -135
  170. package/dist/contracts/superadmin-activity.d.ts +3 -43
  171. package/dist/contracts/superadmin-activity.js +6 -30
  172. package/dist/contracts/superadmin-emails.d.ts +1 -0
  173. package/dist/contracts/superadmin-emails.js +17 -1
  174. package/dist/contracts/superadmin-runtime.d.ts +199 -0
  175. package/dist/contracts/superadmin-runtime.js +141 -0
  176. package/dist/contracts/superadmin-search.d.ts +22 -2
  177. package/dist/contracts/superadmin-search.js +14 -6
  178. package/dist/contracts/superadmin-spaces.d.ts +438 -189
  179. package/dist/contracts/superadmin-spaces.js +131 -25
  180. package/dist/contracts/superadmin-teams.d.ts +5 -2
  181. package/dist/contracts/superadmin-teams.js +1 -2
  182. package/dist/contracts/superadmin-tenants.d.ts +627 -12
  183. package/dist/contracts/superadmin-tenants.js +32 -13
  184. package/dist/contracts/superadmin.d.ts +232 -37
  185. package/dist/contracts/superadmin.js +106 -22
  186. package/dist/contracts/tags.d.ts +85 -58
  187. package/dist/contracts/tags.js +47 -37
  188. package/dist/contracts/teams.d.ts +86 -26
  189. package/dist/contracts/teams.js +90 -31
  190. package/dist/contracts/tenants.d.ts +135 -0
  191. package/dist/contracts/tenants.js +120 -0
  192. package/dist/contracts/test-triggers.d.ts +70 -0
  193. package/dist/contracts/test-triggers.js +116 -0
  194. package/dist/contracts/theme-json.js +3 -8
  195. package/dist/contracts/transfers.d.ts +1 -0
  196. package/dist/contracts/transfers.js +3 -2
  197. package/dist/contracts/usage.d.ts +209 -0
  198. package/dist/contracts/usage.js +124 -12
  199. package/dist/contracts/variables.d.ts +2 -2
  200. package/dist/contracts/variables.js +9 -13
  201. package/dist/contracts/webhooks.d.ts +13 -5
  202. package/dist/contracts/webhooks.js +3 -1
  203. package/dist/contracts/zero.d.ts +72 -81
  204. package/dist/contracts/zero.js +80 -78
  205. package/dist/dashboard-paths/index.d.ts +24 -21
  206. package/dist/dashboard-paths/index.js +35 -47
  207. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
  208. package/dist/dashboard-paths/route-reservations.generated.js +36 -0
  209. package/dist/docs/agent-arrival.d.ts +92 -0
  210. package/dist/docs/agent-arrival.js +227 -0
  211. package/dist/docs/agent-output-policy.d.ts +6 -0
  212. package/dist/docs/agent-output-policy.js +22 -0
  213. package/dist/docs/agent-prose.d.ts +12 -18
  214. package/dist/docs/agent-prose.js +73 -51
  215. package/dist/docs/agent-setup.d.ts +72 -41
  216. package/dist/docs/agent-setup.js +339 -436
  217. package/dist/docs/catalog.d.ts +153 -95
  218. package/dist/docs/catalog.js +163 -48
  219. package/dist/docs/error-docs.d.ts +2098 -1
  220. package/dist/docs/error-docs.js +421 -144
  221. package/dist/docs/index-build.d.ts +0 -1
  222. package/dist/docs/index-build.js +2 -3
  223. package/dist/docs/page-context-prompt.d.ts +77 -0
  224. package/dist/docs/page-context-prompt.js +131 -0
  225. package/dist/docs/reference-urls.d.ts +46 -0
  226. package/dist/docs/reference-urls.js +79 -0
  227. package/dist/docs/search.d.ts +6 -8
  228. package/dist/docs/search.js +10 -13
  229. package/dist/docs/skill-distribution.d.ts +4 -1
  230. package/dist/docs/skill-distribution.js +10 -5
  231. package/dist/docs/skills.d.ts +120 -120
  232. package/dist/docs/skills.js +121 -73
  233. package/dist/docs/start-prompts.d.ts +45 -0
  234. package/dist/docs/start-prompts.js +62 -0
  235. package/dist/domain-exploration.js +9 -13
  236. package/dist/og-template.d.ts +56 -0
  237. package/dist/og-template.js +56 -0
  238. package/dist/slug-policy/index.js +5 -11
  239. package/dist/test-helpers/fetch-stub.js +1 -0
  240. package/dist/utils/browser-credential.d.ts +13 -6
  241. package/dist/utils/browser-credential.js +14 -7
  242. package/dist/utils/build-settings.d.ts +21 -1
  243. package/dist/utils/build-settings.js +133 -15
  244. package/dist/utils/canonical-json.d.ts +3 -5
  245. package/dist/utils/canonical-json.js +4 -5
  246. package/dist/utils/cast-transport.d.ts +5 -17
  247. package/dist/utils/cast-transport.js +6 -19
  248. package/dist/utils/claim-token.js +1 -2
  249. package/dist/utils/comment-avatars.js +4 -6
  250. package/dist/utils/concurrency.js +3 -3
  251. package/dist/utils/content-type.d.ts +7 -6
  252. package/dist/utils/content-type.js +73 -51
  253. package/dist/utils/credential-policy.d.ts +50 -6
  254. package/dist/utils/credential-policy.js +126 -59
  255. package/dist/utils/dns-instructions.js +9 -9
  256. package/dist/utils/egress-policy.fixtures.json +1 -1
  257. package/dist/utils/error-code.js +1 -0
  258. package/dist/utils/generate-space-name.d.ts +3 -8
  259. package/dist/utils/generate-space-name.js +3 -8
  260. package/dist/utils/grant-decision.fixtures.json +2 -2
  261. package/dist/utils/grants.d.ts +0 -1
  262. package/dist/utils/grants.js +7 -8
  263. package/dist/utils/gravatar.d.ts +2 -4
  264. package/dist/utils/gravatar.js +6 -12
  265. package/dist/utils/id-hints.js +14 -23
  266. package/dist/utils/idempotency.d.ts +3 -3
  267. package/dist/utils/idempotency.js +6 -7
  268. package/dist/utils/local-space-state.d.ts +23 -26
  269. package/dist/utils/local-space-state.js +46 -46
  270. package/dist/utils/oauth-signed-query.d.ts +3 -5
  271. package/dist/utils/oauth-signed-query.js +6 -9
  272. package/dist/utils/one-shot-replay.d.ts +7 -6
  273. package/dist/utils/one-shot-replay.js +3 -5
  274. package/dist/utils/page-colors.d.ts +15 -19
  275. package/dist/utils/page-colors.js +23 -45
  276. package/dist/utils/page-fonts.d.ts +1 -1
  277. package/dist/utils/page-fonts.js +8 -20
  278. package/dist/utils/page-preview.d.ts +0 -1
  279. package/dist/utils/page-preview.js +0 -1
  280. package/dist/utils/pages.d.ts +33 -3
  281. package/dist/utils/pages.js +83 -30
  282. package/dist/utils/privacy-regions.d.ts +19 -0
  283. package/dist/utils/privacy-regions.js +91 -0
  284. package/dist/utils/publish-form-data.d.ts +4 -5
  285. package/dist/utils/publish-form-data.js +2 -3
  286. package/dist/utils/publish-policy.d.ts +11 -17
  287. package/dist/utils/publish-policy.fixtures.json +11 -5
  288. package/dist/utils/publish-policy.js +65 -110
  289. package/dist/utils/query-client.d.ts +2 -0
  290. package/dist/utils/query-client.js +10 -1
  291. package/dist/utils/runtime-paths.d.ts +4 -4
  292. package/dist/utils/runtime-paths.js +6 -8
  293. package/dist/utils/runtime-upload.d.ts +9 -0
  294. package/dist/utils/runtime-upload.js +12 -0
  295. package/dist/utils/secure-local-file.d.ts +3 -3
  296. package/dist/utils/secure-local-file.js +23 -40
  297. package/dist/utils/space-config.d.ts +12 -15
  298. package/dist/utils/space-config.js +13 -16
  299. package/dist/utils/static-runtime-policy.d.ts +10 -7
  300. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  301. package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
  302. package/dist/utils/static-runtime-policy.generated.js +70 -0
  303. package/dist/utils/static-runtime-policy.js +31 -132
  304. package/dist/utils/storage-policy.js +1 -2
  305. package/dist/utils/upload-session.d.ts +4 -1
  306. package/dist/utils/upload-session.js +41 -19
  307. package/dist/utils/version-path.js +11 -19
  308. package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
  309. package/dist/utils/wpcom-auth-redirects.js +1 -4
  310. package/dist/vocabulary.d.ts +13 -13
  311. package/dist/vocabulary.js +52 -27
  312. package/package.json +15 -18
  313. package/dist/agents/client-registry.d.ts +0 -22
  314. package/dist/agents/client-registry.js +0 -41
  315. package/dist/docs/agent-handoff-document.d.ts +0 -15
  316. package/dist/docs/agent-handoff-document.js +0 -180
  317. package/dist/docs/agent-solutions.d.ts +0 -110
  318. package/dist/docs/agent-solutions.js +0 -183
  319. package/dist/utils/query-keys.d.ts +0 -84
  320. package/dist/utils/query-keys.js +0 -108
@@ -1,9 +1,8 @@
1
- // Error reference content (internal-docs/platform.md "Global API Conventions"):
2
- // every problem document `type` points at `https://spacefast.com/docs/errors/{code}`,
3
- // and those pages are GENERATED from this table one entry per member of
4
- // `ERROR_CODES`, asserted complete by the conformance suite so links never rot
5
- // and pages never go missing. apps/www renders the HTML pages and writes the
6
- // `.md` twins from the same entries.
1
+ // Error reference content (the platform spec "Global API Conventions"): every
2
+ // problem document `type` points at `https://spacefast.com/docs/errors/{code}`,
3
+ // and those pages are GENERATED from this table, one entry per `ERROR_CODES`
4
+ // member. The conformance suite asserts completeness, so links never rot; the
5
+ // website renders the HTML pages and `.md` twins from the same entries.
7
6
  import { BRAND } from "../brand.js";
8
7
  import { serviceOrigin } from "../config/domains.js";
9
8
  import { errorDocsUrl, errorTitle, PROBLEM_CONTENT_TYPE, } from "../contracts/error-codes.js";
@@ -15,7 +14,7 @@ export const ERROR_DOCS = {
15
14
  },
16
15
  account_suspended: {
17
16
  summary: "This account is suspended for a policy or abuse violation and cannot be used.",
18
- fix: "Contact support to review the suspension if you believe it is a mistake.",
17
+ fix: "If you believe the suspension is a mistake, contact support to review it.",
19
18
  },
20
19
  abuse_report_rate_limited: {
21
20
  summary: "Too many abuse reports were submitted from this client in a short window.",
@@ -23,7 +22,7 @@ export const ERROR_DOCS = {
23
22
  },
24
23
  abuse_takedown: {
25
24
  summary: "This space was disabled by an abuse takedown and cannot be served or modified.",
26
- fix: "If you believe this is a mistake, contact support with the space id.",
25
+ fix: "If you believe the takedown is a mistake, contact support with the space id.",
27
26
  },
28
27
  access_denied: {
29
28
  summary: "The authorization request was denied by the user.",
@@ -39,7 +38,7 @@ export const ERROR_DOCS = {
39
38
  },
40
39
  agent_handoff_origin_unsupported: {
41
40
  summary: "The dashboard origin this deployment is configured with cannot mint canonical agent handoff links.",
42
- fix: "Point SPACEFAST_DASHBOARD_URL at a valid HTTP(S) origin. If you cannot change it, contact support.",
41
+ fix: "Point SPACEFAST_DASHBOARD_URL at a valid HTTP or HTTPS origin. If you cannot change it, contact support.",
43
42
  },
44
43
  ambiguous_space_slug: {
45
44
  summary: "The slug matches spaces in more than one of your teams, so it cannot be resolved.",
@@ -54,8 +53,8 @@ export const ERROR_DOCS = {
54
53
  fix: "Wait for the window to pass, or sign in with an API key for higher limits.",
55
54
  },
56
55
  anonymous_space_limit_reached: {
57
- summary: "This client already holds the maximum number of unclaimed Spaces.",
58
- fix: "Sign in and publish into your account, or claim or delete one of the unclaimed Spaces you already have.",
56
+ summary: "This client already holds the maximum number of unclaimed spaces.",
57
+ fix: "Sign in and publish into your account, or claim or delete one of the unclaimed spaces you already have.",
59
58
  },
60
59
  api_key_scope_underivable: {
61
60
  summary: "A concrete access policy cannot be derived from the requested scope and permissions.",
@@ -69,6 +68,10 @@ export const ERROR_DOCS = {
69
68
  summary: "An authorization code is required to complete this step.",
70
69
  fix: "Pass the code returned by the authorization step.",
71
70
  },
71
+ authorization_level_not_allowed: {
72
+ summary: "This operation is reserved for a signed-in person, or the credential is acting at an authorization level the operation does not accept.",
73
+ fix: "This is not a scope problem and elevation will not clear it. Ask the person to perform the action in the dashboard.",
74
+ },
72
75
  authorization_pending: {
73
76
  summary: "The device login is not approved yet.",
74
77
  fix: "Keep polling at the advised interval until the user approves the request.",
@@ -79,7 +82,7 @@ export const ERROR_DOCS = {
79
82
  },
80
83
  build_execution_unavailable: {
81
84
  summary: "Build execution is not available on this deployment.",
82
- fix: "Publish prebuilt static output instead, or wait for builds to become available.",
85
+ fix: "Publish prebuilt output instead.",
83
86
  },
84
87
  build_failed: {
85
88
  summary: "The build run failed before producing a version.",
@@ -101,6 +104,10 @@ export const ERROR_DOCS = {
101
104
  summary: "The build process was killed, most likely after running out of memory.",
102
105
  fix: "Reduce the build's memory usage or concurrency, then start a new build.",
103
106
  },
107
+ build_output_contains_server_bundle: {
108
+ summary: "The build output contains a compiled server bundle (an OpenNext worker.js), which a file-only publish would expose as a public download.",
109
+ fix: "This app needs the Spacefast Functions pipeline: run `sf publish` in the project with the Spacefast CLI so the worker deploys as a Function, or point the output directory at a browser-ready export.",
110
+ },
104
111
  build_output_dir_missing: {
105
112
  summary: "The build finished but its output directory was not produced.",
106
113
  fix: "Point the output directory setting at the folder your build writes (for example dist, build, out, or public).",
@@ -111,7 +118,7 @@ export const ERROR_DOCS = {
111
118
  },
112
119
  blob_gate_record_missing: {
113
120
  summary: "The file behind this download link no longer exists.",
114
- fix: "Ask the owner for a fresh link; the underlying object was deleted.",
121
+ fix: "The underlying object was deleted. Ask the owner for a fresh link.",
115
122
  },
116
123
  blob_gate_token_invalid: {
117
124
  summary: "The download token is invalid or expired.",
@@ -139,7 +146,7 @@ export const ERROR_DOCS = {
139
146
  },
140
147
  claim_blocked_takedown: {
141
148
  summary: "This space is under an abuse takedown and cannot be claimed.",
142
- fix: "Contact support if you believe the takedown is a mistake.",
149
+ fix: "If you believe the takedown is a mistake, contact support.",
143
150
  },
144
151
  claim_target_not_found: {
145
152
  summary: "The team or account to claim the space into was not found.",
@@ -147,7 +154,7 @@ export const ERROR_DOCS = {
147
154
  },
148
155
  claimed_space_quota_exceeded: {
149
156
  summary: "Claiming this space would exceed the target team's space quota.",
150
- fix: "Delete unused spaces, then claim again. Still stuck? POST /v1/feedback with the error code and request id.",
157
+ fix: "Delete unused spaces, then claim again. If you are still stuck, POST /v1/feedback with the error code and requestId.",
151
158
  },
152
159
  cli_upgrade_required: {
153
160
  summary: "This CLI version is too old to talk to the API safely.",
@@ -155,7 +162,7 @@ export const ERROR_DOCS = {
155
162
  },
156
163
  config_file_too_large: {
157
164
  summary: "The sf.jsonc configuration file exceeds the maximum size.",
158
- fix: "Keep the configuration file under the documented size limit (256 KB).",
165
+ fix: "Keep the configuration file at or under 256 KB.",
159
166
  },
160
167
  config_functions_key_removed: {
161
168
  summary: "The sf.jsonc configuration still uses the removed top-level functions key.",
@@ -175,7 +182,7 @@ export const ERROR_DOCS = {
175
182
  },
176
183
  config_runtime_entry_missing: {
177
184
  summary: "The declared runtime has no entry module to compile.",
178
- 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.",
185
+ fix: "Name the entry in sf.jsonc: runtime.entry for functions, runtime.server and runtime.client for zero. Remove the runtime block to publish files without a runtime instead.",
179
186
  },
180
187
  config_runtime_invalid_kind: {
181
188
  summary: "The runtime block in the space configuration declares an unknown kind.",
@@ -183,11 +190,31 @@ export const ERROR_DOCS = {
183
190
  },
184
191
  config_templates_over_limit: {
185
192
  summary: "The configuration declares more template files than the plan allows.",
186
- fix: "Reduce the number of template entries in sf.jsonc. Still stuck? POST /v1/feedback with the error code and request id.",
193
+ fix: "Reduce the number of template entries in sf.jsonc. If you are still stuck, POST /v1/feedback with the error code and requestId.",
194
+ },
195
+ confirmation_denied: {
196
+ summary: "A person reviewed this exact action and denied it. The denial is terminal.",
197
+ fix: "Stop retrying. You cannot clear this yourself; report the denial to the person who asked for the action.",
198
+ },
199
+ confirmation_expired: {
200
+ summary: "The confirmation for this action expired before a person decided it.",
201
+ fix: "Request the action again to get a fresh confirmation URL and continuation token. Do not retry the old token.",
202
+ },
203
+ confirmation_mismatch: {
204
+ summary: "The continuation token is bound to different action terms or a different resource revision than the request presenting it.",
205
+ fix: "Request a fresh confirmation for the action you actually intend to perform.",
206
+ },
207
+ confirmation_required: {
208
+ summary: "This action destroys live content or spends money, so a person must approve this exact action before it runs.",
209
+ fix: "Send the person to the `url` in the error details, then poll `pollUrl` with the `continuationToken` every 5 seconds. Give up after 10 minutes and report back. No flag or environment variable can clear this.",
210
+ },
211
+ confirmation_token_required: {
212
+ summary: "This exact action already has a decision, and a retry without its continuation token cannot clear the gate.",
213
+ fix: "Resume the existing decision with its continuation token instead of repeating the original request.",
187
214
  },
188
215
  continuation_unavailable: {
189
216
  summary: "This space key can no longer be exchanged for an API key.",
190
- 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 space key as bearer auth instead of exchanging it. Still stuck? POST /v1/feedback with the error code and request id.",
217
+ fix: "If the space is claimed, ask its owner for an API key (dashboard: teamAgents → API keys). If it is still unclaimed, keep using the space key as bearer auth instead of exchanging it. If you are still stuck, POST /v1/feedback with the error code and requestId.",
191
218
  },
192
219
  continuation_used: {
193
220
  summary: "This space key was already exchanged for a durable API key.",
@@ -199,7 +226,7 @@ export const ERROR_DOCS = {
199
226
  },
200
227
  credential_not_yet_valid: {
201
228
  summary: "The credential is not valid yet because its start time is in the future.",
202
- fix: "Wait until the credential's notBefore time, or adjust it.",
229
+ fix: "Wait until the credential's notBefore time, or adjust the notBefore value.",
203
230
  },
204
231
  credential_retired: {
205
232
  summary: "This request used a retired Spacefast token format or authentication header.",
@@ -209,6 +236,10 @@ export const ERROR_DOCS = {
209
236
  summary: "The credential used for this request was revoked.",
210
237
  fix: "Create a new API key and update your client.",
211
238
  },
239
+ credential_sponsor_inactive: {
240
+ summary: "The person who authorized this machine credential is no longer an active member of the team it acts for.",
241
+ fix: "A team admin must re-authorize the credential, or point it at a live member, before it works again.",
242
+ },
212
243
  csam_blocked: {
213
244
  summary: "The content was blocked because it matched known child sexual abuse material.",
214
245
  fix: "This action is final and reported as required by law. Do not retry.",
@@ -217,6 +248,18 @@ export const ERROR_DOCS = {
217
248
  summary: "CSAM enforcement policy cannot be set below the mandatory account-suspend floor.",
218
249
  fix: "Set the CSAM category enforcement tier to account suspension.",
219
250
  },
251
+ dashboard_prefs_key_invalid: {
252
+ summary: "A dashboard preference key is empty or longer than the 64-character limit.",
253
+ fix: "Send preference keys that are between 1 and 64 characters long.",
254
+ },
255
+ dashboard_prefs_too_large: {
256
+ summary: "The merged dashboard preferences would exceed the 16KB serialized size limit.",
257
+ fix: "Store smaller values, or delete preferences you no longer need by setting them to null.",
258
+ },
259
+ dashboard_prefs_too_many_keys: {
260
+ summary: "The merged dashboard preferences would hold more than the 50 allowed keys.",
261
+ fix: "Delete preferences you no longer need by setting them to null before adding more.",
262
+ },
220
263
  data_location_immutable: {
221
264
  summary: "This request tried to change data location through an immutable path.",
222
265
  fix: "Data location is fixed when the space is created and cannot be changed afterwards. Create a new space in the region you want.",
@@ -225,13 +268,21 @@ export const ERROR_DOCS = {
225
268
  summary: "The live version has no database to read.",
226
269
  fix: 'Publish a Zero app, or declare `"database": true` under `runtime` in sf.jsonc for a Functions app.',
227
270
  },
271
+ decision_execution_lost: {
272
+ summary: "The approved action's execution lease is no longer held, so its result cannot be recorded.",
273
+ fix: "Poll the continuation to read the decision's current state before requesting the action again.",
274
+ },
275
+ decision_in_progress: {
276
+ summary: "This approved action is already executing.",
277
+ fix: "Poll the continuation instead of retrying the action; the original receipt is returned once it finishes.",
278
+ },
228
279
  device_authorization_failed: {
229
280
  summary: "The device login request failed and cannot be completed.",
230
281
  fix: "Start a new device login flow.",
231
282
  },
232
283
  device_verification_rate_limited: {
233
284
  summary: "Too many incorrect device codes were entered in a short window.",
234
- fix: "Wait for the lockout to pass, then enter the code shown by your CLI exactly.",
285
+ fix: "Wait for the lockout to pass, then enter the code exactly as your CLI shows it.",
235
286
  },
236
287
  dns_export_required: {
237
288
  summary: "This operation requires exporting the current DNS records first.",
@@ -243,7 +294,7 @@ export const ERROR_DOCS = {
243
294
  },
244
295
  dns_import_partial_visibility: {
245
296
  summary: "The DNS import cannot see the full zone, so importing would lose records.",
246
- fix: "Verify delegation and retry once the full zone is visible.",
297
+ fix: "Verify delegation. Once the full zone is visible, retry the import.",
247
298
  },
248
299
  dns_provider_auth_expired: {
249
300
  summary: "The connected DNS provider authorization expired or was revoked.",
@@ -251,7 +302,7 @@ export const ERROR_DOCS = {
251
302
  },
252
303
  dns_provider_batch_unsupported: {
253
304
  summary: "The connected DNS provider cannot apply this batch with the required semantics.",
254
- fix: "Split the change or use a provider/zone that supports atomic batch writes.",
305
+ fix: "Split the change, or use a provider or zone that supports atomic batch writes.",
255
306
  },
256
307
  dns_provider_change_pending: {
257
308
  summary: "The DNS provider accepted the change but propagation or provider completion is still pending.",
@@ -323,7 +374,7 @@ export const ERROR_DOCS = {
323
374
  },
324
375
  dns_provider_replace_all_write_strategy: {
325
376
  summary: "This provider applies DNS changes with a replace-all write strategy.",
326
- fix: "Review the full-zone diff carefully so unrelated MX, TXT, CAA, NS, and wildcard records are preserved.",
377
+ fix: "To preserve unrelated MX, TXT, CAA, NS, and wildcard records, review the full-zone diff carefully.",
327
378
  },
328
379
  dns_provider_snapshot_stale: {
329
380
  summary: "The cached DNS provider snapshot is stale.",
@@ -331,7 +382,7 @@ export const ERROR_DOCS = {
331
382
  },
332
383
  dns_provider_snapshot_unavailable: {
333
384
  summary: `${BRAND.productName} cannot cache the latest DNS provider snapshot.`,
334
- fix: "Retry refresh after the cache or provider recovers. Do not edit connected-provider records from stale data.",
385
+ fix: "Retry the refresh after the cache or provider recovers. Do not edit connected-provider records from stale data.",
335
386
  },
336
387
  dns_provider_temporarily_unavailable: {
337
388
  summary: "The DNS provider is rate-limited, degraded, or temporarily unavailable.",
@@ -403,7 +454,7 @@ export const ERROR_DOCS = {
403
454
  },
404
455
  domain_quota_exceeded: {
405
456
  summary: "Adding this domain would exceed the plan's external domain allowance.",
406
- fix: "Remove unused domains. Still stuck? POST /v1/feedback with the error code and request id.",
457
+ fix: "Remove unused domains. If you are still stuck, POST /v1/feedback with the error code and requestId.",
407
458
  },
408
459
  domain_registration_active: {
409
460
  summary: "The domain has an active registration, which blocks this operation.",
@@ -415,7 +466,7 @@ export const ERROR_DOCS = {
415
466
  },
416
467
  domain_reserved_suffix: {
417
468
  summary: `The hostname is under a ${BRAND.productName}-managed suffix and cannot be added as a domain.`,
418
- fix: `Use a domain you own. ${BRAND.productName} assigns default and management hostnames automatically.`,
469
+ fix: `Use a domain you own. ${BRAND.productName} assigns default hostnames automatically.`,
419
470
  },
420
471
  domain_transfer_active: {
421
472
  summary: "The domain has a transfer in progress, which blocks this operation.",
@@ -437,9 +488,21 @@ export const ERROR_DOCS = {
437
488
  summary: "The version upload declares the same file path twice.",
438
489
  fix: "Deduplicate the file list so every path appears once.",
439
490
  },
491
+ elevation_not_required: {
492
+ summary: "The grant already includes every scope the elevation asked for.",
493
+ fix: "Retry the operation with the credential you already have; no elevation is needed.",
494
+ },
495
+ email_already_claimed: {
496
+ summary: "That email address is already verified on an account.",
497
+ fix: "Sign in with the address instead of adding it, or use a different address.",
498
+ },
499
+ email_verification_code_invalid: {
500
+ summary: "The emailed confirmation code is wrong, expired, or already used.",
501
+ fix: "Request a new code and enter the six digits from the newest email.",
502
+ },
440
503
  enforcement_policy_overlap: {
441
504
  summary: "Enforcement policy severity ranges overlap within a category.",
442
- fix: "Adjust the category ranges so each severity is covered by at most one policy.",
505
+ fix: "Adjust the category ranges so at most one policy covers each severity.",
443
506
  },
444
507
  expired_token: {
445
508
  summary: "The token is expired.",
@@ -447,7 +510,7 @@ export const ERROR_DOCS = {
447
510
  },
448
511
  feature_unavailable: {
449
512
  summary: "This feature is not available on this deployment or plan.",
450
- fix: "Check the feature's availability and try again when it is enabled for your team.",
513
+ fix: "Check the feature's availability. When the feature is enabled for your team, try again.",
451
514
  },
452
515
  files_mode_does_not_support_spa: {
453
516
  summary: "SPA fallback cannot be combined with files-listing mode.",
@@ -459,11 +522,11 @@ export const ERROR_DOCS = {
459
522
  },
460
523
  free_external_proxy_disabled: {
461
524
  summary: "Proxy routes to external upstreams are not available on the Free plan.",
462
- fix: "Remove the proxy rules before publishing. Still stuck? POST /v1/feedback with the error code and request id.",
525
+ fix: "Remove the proxy rules before publishing. If you are still stuck, POST /v1/feedback with the error code and requestId.",
463
526
  },
464
527
  idempotency_conflict_in_progress: {
465
528
  summary: "Another request with the same Idempotency-Key is still in flight.",
466
- fix: "Wait for the original request to finish. Its response will be replayed.",
529
+ fix: "Wait for the original request to finish. The API will replay that request's response.",
467
530
  },
468
531
  idempotency_key_reused: {
469
532
  summary: "The Idempotency-Key was reused with a different request body.",
@@ -475,15 +538,19 @@ export const ERROR_DOCS = {
475
538
  },
476
539
  inject_invalid: {
477
540
  summary: "The inject config key is malformed.",
478
- fix: "Make inject an object whose head/bodyStart/bodyEnd/noscript entries are arrays of up to 16 strings.",
541
+ fix: "Make `inject` an object whose `head`, `bodyStart`, `bodyEnd`, and `noscript` entries are arrays of up to 16 strings.",
479
542
  },
480
543
  inject_snippet_too_large: {
481
544
  summary: "An inject snippet exceeds the per-snippet size limit.",
482
545
  fix: "Keep each inject snippet at or under 8 KB.",
483
546
  },
547
+ insufficient_scope: {
548
+ summary: "The credential authenticated, but its granted scopes do not include a set this operation accepts.",
549
+ fix: "Read the `WWW-Authenticate` challenge for the missing scopes, then request elevation or reconnect with them.",
550
+ },
484
551
  internal_error: {
485
552
  summary: "Something went wrong on our side.",
486
- fix: "Retry the request. If it persists, contact support with the requestId.",
553
+ fix: "Retry the request. If the error persists, contact support with the requestId.",
487
554
  },
488
555
  invalid_claim_token: {
489
556
  summary: "The space key is invalid or does not match this space.",
@@ -497,6 +564,10 @@ export const ERROR_DOCS = {
497
564
  summary: "The requested data location is not a supported region.",
498
565
  fix: "Pick a region from the documented data locations, or use auto.",
499
566
  },
567
+ invalid_decision_state: {
568
+ summary: "The decision record is in a state this endpoint cannot interpret.",
569
+ fix: "Request the action again to open a fresh decision.",
570
+ },
500
571
  invalid_device_code: {
501
572
  summary: "The device code is invalid or expired.",
502
573
  fix: "Start a new device login flow.",
@@ -507,7 +578,11 @@ export const ERROR_DOCS = {
507
578
  },
508
579
  invalid_domain_name: {
509
580
  summary: "The domain name is not a valid registrable hostname.",
510
- fix: "Check the spelling and use a fully-qualified domain name.",
581
+ fix: "Check the spelling and use a fully qualified domain name.",
582
+ },
583
+ invalid_elevation_request: {
584
+ summary: "An elevation request needs at least one scope and a rationale of 1 to 1024 characters.",
585
+ fix: "Send a non-empty scope list and a specific rationale, then retry.",
511
586
  },
512
587
  invalid_file_path: {
513
588
  summary: "A file path in the request is not a valid space path.",
@@ -551,7 +626,19 @@ export const ERROR_DOCS = {
551
626
  },
552
627
  invalid_user_code: {
553
628
  summary: "The user code does not match a pending device login.",
554
- fix: "Enter the code exactly as shown by your CLI. Codes expire after a few minutes.",
629
+ fix: "Enter the code exactly as your CLI shows it. Codes expire after a few minutes.",
630
+ },
631
+ invalid_usage_bucket: {
632
+ summary: "The usage bucket has an invalid time range.",
633
+ fix: "Set bucketEnd to an instant after bucketStart, then retry.",
634
+ },
635
+ invalid_usage_correction: {
636
+ summary: "The correction does not match the original usage record.",
637
+ fix: "Use the same tenant, principal, space, mode, dimension, and bucket as the original.",
638
+ },
639
+ invalid_usage_window: {
640
+ summary: "The requested usage window is invalid or longer than 92 days.",
641
+ fix: "Use a positive window of 92 days or less.",
555
642
  },
556
643
  invalid_version_path: {
557
644
  summary: "A file path in the version is not a valid space path.",
@@ -579,7 +666,7 @@ export const ERROR_DOCS = {
579
666
  },
580
667
  invalid_zero_realtime_replay_query: {
581
668
  summary: "The Zero realtime replay query parameters are invalid.",
582
- fix: "Use a valid afterEventId cursor and a numeric replay limit between 1 and 100.",
669
+ fix: "Send a retained `afterEventId` from a previous page's `nextAfterEventId`, and a replay limit between 1 and 100.",
583
670
  },
584
671
  invitation_already_exists: {
585
672
  summary: "An invitation for this email already exists on the team.",
@@ -595,15 +682,35 @@ export const ERROR_DOCS = {
595
682
  },
596
683
  invitation_not_pending: {
597
684
  summary: "The invitation is no longer pending.",
598
- fix: "Create a new invitation if the member still needs to join.",
685
+ fix: "If the member still needs to join, create a new invitation.",
599
686
  },
600
687
  ip_blocked: {
601
688
  summary: "Requests from this IP address are blocked for abuse or policy reasons.",
602
- fix: "Contact support with your IP address if you believe this block is in error.",
689
+ fix: "If you believe this block is a mistake, contact support with your IP address.",
690
+ },
691
+ issuer_exists: {
692
+ summary: "This partner token issuer is already active for another tenant.",
693
+ fix: "Use a globally unique issuer URL, or revoke the existing issuer before registering it here.",
694
+ },
695
+ issuer_not_active: {
696
+ summary: "The partner token issuer is registered but is not active.",
697
+ fix: "Activate the issuer, then request a new partner token.",
698
+ },
699
+ issuer_proof_invalid: {
700
+ summary: "The partner token issuer key-possession proof is invalid.",
701
+ fix: "Sign the current challenge and minted audience with one of the registered Ed25519 keys, then retry activation.",
702
+ },
703
+ issuer_tenant_occupied: {
704
+ summary: "This tenant already has a pending or active partner token issuer.",
705
+ fix: "Activate or revoke the tenant's existing issuer before registering another one.",
706
+ },
707
+ issuer_unknown: {
708
+ summary: "The partner token names an issuer that Spacefast does not recognize.",
709
+ fix: "Register the exact token issuer, then request a new partner token.",
603
710
  },
604
711
  job_not_found: {
605
712
  summary: "The background job was not found.",
606
- fix: "Verify the job id. Completed jobs are eventually pruned.",
713
+ fix: "Verify the job id. Spacefast eventually prunes completed jobs.",
607
714
  },
608
715
  job_not_promotable: {
609
716
  summary: "The job cannot be promoted in its current state.",
@@ -635,11 +742,11 @@ export const ERROR_DOCS = {
635
742
  },
636
743
  malware_detected: {
637
744
  summary: "Malware was detected in the uploaded content.",
638
- fix: "Remove the flagged files. Contact support if you believe this is a false positive.",
745
+ fix: "Remove the flagged files. If you believe the detection is a false positive, contact support.",
639
746
  },
640
747
  managed_domain_protected: {
641
748
  summary: "This is a system-managed view.fast hostname and cannot be mutated like a custom domain.",
642
- fix: "Use it as a read-only managed hostname, or add a custom domain if you need editable DNS and binding controls.",
749
+ fix: "Use the hostname as a read-only managed hostname. If you need editable DNS and binding controls, add a custom domain.",
643
750
  },
644
751
  manifest_body_too_large: {
645
752
  summary: "The upload manifest body exceeds the maximum size.",
@@ -647,7 +754,7 @@ export const ERROR_DOCS = {
647
754
  },
648
755
  manifest_duplicate_path: {
649
756
  summary: "The upload manifest declares the same path more than once.",
650
- fix: "Deduplicate paths. Comparisons use the canonical (decoded, NFC) form.",
757
+ fix: "Deduplicate paths. Comparisons use the canonical form: decoded and NFC-normalized.",
651
758
  },
652
759
  manifest_too_many_files: {
653
760
  summary: "The upload manifest declares more files than the allowed ceiling.",
@@ -667,23 +774,27 @@ export const ERROR_DOCS = {
667
774
  },
668
775
  move_target_capacity_lost: {
669
776
  summary: "The selected move target no longer has capacity for the space.",
670
- fix: "Retry the move with a different target or after capacity is freed.",
777
+ fix: "Retry the move with a different target, or retry after capacity is freed.",
671
778
  },
672
779
  name_managed_by_config: {
673
780
  summary: "The space name is managed by sf.jsonc while its live version declares one.",
674
- fix: "Change name in sf.jsonc and publish, or remove name from the file to rename the space through the API.",
781
+ fix: "Change `name` in `sf.jsonc` and publish, or remove `name` from the file to rename the space through the API.",
675
782
  },
676
783
  nameserver_delegation_required: {
677
784
  summary: `This operation requires the domain to be delegated to ${BRAND.productName} nameservers.`,
678
- fix: "Update the domain's nameservers at the registrar, then retry once delegation propagates.",
785
+ fix: "Update the domain's nameservers at the registrar. After delegation propagates, retry.",
679
786
  },
680
787
  nameserver_divergence: {
681
788
  summary: "The domain's observed nameservers diverge from the expected set.",
682
789
  fix: "Align the registrar's nameserver records with the expected set, then re-check.",
683
790
  },
791
+ no_space_selected: {
792
+ summary: "The command needs a Space and this directory does not select one.",
793
+ fix: "Pass --space, link the directory with `sf link --space <id>`, or run it where a project link already selects a Space. `sf spaces ls` lists what the credential can reach.",
794
+ },
684
795
  noop_publish: {
685
796
  summary: "The publish matched the live version exactly, so nothing changed.",
686
- fix: "No action needed. The existing live version already serves this content.",
797
+ fix: "No action is needed. The existing live version already serves this content.",
687
798
  },
688
799
  not_enrolled: {
689
800
  summary: "This account is not enrolled in the private beta, so the API cannot be used yet.",
@@ -691,11 +802,27 @@ export const ERROR_DOCS = {
691
802
  },
692
803
  not_found: {
693
804
  summary: "The requested resource was not found.",
694
- fix: "Verify the id and that your credential can access the resource.",
805
+ fix: "Verify that the id is correct and that your credential can access the resource.",
806
+ },
807
+ partner_preset_not_grantable: {
808
+ summary: "The `partner_admin` preset is a tenant-rooted partner credential and cannot be minted as an ordinary team API key.",
809
+ fix: "Ask an operator to bootstrap a partner key for the tenant, or request a team-scoped preset such as `space_admin`.",
810
+ },
811
+ partner_tenant_immutable_client: {
812
+ summary: "The tenant's provider client cannot be changed.",
813
+ fix: "Create a new tenant with the desired provider client instead.",
814
+ },
815
+ password_already_set: {
816
+ summary: "The account already has a password.",
817
+ fix: "Change the existing password instead of setting a new one.",
818
+ },
819
+ password_compromised: {
820
+ summary: "The password appears in a public breach corpus.",
821
+ fix: "Pick a password you have not used anywhere else, then try again.",
695
822
  },
696
823
  path_case_collision: {
697
824
  summary: "Two file paths differ only by letter case, which collides on serving.",
698
- fix: "Rename one of the files so paths are unique case-insensitively.",
825
+ fix: "Rename one of the files so that paths are unique case-insensitively.",
699
826
  },
700
827
  path_too_long: {
701
828
  summary: "A file path exceeds the maximum length.",
@@ -707,35 +834,91 @@ export const ERROR_DOCS = {
707
834
  },
708
835
  plan_grant_already_revoked: {
709
836
  summary: "This plan grant was already revoked.",
710
- fix: "Nothing to do. Create a new grant if the team should regain the plan.",
837
+ fix: "No action is needed. If the team should regain the plan, create a new grant.",
838
+ },
839
+ plan_unknown: {
840
+ summary: "The requested plan name is not in the tenant's live plan catalog, so it cannot be assigned to a principal.",
841
+ fix: "Assign a plan declared in the tenant's system-space manifest. List the catalog's plan names and use one of them.",
711
842
  },
712
843
  placement_invalid_burstable: {
713
844
  summary: "The placement burstable option was used with an unsupported placement mode.",
714
- fix: 'Set placement.mode to "dedicated" before setting placement.burstable, or remove the burstable option.',
715
- },
716
- platform_tenant_immutable_client: {
717
- summary: "The tenant's provider client cannot be changed.",
718
- fix: "Create a new tenant with the desired provider client instead.",
845
+ fix: 'Set `placement.mode` to `"dedicated"` before setting `placement.burstable`, or remove the burstable option.',
719
846
  },
720
847
  policy_exceeds_grantor: {
721
848
  summary: "The requested key policy grants more than your own credential allows.",
722
849
  fix: "Request a policy that is a subset of the credential creating the key.",
723
850
  },
851
+ prebuilt_metadata_invalid: {
852
+ summary: "The metadata file next to the prebuilt archive exists but cannot be read or parsed, so the build's runtime shape is unknown.",
853
+ fix: "Re-run `sf build` to regenerate the archive and its metadata together. If the archive contains plain files, delete the metadata file.",
854
+ },
724
855
  ingest_admission_exceeded: {
725
856
  summary: "Too many concurrent uploads for this space.",
726
- fix: "Wait for the Retry-After window, then resume; at most 4 uploads run per space at once.",
857
+ fix: "Wait for the Retry-After window, then resume. At most 4 uploads run per space at once.",
858
+ },
859
+ primary_email_not_removable: {
860
+ summary: "The primary email address cannot be removed while it is the primary.",
861
+ fix: "Make another verified address primary first, then remove this one.",
862
+ },
863
+ principal_closed: {
864
+ summary: "The external principal is closed. Its spaces are tombstoned and cannot be modified.",
865
+ fix: "A closed principal is terminal and cannot be reopened; create a new principal to resume.",
866
+ },
867
+ principal_has_active_spaces: {
868
+ summary: "The external principal still owns spaces, so it cannot be closed.",
869
+ fix: "Delete the principal's spaces first, or retry with `force` to tombstone them as part of the close.",
870
+ },
871
+ principal_not_found: {
872
+ summary: "No external principal with that id exists in this tenant.",
873
+ fix: "List `/v1/principals` to see the ids this tenant knows; a principal appears only once it owns a resource.",
727
874
  },
728
875
  principal_space_mismatch: {
729
876
  summary: "The space does not belong to the principal in the request.",
730
877
  fix: "Use the space's owning team or account in the request path.",
731
878
  },
879
+ principal_suspended: {
880
+ summary: "The external principal is suspended. Its spaces serve the suspended page and its mutations are blocked.",
881
+ fix: "Unsuspend the principal to restore serving and writes; a Spacefast-applied suspension can only be lifted by Spacefast.",
882
+ },
883
+ principal_suspension_locked: {
884
+ summary: "The suspension was applied by Spacefast (legal/abuse) and cannot be lifted by the partner.",
885
+ fix: "Contact Spacefast support to resolve a platform-applied suspension.",
886
+ },
732
887
  promote_admission_exceeded: {
733
888
  summary: "Too many archived files are being restored for this space right now.",
734
- fix: "Retry shortly; restores are limited to protect the host.",
889
+ fix: "Retry shortly. Spacefast limits restores to protect the host.",
890
+ },
891
+ promotion_live_content_missing: {
892
+ summary: "The live tenant's system space has nothing published, so promotion has no content to carry forward.",
893
+ fix: "Publish the live system space once, then promote the test tenant again.",
894
+ },
895
+ promotion_live_system_space_invalid: {
896
+ summary: "The space designated as the live tenant's system space is not an active space that tenant owns.",
897
+ fix: "Designate a live, active space owned by this tenant as its system space, then promote again.",
898
+ },
899
+ promotion_live_system_space_not_designated: {
900
+ summary: "The live tenant has no designated system space, and promotion publishes the test manifest onto it.",
901
+ fix: "Set the live tenant's systemSpaceId to a space it owns, then promote again.",
902
+ },
903
+ promotion_not_live_tenant: {
904
+ summary: "Promotion targets a live tenant, and the tenant named in the request is not in live mode.",
905
+ fix: "Call promotion against the live tenant, not its test twin.",
906
+ },
907
+ promotion_nothing_to_promote: {
908
+ summary: "The test tenant's system space has no live manifest, so there is no configuration to promote.",
909
+ fix: "Publish the test tenant's system space first, then promote it.",
910
+ },
911
+ promotion_runtime_publish_incomplete: {
912
+ summary: "The promoted version was accepted but its runtime publish did not finish, so live is unchanged.",
913
+ fix: "Retry the promotion. If it keeps failing, contact support with the `requestId`.",
914
+ },
915
+ promotion_test_twin_missing: {
916
+ summary: "This live tenant has no linked test tenant, so there is nothing to promote from.",
917
+ fix: "Create the tenant's test twin and publish its system space before promoting.",
735
918
  },
736
919
  provider_error: {
737
- summary: "The hosting provider reported an error.",
738
- fix: "Retry. If the error persists, contact support with the requestId.",
920
+ summary: "WP Cloud reported an error.",
921
+ fix: "Retry. If the error persists, contact support with the `requestId`.",
739
922
  },
740
923
  provider_job_failed: {
741
924
  summary: "A hosting-provider job failed while processing this operation.",
@@ -743,35 +926,35 @@ export const ERROR_DOCS = {
743
926
  },
744
927
  provider_job_timeout: {
745
928
  summary: "A hosting-provider job timed out while processing this operation.",
746
- fix: "Retry the operation. If the provider is slow right now, wait and retry again.",
929
+ fix: "Retry the operation. If the provider is slow, wait and retry again.",
747
930
  },
748
931
  provider_privilege: {
749
- summary: "The hosting provider does not grant this client permission to change the setting.",
932
+ summary: "WP Cloud does not grant this client permission to change the setting.",
750
933
  fix: "Leave the provider-owned setting unchanged or contact support to request the required provider capability.",
751
934
  },
752
935
  provider_runtime_feature_unsupported: {
753
- summary: "The hosting provider does not support this runtime feature.",
936
+ summary: "WP Cloud does not support this runtime feature.",
754
937
  fix: "Check the feature's availability for this site's runtime.",
755
938
  },
756
939
  provider_site_id_required: {
757
940
  summary: "A provider site id is required for this internal operation.",
758
- fix: "Pass the provider site reference.",
941
+ fix: "Pass the provider site id.",
759
942
  },
760
943
  proxy_upstream_denied: {
761
944
  summary: "The proxy upstream is on a denied network and cannot be used.",
762
- fix: "Proxy only to public HTTPS upstreams. Private and internal addresses are blocked.",
945
+ fix: "Proxy only to public HTTPS upstreams. Spacefast blocks private and internal addresses.",
763
946
  },
764
947
  proxy_upstream_unresolved: {
765
948
  summary: "The proxy upstream hostname cannot be resolved.",
766
- fix: "Verify the upstream DNS name resolves publicly, then publish again.",
949
+ fix: "Verify that the upstream DNS name resolves publicly, then publish again.",
767
950
  },
768
951
  publish_session_expired: {
769
952
  summary: "This publish session expired before it was finalized.",
770
- fix: "Start a new publish; declared uploads are kept for 24 hours only.",
953
+ fix: "Start a new publish. Spacefast keeps declared uploads for 24 hours only.",
771
954
  },
772
955
  publish_archive_compression_ratio_exceeded: {
773
956
  summary: "The archive's compression ratio is suspiciously high and was rejected.",
774
- fix: "Repackage the content without highly-compressible filler data.",
957
+ fix: "Repackage the content without highly compressible filler data.",
775
958
  },
776
959
  publish_archive_expanded_size_exceeded: {
777
960
  summary: "The archive expands beyond the maximum allowed total size.",
@@ -787,7 +970,7 @@ export const ERROR_DOCS = {
787
970
  },
788
971
  publish_base_changed: {
789
972
  summary: "Someone published new space settings after the base you loaded, so saving would overwrite their change.",
790
- fix: "Reload the latest settings, review the difference, and save again. Pass force only to overwrite deliberately.",
973
+ fix: "Reload the latest settings, review the difference, and save again. Pass `force` only to overwrite deliberately.",
791
974
  },
792
975
  publish_bytes_missing: {
793
976
  summary: "The publish has no complete staged content to materialize.",
@@ -795,7 +978,7 @@ export const ERROR_DOCS = {
795
978
  },
796
979
  publish_config_unsupported: {
797
980
  summary: "The publish carries configuration this endpoint does not support.",
798
- fix: "Move the configuration into sf.jsonc or the space settings.",
981
+ fix: "Move the configuration into `sf.jsonc` or the space settings.",
799
982
  },
800
983
  publish_failed: {
801
984
  summary: "The publish failed before going live.",
@@ -815,11 +998,11 @@ export const ERROR_DOCS = {
815
998
  },
816
999
  publish_not_cancelable: {
817
1000
  summary: "The publish is past the point where it can be canceled.",
818
- fix: "Wait for the publish to finish, then roll back by promoting a previous version if needed.",
1001
+ fix: "Wait for the publish to finish. To roll back, promote a previous version.",
819
1002
  },
820
1003
  publish_path_collision: {
821
1004
  summary: "Two different artifacts would serve the same URL after directory-index or clean-URL resolution.",
822
- fix: "Rename or remove one artifact so every request route has one owner.",
1005
+ fix: "Rename or remove one artifact so that every request route has one owner.",
823
1006
  },
824
1007
  publish_path_invalid: {
825
1008
  summary: "A publish path is not a relative, normalized POSIX path.",
@@ -827,7 +1010,7 @@ export const ERROR_DOCS = {
827
1010
  },
828
1011
  publish_setup_failed: {
829
1012
  summary: "Provisioning for this publish failed.",
830
- fix: "Retry the publish. If it persists, contact support with the requestId.",
1013
+ fix: "Retry the publish. If the error persists, contact support with the `requestId`.",
831
1014
  },
832
1015
  publish_snapshot_empty: {
833
1016
  summary: "An empty snapshot was sent without an explicit base version.",
@@ -845,13 +1028,17 @@ export const ERROR_DOCS = {
845
1028
  summary: "The named job queue does not exist.",
846
1029
  fix: "Check the queue name against the operator queue list.",
847
1030
  },
1031
+ quota_exceeded: {
1032
+ summary: "This action would exceed a quota on the plan assigned to the owning customer. The problem details name which quota (for example, the spaces cap) and its limit.",
1033
+ fix: "Delete an existing resource to free room, or assign the customer a plan whose quota allows it.",
1034
+ },
848
1035
  response_headers_unservable: {
849
1036
  summary: "A file needs a response header that the platform cannot deliver for large files.",
850
1037
  fix: "Reduce the file below 100 MiB or drop the custom header.",
851
1038
  },
852
1039
  response_table_too_large: {
853
1040
  summary: "A compiled response table exceeded the 1 MiB per-file limit.",
854
- fix: "This version has an unusually dense path set; contact support with the requestId.",
1041
+ fix: "This version has an unusually dense path set. Contact support with the `requestId`.",
855
1042
  },
856
1043
  rate_limited: {
857
1044
  summary: "Too many requests were made in a short window.",
@@ -867,23 +1054,23 @@ export const ERROR_DOCS = {
867
1054
  },
868
1055
  resource_revision_changed: {
869
1056
  summary: "The resource changed after you loaded it, so the stale write was rejected.",
870
- fix: "Use the current resource returned in error.details.current, reapply the intended fields, and send its revision as expectedRevision.",
1057
+ fix: "Use the current resource returned in `error.details.current`, reapply the intended fields, and send its revision as `expectedRevision`.",
871
1058
  },
872
1059
  review_item_claimed: {
873
1060
  summary: "Another reviewer already claimed this review item.",
874
- fix: "Pick a different item, or ask the current assignee (error.details.assignedToUserId) to release it.",
1061
+ fix: "Pick a different item, or ask the current assignee to release it. The assignee's id is in `error.details.assignedToUserId`.",
875
1062
  },
876
1063
  routing_rules_over_plan: {
877
1064
  summary: "The published _redirects and _headers exceed the plan's routing-rule allowance.",
878
- fix: "Reduce the rule count. Still stuck? POST /v1/feedback with the error code and request id.",
1065
+ fix: "Reduce the rule count. If you still need more rules, POST to `/v1/feedback` with the error code and the `requestId`.",
879
1066
  },
880
1067
  runtime_action_forbidden: {
881
1068
  summary: "The runtime credential does not allow this action.",
882
1069
  fix: "Use a runtime token scoped for this action.",
883
1070
  },
884
1071
  runtime_api_not_found: {
885
- summary: "The runtime management endpoint was not found.",
886
- fix: "Send the request with the management hostname as the Host header. Management routes are not served on public hostnames.",
1072
+ summary: "The requested runtime action was not found.",
1073
+ fix: "Use a supported runtime action and a token scoped for that action.",
887
1074
  },
888
1075
  runtime_callback_forbidden: {
889
1076
  summary: "The runtime callback cannot be authenticated.",
@@ -891,19 +1078,19 @@ export const ERROR_DOCS = {
891
1078
  },
892
1079
  runtime_dev_unsupported: {
893
1080
  summary: "`sf dev` cannot run this runtime locally yet.",
894
- fix: "Run your framework's own dev server (`next dev`, `vite`, …) and publish with `sf publish` when you are ready.",
1081
+ fix: "Run your framework's own dev server, such as `next dev` or `vite`. When you are ready, publish with `sf publish`.",
895
1082
  },
896
1083
  runtime_hostname_unassigned: {
897
1084
  summary: "The hostname is not assigned to a runtime, so the request cannot be routed.",
898
- fix: `Verify the binding is active and DNS points at ${BRAND.productName}.`,
1085
+ fix: `Verify that the binding is active and that DNS points at ${BRAND.productName}.`,
899
1086
  },
900
1087
  runtime_instance_mismatch: {
901
1088
  summary: "The request reached a different runtime instance than the one it was issued for.",
902
- fix: "Re-request instructions. The space is on another instance now.",
1089
+ fix: "Re-request instructions. The space is on another instance.",
903
1090
  },
904
1091
  runtime_jti_missing: {
905
1092
  summary: "The runtime token is missing its replay-protection id.",
906
- fix: "Mint a fresh runtime token. Tokens must carry a jti claim.",
1093
+ fix: "Mint a fresh runtime token. Tokens must carry a `jti` claim.",
907
1094
  },
908
1095
  runtime_jti_replayed: {
909
1096
  summary: "The runtime token was already used. Replays are rejected.",
@@ -915,7 +1102,7 @@ export const ERROR_DOCS = {
915
1102
  },
916
1103
  runtime_kind_mismatch: {
917
1104
  summary: "This operation is only available for a different runtime kind.",
918
- fix: "Check `sf runtime status` for what the live version actually runs, then use the surface that runtime supports.",
1105
+ fix: "Check `sf runtime status` for what the live version actually runs, then use the operations that runtime supports.",
919
1106
  },
920
1107
  runtime_management_unavailable: {
921
1108
  summary: "The runtime management surface is unavailable for this site.",
@@ -923,7 +1110,7 @@ export const ERROR_DOCS = {
923
1110
  },
924
1111
  runtime_not_provisioned: {
925
1112
  summary: "The space does not serve a published version yet, so it has no runtime data to read.",
926
- fix: "Publish a version first. If a publish is already running, wait for it the operation receipt reports progress.",
1113
+ fix: "Publish a version first. If a publish is already running, wait for it. The operation receipt reports progress.",
927
1114
  },
928
1115
  runtime_operation_missing: {
929
1116
  summary: "The runtime operation referenced by this request was not found.",
@@ -931,7 +1118,11 @@ export const ERROR_DOCS = {
931
1118
  },
932
1119
  runtime_purge_failed: {
933
1120
  summary: "Content updated but the edge cache purge did not confirm.",
934
- fix: "The runtime retries automatically; recent visitors may briefly see the previous version.",
1121
+ fix: "The runtime retries automatically. Recent visitors may briefly see the previous version.",
1122
+ },
1123
+ runtime_release_unverifiable: {
1124
+ summary: "The requested platform release could not be verified at its origin.",
1125
+ fix: "Check that the release exists and published its full set of artifacts, then request it again.",
935
1126
  },
936
1127
  runtime_scope_forbidden: {
937
1128
  summary: "The runtime token's scope does not cover this path or action.",
@@ -939,7 +1130,7 @@ export const ERROR_DOCS = {
939
1130
  },
940
1131
  runtime_token_bad_signature: {
941
1132
  summary: "The runtime token signature did not verify.",
942
- fix: "Mint a fresh token. Verify clocks and JWKS freshness if it persists.",
1133
+ fix: "Mint a fresh runtime token. If the error persists, verify clocks and JWKS freshness.",
943
1134
  },
944
1135
  runtime_token_expired: {
945
1136
  summary: "The runtime token is expired.",
@@ -951,7 +1142,7 @@ export const ERROR_DOCS = {
951
1142
  },
952
1143
  runtime_unauthorized: {
953
1144
  summary: "The request to the runtime carried no valid credential.",
954
- fix: "Send the runtime JWT in the Authorization header.",
1145
+ fix: "Send the runtime token in the Authorization header.",
955
1146
  },
956
1147
  runtime_upload_operation_not_supported: {
957
1148
  summary: "The runtime upload session does not support this operation.",
@@ -963,7 +1154,7 @@ export const ERROR_DOCS = {
963
1154
  },
964
1155
  scan_pending: {
965
1156
  summary: "The content is still being scanned for safety and cannot be served yet.",
966
- fix: "Wait for the scan to finish. Serving resumes automatically once it clears.",
1157
+ fix: "Wait for the scan to finish. Serving resumes automatically once the scan clears.",
967
1158
  },
968
1159
  secret_variable_in_template: {
969
1160
  summary: "A secret variable was referenced in a template, which is blocked.",
@@ -971,15 +1162,19 @@ export const ERROR_DOCS = {
971
1162
  },
972
1163
  service_booting: {
973
1164
  summary: "The process that received this request is still starting and cannot serve it yet.",
974
- fix: "Wait for the Retry-After window, then send the same request again.",
1165
+ fix: "Wait for the `Retry-After` window, then send the same request again.",
975
1166
  },
976
1167
  service_signature_invalid: {
977
1168
  summary: "The service request signature cannot be verified.",
978
1169
  fix: "Sign the exact request method, path, body digest, timestamp, and a fresh nonce.",
979
1170
  },
1171
+ session_not_fresh: {
1172
+ summary: "This action needs a recent identity confirmation.",
1173
+ fix: "Confirm it's you (password, authenticator code, or a code sent to your primary email), then retry.",
1174
+ },
980
1175
  site_already_deleted: {
981
1176
  summary: "The site was already deleted.",
982
- fix: "No action needed. The site is gone.",
1177
+ fix: "No action is needed. The site is gone.",
983
1178
  },
984
1179
  site_has_live_spaces: {
985
1180
  summary: "The site still has live spaces assigned to it, so it cannot be deleted.",
@@ -1027,7 +1222,7 @@ export const ERROR_DOCS = {
1027
1222
  },
1028
1223
  space_already_claimed: {
1029
1224
  summary: "The space was already claimed. A claim can only succeed once.",
1030
- fix: "If you published this space, exchange your space key once at POST /v1/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.",
1225
+ fix: "If you published this space, exchange your space key once at `POST /v1/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.",
1031
1226
  },
1032
1227
  space_claim_unavailable: {
1033
1228
  summary: "This space cannot be claimed.",
@@ -1035,15 +1230,15 @@ export const ERROR_DOCS = {
1035
1230
  },
1036
1231
  space_claimed_credential_available: {
1037
1232
  summary: "The space was claimed and its owner kept agent publishing enabled; this space key now works exactly once as an exchange voucher.",
1038
- fix: "POST /v1/claim/exchange with this space key 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.",
1233
+ fix: "`POST /v1/claim/exchange` with this space key as bearer auth. Save the returned API key (for example in `.spacefast/state.json`), then retry the request with that key as `Authorization: Bearer`. Do not publish a new space.",
1039
1234
  },
1040
1235
  space_disabled: {
1041
1236
  summary: "The space is disabled and cannot be served or modified.",
1042
- fix: "Check the disabled reason on the space. It explains the path to restore it.",
1237
+ fix: "Check the disabled reason on the space. The reason explains how to restore the space.",
1043
1238
  },
1044
1239
  space_expired: {
1045
1240
  summary: "The space expired and is no longer served.",
1046
- fix: "If it is within the recovery window, claim or restore it. Otherwise publish again.",
1241
+ fix: "If the space is within the recovery window, claim or restore it. Otherwise publish again.",
1047
1242
  },
1048
1243
  space_has_active_publish: {
1049
1244
  summary: "The space has a publish in progress, which blocks this operation.",
@@ -1063,7 +1258,7 @@ export const ERROR_DOCS = {
1063
1258
  },
1064
1259
  space_not_disabled: {
1065
1260
  summary: "The space is not disabled, so it cannot be restored.",
1066
- fix: "No action needed. The space is already active.",
1261
+ fix: "No action is needed. The space is already active.",
1067
1262
  },
1068
1263
  space_not_restorable: {
1069
1264
  summary: "The space is past its recovery window and cannot be restored.",
@@ -1083,11 +1278,15 @@ export const ERROR_DOCS = {
1083
1278
  },
1084
1279
  space_ref_ambiguous: {
1085
1280
  summary: "The space reference matches more than one accessible space.",
1086
- fix: "Use the spc_ id, or scope the reference with a teamRef.",
1281
+ fix: "Use the `spc_` id, or scope the reference with a `teamRef`.",
1087
1282
  },
1088
1283
  space_ref_required: {
1089
1284
  summary: "A space reference is required for this operation.",
1090
- fix: "Pass a spc_ id, slug, or hostname.",
1285
+ fix: "Pass a `spc_` id, slug, or hostname.",
1286
+ },
1287
+ space_selection_conflict: {
1288
+ summary: "The command asked to create a Space while this directory already selects one.",
1289
+ fix: "Drop --slug to publish to the selected Space, or publish from an unlinked directory to create a new one.",
1091
1290
  },
1092
1291
  space_transferring: {
1093
1292
  summary: "The space has a transfer in progress, which blocks this operation.",
@@ -1139,7 +1338,7 @@ export const ERROR_DOCS = {
1139
1338
  },
1140
1339
  storage_key_invalid: {
1141
1340
  summary: "The storage object id is malformed.",
1142
- fix: "Use the 32-character object id returned by storage.upload.",
1341
+ fix: "Use the 32-character object id returned by `storage.upload`.",
1143
1342
  },
1144
1343
  storage_object_not_found: {
1145
1344
  summary: "The requested storage object does not exist.",
@@ -1159,15 +1358,31 @@ export const ERROR_DOCS = {
1159
1358
  },
1160
1359
  storage_unavailable: {
1161
1360
  summary: "The runtime cannot read or persist object storage.",
1162
- fix: "Retry on a healthy runtime. Contact support if the failure persists.",
1361
+ fix: "Retry on a healthy runtime. If the failure persists, contact support.",
1163
1362
  },
1164
1363
  stripe_error: {
1165
1364
  summary: "The billing provider reported an error.",
1166
- fix: "Retry. If it persists, check the team's billing settings.",
1365
+ fix: "Retry. If the error persists, check the team's billing settings.",
1366
+ },
1367
+ superadmin_two_factor_required: {
1368
+ summary: "The user must have two-factor authentication enrolled before being granted superadmin.",
1369
+ fix: "Ask them to enrol a second factor in account security, then grant the role again.",
1370
+ },
1371
+ superadmin_wpcom_account_required: {
1372
+ summary: "The user must have a WordPress.com account linked before being granted superadmin.",
1373
+ fix: "Ask them to link WordPress.com in account security, then grant the role again.",
1167
1374
  },
1168
1375
  superseded_by_publish: {
1169
1376
  summary: "A newer publish superseded this operation, so it was skipped.",
1170
- fix: "No action needed. The newer publish already carries the change.",
1377
+ fix: "No action is needed. The newer publish already carries the change.",
1378
+ },
1379
+ system_space_conflict: {
1380
+ summary: "The tenant's system space changed since the value you sent as `baseSystemSpaceId`, so the update was rejected.",
1381
+ fix: "Re-read `/v1/tenants/{tenantId}`, confirm the current `systemSpaceId`, and retry with a matching `baseSystemSpaceId`.",
1382
+ },
1383
+ system_space_invalid: {
1384
+ summary: "The requested system space does not exist, is disabled, or belongs to another tenant.",
1385
+ fix: "Designate a live space this tenant owns as its system space.",
1171
1386
  },
1172
1387
  takeover_notice_window: {
1173
1388
  summary: "The hostname was recently bound elsewhere. A takeover notice window applies.",
@@ -1185,6 +1400,10 @@ export const ERROR_DOCS = {
1185
1400
  summary: "This operation requires an acting team.",
1186
1401
  fix: "Choose a team or pass a team reference.",
1187
1402
  },
1403
+ team_scope_mismatch: {
1404
+ summary: "The requested team conflicts with the team this credential or resource is bound to.",
1405
+ fix: "Drop the team parameter to act on the bound team, or use a credential for the team you named.",
1406
+ },
1188
1407
  team_slug_conflict: {
1189
1408
  summary: "The team slug is already taken.",
1190
1409
  fix: "Choose a different slug.",
@@ -1199,11 +1418,11 @@ export const ERROR_DOCS = {
1199
1418
  },
1200
1419
  template_file_too_large: {
1201
1420
  summary: "A template file exceeds the maximum size for substitution.",
1202
- fix: "Keep template files under the documented size limit (16 KB).",
1421
+ fix: "Keep template files at or under 16 KB.",
1203
1422
  },
1204
1423
  template_not_in_version: {
1205
1424
  summary: "The configuration names a template file the version does not contain.",
1206
- fix: "Upload the file or remove its templates entry from sf.jsonc.",
1425
+ fix: "Upload the file or remove its `templates` entry from `sf.jsonc`.",
1207
1426
  },
1208
1427
  template_variable_unresolved: {
1209
1428
  summary: "A template references a variable that has no value.",
@@ -1235,7 +1454,43 @@ export const ERROR_DOCS = {
1235
1454
  },
1236
1455
  theme_value_invalid: {
1237
1456
  summary: "A theme value in the configuration is outside the allowed grammar.",
1238
- fix: "Use allowed CSS values. The offending key is dropped with a warning otherwise.",
1457
+ fix: "Use allowed CSS values. Otherwise the offending key is dropped with a warning.",
1458
+ },
1459
+ token_alg_invalid: {
1460
+ summary: "The partner token uses a signing algorithm that Spacefast does not allow.",
1461
+ fix: "Sign the token with a registered Ed25519 key.",
1462
+ },
1463
+ token_audience_mismatch: {
1464
+ summary: "The partner token audience does not match the audience for its issuer.",
1465
+ fix: "Set aud to the exact audience that Spacefast assigned to the issuer.",
1466
+ },
1467
+ token_claims_invalid: {
1468
+ summary: "The partner token omits a required claim or contains an invalid claim value.",
1469
+ fix: "Add valid iss, aud, sub, client_id, jti, iat, and exp claims.",
1470
+ },
1471
+ token_header_forbidden: {
1472
+ summary: "The partner token contains a header that can select an untrusted key.",
1473
+ fix: "Remove jku, x5u, jwk, and x5c from the token header.",
1474
+ },
1475
+ token_malformed: {
1476
+ summary: "The partner token is not a valid compact JWT within the size limit.",
1477
+ fix: "Send a valid compact JWT that is no larger than 8192 bytes.",
1478
+ },
1479
+ token_signature_invalid: {
1480
+ summary: "The partner token signature does not match a registered issuer key.",
1481
+ fix: "Sign the token with an active key that is registered for the issuer.",
1482
+ },
1483
+ token_subject_invalid: {
1484
+ summary: "The partner token subject is not a normalized lowercase external principal id.",
1485
+ fix: "Use a trimmed lowercase ASCII subject without wildcards, slashes, or reserved policy characters.",
1486
+ },
1487
+ token_ttl_invalid: {
1488
+ summary: "The partner token time claims are expired, premature, or outside the lifetime limit.",
1489
+ fix: "Issue a new token with exp after iat and no more than 1800 seconds after iat.",
1490
+ },
1491
+ token_type_invalid: {
1492
+ summary: "The partner token has a typ header that Spacefast does not accept.",
1493
+ fix: "Set typ to at+jwt or application/at+jwt.",
1239
1494
  },
1240
1495
  transfer_cross_tenant_unsupported: {
1241
1496
  summary: "Spaces cannot be transferred across tenants.",
@@ -1247,7 +1502,7 @@ export const ERROR_DOCS = {
1247
1502
  },
1248
1503
  transfer_push_failed: {
1249
1504
  summary: "The source runtime cannot push the space blobs into the transfer bucket.",
1250
- fix: "Retry the move. If it persists, check the source runtime and bucket configuration.",
1505
+ fix: "Retry the move. If the failure persists, check the source runtime and bucket configuration.",
1251
1506
  },
1252
1507
  transfer_source_changed: {
1253
1508
  summary: "The space changed since the transfer was created, so it must be re-confirmed.",
@@ -1259,7 +1514,7 @@ export const ERROR_DOCS = {
1259
1514
  },
1260
1515
  transfer_verify_failed: {
1261
1516
  summary: "The target runtime cannot verify transferred blob content.",
1262
- fix: "Retry the move. If it persists, check the target runtime and bucket integrity.",
1517
+ fix: "Retry the move. If the failure persists, check the target runtime and bucket integrity.",
1263
1518
  },
1264
1519
  unauthorized: {
1265
1520
  summary: "The request carried no valid credential.",
@@ -1285,13 +1540,17 @@ export const ERROR_DOCS = {
1285
1540
  summary: "An uploaded file's size does not match the declared size.",
1286
1541
  fix: "Re-check the local file and upload it again.",
1287
1542
  },
1543
+ usage_period_not_found: {
1544
+ summary: "The requested usage period does not exist in this tenant.",
1545
+ fix: "List usage periods and use an id returned for the selected tenant.",
1546
+ },
1288
1547
  user_banned: {
1289
1548
  summary: "This user is banned for a policy or abuse violation and cannot perform this action.",
1290
- fix: "Contact support to appeal the ban if you believe it is a mistake.",
1549
+ fix: "If you believe the ban is a mistake, contact support to appeal it.",
1291
1550
  },
1292
1551
  validation_error: {
1293
1552
  summary: "A request field failed validation.",
1294
- fix: "Fix the field referenced by pointer and details, then retry.",
1553
+ fix: "Fix the field referenced by `pointer` and `details`, then retry.",
1295
1554
  },
1296
1555
  verification_required: {
1297
1556
  summary: "Domain verification is required before this operation.",
@@ -1299,7 +1558,7 @@ export const ERROR_DOCS = {
1299
1558
  },
1300
1559
  version_already_live: {
1301
1560
  summary: "The version is already live on this channel.",
1302
- fix: "No action needed.",
1561
+ fix: "No action is needed.",
1303
1562
  },
1304
1563
  version_artifact_not_found: {
1305
1564
  summary: "The requested version artifact was not found.",
@@ -1343,7 +1602,7 @@ export const ERROR_DOCS = {
1343
1602
  },
1344
1603
  version_in_use: {
1345
1604
  summary: "The version is referenced by one or more channels and cannot be deleted.",
1346
- fix: "Promote another version on those channels first. Details lists them.",
1605
+ fix: "Promote another version on those channels first. The `details` field lists them.",
1347
1606
  },
1348
1607
  version_live: {
1349
1608
  summary: "The version is live and cannot be deleted.",
@@ -1375,7 +1634,7 @@ export const ERROR_DOCS = {
1375
1634
  },
1376
1635
  version_quota_exceeded: {
1377
1636
  summary: "The space is at its version quota.",
1378
- fix: "Delete old versions. Still stuck? POST /v1/feedback with the error code and request id.",
1637
+ fix: "Delete old versions. If the quota error persists, `POST /v1/feedback` with the error code and request id.",
1379
1638
  },
1380
1639
  version_total_bytes_exceeded: {
1381
1640
  summary: "The version exceeds the maximum total size.",
@@ -1385,6 +1644,10 @@ export const ERROR_DOCS = {
1385
1644
  summary: "The webhook exhausted its delivery budget and was paused.",
1386
1645
  fix: "Fix the receiving endpoint, then redeliver or re-enable the webhook.",
1387
1646
  },
1647
+ webhook_managed_by_manifest: {
1648
+ summary: "The webhook is declared in the tenant's system-space manifest.",
1649
+ fix: "Edit its `system.subscriptions` entry and publish the system space.",
1650
+ },
1388
1651
  whois_unavailable: {
1389
1652
  summary: "WHOIS data is unavailable for this domain right now.",
1390
1653
  fix: "Retry later.",
@@ -1395,7 +1658,7 @@ export const ERROR_DOCS = {
1395
1658
  },
1396
1659
  zero_artifact_abi_mismatch: {
1397
1660
  summary: "The Zero endpoint artifact was built for a different runner ABI.",
1398
- fix: `Rebuild and republish the Zero project with the current ${BRAND.productName} CLI and runtime.`,
1661
+ fix: `Rebuild the Zero project with the current ${BRAND.productName} CLI and runtime, then publish it again.`,
1399
1662
  },
1400
1663
  zero_artifact_invalid: {
1401
1664
  summary: "The Zero endpoint artifact is missing required runtime metadata.",
@@ -1415,7 +1678,7 @@ export const ERROR_DOCS = {
1415
1678
  },
1416
1679
  zero_auth_unavailable: {
1417
1680
  summary: "Hosted Zero auth is not configured for this deployment.",
1418
- fix: "Finalize the Zero version with hosted auth URLs or use guest/local auth.",
1681
+ fix: "Finalize the Zero version with hosted auth URLs, or use guest or local auth.",
1419
1682
  },
1420
1683
  zero_blob_key_invalid: {
1421
1684
  summary: "The local Zero blob key is invalid.",
@@ -1435,15 +1698,15 @@ export const ERROR_DOCS = {
1435
1698
  },
1436
1699
  zero_bootstrap_encode_failed: {
1437
1700
  summary: "The Zero runner cannot encode the JavaScript bootstrap data.",
1438
- fix: "Retry with valid request metadata. Report the issue if it persists.",
1701
+ fix: "Retry with valid request metadata. If the issue persists, report it.",
1439
1702
  },
1440
1703
  zero_bytecode_hash_mismatch: {
1441
1704
  summary: "The Zero endpoint bytecode hash does not match its artifact metadata.",
1442
- fix: "Rebuild and republish so bytecode and endpoint metadata are from the same build.",
1705
+ fix: "Rebuild and publish again so bytecode and endpoint metadata are from the same build.",
1443
1706
  },
1444
1707
  zero_bytecode_invalid: {
1445
1708
  summary: "The Zero endpoint bytecode cannot be loaded by QuickJS.",
1446
- fix: "Rebuild the project with the current Zero runner and redeploy.",
1709
+ fix: "Rebuild the project with the current Zero runner and publish again.",
1447
1710
  },
1448
1711
  zero_bytecode_path_invalid: {
1449
1712
  summary: "The Zero endpoint bytecode path is invalid.",
@@ -1455,7 +1718,7 @@ export const ERROR_DOCS = {
1455
1718
  },
1456
1719
  zero_capabilities_encode_failed: {
1457
1720
  summary: "The runtime cannot encode the Zero endpoint capabilities.",
1458
- fix: "Rebuild with valid capability metadata. Report the failure if it persists.",
1721
+ fix: "Rebuild with valid capability metadata. If the failure persists, report it.",
1459
1722
  },
1460
1723
  zero_client_bundle_not_loaded: {
1461
1724
  summary: "The local Zero dev client bundle is not generated or loaded.",
@@ -1463,11 +1726,11 @@ export const ERROR_DOCS = {
1463
1726
  },
1464
1727
  zero_db_connect_failed: {
1465
1728
  summary: "The Zero runner cannot connect to the configured database.",
1466
- fix: "Verify DATABASE_URL or the generated MySQL connection variables and retry.",
1729
+ fix: "Verify `DATABASE_URL` or the generated MySQL connection variables and retry.",
1467
1730
  },
1468
1731
  zero_db_execute_failed: {
1469
1732
  summary: "A Zero database write failed.",
1470
- fix: "Inspect the mutation, schema, and database logs, then retry after fixing the SQL issue.",
1733
+ fix: "Inspect the mutation, schema, and database logs. Fix the SQL issue, then retry.",
1471
1734
  },
1472
1735
  zero_db_export_cursor_invalid: {
1473
1736
  summary: "The local database export cursor is invalid or belongs to another export.",
@@ -1495,7 +1758,7 @@ export const ERROR_DOCS = {
1495
1758
  },
1496
1759
  zero_db_host_install_failed: {
1497
1760
  summary: "The Zero runner cannot install the database host bridge.",
1498
- fix: "Rebuild with a current runner and report the failure if it repeats.",
1761
+ fix: "Rebuild with a current runner. If the failure repeats, report it.",
1499
1762
  },
1500
1763
  zero_db_operation_invalid: {
1501
1764
  summary: "The Zero database bridge received an invalid operation payload.",
@@ -1511,7 +1774,7 @@ export const ERROR_DOCS = {
1511
1774
  },
1512
1775
  zero_db_query_failed: {
1513
1776
  summary: "A Zero database read failed.",
1514
- fix: "Inspect the query, schema, and database logs, then retry after fixing the SQL issue.",
1777
+ fix: "Inspect the query, schema, and database logs. Fix the SQL issue, then retry.",
1515
1778
  },
1516
1779
  zero_db_row_invalid: {
1517
1780
  summary: "A database row cannot be converted into a Zero response value.",
@@ -1527,7 +1790,7 @@ export const ERROR_DOCS = {
1527
1790
  },
1528
1791
  zero_db_transaction_active: {
1529
1792
  summary: "The Zero runner tried to start a database transaction while one was already active.",
1530
- fix: "Rebuild with the current Zero runner and report the failure if it repeats.",
1793
+ fix: "Rebuild with the current Zero runner. If the failure repeats, report it.",
1531
1794
  },
1532
1795
  zero_db_transaction_commit_failed: {
1533
1796
  summary: "The Zero database transaction cannot be committed.",
@@ -1539,7 +1802,7 @@ export const ERROR_DOCS = {
1539
1802
  },
1540
1803
  zero_db_transaction_missing: {
1541
1804
  summary: "The Zero runner tried to finish a database transaction that was not active.",
1542
- fix: "Rebuild with the current Zero runner and report the failure if it repeats.",
1805
+ fix: "Rebuild with the current Zero runner. If the failure repeats, report it.",
1543
1806
  },
1544
1807
  zero_db_transaction_rollback_failed: {
1545
1808
  summary: "The Zero database transaction cannot be rolled back cleanly.",
@@ -1559,11 +1822,11 @@ export const ERROR_DOCS = {
1559
1822
  },
1560
1823
  zero_db_url_invalid: {
1561
1824
  summary: "The Zero database URL is malformed.",
1562
- fix: "Set DATABASE_URL or the generated database variables to a valid MySQL connection URL.",
1825
+ fix: "Set `DATABASE_URL` or the generated database variables to a valid MySQL connection URL.",
1563
1826
  },
1564
1827
  zero_db_url_missing: {
1565
1828
  summary: "No Zero database URL is configured.",
1566
- fix: "Configure DATABASE_URL or finalize the version with database connection variables.",
1829
+ fix: "Configure `DATABASE_URL` or finalize the version with database connection variables.",
1567
1830
  },
1568
1831
  zero_dev_endpoint_failed: {
1569
1832
  summary: "A local Zero dev endpoint failed while handling the request.",
@@ -1571,7 +1834,7 @@ export const ERROR_DOCS = {
1571
1834
  },
1572
1835
  zero_dump_query_invalid: {
1573
1836
  summary: "The Zero database dump query parameters are invalid.",
1574
- fix: "Use valid table, limit, and cursor parameters.",
1837
+ fix: "Use valid `table`, `limit`, and `cursor` parameters.",
1575
1838
  },
1576
1839
  zero_endpoint_compile_failed: {
1577
1840
  summary: "The runtime cannot compile the Zero endpoint bytecode.",
@@ -1591,11 +1854,11 @@ export const ERROR_DOCS = {
1591
1854
  },
1592
1855
  zero_endpoint_index_invalid: {
1593
1856
  summary: "The Zero endpoint index does not contain valid endpoint mappings.",
1594
- fix: "Rebuild and republish the Zero project.",
1857
+ fix: "Rebuild the Zero project and publish it again.",
1595
1858
  },
1596
1859
  zero_endpoint_index_malformed: {
1597
1860
  summary: "The Zero endpoint index cannot be parsed.",
1598
- fix: "Rebuild the generated endpoint index and redeploy.",
1861
+ fix: "Rebuild the generated endpoint index and publish again.",
1599
1862
  },
1600
1863
  zero_endpoint_index_path_invalid: {
1601
1864
  summary: "The Zero endpoint index path is invalid.",
@@ -1603,7 +1866,7 @@ export const ERROR_DOCS = {
1603
1866
  },
1604
1867
  zero_endpoint_index_unreadable: {
1605
1868
  summary: "The Zero endpoint index cannot be read.",
1606
- fix: "Verify the version finalized with zero/endpoints-index.json present.",
1869
+ fix: "Verify the version finalized with `zero/endpoints-index.json` present.",
1607
1870
  },
1608
1871
  zero_endpoint_invalid: {
1609
1872
  summary: "A Zero endpoint definition or its database metadata is invalid.",
@@ -1611,7 +1874,7 @@ export const ERROR_DOCS = {
1611
1874
  },
1612
1875
  zero_endpoint_mismatch: {
1613
1876
  summary: "The requested Zero endpoint does not match the endpoint artifact.",
1614
- fix: "Rebuild routes and artifacts together and redeploy the version.",
1877
+ fix: "Rebuild routes and artifacts together, then publish the version again.",
1615
1878
  },
1616
1879
  zero_endpoint_not_found: {
1617
1880
  summary: "No Zero endpoint artifact exists for this endpoint id.",
@@ -1625,9 +1888,17 @@ export const ERROR_DOCS = {
1625
1888
  summary: "The Zero endpoints payload exceeds the supported endpoint count.",
1626
1889
  fix: "Reduce the project to at most 128 Zero endpoints, then publish again.",
1627
1890
  },
1891
+ zero_email_unavailable: {
1892
+ summary: "The local Zero email service is not configured.",
1893
+ fix: "Publish the capsule to call the hosted email service, or guard the `ctx.email` call so local runs skip it.",
1894
+ },
1628
1895
  zero_envelope_encode_failed: {
1629
1896
  summary: "The PHP bridge cannot encode the Zero runner request envelope.",
1630
- fix: "Retry with valid request data. Report the issue if it persists.",
1897
+ fix: "Retry with valid request data. If the issue persists, report it.",
1898
+ },
1899
+ zero_gravatar_unavailable: {
1900
+ summary: "The local Zero gravatar service is not configured.",
1901
+ fix: "Publish the capsule to call the hosted gravatar service. `ctx.gravatar.avatarUrl` needs no service and works locally.",
1631
1902
  },
1632
1903
  zero_js_context_init_failed: {
1633
1904
  summary: "The Zero runner cannot initialize a QuickJS context.",
@@ -1643,11 +1914,11 @@ export const ERROR_DOCS = {
1643
1914
  },
1644
1915
  zero_js_globals_failed: {
1645
1916
  summary: "The Zero runner cannot install runtime globals for the endpoint.",
1646
- fix: "Rebuild with a current runner and report the failure if it repeats.",
1917
+ fix: "Rebuild with a current runner. If the failure repeats, report it.",
1647
1918
  },
1648
1919
  zero_js_response_malformed: {
1649
1920
  summary: "The Zero endpoint returned a malformed runner response.",
1650
- fix: "Return a valid Response or supported Zero handler result.",
1921
+ fix: "Return a valid `Response` or supported Zero handler result.",
1651
1922
  },
1652
1923
  zero_js_runtime_init_failed: {
1653
1924
  summary: "The Zero runner cannot initialize QuickJS.",
@@ -1655,7 +1926,7 @@ export const ERROR_DOCS = {
1655
1926
  },
1656
1927
  zero_log_query_invalid: {
1657
1928
  summary: "The Zero log query parameters are invalid.",
1658
- fix: "Use valid cursor, limit, handlerName, and requestId parameters.",
1929
+ fix: "Pass `cursor` exactly as the previous page's `nextCursor`, keep `limit` between 1 and 100, and send `since` and `until` as ISO timestamps.",
1659
1930
  },
1660
1931
  zero_method_not_allowed: {
1661
1932
  summary: "The request method is not allowed for this Zero endpoint.",
@@ -1667,7 +1938,7 @@ export const ERROR_DOCS = {
1667
1938
  },
1668
1939
  zero_query_name_missing: {
1669
1940
  summary: "A Zero realtime query subscription did not include a query name.",
1670
- fix: "Send a query.subscribe frame with a valid query name.",
1941
+ fix: "Send a `query.subscribe` frame with a valid query name.",
1671
1942
  },
1672
1943
  zero_realtime_forbidden: {
1673
1944
  summary: "The Zero realtime event intake credential is invalid.",
@@ -1679,7 +1950,7 @@ export const ERROR_DOCS = {
1679
1950
  },
1680
1951
  zero_realtime_operation_unsupported: {
1681
1952
  summary: "The Zero realtime websocket operation is unsupported.",
1682
- fix: "Use a supported Zero realtime operation such as query.subscribe or query.unsubscribe.",
1953
+ fix: "Use a supported Zero realtime operation such as `query.subscribe` or `query.unsubscribe`.",
1683
1954
  },
1684
1955
  zero_realtime_query_invalid: {
1685
1956
  summary: "The Zero realtime query subscription payload is invalid.",
@@ -1687,7 +1958,7 @@ export const ERROR_DOCS = {
1687
1958
  },
1688
1959
  zero_realtime_space_required: {
1689
1960
  summary: "The Zero realtime request does not identify a space.",
1690
- fix: "Use a /spaces/{spaceId} realtime URL or include a valid spaceId query parameter.",
1961
+ fix: "Use a `/spaces/{spaceId}` realtime URL or include a valid `spaceId` query parameter.",
1691
1962
  },
1692
1963
  zero_realtime_unavailable: {
1693
1964
  summary: "Zero realtime helpers are unavailable for this endpoint.",
@@ -1699,11 +1970,11 @@ export const ERROR_DOCS = {
1699
1970
  },
1700
1971
  zero_replay_failed: {
1701
1972
  summary: "The hosted Zero runtime cannot fetch realtime replay events.",
1702
- fix: "Retry shortly. Check the central realtime and control-plane logs if it persists.",
1973
+ fix: "Retry shortly. If the failure persists, check the central realtime and control-plane logs.",
1703
1974
  },
1704
1975
  zero_replay_query_invalid: {
1705
1976
  summary: "The hosted Zero realtime replay query is invalid.",
1706
- fix: "Use a valid afterEventId cursor and numeric limit.",
1977
+ fix: "Send a retained `afterEventId` from a previous page's `nextAfterEventId`, and a numeric limit.",
1707
1978
  },
1708
1979
  zero_replay_unavailable: {
1709
1980
  summary: "Realtime replay is not configured for this Zero version.",
@@ -1711,7 +1982,7 @@ export const ERROR_DOCS = {
1711
1982
  },
1712
1983
  zero_request_body_too_large: {
1713
1984
  summary: "The Zero request body exceeds the runtime size limit.",
1714
- fix: "Send a smaller request body or move large payloads to blob/object storage.",
1985
+ fix: "Send a smaller request body or move large payloads to blob or object storage.",
1715
1986
  },
1716
1987
  zero_response_header_forbidden: {
1717
1988
  summary: "A Zero endpoint attempted to set a platform-managed response header.",
@@ -1747,7 +2018,7 @@ export const ERROR_DOCS = {
1747
2018
  },
1748
2019
  zero_runner_envelope_invalid: {
1749
2020
  summary: "The Zero runner request envelope is malformed.",
1750
- fix: "Use the generated runtime bridge and redeploy if generated files are stale.",
2021
+ fix: "Use the generated runtime bridge. If generated files are stale, publish again.",
1751
2022
  },
1752
2023
  zero_runner_failed: {
1753
2024
  summary: "The Zero runner process exited without a valid response.",
@@ -1759,15 +2030,15 @@ export const ERROR_DOCS = {
1759
2030
  },
1760
2031
  zero_runner_invalid_response: {
1761
2032
  summary: "The Zero runner output was not valid JSON.",
1762
- fix: "Inspect runner stderr and rebuild the runner if the failure persists.",
2033
+ fix: "Inspect runner stderr. If the failure persists, rebuild the runner.",
1763
2034
  },
1764
2035
  zero_runner_invalid_status: {
1765
2036
  summary: "The Zero runner returned an invalid HTTP status.",
1766
- fix: "Ensure endpoint handlers return a status between 100 and 599.",
2037
+ fix: "Return a status between 100 and 599 from endpoint handlers.",
1767
2038
  },
1768
2039
  zero_runner_protocol_unsupported: {
1769
2040
  summary: "The Zero runner received an unsupported invoke protocol.",
1770
- fix: "Rebuild and redeploy so the PHP bridge and Rust runner versions match.",
2041
+ fix: "Rebuild and publish again so the PHP bridge and Rust runner versions match.",
1771
2042
  },
1772
2043
  zero_runner_response_encode_failed: {
1773
2044
  summary: "The Zero runner cannot encode its response.",
@@ -1775,7 +2046,7 @@ export const ERROR_DOCS = {
1775
2046
  },
1776
2047
  zero_runner_stdin_invalid: {
1777
2048
  summary: "The Zero runner cannot read its request envelope.",
1778
- fix: "Retry. Report the runtime bridge failure if it persists.",
2049
+ fix: "Retry. If the runtime bridge failure persists, report it.",
1779
2050
  },
1780
2051
  zero_runner_stdin_too_large: {
1781
2052
  summary: "The Zero runner request envelope is too large.",
@@ -1785,6 +2056,10 @@ export const ERROR_DOCS = {
1785
2056
  summary: "The Zero runner process cannot be started.",
1786
2057
  fix: "Verify the runner binary is installed and executable in the runtime.",
1787
2058
  },
2059
+ zero_spam_unavailable: {
2060
+ summary: "The local Zero spam service is not configured.",
2061
+ fix: "Publish the capsule to call the hosted spam service, or guard the `ctx.spam` call so local runs skip it.",
2062
+ },
1788
2063
  zero_runs_invalid: {
1789
2064
  summary: "The Zero run-handler payload is invalid.",
1790
2065
  fix: "Send a valid array of generated run handlers and publish again.",
@@ -1829,6 +2104,8 @@ export const ERROR_DOCS = {
1829
2104
  summary: "The infra webhook secret is not configured on this deployment.",
1830
2105
  fix: "Set the infra webhook secret in the control-plane environment.",
1831
2106
  },
2107
+ // `satisfies`, not an annotation, so the table keeps its literal types while
2108
+ // still failing the build the moment a code has no entry.
1832
2109
  };
1833
2110
  const PRODUCT = BRAND.productName;
1834
2111
  /** One generated reference page per error code; the `.md` twin is this exact text. */