@spacefast/common 0.0.23 → 0.0.26

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 (224) 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.js +1 -1
  7. package/dist/agents/private-key-oauth.d.ts +0 -1
  8. package/dist/agents/private-key-oauth.js +46 -63
  9. package/dist/brand-assets-build.js +4 -6
  10. package/dist/brand-assets.d.ts +5 -15
  11. package/dist/brand-assets.js +15 -14
  12. package/dist/config/domains.d.ts +47 -7
  13. package/dist/config/domains.js +66 -10
  14. package/dist/config/index.d.ts +0 -1
  15. package/dist/config/index.js +0 -1
  16. package/dist/contracts/abuse.d.ts +2 -0
  17. package/dist/contracts/abuse.js +12 -0
  18. package/dist/contracts/access.d.ts +124 -12
  19. package/dist/contracts/access.js +73 -9
  20. package/dist/contracts/activity.d.ts +1 -1
  21. package/dist/contracts/activity.js +5 -12
  22. package/dist/contracts/api-keys.d.ts +21 -21
  23. package/dist/contracts/api-keys.js +2 -2
  24. package/dist/contracts/beta.js +1 -1
  25. package/dist/contracts/billing.d.ts +3 -35
  26. package/dist/contracts/billing.js +33 -52
  27. package/dist/contracts/builds.d.ts +30 -18
  28. package/dist/contracts/builds.js +28 -9
  29. package/dist/contracts/channels.js +1 -1
  30. package/dist/contracts/cli.d.ts +10 -0
  31. package/dist/contracts/cli.js +10 -0
  32. package/dist/contracts/collab-public.d.ts +63 -0
  33. package/dist/contracts/collab-public.js +46 -0
  34. package/dist/contracts/comments.d.ts +282 -53
  35. package/dist/contracts/comments.js +173 -52
  36. package/dist/contracts/common.d.ts +3 -3
  37. package/dist/contracts/common.js +5 -5
  38. package/dist/contracts/crons.d.ts +35 -0
  39. package/dist/contracts/crons.js +42 -0
  40. package/dist/contracts/device-auth.d.ts +6 -6
  41. package/dist/contracts/device-auth.js +2 -2
  42. package/dist/contracts/docs.js +2 -2
  43. package/dist/contracts/domains.d.ts +38 -27
  44. package/dist/contracts/domains.js +29 -2
  45. package/dist/contracts/enums.d.ts +34 -30
  46. package/dist/contracts/enums.js +62 -48
  47. package/dist/contracts/error-code-meta.d.ts +50 -125
  48. package/dist/contracts/error-code-meta.js +29 -41
  49. package/dist/contracts/error-codes.d.ts +1 -1
  50. package/dist/contracts/error-codes.js +14 -33
  51. package/dist/contracts/execution.d.ts +47 -66
  52. package/dist/contracts/execution.js +53 -49
  53. package/dist/contracts/feature-lifecycle-core.d.ts +0 -6
  54. package/dist/contracts/feature-lifecycle-core.js +2 -31
  55. package/dist/contracts/feature-lifecycle.d.ts +12 -52
  56. package/dist/contracts/feature-lifecycle.js +16 -59
  57. package/dist/contracts/features.d.ts +48 -60
  58. package/dist/contracts/features.js +59 -51
  59. package/dist/contracts/functions.d.ts +266 -72
  60. package/dist/contracts/functions.js +260 -37
  61. package/dist/contracts/git.d.ts +28 -34
  62. package/dist/contracts/git.js +10 -11
  63. package/dist/contracts/grants.d.ts +9 -5
  64. package/dist/contracts/grants.js +18 -9
  65. package/dist/contracts/ids.js +2 -2
  66. package/dist/contracts/internal.d.ts +8 -6
  67. package/dist/contracts/internal.js +12 -12
  68. package/dist/contracts/mcp.d.ts +11 -0
  69. package/dist/contracts/mcp.js +5 -0
  70. package/dist/contracts/me.js +1 -1
  71. package/dist/contracts/oauth-resources.d.ts +4 -3
  72. package/dist/contracts/oauth-resources.js +12 -3
  73. package/dist/contracts/operations.d.ts +90 -5
  74. package/dist/contracts/operations.js +77 -3
  75. package/dist/contracts/pages.d.ts +12 -7
  76. package/dist/contracts/pages.js +24 -1
  77. package/dist/contracts/plan-policy.d.ts +0 -2
  78. package/dist/contracts/plan-policy.js +2 -3
  79. package/dist/contracts/platform.d.ts +61 -148
  80. package/dist/contracts/platform.js +70 -126
  81. package/dist/contracts/publish-archive.d.ts +508 -0
  82. package/dist/contracts/publish-archive.js +32 -0
  83. package/dist/contracts/push-new.d.ts +4 -4
  84. package/dist/contracts/quotas.js +2 -2
  85. package/dist/contracts/repository-connections.d.ts +43 -30
  86. package/dist/contracts/repository-connections.js +11 -3
  87. package/dist/contracts/resources.d.ts +12 -24
  88. package/dist/contracts/resources.js +36 -16
  89. package/dist/contracts/runtime-api.d.ts +433 -192
  90. package/dist/contracts/runtime-api.js +421 -356
  91. package/dist/contracts/runtime-app.d.ts +127 -120
  92. package/dist/contracts/runtime-app.js +19 -10
  93. package/dist/contracts/runtime-db.d.ts +5 -5
  94. package/dist/contracts/runtime-db.js +2 -2
  95. package/dist/contracts/runtime-purge.d.ts +8 -0
  96. package/dist/contracts/runtime-purge.js +7 -0
  97. package/dist/contracts/runtime-services.d.ts +219 -0
  98. package/dist/contracts/runtime-services.js +437 -0
  99. package/dist/contracts/runtime-storage.d.ts +46 -32
  100. package/dist/contracts/runtime-storage.js +31 -8
  101. package/dist/contracts/sf-config-v1.d.ts +48 -10
  102. package/dist/contracts/space-config.d.ts +69 -18
  103. package/dist/contracts/space-config.js +226 -27
  104. package/dist/contracts/spaces.d.ts +236 -450
  105. package/dist/contracts/spaces.js +131 -151
  106. package/dist/contracts/superadmin-activity.d.ts +57 -4
  107. package/dist/contracts/superadmin-activity.js +48 -2
  108. package/dist/contracts/superadmin-search.d.ts +126 -0
  109. package/dist/contracts/superadmin-search.js +61 -0
  110. package/dist/contracts/superadmin-spaces.d.ts +361 -92
  111. package/dist/contracts/superadmin-spaces.js +97 -24
  112. package/dist/contracts/superadmin-teams.d.ts +28 -10
  113. package/dist/contracts/superadmin-teams.js +5 -8
  114. package/dist/contracts/superadmin-tenants.d.ts +0 -6
  115. package/dist/contracts/superadmin-tenants.js +1 -7
  116. package/dist/contracts/superadmin.d.ts +135 -54
  117. package/dist/contracts/superadmin.js +46 -23
  118. package/dist/contracts/tags.d.ts +12 -12
  119. package/dist/contracts/tags.js +3 -3
  120. package/dist/contracts/teams.d.ts +49 -14
  121. package/dist/contracts/teams.js +40 -22
  122. package/dist/contracts/transfers.d.ts +0 -49
  123. package/dist/contracts/transfers.js +4 -8
  124. package/dist/contracts/usage.d.ts +61 -0
  125. package/dist/contracts/usage.js +64 -0
  126. package/dist/contracts/variables.d.ts +2 -7
  127. package/dist/contracts/variables.js +9 -8
  128. package/dist/contracts/webhooks.d.ts +2 -2
  129. package/dist/contracts/zero.d.ts +102 -73
  130. package/dist/contracts/zero.js +94 -32
  131. package/dist/dashboard-paths/index.d.ts +1 -1
  132. package/dist/dashboard-paths/index.js +1 -0
  133. package/dist/docs/agent-prose.d.ts +2 -2
  134. package/dist/docs/agent-prose.js +63 -70
  135. package/dist/docs/agent-setup.js +45 -15
  136. package/dist/docs/catalog.d.ts +24 -24
  137. package/dist/docs/catalog.js +35 -24
  138. package/dist/docs/error-docs.js +194 -270
  139. package/dist/docs/skills.d.ts +12 -12
  140. package/dist/docs/skills.js +4 -4
  141. package/dist/test-helpers/fetch-stub.d.ts +16 -0
  142. package/dist/test-helpers/fetch-stub.js +25 -0
  143. package/dist/utils/build-settings.d.ts +5 -1
  144. package/dist/utils/build-settings.js +91 -13
  145. package/dist/utils/canonical-json.d.ts +10 -0
  146. package/dist/utils/canonical-json.js +22 -0
  147. package/dist/utils/cast-transport.d.ts +28 -0
  148. package/dist/utils/cast-transport.js +52 -0
  149. package/dist/utils/claim-token.d.ts +0 -8
  150. package/dist/utils/claim-token.js +3 -15
  151. package/dist/utils/concurrency.js +1 -0
  152. package/dist/utils/credential-policy.d.ts +1 -1
  153. package/dist/utils/credential-policy.js +4 -3
  154. package/dist/utils/dns-instructions.js +9 -9
  155. package/dist/utils/env-file.d.ts +17 -0
  156. package/dist/utils/env-file.js +96 -0
  157. package/dist/utils/error-code.d.ts +2 -0
  158. package/dist/utils/error-code.js +8 -0
  159. package/dist/utils/generate-space-name.d.ts +8 -10
  160. package/dist/utils/generate-space-name.js +206 -21
  161. package/dist/utils/grant-decision.fixtures.json +2938 -0
  162. package/dist/utils/grants.d.ts +2 -0
  163. package/dist/utils/grants.js +26 -1
  164. package/dist/utils/gravatar.d.ts +9 -0
  165. package/dist/utils/gravatar.js +31 -0
  166. package/dist/utils/idempotency.d.ts +6 -0
  167. package/dist/utils/idempotency.js +28 -0
  168. package/dist/utils/local-space-state.d.ts +9 -16
  169. package/dist/utils/local-space-state.js +20 -50
  170. package/dist/utils/one-shot-replay.d.ts +4 -1
  171. package/dist/utils/page-colors.d.ts +14 -12
  172. package/dist/utils/page-colors.js +15 -13
  173. package/dist/utils/page-fonts.d.ts +2 -2
  174. package/dist/utils/page-fonts.js +15 -4
  175. package/dist/utils/pages.d.ts +21 -3
  176. package/dist/utils/pages.js +42 -13
  177. package/dist/utils/publish-form-data.d.ts +12 -0
  178. package/dist/utils/publish-form-data.js +10 -0
  179. package/dist/utils/publish-policy.d.ts +27 -0
  180. package/dist/utils/publish-policy.fixtures.json +403 -0
  181. package/dist/utils/publish-policy.js +45 -20
  182. package/dist/utils/push-new.d.ts +7 -0
  183. package/dist/utils/push-new.js +7 -0
  184. package/dist/utils/query-keys.d.ts +4 -5
  185. package/dist/utils/query-keys.js +2 -3
  186. package/dist/utils/runtime-paths.d.ts +5 -0
  187. package/dist/utils/runtime-paths.js +5 -0
  188. package/dist/utils/runtime-upload-batch.d.ts +0 -5
  189. package/dist/utils/runtime-upload-batch.js +1 -27
  190. package/dist/utils/runtime-upload.d.ts +6 -11
  191. package/dist/utils/runtime-upload.js +10 -13
  192. package/dist/utils/secure-local-file.js +5 -16
  193. package/dist/utils/space-config.d.ts +1 -34
  194. package/dist/utils/space-config.js +8 -326
  195. package/dist/utils/static-runtime-policy.d.ts +9 -3
  196. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  197. package/dist/utils/static-runtime-policy.js +22 -56
  198. package/dist/utils/storage-policy.d.ts +1 -1
  199. package/dist/utils/storage-policy.js +3 -1
  200. package/dist/utils/structured-error.d.ts +14 -0
  201. package/dist/utils/structured-error.js +22 -0
  202. package/dist/utils/upload-session.d.ts +4 -1
  203. package/dist/utils/upload-session.js +33 -5
  204. package/dist/utils/version-path.js +13 -4
  205. package/dist/vocabulary.d.ts +13 -11
  206. package/dist/vocabulary.js +42 -28
  207. package/package.json +7 -17
  208. package/dist/config/postgres-budget.d.ts +0 -129
  209. package/dist/config/postgres-budget.js +0 -140
  210. package/dist/config/postgres-budget.json +0 -51
  211. package/dist/contracts/archives.d.ts +0 -331
  212. package/dist/contracts/archives.js +0 -120
  213. package/dist/contracts/deployments.d.ts +0 -574
  214. package/dist/contracts/deployments.js +0 -97
  215. package/dist/contracts/sites.d.ts +0 -416
  216. package/dist/contracts/sites.js +0 -168
  217. package/dist/contracts/superadmin-queues.d.ts +0 -414
  218. package/dist/contracts/superadmin-queues.js +0 -202
  219. package/dist/contracts/superadmin-runtime.d.ts +0 -27
  220. package/dist/contracts/superadmin-runtime.js +0 -38
  221. package/dist/index.d.ts +0 -1
  222. package/dist/index.js +0 -1
  223. package/dist/utils/api.d.ts +0 -4
  224. package/dist/utils/api.js +0 -13
@@ -1,8 +1,9 @@
1
1
  import { buildClaudeMcpAddCommand, buildHermesMcpAddCommand, cursorHostedMcpDeeplink, cursorHostedMcpServersJson, getConnectTarget, opencodeHostedMcpConfig, vscodeHostedMcpDeeplink, vscodeHostedMcpServersJson, } from "../agents/connect-targets.js";
2
2
  import { BRAND } from "../brand.js";
3
3
  import { serviceOrigin } from "../config/domains.js";
4
+ import { PLAN_DEFINITIONS, SELF_SERVE_PLAN_CODES } from "../contracts/features.js";
4
5
  import { createBrowserCredentialUrl, parseBrowserCredentialUrl, } from "../utils/browser-credential.js";
5
- import { CHECK_BEFORE_PUBLISH_PROSE, CONTINUE_AFTER_CLAIM_PROSE, ENV_NOTES_PROSE, FAILURE_CONDUCT_PROSE, HOW_TO_RESEARCH_PROSE, LANE_PICKER_PROSE, POSITIONING_PROSE, PUBLISH_SEQUENCE_PROSE, RECEIPT_SHAPE_PROSE, SAVE_STATE_PROSE, SECRET_RULES_PROSE, SIGNED_UPLOAD_PROSE, UPDATE_SPACE_PROSE, } from "./agent-prose.js";
6
+ import { CHECK_BEFORE_PUBLISH_PROSE, CONTINUE_AFTER_CLAIM_PROSE, ENV_NOTES_PROSE, FAILURE_CONDUCT_PROSE, FEEDBACK_PROSE, HOW_TO_RESEARCH_PROSE, LANE_PICKER_PROSE, POSITIONING_PROSE, PUBLISH_SEQUENCE_PROSE, RECEIPT_SHAPE_PROSE, SAVE_STATE_PROSE, SECRET_RULES_PROSE, SIGNED_UPLOAD_PROSE, UPDATE_SPACE_PROSE, } from "./agent-prose.js";
6
7
  import { spacefastClaudePluginAddCommand, spacefastClaudeDesktopExtensionUrl, spacefastClaudePluginInstallCommand, spacefastCodexPluginAddCommand, spacefastCodexPluginInstallCommand, spacefastInstallCurlCommand, spacefastInstallPowerShellCommand, spacefastSkillFetchCommand, spacefastSkillInstallCommand, spacefastSkillUrl, } from "./skill-distribution.js";
7
8
  // The one URL every agent prompt points at. /setup.md is the actionable front
8
9
  // door (publish now, then set up your client); /ai.txt stays the deep
@@ -17,7 +18,19 @@ export const agentSetupHostLabel = agentSetupParsedUrl.host + agentSetupParsedUr
17
18
  export const agentSetupPrompt = `Fetch ${agentSetupUrl}`;
18
19
  // The no-install publish: one POST, no account. Single-sourced so the
19
20
  // marketing pages and the setup doc can never show different commands.
20
- export const anonymousPublishCurlCommand = `curl -F "files=@index.html" ${serviceOrigin("api", "prod")}/v1/publish`;
21
+ //
22
+ // `?wait=1` is load-bearing, not decoration. Without it the request takes the
23
+ // default finalize budget (SPACEFAST_PUBLISH_DEFAULT_WAIT_MS, 1.5s), so the 201
24
+ // comes back with `activation.outcome: "pending"` plus a `next.action: "poll"`
25
+ // pointer — measured in production at ~4.2s to a receipt describing a site that
26
+ // is not serving yet, settling ~37s later. A one-shot agent then has to run a
27
+ // poll loop against an endpoint that requires the space key as bearer. With
28
+ // `?wait=1` the same publish returns `activation.outcome: "activated"` and
29
+ // `next.action: "done"`, so the documented happy path is genuinely one command.
30
+ //
31
+ // The URL is quoted because `?` is a glob character in zsh: unquoted, the
32
+ // documented command dies with "no matches found" before curl ever runs.
33
+ export const anonymousPublishCurlCommand = `curl -F "files=@index.html" "${serviceOrigin("api", "prod")}/v1/publish?wait=1"`;
21
34
  /*
22
35
  * Agent handoff contract: private links carry a one-use path token on
23
36
  * https://<access-origin>/agent/<documentId>/<token>; durable agent credentials stay encrypted at
@@ -366,8 +379,8 @@ export function aiInstructionsText() {
366
379
  " — for anonymous spaces — the claim link with its expiry. Bare Live and Version URLs carry",
367
380
  " no authority for a private Space; create a scoped Link when a recipient needs access.",
368
381
  " If the receipt's immutable URL is null, poll the",
369
- " operation and version links with the claim token as bearer auth until the version is ready.",
370
- "- Never print access tokens, claim tokens, auth files, or `.spacefast/state.json`.",
382
+ " operation and version links with the space key as bearer auth until the version is ready.",
383
+ "- Never print access tokens, space keys, auth files, or `.spacefast/state.json`.",
371
384
  "",
372
385
  "## After the user claims",
373
386
  "",
@@ -386,7 +399,7 @@ export function aiInstructionsText() {
386
399
  " agent-readable too.",
387
400
  "- Plan limits surface as diagnostics, not failures you should guess at: publish the",
388
401
  " intended artifact, then read and report what the CLI or API says. When a feature",
389
- ' is plan-gated, say: "Not available on Free. Available on Personal and Work."',
402
+ ` is plan-gated, say: "Not available on ${PLAN_DEFINITIONS.free.name}. Available on ${SELF_SERVE_PLAN_CODES.map((code) => PLAN_DEFINITIONS[code].name).join(" and ")}."`,
390
403
  "",
391
404
  "## Agent-aware routing",
392
405
  "",
@@ -452,14 +465,26 @@ export function agentSetupMarkdown() {
452
465
  "endpoint. Fetch the full contract when a publish goes beyond the happy path:",
453
466
  `${agentSetupTextUrl}.`,
454
467
  "",
455
- "The JSON receipt is the result:",
456
- "",
457
- "- `data.space.liveUrl` the live URL. Lead the reply with it.",
458
- "- `data.version.immutableUrl` — the permanent address of this version.",
459
- "- `data.claim.url` and `data.claim.expiresAt` an anonymous space expires unless claimed.",
460
- " Always show the claim link and its deadline.",
461
- "- `data.claim.token` a secret. Use it as the bearer to update the same `spaceId`;",
462
- " never print it.",
468
+ "The JSON receipt is the result. **An anonymous space is private.** Until someone",
469
+ "claims it, the only way in is the space key, so treat every link below as a",
470
+ "credential unless this page says otherwise:",
471
+ "",
472
+ "- `data.claim.url` the door. Open this yourself to check the page, and give it to",
473
+ " the user, because it is the one link that renders the site. It is `/__/<key>`: the",
474
+ " key is *in the URL*, so anyone who has it can also publish over this space and claim",
475
+ " it. Hand it to the person you are working for, never to a wider audience, and keep",
476
+ " it out of commits, logs, and anything public.",
477
+ "- `data.claim.key` — the same secret, bare. Use it as the bearer to update this",
478
+ " `spaceId`. Never print it on its own; the user has it already inside `data.claim.url`.",
479
+ "- `data.claim.claimUrl` and `data.claim.expiresAt` — an anonymous space expires unless",
480
+ " claimed. Always show the claim link and its deadline: claiming is what makes the",
481
+ " space permanent and lets the owner share it with people who should not get the key.",
482
+ "- `data.space.liveUrl` — the space's permanent address, and what it will serve from",
483
+ " once claimed. Do not lead with it and do not hand it to anyone yet: while the space",
484
+ " is anonymous this URL answers 403 for every visitor who has not been through the",
485
+ " door above.",
486
+ "- `data.version.immutableUrl` — the permanent address of this exact version. Same",
487
+ " rule: it carries no authority of its own while the space is anonymous.",
463
488
  "",
464
489
  "## If you can't act on this page",
465
490
  "",
@@ -586,8 +611,11 @@ export function agentSetupMarkdown() {
586
611
  "",
587
612
  "## After publishing",
588
613
  "",
589
- "- Report the live URL first, then the immutable version URL, then the claim link with",
590
- " its expiry.",
614
+ "- Lead with `data.claim.url` it is the only link that renders an anonymous space ",
615
+ " then the claim link with its expiry. Mention the live and immutable URLs as the",
616
+ " addresses the space will serve from once it is claimed, not as links to open now.",
617
+ "- Say plainly that the door link carries the key, so it is for the user and not for",
618
+ " a public post. Claiming is what turns the space into something shareable.",
591
619
  "- Persist the space id and credential so the next publish updates the same space instead",
592
620
  " of creating a new one. The CLI and On-Device MCP do this automatically in `.spacefast/`.",
593
621
  " Hosted MCP is stateless between publishes: retain the receipt's `spaceId` in conversation",
@@ -596,6 +624,8 @@ export function agentSetupMarkdown() {
596
624
  " saved bearer token.",
597
625
  "- Recommend the matching setup above so the next publish is one word.",
598
626
  "",
627
+ FEEDBACK_PROSE,
628
+ "",
599
629
  "## Resources",
600
630
  "",
601
631
  `- Full publishing contract for agents: ${agentSetupTextUrl}`,
@@ -39,7 +39,7 @@ export declare const DOCS_CATALOG: readonly [{
39
39
  readonly kind: "guide";
40
40
  readonly tier: "essential";
41
41
  readonly summary: "How `sf publish` builds, uploads, and goes live.";
42
- readonly keywords: readonly ["publish", "go live", "upload", "release", "static"];
42
+ readonly keywords: readonly ["publish", "go live", "upload", "release", "artifact"];
43
43
  readonly url: "https://spacefast.com/docs/publishing";
44
44
  readonly body: "`sf publish` snapshots your output directory into an immutable version and promotes it to the production channel. Use `--no-wait` to return before serving finishes.";
45
45
  }, {
@@ -65,10 +65,10 @@ export declare const DOCS_CATALOG: readonly [{
65
65
  readonly title: "Anonymous publish and claim";
66
66
  readonly kind: "guide";
67
67
  readonly tier: "essential";
68
- readonly summary: "Publish without an account, then claim the space with its token.";
68
+ readonly summary: "Publish without an account, then claim the space with its key.";
69
69
  readonly keywords: readonly ["anonymous", "claim", "unclaimed", "agent", "token", "adopt"];
70
70
  readonly url: "https://spacefast.com/docs/anonymous-publish";
71
- readonly body: "Publish without logging in to get an instant URL and a claim token; run `sf spaces claim` with that token to bind the space to your account.";
71
+ readonly body: "Publish without logging in to get an instant URL and a space key; run `sf spaces claim` with that key to bind the space to your account.";
72
72
  }, {
73
73
  readonly slug: "agents";
74
74
  readonly title: "Agents and MCP";
@@ -86,13 +86,13 @@ export declare const DOCS_CATALOG: readonly [{
86
86
  readonly summary: "Publish a file or zipped output folder directly to /v1/publish. No account, CLI install, or MCP setup is required for anonymous publishes.";
87
87
  readonly keywords: readonly ["publish", "curl", "anonymous", "no install", "claim"];
88
88
  readonly url: "https://spacefast.com/docs/agents#publish-with-curl";
89
- readonly body: "curl publish static file folder archive zip anonymous no account no install live URL immutable version claim link /v1/publish";
89
+ readonly body: "curl publish file folder archive zip anonymous no account no install live URL immutable version claim link /v1/publish";
90
90
  }, {
91
91
  readonly slug: "workflow/publish-receipt";
92
92
  readonly title: "Publish receipt fields";
93
93
  readonly kind: "workflow";
94
94
  readonly tier: "full";
95
- readonly summary: "Use the receipt as the source of truth. Present open.url and claim.url as the two user-facing links; liveUrl and immutableUrl identify resources for automation.";
95
+ readonly summary: "Use the receipt as the source of truth. For anonymous publishes, claim.url is the private-site door and claim.claimUrl is the browser claim link; liveUrl and immutableUrl identify resources for automation.";
96
96
  readonly keywords: readonly ["receipt", "share", "claim", "diagnostics"];
97
97
  readonly url: "https://spacefast.com/docs/api#publish";
98
98
  readonly body: "receipt liveUrl open url immutableUrl claim expiresAt diagnostics links finalize promote upload errors docsUrl";
@@ -101,16 +101,16 @@ export declare const DOCS_CATALOG: readonly [{
101
101
  readonly title: "Keep publishing after the user claims";
102
102
  readonly kind: "workflow";
103
103
  readonly tier: "full";
104
- readonly summary: "After the owner claims an anonymous space with continuation enabled, exchange the saved claim token once for a durable space-scoped access token, save it over the claim token, and keep publishing.";
104
+ readonly summary: "After the owner claims an anonymous space with continuation enabled, exchange the saved space key once for a durable space-scoped access token, save it over the key, and keep publishing.";
105
105
  readonly keywords: readonly ["continue", "exchange", "claim token", "space_claimed_credential_available", "continuation"];
106
106
  readonly url: "https://spacefast.com/docs/agents#continue-after-claim";
107
- readonly body: "continue continuation claim token exchange voucher publish execute POST /v1/anonymous-claim/exchange space_claimed_credential_available continuation_used continuation_unavailable durable access token state.json update after claim";
107
+ readonly body: "continue continuation space key claim token exchange voucher publish execute POST /v1/claim/exchange space_claimed_credential_available continuation_used continuation_unavailable durable access token state.json update after claim";
108
108
  }, {
109
109
  readonly slug: "workflow/secret-handling";
110
110
  readonly title: "Secret handling rules";
111
111
  readonly kind: "workflow";
112
112
  readonly tier: "full";
113
- readonly summary: "Treat claim tokens, upload tokens, device codes, API keys, auth files, and .spacefast state as credentials. Do not print, commit, archive, or log them.";
113
+ readonly summary: "Treat space keys, upload tokens, device codes, API keys, auth files, and .spacefast state as credentials. Do not print, commit, archive, or log them.";
114
114
  readonly keywords: readonly ["secret", "token", "claim token", "redact"];
115
115
  readonly url: "https://spacefast.com/docs/agents#secret-handling";
116
116
  readonly body: "secret handling claim token upload token device code API key auth file .spacefast state redact logs transcripts archive";
@@ -137,10 +137,10 @@ export declare const DOCS_CATALOG: readonly [{
137
137
  readonly title: "Space file conventions";
138
138
  readonly kind: "workflow";
139
139
  readonly tier: "full";
140
- readonly summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Static artifacts are served as files; server code is not executed.";
140
+ readonly summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Published artifacts are served as files; server code is not executed.";
141
141
  readonly keywords: readonly ["_redirects", "_headers", "sf.jsonc", "spacefast.jsonc", "404"];
142
142
  readonly url: "https://spacefast.com/docs/configuration";
143
- readonly body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers";
143
+ readonly body: "_redirects _headers 404.html sf.jsonc artifact server code not executed proxy rewrite headers";
144
144
  }, {
145
145
  readonly slug: "workflow/domains-diagnostics";
146
146
  readonly title: "Domains and DNS diagnostics";
@@ -239,7 +239,7 @@ export declare const DOCS_CATALOG: readonly [{
239
239
  readonly summary: "Run code on a space with Zero or Functions.";
240
240
  readonly keywords: readonly ["runtime", "zero", "functions", "server", "dynamic", "code", "backend", "sf.jsonc"];
241
241
  readonly url: "https://spacefast.com/docs/runtimes";
242
- readonly body: "A space serves static files until you declare a `runtime` block in sf.jsonc. Zero is a capsule with its own database and transactions; Functions is a worker with one `fetch` handler and any npm package. Both compile during `sf publish`. Zero runs on plans with dedicated runtime isolation; Functions remains in private beta.";
242
+ readonly body: "A space serves published files until you declare a `runtime` block in sf.jsonc. Every space has its own runtime site. Zero is a capsule with its own database and transactions; Functions is a Cloudflare worker with one `fetch` handler and any npm package. Both are available on every plan and compile during `sf publish`.";
243
243
  }, {
244
244
  readonly slug: "runtimes/zero";
245
245
  readonly title: "Spacefast Zero";
@@ -248,7 +248,7 @@ export declare const DOCS_CATALOG: readonly [{
248
248
  readonly summary: "A capsule with a database: schema, queries, mutations, endpoints.";
249
249
  readonly keywords: readonly ["zero", "capsule", "database", "schema", "query", "mutation", "endpoint", "transaction", "sql", "sf dev"];
250
250
  readonly url: "https://spacefast.com/docs/runtimes/zero";
251
- readonly body: "Zero is for apps where the data is the point. Write one capsule — schema, queries, mutations, endpoints — start it locally with `sf dev`, and `sf publish` puts it live with its own database on a plan with dedicated runtime isolation.";
251
+ readonly body: "Zero is for apps where the data is the point. Write one capsule — schema, queries, mutations, endpoints — start it locally with `sf dev`, and `sf publish` puts it live with its own database and dedicated runtime site on every plan.";
252
252
  }, {
253
253
  readonly slug: "runtimes/functions";
254
254
  readonly title: "Spacefast Functions";
@@ -257,7 +257,7 @@ export declare const DOCS_CATALOG: readonly [{
257
257
  readonly summary: "A worker for your space: one `fetch` handler, any npm package.";
258
258
  readonly keywords: readonly ["functions", "worker", "fetch", "ssr", "cloudflare", "npm", "handler", "server", "api"];
259
259
  readonly url: "https://spacefast.com/docs/runtimes/functions";
260
- readonly body: "Functions runs a worker for your space: a default export with a `fetch` method, served from your space's own origin, so requests no file answers reach your code. Opt into a database with `\"database\": true`. Private beta the team needs the flag.";
260
+ readonly body: "Functions runs a Cloudflare worker for your space: a default export with a `fetch` method, served from your space's own origin, so requests no file answers reach your code. It is available on every plan. Opt into a database with `\"database\": true`. Automatic Next.js builds use a private, version-scoped origin cache for the Data Cache, `revalidateTag()`, `revalidatePath()`, and ISR regeneration leases; no cache credential enters the worker.";
261
261
  }, {
262
262
  readonly slug: "collab";
263
263
  readonly title: "Comments";
@@ -284,7 +284,7 @@ export declare const DOCS_CATALOG: readonly [{
284
284
  readonly summary: "Proxy selected paths to an upstream origin.";
285
285
  readonly keywords: readonly ["proxy", "upstream", "route", "api", "backend", "rewrite"];
286
286
  readonly url: "https://spacefast.com/docs/proxy-routes";
287
- readonly body: "Forward specific path prefixes to an external upstream so a static space can front a dynamic API without exposing the origin.";
287
+ readonly body: "Forward specific path prefixes to an external upstream so a space can front an external API without exposing its origin.";
288
288
  }, {
289
289
  readonly slug: "image-acceleration";
290
290
  readonly title: "Image acceleration";
@@ -299,10 +299,10 @@ export declare const DOCS_CATALOG: readonly [{
299
299
  readonly title: "Next.js integration";
300
300
  readonly kind: "guide";
301
301
  readonly tier: "reference";
302
- readonly summary: "Publish a Next.js static export to a space.";
303
- readonly keywords: readonly ["nextjs", "next", "react", "framework", "integration", "export"];
302
+ readonly summary: "Build and publish a full Next.js app with OpenNext.";
303
+ readonly keywords: readonly ["nextjs", "next", "react", "framework", "integration", "opennext", "isr", "data cache", "revalidateTag", "revalidatePath"];
304
304
  readonly url: "https://spacefast.com/docs/integrations/nextjs";
305
- readonly body: "Build your Next.js static export and publish the output directory with `sf publish`; `sf init` detects the framework and sets the output path.";
305
+ readonly body: "Run `sf publish` in a Next.js project. Spacefast builds it with pinned OpenNext and publishes the browser assets plus its Functions worker. The automatic adapter keeps the Next Data Cache and tag invalidations in private origin storage scoped to the exact space and version, so cached data survives cold Worker isolates; `revalidateTag()` and `revalidatePath()` invalidate that same store. Concurrent stale ISR requests share a 30-second regeneration lease, with at most 4,096 leases active for one version. Each cached value is limited to 4 MiB; one version may retain 128 MiB, 4,096 entries, and 8,192 tags. A project with its own `open-next.config.ts` owns its adapters instead of receiving Spacefast's automatic cache config.";
306
306
  }, {
307
307
  readonly slug: "integrations/vite";
308
308
  readonly title: "Vite integration";
@@ -320,7 +320,7 @@ export declare const DOCS_CATALOG: readonly [{
320
320
  readonly summary: "File counts, sizes, and rate limits per plan.";
321
321
  readonly keywords: readonly ["limits", "quota", "size", "rate limit", "plan", "storage"];
322
322
  readonly url: "https://spacefast.com/docs/limits";
323
- readonly body: "Reference for per-space file counts, archive and file size ceilings, version retention, and rate limits, which vary by plan.";
323
+ readonly body: "Reference for per-space file counts, archive and file size ceilings, and rate limits, which vary by plan.";
324
324
  }, {
325
325
  readonly slug: "troubleshooting";
326
326
  readonly title: "Troubleshooting";
@@ -383,23 +383,23 @@ export declare const DOCS_CATALOG: readonly [{
383
383
  readonly summary: "Attach an anonymously-published space to your account.";
384
384
  readonly keywords: readonly ["claim", "anonymous", "attach", "token", "adopt", "spaces"];
385
385
  readonly url: "https://spacefast.com/docs/cli";
386
- readonly body: "After an agent publishes anonymously, run `sf spaces claim` with the claim token to bind the space to your account.";
386
+ readonly body: "After an agent publishes anonymously, run `sf spaces claim` with the space key to bind the space to your account.";
387
387
  }, {
388
388
  readonly slug: "cli/spaces";
389
389
  readonly title: "sf spaces";
390
390
  readonly kind: "cli";
391
391
  readonly tier: "full";
392
- readonly summary: "List, inspect, transfer, import, and remove spaces.";
393
- readonly keywords: readonly ["spaces", "space", "ls", "get", "rm", "transfer", "import", "export"];
392
+ readonly summary: "List, inspect, download, duplicate, transfer, and remove spaces.";
393
+ readonly keywords: readonly ["spaces", "space", "ls", "get", "download", "duplicate", "rm", "transfer"];
394
394
  readonly url: "https://spacefast.com/docs/cli";
395
- readonly body: "The `sf spaces` group manages spaces: `ls`, `get`, `claim`, `transfer`, `duplicate`, `import`/`export`, and `rm`.";
395
+ readonly body: "The `sf spaces` group manages spaces: `ls`, `get`, `claim`, `download`, `duplicate`, `transfer`, and `rm`. Use `sf spaces download --version <ref>` to retrieve one immutable version.";
396
396
  }, {
397
397
  readonly slug: "cli/versions";
398
398
  readonly title: "sf versions";
399
399
  readonly kind: "cli";
400
400
  readonly tier: "full";
401
- readonly summary: "List, inspect, download, and remove immutable versions.";
402
- readonly keywords: readonly ["versions", "version", "ls", "get", "download", "rollback", "history"];
401
+ readonly summary: "List, inspect, and remove immutable versions.";
402
+ readonly keywords: readonly ["versions", "version", "ls", "get", "rm", "rollback", "history"];
403
403
  readonly url: "https://spacefast.com/docs/cli";
404
404
  readonly body: "`sf versions ls` shows a space's history; `sf versions get` inspects one and `sf rollback` promotes an earlier version back to live.";
405
405
  }, {
@@ -40,7 +40,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
40
40
  kind: "guide",
41
41
  tier: "essential",
42
42
  summary: "How `sf publish` builds, uploads, and goes live.",
43
- keywords: ["publish", "go live", "upload", "release", "static"],
43
+ keywords: ["publish", "go live", "upload", "release", "artifact"],
44
44
  url: `${DOCS_BASE_URL}/publishing`,
45
45
  body: "`sf publish` snapshots your output directory into an immutable version and promotes it to the production channel. Use `--no-wait` to return before serving finishes.",
46
46
  },
@@ -69,10 +69,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
69
69
  title: "Anonymous publish and claim",
70
70
  kind: "guide",
71
71
  tier: "essential",
72
- summary: "Publish without an account, then claim the space with its token.",
72
+ summary: "Publish without an account, then claim the space with its key.",
73
73
  keywords: ["anonymous", "claim", "unclaimed", "agent", "token", "adopt"],
74
74
  url: `${DOCS_BASE_URL}/anonymous-publish`,
75
- body: "Publish without logging in to get an instant URL and a claim token; run `sf spaces claim` with that token to bind the space to your account.",
75
+ body: "Publish without logging in to get an instant URL and a space key; run `sf spaces claim` with that key to bind the space to your account.",
76
76
  },
77
77
  {
78
78
  slug: "agents",
@@ -93,14 +93,14 @@ const HAND_WRITTEN_DOCS_CATALOG = [
93
93
  summary: "Publish a file or zipped output folder directly to /v1/publish. No account, CLI install, or MCP setup is required for anonymous publishes.",
94
94
  keywords: ["publish", "curl", "anonymous", "no install", "claim"],
95
95
  url: `${DOCS_BASE_URL}/agents#publish-with-curl`,
96
- body: "curl publish static file folder archive zip anonymous no account no install live URL immutable version claim link /v1/publish",
96
+ body: "curl publish file folder archive zip anonymous no account no install live URL immutable version claim link /v1/publish",
97
97
  },
98
98
  {
99
99
  slug: "workflow/publish-receipt",
100
100
  title: "Publish receipt fields",
101
101
  kind: "workflow",
102
102
  tier: "full",
103
- summary: "Use the receipt as the source of truth. Present open.url and claim.url as the two user-facing links; liveUrl and immutableUrl identify resources for automation.",
103
+ summary: "Use the receipt as the source of truth. For anonymous publishes, claim.url is the private-site door and claim.claimUrl is the browser claim link; liveUrl and immutableUrl identify resources for automation.",
104
104
  keywords: ["receipt", "share", "claim", "diagnostics"],
105
105
  url: `${DOCS_BASE_URL}/api#publish`,
106
106
  body: "receipt liveUrl open url immutableUrl claim expiresAt diagnostics links finalize promote upload errors docsUrl",
@@ -110,7 +110,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
110
110
  title: "Keep publishing after the user claims",
111
111
  kind: "workflow",
112
112
  tier: "full",
113
- summary: "After the owner claims an anonymous space with continuation enabled, exchange the saved claim token once for a durable space-scoped access token, save it over the claim token, and keep publishing.",
113
+ summary: "After the owner claims an anonymous space with continuation enabled, exchange the saved space key once for a durable space-scoped access token, save it over the key, and keep publishing.",
114
114
  keywords: [
115
115
  "continue",
116
116
  "exchange",
@@ -119,14 +119,14 @@ const HAND_WRITTEN_DOCS_CATALOG = [
119
119
  "continuation",
120
120
  ],
121
121
  url: `${DOCS_BASE_URL}/agents#continue-after-claim`,
122
- body: "continue continuation claim token exchange voucher publish execute POST /v1/anonymous-claim/exchange space_claimed_credential_available continuation_used continuation_unavailable durable access token state.json update after claim",
122
+ body: "continue continuation space key claim token exchange voucher publish execute POST /v1/claim/exchange space_claimed_credential_available continuation_used continuation_unavailable durable access token state.json update after claim",
123
123
  },
124
124
  {
125
125
  slug: "workflow/secret-handling",
126
126
  title: "Secret handling rules",
127
127
  kind: "workflow",
128
128
  tier: "full",
129
- summary: "Treat claim tokens, upload tokens, device codes, API keys, auth files, and .spacefast state as credentials. Do not print, commit, archive, or log them.",
129
+ summary: "Treat space keys, upload tokens, device codes, API keys, auth files, and .spacefast state as credentials. Do not print, commit, archive, or log them.",
130
130
  keywords: ["secret", "token", "claim token", "redact"],
131
131
  url: `${DOCS_BASE_URL}/agents#secret-handling`,
132
132
  body: "secret handling claim token upload token device code API key auth file .spacefast state redact logs transcripts archive",
@@ -156,10 +156,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
156
156
  title: "Space file conventions",
157
157
  kind: "workflow",
158
158
  tier: "full",
159
- summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Static artifacts are served as files; server code is not executed.",
159
+ summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Published artifacts are served as files; server code is not executed.",
160
160
  keywords: ["_redirects", "_headers", "sf.jsonc", "spacefast.jsonc", "404"],
161
161
  url: `${DOCS_BASE_URL}/configuration`,
162
- body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers",
162
+ body: "_redirects _headers 404.html sf.jsonc artifact server code not executed proxy rewrite headers",
163
163
  },
164
164
  {
165
165
  slug: "workflow/domains-diagnostics",
@@ -269,7 +269,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
269
269
  summary: "Run code on a space with Zero or Functions.",
270
270
  keywords: ["runtime", "zero", "functions", "server", "dynamic", "code", "backend", "sf.jsonc"],
271
271
  url: `${DOCS_BASE_URL}/runtimes`,
272
- body: "A space serves static files until you declare a `runtime` block in sf.jsonc. Zero is a capsule with its own database and transactions; Functions is a worker with one `fetch` handler and any npm package. Both compile during `sf publish`. Zero runs on plans with dedicated runtime isolation; Functions remains in private beta.",
272
+ body: "A space serves published files until you declare a `runtime` block in sf.jsonc. Every space has its own runtime site. Zero is a capsule with its own database and transactions; Functions is a Cloudflare worker with one `fetch` handler and any npm package. Both are available on every plan and compile during `sf publish`.",
273
273
  },
274
274
  {
275
275
  slug: "runtimes/zero",
@@ -290,7 +290,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
290
290
  "sf dev",
291
291
  ],
292
292
  url: `${DOCS_BASE_URL}/runtimes/zero`,
293
- body: "Zero is for apps where the data is the point. Write one capsule — schema, queries, mutations, endpoints — start it locally with `sf dev`, and `sf publish` puts it live with its own database on a plan with dedicated runtime isolation.",
293
+ body: "Zero is for apps where the data is the point. Write one capsule — schema, queries, mutations, endpoints — start it locally with `sf dev`, and `sf publish` puts it live with its own database and dedicated runtime site on every plan.",
294
294
  },
295
295
  {
296
296
  slug: "runtimes/functions",
@@ -310,7 +310,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
310
310
  "api",
311
311
  ],
312
312
  url: `${DOCS_BASE_URL}/runtimes/functions`,
313
- body: 'Functions runs a worker for your space: a default export with a `fetch` method, served from your space\'s own origin, so requests no file answers reach your code. Opt into a database with `"database": true`. Private beta the team needs the flag.',
313
+ body: 'Functions runs a Cloudflare worker for your space: a default export with a `fetch` method, served from your space\'s own origin, so requests no file answers reach your code. It is available on every plan. Opt into a database with `"database": true`. Automatic Next.js builds use a private, version-scoped origin cache for the Data Cache, `revalidateTag()`, `revalidatePath()`, and ISR regeneration leases; no cache credential enters the worker.',
314
314
  },
315
315
  {
316
316
  slug: "collab",
@@ -340,7 +340,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
340
340
  summary: "Proxy selected paths to an upstream origin.",
341
341
  keywords: ["proxy", "upstream", "route", "api", "backend", "rewrite"],
342
342
  url: `${DOCS_BASE_URL}/proxy-routes`,
343
- body: "Forward specific path prefixes to an external upstream so a static space can front a dynamic API without exposing the origin.",
343
+ body: "Forward specific path prefixes to an external upstream so a space can front an external API without exposing its origin.",
344
344
  },
345
345
  {
346
346
  slug: "image-acceleration",
@@ -357,10 +357,21 @@ const HAND_WRITTEN_DOCS_CATALOG = [
357
357
  title: "Next.js integration",
358
358
  kind: "guide",
359
359
  tier: "reference",
360
- summary: "Publish a Next.js static export to a space.",
361
- keywords: ["nextjs", "next", "react", "framework", "integration", "export"],
360
+ summary: "Build and publish a full Next.js app with OpenNext.",
361
+ keywords: [
362
+ "nextjs",
363
+ "next",
364
+ "react",
365
+ "framework",
366
+ "integration",
367
+ "opennext",
368
+ "isr",
369
+ "data cache",
370
+ "revalidateTag",
371
+ "revalidatePath",
372
+ ],
362
373
  url: `${DOCS_BASE_URL}/integrations/nextjs`,
363
- body: "Build your Next.js static export and publish the output directory with `sf publish`; `sf init` detects the framework and sets the output path.",
374
+ body: "Run `sf publish` in a Next.js project. Spacefast builds it with pinned OpenNext and publishes the browser assets plus its Functions worker. The automatic adapter keeps the Next Data Cache and tag invalidations in private origin storage scoped to the exact space and version, so cached data survives cold Worker isolates; `revalidateTag()` and `revalidatePath()` invalidate that same store. Concurrent stale ISR requests share a 30-second regeneration lease, with at most 4,096 leases active for one version. Each cached value is limited to 4 MiB; one version may retain 128 MiB, 4,096 entries, and 8,192 tags. A project with its own `open-next.config.ts` owns its adapters instead of receiving Spacefast's automatic cache config.",
364
375
  },
365
376
  {
366
377
  slug: "integrations/vite",
@@ -380,7 +391,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
380
391
  summary: "File counts, sizes, and rate limits per plan.",
381
392
  keywords: ["limits", "quota", "size", "rate limit", "plan", "storage"],
382
393
  url: `${DOCS_BASE_URL}/limits`,
383
- body: "Reference for per-space file counts, archive and file size ceilings, version retention, and rate limits, which vary by plan.",
394
+ body: "Reference for per-space file counts, archive and file size ceilings, and rate limits, which vary by plan.",
384
395
  },
385
396
  {
386
397
  slug: "troubleshooting",
@@ -451,25 +462,25 @@ const HAND_WRITTEN_DOCS_CATALOG = [
451
462
  summary: "Attach an anonymously-published space to your account.",
452
463
  keywords: ["claim", "anonymous", "attach", "token", "adopt", "spaces"],
453
464
  url: `${DOCS_BASE_URL}/cli`,
454
- body: "After an agent publishes anonymously, run `sf spaces claim` with the claim token to bind the space to your account.",
465
+ body: "After an agent publishes anonymously, run `sf spaces claim` with the space key to bind the space to your account.",
455
466
  },
456
467
  {
457
468
  slug: "cli/spaces",
458
469
  title: "sf spaces",
459
470
  kind: "cli",
460
471
  tier: "full",
461
- summary: "List, inspect, transfer, import, and remove spaces.",
462
- keywords: ["spaces", "space", "ls", "get", "rm", "transfer", "import", "export"],
472
+ summary: "List, inspect, download, duplicate, transfer, and remove spaces.",
473
+ keywords: ["spaces", "space", "ls", "get", "download", "duplicate", "rm", "transfer"],
463
474
  url: `${DOCS_BASE_URL}/cli`,
464
- body: "The `sf spaces` group manages spaces: `ls`, `get`, `claim`, `transfer`, `duplicate`, `import`/`export`, and `rm`.",
475
+ body: "The `sf spaces` group manages spaces: `ls`, `get`, `claim`, `download`, `duplicate`, `transfer`, and `rm`. Use `sf spaces download --version <ref>` to retrieve one immutable version.",
465
476
  },
466
477
  {
467
478
  slug: "cli/versions",
468
479
  title: "sf versions",
469
480
  kind: "cli",
470
481
  tier: "full",
471
- summary: "List, inspect, download, and remove immutable versions.",
472
- keywords: ["versions", "version", "ls", "get", "download", "rollback", "history"],
482
+ summary: "List, inspect, and remove immutable versions.",
483
+ keywords: ["versions", "version", "ls", "get", "rm", "rollback", "history"],
473
484
  url: `${DOCS_BASE_URL}/cli`,
474
485
  body: "`sf versions ls` shows a space's history; `sf versions get` inspects one and `sf rollback` promotes an earlier version back to live.",
475
486
  },