@spacefast/common 0.0.12 → 0.0.13

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 (113) hide show
  1. package/dist/contracts/access.d.ts +386 -1201
  2. package/dist/contracts/access.js +240 -1057
  3. package/dist/contracts/activity.d.ts +1 -1
  4. package/dist/contracts/activity.js +6 -14
  5. package/dist/contracts/api-keys.d.ts +16 -0
  6. package/dist/contracts/api-keys.js +2 -0
  7. package/dist/contracts/archives.d.ts +1 -2
  8. package/dist/contracts/archives.js +4 -6
  9. package/dist/contracts/comments.d.ts +58 -85
  10. package/dist/contracts/comments.js +86 -67
  11. package/dist/contracts/countries.js +2 -7
  12. package/dist/contracts/data-source-routes.d.ts +20 -0
  13. package/dist/contracts/data-source-routes.js +15 -0
  14. package/dist/contracts/device-auth.d.ts +7 -3
  15. package/dist/contracts/enums.d.ts +2 -4
  16. package/dist/contracts/enums.js +3 -8
  17. package/dist/contracts/error-code-meta.d.ts +17 -20
  18. package/dist/contracts/error-code-meta.js +8 -5
  19. package/dist/contracts/error-codes.d.ts +1 -1
  20. package/dist/contracts/error-codes.js +4 -5
  21. package/dist/contracts/events.d.ts +13 -13
  22. package/dist/contracts/execution.d.ts +212 -0
  23. package/dist/contracts/execution.js +288 -0
  24. package/dist/contracts/feature-lifecycle.d.ts +21 -167
  25. package/dist/contracts/feature-lifecycle.js +27 -173
  26. package/dist/contracts/features.d.ts +13 -115
  27. package/dist/contracts/features.js +1 -31
  28. package/dist/contracts/functions.d.ts +729 -0
  29. package/dist/contracts/functions.js +485 -0
  30. package/dist/contracts/git.d.ts +1 -1
  31. package/dist/contracts/grants.d.ts +1158 -0
  32. package/dist/contracts/grants.js +696 -0
  33. package/dist/contracts/ids.d.ts +5 -3
  34. package/dist/contracts/ids.js +5 -3
  35. package/dist/contracts/mcp.d.ts +6 -6
  36. package/dist/contracts/oauth-resources.d.ts +5 -5
  37. package/dist/contracts/oauth-resources.js +1 -0
  38. package/dist/contracts/operations.d.ts +2 -2
  39. package/dist/contracts/pages.d.ts +6 -14
  40. package/dist/contracts/pages.js +6 -23
  41. package/dist/contracts/plan-policy.d.ts +1 -8
  42. package/dist/contracts/plan-policy.js +1 -4
  43. package/dist/contracts/platform.d.ts +78 -30
  44. package/dist/contracts/platform.js +59 -12
  45. package/dist/contracts/push-new.d.ts +26 -2
  46. package/dist/contracts/push-new.js +8 -0
  47. package/dist/contracts/quotas.d.ts +0 -1
  48. package/dist/contracts/quotas.js +0 -5
  49. package/dist/contracts/repository-connections.d.ts +1 -1
  50. package/dist/contracts/resources.d.ts +10 -66
  51. package/dist/contracts/resources.js +4 -10
  52. package/dist/contracts/runtime-api.d.ts +558 -265
  53. package/dist/contracts/runtime-api.js +178 -91
  54. package/dist/contracts/runtime-app.d.ts +138 -0
  55. package/dist/contracts/runtime-app.js +21 -0
  56. package/dist/contracts/sf-config-v1.d.ts +5 -0
  57. package/dist/contracts/sites.d.ts +5 -0
  58. package/dist/contracts/sites.js +12 -1
  59. package/dist/contracts/space-config.d.ts +46 -116
  60. package/dist/contracts/space-config.js +320 -24
  61. package/dist/contracts/spaces.d.ts +253 -158
  62. package/dist/contracts/spaces.js +68 -54
  63. package/dist/contracts/superadmin-emails.d.ts +2 -2
  64. package/dist/contracts/superadmin-spaces.d.ts +15 -130
  65. package/dist/contracts/superadmin-spaces.js +7 -0
  66. package/dist/contracts/tags.d.ts +23 -23
  67. package/dist/contracts/teams.d.ts +9 -9
  68. package/dist/contracts/transfers.d.ts +0 -1
  69. package/dist/contracts/zero.d.ts +195 -273
  70. package/dist/contracts/zero.js +78 -206
  71. package/dist/dashboard-paths/index.d.ts +2 -2
  72. package/dist/dashboard-paths/index.js +1 -0
  73. package/dist/docs/agent-prose.js +10 -8
  74. package/dist/docs/agent-setup.d.ts +2 -2
  75. package/dist/docs/agent-setup.js +11 -9
  76. package/dist/docs/agent-solutions.js +1 -1
  77. package/dist/docs/catalog.d.ts +28 -28
  78. package/dist/docs/catalog.js +29 -29
  79. package/dist/docs/error-docs.js +23 -27
  80. package/dist/utils/asset-fingerprint.d.ts +11 -0
  81. package/dist/utils/asset-fingerprint.js +46 -0
  82. package/dist/utils/auth-redirect.d.ts +1 -3
  83. package/dist/utils/auth-redirect.js +1 -21
  84. package/dist/utils/build-settings.d.ts +2 -0
  85. package/dist/utils/build-settings.js +61 -9
  86. package/dist/utils/credential-policy.d.ts +1 -1
  87. package/dist/utils/credential-policy.js +4 -0
  88. package/dist/utils/egress-policy.fixtures.json +1 -1
  89. package/dist/utils/grants.d.ts +53 -0
  90. package/dist/utils/grants.js +160 -0
  91. package/dist/utils/local-space-state.js +1 -0
  92. package/dist/utils/pages.d.ts +11 -5
  93. package/dist/utils/pages.js +19 -32
  94. package/dist/utils/publish-policy.d.ts +34 -4
  95. package/dist/utils/publish-policy.js +132 -61
  96. package/dist/utils/query-keys.d.ts +1 -6
  97. package/dist/utils/query-keys.js +1 -6
  98. package/dist/utils/space-config.d.ts +5 -1
  99. package/dist/utils/space-config.js +35 -0
  100. package/dist/utils/static-runtime-policy.d.ts +5 -0
  101. package/dist/utils/static-runtime-policy.js +54 -10
  102. package/dist/utils/upload-session.d.ts +3 -0
  103. package/dist/utils/upload-session.js +31 -0
  104. package/package.json +2 -1
  105. package/dist/utils/access-grant.d.ts +0 -14
  106. package/dist/utils/access-grant.js +0 -88
  107. package/dist/utils/access-match.d.ts +0 -46
  108. package/dist/utils/access-match.fixtures.json +0 -513
  109. package/dist/utils/access-match.js +0 -312
  110. package/dist/utils/access-verdict.fixtures.json +0 -421
  111. package/dist/utils/sf-config-v1.d.ts +0 -2
  112. package/dist/utils/sf-config-v1.fixtures.json +0 -9
  113. package/dist/utils/sf-config-v1.js +0 -551
@@ -42,6 +42,15 @@ export declare const DOCS_CATALOG: readonly [{
42
42
  readonly keywords: readonly ["publish", "go live", "upload", "release", "static"];
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
+ }, {
46
+ readonly slug: "spaces/rename";
47
+ readonly title: "Rename a space";
48
+ readonly kind: "guide";
49
+ readonly tier: "full";
50
+ readonly summary: "Change a space slug and its managed view.fast address without breaking old links.";
51
+ readonly keywords: readonly ["space", "rename", "slug", "view.fast", "redirect", "managed hostname"];
52
+ readonly url: "https://spacefast.com/docs/spaces/rename";
53
+ readonly body: "Run `sf spaces update --space <space> --slug <new-slug> --wait`, or PATCH `/v1/spaces/{spaceId}` with `{ \"slug\": \"<new-slug>\" }`. The managed view.fast hostname changes with the slug. Former managed addresses and branch aliases redirect directly to their current counterparts with a temporary, path- and query-preserving 307 for the life of the space unless an operator explicitly releases them. Custom domains stay attached, and immutable version URLs do not change.";
45
54
  }, {
46
55
  readonly slug: "versions-and-rollback";
47
56
  readonly title: "Versions and rollback";
@@ -83,10 +92,10 @@ export declare const DOCS_CATALOG: readonly [{
83
92
  readonly title: "Publish receipt fields";
84
93
  readonly kind: "workflow";
85
94
  readonly tier: "full";
86
- readonly summary: "Use the receipt as the source of truth: space.liveUrl, version.immutableUrl, shareBlurb, claim.url, claim.expiresAt, links, diagnostics, and errors.";
95
+ readonly summary: "Use the receipt as the source of truth: space.liveUrl, open.url, version.immutableUrl, claim.url, claim.expiresAt, links, diagnostics, and errors.";
87
96
  readonly keywords: readonly ["receipt", "share", "claim", "diagnostics"];
88
97
  readonly url: "https://spacefast.com/docs/api#publish";
89
- readonly body: "receipt liveUrl immutableUrl shareBlurb claim url expiresAt diagnostics links finalize promote upload errors docsUrl";
98
+ readonly body: "receipt liveUrl open url immutableUrl claim expiresAt diagnostics links finalize promote upload errors docsUrl";
90
99
  }, {
91
100
  readonly slug: "workflow/continue-after-claim";
92
101
  readonly title: "Keep publishing after the user claims";
@@ -110,10 +119,10 @@ export declare const DOCS_CATALOG: readonly [{
110
119
  readonly title: "CLI command surface";
111
120
  readonly kind: "workflow";
112
121
  readonly tier: "full";
113
- readonly summary: "Use sf for repeat work: publish, versions, rollback, logs, domains, passwords, teams, API calls, and On-Device MCP serving.";
122
+ readonly summary: "Use sf for repeat work: publish, versions, rollback, logs, domains, sharing, teams, API calls, and On-Device MCP serving.";
114
123
  readonly keywords: readonly ["sf", "cli", "spacefast", "mcp", "json"];
115
124
  readonly url: "https://spacefast.com/docs/cli";
116
- readonly body: "sf spacefast CLI publish versions rollback logs domains passwords teams api mcp setup profile login --json";
125
+ readonly body: "sf spacefast CLI publish versions rollback logs domains share teams api mcp setup profile login --json";
117
126
  }, {
118
127
  readonly slug: "workflow/mcp-local";
119
128
  readonly title: "On-Device MCP through the CLI";
@@ -149,7 +158,7 @@ export declare const DOCS_CATALOG: readonly [{
149
158
  readonly summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Static artifacts are served as files; server code is not executed.";
150
159
  readonly keywords: readonly ["_redirects", "_headers", "sf.jsonc", "spacefast.jsonc", "404"];
151
160
  readonly url: "https://spacefast.com/docs/configuration";
152
- readonly body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers basic auth";
161
+ readonly body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers";
153
162
  }, {
154
163
  readonly slug: "workflow/domains-diagnostics";
155
164
  readonly title: "Domains and DNS diagnostics";
@@ -209,10 +218,10 @@ export declare const DOCS_CATALOG: readonly [{
209
218
  readonly title: "Access control";
210
219
  readonly kind: "guide";
211
220
  readonly tier: "full";
212
- readonly summary: "Password-protect a space or grant access to specific people.";
213
- readonly keywords: readonly ["access", "password", "grant", "ban", "private", "audience", "auth"];
221
+ readonly summary: "Create scoped Grants, invite People, and manage Links or credentials.";
222
+ readonly keywords: readonly ["access", "share", "people", "links", "private", "team", "public"];
214
223
  readonly url: "https://spacefast.com/docs/access";
215
- readonly body: "Gate a space with `sf password set`, grant individuals with `sf access grant`, and review effective rules with `sf access effective`.";
224
+ readonly body: "Use `sf share grant`, `sf share people`, `sf share link`, `sf share password`, or `sf share token`. Inspect one route with `sf share check`; every audience uses the same path, capability, target, and constraint evaluator.";
216
225
  }, {
217
226
  readonly slug: "redirects";
218
227
  readonly title: "Redirects";
@@ -227,10 +236,10 @@ export declare const DOCS_CATALOG: readonly [{
227
236
  readonly title: "Custom headers";
228
237
  readonly kind: "guide";
229
238
  readonly tier: "full";
230
- readonly summary: "Attach response headers and path-scoped Basic Auth.";
231
- readonly keywords: readonly ["headers", "cache", "security", "basic auth", "_headers", "cors"];
239
+ readonly summary: "Attach supported response headers by path.";
240
+ readonly keywords: readonly ["headers", "cache", "security", "_headers", "cors"];
232
241
  readonly url: "https://spacefast.com/docs/headers";
233
- readonly body: "Add a `_headers` file at your publish root to set or remove response headers per path. Path-scoped Basic Auth credentials travel with the publish.";
242
+ readonly body: "Add a `_headers` file at your publish root to set or remove supported response headers per path.";
234
243
  }, {
235
244
  readonly slug: "builds";
236
245
  readonly title: "Build from Git";
@@ -239,7 +248,7 @@ export declare const DOCS_CATALOG: readonly [{
239
248
  readonly summary: "Connect a repository so pushes build and publish automatically.";
240
249
  readonly keywords: readonly ["build", "git", "github", "ci", "push", "connect", "preview"];
241
250
  readonly url: "https://spacefast.com/docs/builds";
242
- readonly body: "Connect a repository with `sf git connect`; each push runs your build on Spacefast and publishes a version, with branches and pull requests getting preview URLs.";
251
+ readonly body: "Connect a repository with `sf git connect`; each push runs your build on Spacefast and publishes a version. Branch and pull-request previews are private by default; use Open for yourself or create a scoped Link for reviewers.";
243
252
  }, {
244
253
  readonly slug: "collab";
245
254
  readonly title: "Comments";
@@ -434,10 +443,10 @@ export declare const DOCS_CATALOG: readonly [{
434
443
  readonly title: "sf access";
435
444
  readonly kind: "cli";
436
445
  readonly tier: "full";
437
- readonly summary: "Grant, ban, and inspect who can view a space.";
438
- readonly keywords: readonly ["access", "grant", "ban", "password", "effective", "rules", "policy"];
446
+ readonly summary: "Emergency visitor-session revocation.";
447
+ readonly keywords: readonly ["access", "sessions", "revoke", "logout"];
439
448
  readonly url: "https://spacefast.com/docs/cli";
440
- readonly body: "`sf access grant` / `sf access ban` edit access rules; `sf access effective` shows the resolved policy. Use `sf password set` for a shared password.";
449
+ readonly body: "Use `sf access logout-all` to revoke every opened visitor session. Define audience-specific network restrictions on the corresponding Grant.";
441
450
  }, {
442
451
  readonly slug: "cli/teams";
443
452
  readonly title: "sf teams";
@@ -527,7 +536,7 @@ export declare const DOCS_CATALOG: readonly [{
527
536
  readonly summary: "Create, list, and update spaces over HTTP.";
528
537
  readonly keywords: readonly ["api", "spaces", "space", "create", "list", "endpoint"];
529
538
  readonly url: "https://spacefast.com/docs/api";
530
- readonly body: "`GET /v1/spaces` lists spaces; `POST /v1/spaces` creates one. Responses carry the space id, slug, and live URL.";
539
+ readonly body: "`GET /v1/spaces` lists spaces; `POST /v1/spaces` creates one. `PATCH /v1/spaces/{spaceId}` with a slug-only body renames the space and managed hostname. Former managed addresses temporarily 307 to the current hostname while immutable version URLs stay unchanged. Responses carry the space id, slug, and live URL.";
531
540
  }, {
532
541
  readonly slug: "api/versions";
533
542
  readonly title: "Versions API";
@@ -590,16 +599,16 @@ export declare const DOCS_CATALOG: readonly [{
590
599
  readonly summary: "Connect a repository so pushes publish automatically.";
591
600
  readonly keywords: readonly ["github", "git", "ci", "push", "connect", "automatic", "recipe"];
592
601
  readonly url: "https://spacefast.com/docs/builds";
593
- readonly body: "Connect a repository with `sf git connect`; each push builds on Spacefast and publishes a version, with pull requests getting preview URLs.";
602
+ readonly body: "Connect a repository with `sf git connect`; each push builds on Spacefast and publishes a version. Pull-request previews stay private until you create a scoped Link for reviewers.";
594
603
  }, {
595
604
  readonly slug: "recipes/preview-channels";
596
605
  readonly title: "Preview channels for pull requests";
597
606
  readonly kind: "recipe";
598
607
  readonly tier: "full";
599
- readonly summary: "Give every branch a shareable preview URL.";
608
+ readonly summary: "Give every branch a private preview with explicit sharing.";
600
609
  readonly keywords: readonly ["preview", "channel", "branch", "pull request", "staging", "recipe"];
601
610
  readonly url: "https://spacefast.com/docs/builds";
602
- readonly body: "Push a branch or open a pull request on a connected repository, or publish to a named channel, to get an isolated preview URL without touching production.";
611
+ readonly body: "Push a branch or open a pull request on a connected repository, or publish to a named channel, to get an isolated private preview without touching production. Use Open for your own browser or create a scoped Link when someone else needs access.";
603
612
  }, {
604
613
  readonly slug: "recipes/agent-publish";
605
614
  readonly title: "Let an agent publish for you";
@@ -618,15 +627,6 @@ export declare const DOCS_CATALOG: readonly [{
618
627
  readonly keywords: readonly ["domain", "custom domain", "dns", "tls", "https", "recipe"];
619
628
  readonly url: "https://spacefast.com/help/domains";
620
629
  readonly body: "Add the domain with `sf domains add`, set the DNS records Spacefast prints, and wait for `sf domains check` to report a ready certificate.";
621
- }, {
622
- readonly slug: "recipes/password-protect";
623
- readonly title: "Password-protect a space";
624
- readonly kind: "recipe";
625
- readonly tier: "full";
626
- readonly summary: "Put one shared password in front of a whole space.";
627
- readonly keywords: readonly ["password", "protect", "private", "access", "gate", "recipe"];
628
- readonly url: "https://spacefast.com/help/access";
629
- readonly body: "Run `sf password set` to gate a space behind a single shared secret; clear it later with `sf password clear`.";
630
630
  }, {
631
631
  readonly slug: "recipes/redirects";
632
632
  readonly title: "Set up redirects";
@@ -43,6 +43,16 @@ const HAND_WRITTEN_DOCS_CATALOG = [
43
43
  url: `${DOCS_BASE_URL}/publishing`,
44
44
  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
  },
46
+ {
47
+ slug: "spaces/rename",
48
+ title: "Rename a space",
49
+ kind: "guide",
50
+ tier: "full",
51
+ summary: "Change a space slug and its managed view.fast address without breaking old links.",
52
+ keywords: ["space", "rename", "slug", "view.fast", "redirect", "managed hostname"],
53
+ url: `${DOCS_BASE_URL}/spaces/rename`,
54
+ body: 'Run `sf spaces update --space <space> --slug <new-slug> --wait`, or PATCH `/v1/spaces/{spaceId}` with `{ "slug": "<new-slug>" }`. The managed view.fast hostname changes with the slug. Former managed addresses and branch aliases redirect directly to their current counterparts with a temporary, path- and query-preserving 307 for the life of the space unless an operator explicitly releases them. Custom domains stay attached, and immutable version URLs do not change.',
55
+ },
46
56
  {
47
57
  slug: "versions-and-rollback",
48
58
  title: "Versions and rollback",
@@ -89,10 +99,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
89
99
  title: "Publish receipt fields",
90
100
  kind: "workflow",
91
101
  tier: "full",
92
- summary: "Use the receipt as the source of truth: space.liveUrl, version.immutableUrl, shareBlurb, claim.url, claim.expiresAt, links, diagnostics, and errors.",
102
+ summary: "Use the receipt as the source of truth: space.liveUrl, open.url, version.immutableUrl, claim.url, claim.expiresAt, links, diagnostics, and errors.",
93
103
  keywords: ["receipt", "share", "claim", "diagnostics"],
94
104
  url: `${DOCS_BASE_URL}/api#publish`,
95
- body: "receipt liveUrl immutableUrl shareBlurb claim url expiresAt diagnostics links finalize promote upload errors docsUrl",
105
+ body: "receipt liveUrl open url immutableUrl claim expiresAt diagnostics links finalize promote upload errors docsUrl",
96
106
  },
97
107
  {
98
108
  slug: "workflow/continue-after-claim",
@@ -125,10 +135,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
125
135
  title: "CLI command surface",
126
136
  kind: "workflow",
127
137
  tier: "full",
128
- summary: "Use sf for repeat work: publish, versions, rollback, logs, domains, passwords, teams, API calls, and On-Device MCP serving.",
138
+ summary: "Use sf for repeat work: publish, versions, rollback, logs, domains, sharing, teams, API calls, and On-Device MCP serving.",
129
139
  keywords: ["sf", "cli", "spacefast", "mcp", "json"],
130
140
  url: `${DOCS_BASE_URL}/cli`,
131
- body: "sf spacefast CLI publish versions rollback logs domains passwords teams api mcp setup profile login --json",
141
+ body: "sf spacefast CLI publish versions rollback logs domains share teams api mcp setup profile login --json",
132
142
  },
133
143
  {
134
144
  slug: "workflow/mcp-local",
@@ -177,7 +187,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
177
187
  summary: "Spacefast recognizes _redirects, _headers, nearest 404.html, and sf.jsonc. Static artifacts are served as files; server code is not executed.",
178
188
  keywords: ["_redirects", "_headers", "sf.jsonc", "spacefast.jsonc", "404"],
179
189
  url: `${DOCS_BASE_URL}/configuration`,
180
- body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers basic auth",
190
+ body: "_redirects _headers 404.html sf.jsonc static artifact server code not executed proxy rewrite headers",
181
191
  },
182
192
  {
183
193
  slug: "workflow/domains-diagnostics",
@@ -244,10 +254,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
244
254
  title: "Access control",
245
255
  kind: "guide",
246
256
  tier: "full",
247
- summary: "Password-protect a space or grant access to specific people.",
248
- keywords: ["access", "password", "grant", "ban", "private", "audience", "auth"],
257
+ summary: "Create scoped Grants, invite People, and manage Links or credentials.",
258
+ keywords: ["access", "share", "people", "links", "private", "team", "public"],
249
259
  url: `${DOCS_BASE_URL}/access`,
250
- body: "Gate a space with `sf password set`, grant individuals with `sf access grant`, and review effective rules with `sf access effective`.",
260
+ body: "Use `sf share grant`, `sf share people`, `sf share link`, `sf share password`, or `sf share token`. Inspect one route with `sf share check`; every audience uses the same path, capability, target, and constraint evaluator.",
251
261
  },
252
262
  {
253
263
  slug: "redirects",
@@ -264,10 +274,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
264
274
  title: "Custom headers",
265
275
  kind: "guide",
266
276
  tier: "full",
267
- summary: "Attach response headers and path-scoped Basic Auth.",
268
- keywords: ["headers", "cache", "security", "basic auth", "_headers", "cors"],
277
+ summary: "Attach supported response headers by path.",
278
+ keywords: ["headers", "cache", "security", "_headers", "cors"],
269
279
  url: `${DOCS_BASE_URL}/headers`,
270
- body: "Add a `_headers` file at your publish root to set or remove response headers per path. Path-scoped Basic Auth credentials travel with the publish.",
280
+ body: "Add a `_headers` file at your publish root to set or remove supported response headers per path.",
271
281
  },
272
282
  {
273
283
  slug: "builds",
@@ -277,7 +287,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
277
287
  summary: "Connect a repository so pushes build and publish automatically.",
278
288
  keywords: ["build", "git", "github", "ci", "push", "connect", "preview"],
279
289
  url: `${DOCS_BASE_URL}/builds`,
280
- body: "Connect a repository with `sf git connect`; each push runs your build on Spacefast and publishes a version, with branches and pull requests getting preview URLs.",
290
+ body: "Connect a repository with `sf git connect`; each push runs your build on Spacefast and publishes a version. Branch and pull-request previews are private by default; use Open for yourself or create a scoped Link for reviewers.",
281
291
  },
282
292
  {
283
293
  slug: "collab",
@@ -495,10 +505,10 @@ const HAND_WRITTEN_DOCS_CATALOG = [
495
505
  title: "sf access",
496
506
  kind: "cli",
497
507
  tier: "full",
498
- summary: "Grant, ban, and inspect who can view a space.",
499
- keywords: ["access", "grant", "ban", "password", "effective", "rules", "policy"],
508
+ summary: "Emergency visitor-session revocation.",
509
+ keywords: ["access", "sessions", "revoke", "logout"],
500
510
  url: `${DOCS_BASE_URL}/cli`,
501
- body: "`sf access grant` / `sf access ban` edit access rules; `sf access effective` shows the resolved policy. Use `sf password set` for a shared password.",
511
+ body: "Use `sf access logout-all` to revoke every opened visitor session. Define audience-specific network restrictions on the corresponding Grant.",
502
512
  },
503
513
  {
504
514
  slug: "cli/teams",
@@ -599,7 +609,7 @@ const HAND_WRITTEN_DOCS_CATALOG = [
599
609
  summary: "Create, list, and update spaces over HTTP.",
600
610
  keywords: ["api", "spaces", "space", "create", "list", "endpoint"],
601
611
  url: `${DOCS_BASE_URL}/api`,
602
- body: "`GET /v1/spaces` lists spaces; `POST /v1/spaces` creates one. Responses carry the space id, slug, and live URL.",
612
+ body: "`GET /v1/spaces` lists spaces; `POST /v1/spaces` creates one. `PATCH /v1/spaces/{spaceId}` with a slug-only body renames the space and managed hostname. Former managed addresses temporarily 307 to the current hostname while immutable version URLs stay unchanged. Responses carry the space id, slug, and live URL.",
603
613
  },
604
614
  {
605
615
  slug: "api/versions",
@@ -670,17 +680,17 @@ const HAND_WRITTEN_DOCS_CATALOG = [
670
680
  summary: "Connect a repository so pushes publish automatically.",
671
681
  keywords: ["github", "git", "ci", "push", "connect", "automatic", "recipe"],
672
682
  url: `${DOCS_BASE_URL}/builds`,
673
- body: "Connect a repository with `sf git connect`; each push builds on Spacefast and publishes a version, with pull requests getting preview URLs.",
683
+ body: "Connect a repository with `sf git connect`; each push builds on Spacefast and publishes a version. Pull-request previews stay private until you create a scoped Link for reviewers.",
674
684
  },
675
685
  {
676
686
  slug: "recipes/preview-channels",
677
687
  title: "Preview channels for pull requests",
678
688
  kind: "recipe",
679
689
  tier: "full",
680
- summary: "Give every branch a shareable preview URL.",
690
+ summary: "Give every branch a private preview with explicit sharing.",
681
691
  keywords: ["preview", "channel", "branch", "pull request", "staging", "recipe"],
682
692
  url: `${DOCS_BASE_URL}/builds`,
683
- body: "Push a branch or open a pull request on a connected repository, or publish to a named channel, to get an isolated preview URL without touching production.",
693
+ body: "Push a branch or open a pull request on a connected repository, or publish to a named channel, to get an isolated private preview without touching production. Use Open for your own browser or create a scoped Link when someone else needs access.",
684
694
  },
685
695
  {
686
696
  slug: "recipes/agent-publish",
@@ -702,16 +712,6 @@ const HAND_WRITTEN_DOCS_CATALOG = [
702
712
  url: "https://spacefast.com/help/domains",
703
713
  body: "Add the domain with `sf domains add`, set the DNS records Spacefast prints, and wait for `sf domains check` to report a ready certificate.",
704
714
  },
705
- {
706
- slug: "recipes/password-protect",
707
- title: "Password-protect a space",
708
- kind: "recipe",
709
- tier: "full",
710
- summary: "Put one shared password in front of a whole space.",
711
- keywords: ["password", "protect", "private", "access", "gate", "recipe"],
712
- url: "https://spacefast.com/help/access",
713
- body: "Run `sf password set` to gate a space behind a single shared secret; clear it later with `sf password clear`.",
714
- },
715
715
  {
716
716
  slug: "recipes/redirects",
717
717
  title: "Set up redirects",
@@ -28,6 +28,10 @@ export const ERROR_DOCS = {
28
28
  summary: "The authorization request was denied by the user.",
29
29
  fix: "Restart the login flow and approve the request to continue.",
30
30
  },
31
+ access_scope_suggestion: {
32
+ summary: "Published dependencies cluster under paths that may be useful as explicit public scopes.",
33
+ fix: "If those files are safe for anyone to read, make only the suggested scopes Public. Otherwise leave access unchanged.",
34
+ },
31
35
  agent_handoff_declined: {
32
36
  summary: "The app-private agent handoff cannot be redeemed.",
33
37
  fix: "Ask the user to create a fresh handoff for this Space and client, then redeem that new link once.",
@@ -173,7 +177,7 @@ export const ERROR_DOCS = {
173
177
  fix: "Upgrade the CLI to the latest release and retry.",
174
178
  },
175
179
  comment_screenshot_rate_limited: {
176
- summary: "Too many anonymous comment screenshot uploads were attempted.",
180
+ summary: "Too many comment screenshot uploads were attempted.",
177
181
  fix: "Wait for the one-minute window to reset, then retry the screenshot upload.",
178
182
  },
179
183
  config_file_too_large: {
@@ -194,11 +198,11 @@ export const ERROR_DOCS = {
194
198
  },
195
199
  continuation_unavailable: {
196
200
  summary: "This claim token can no longer be exchanged for an access token.",
197
- fix: "If the space is claimed, ask its owner for an access token (dashboard: Account → Access tokens). If it is still unclaimed, keep using the claim token as bearer auth instead of exchanging it. Still stuck? POST /v1/feedback with the error code and request id.",
201
+ fix: "If the space is claimed, ask its owner for an API key (dashboard: Account → API keys). If it is still unclaimed, keep using the claim token as bearer auth instead of exchanging it. Still stuck? POST /v1/feedback with the error code and request id.",
198
202
  },
199
203
  continuation_used: {
200
204
  summary: "This claim token was already exchanged for a durable access token.",
201
- fix: "Authenticate with the exchanged access token (check .spacefast/state.json or wherever it was saved). If it was lost, ask the space owner to mint a new access token.",
205
+ fix: "Authenticate with the exchanged access token (check .spacefast/state.json or wherever it was saved). If it was lost, ask the space owner to create a new API key.",
202
206
  },
203
207
  credential_expired: {
204
208
  summary: "The credential used for this request has expired.",
@@ -476,10 +480,6 @@ export const ERROR_DOCS = {
476
480
  summary: "Proxy routes to external upstreams are not available on the Free plan.",
477
481
  fix: "Remove the proxy rules before publishing. Still stuck? POST /v1/feedback with the error code and request id.",
478
482
  },
479
- free_headers_basic_auth_disabled: {
480
- summary: "Basic-Auth via _headers is not available on the Free plan.",
481
- fix: "Use space password protection instead. Still stuck? POST /v1/feedback with the error code and request id.",
482
- },
483
483
  google_play_webhook_identity_not_configured: {
484
484
  summary: "Google Play Pub/Sub push authentication is not configured on this deployment.",
485
485
  fix: "Configure the exact push audience and dedicated Pub/Sub service-account email before enabling RTDN delivery.",
@@ -492,10 +492,6 @@ export const ERROR_DOCS = {
492
492
  summary: "The Idempotency-Key was reused with a different request body.",
493
493
  fix: "Use a fresh key for new requests; keys bind to one exact request body.",
494
494
  },
495
- immutable_version_requires_login: {
496
- summary: "This immutable version URL is past its public window and now requires login.",
497
- fix: "Sign in to view it, or promote the version to a channel for public serving.",
498
- },
499
495
  import_archive_not_uploaded: {
500
496
  summary: "The import has no uploaded archive yet.",
501
497
  fix: "Upload the archive to the import's upload target, then finalize.",
@@ -845,13 +841,17 @@ export const ERROR_DOCS = {
845
841
  fix: "Wait for the publish to finish, then roll back by promoting a previous version if needed.",
846
842
  },
847
843
  publish_path_collision: {
848
- summary: "Two entries in the publish payload normalize to the same path.",
849
- fix: "Remove the duplicate; each path may appear once across files and deletes.",
844
+ summary: "Two different artifacts would serve the same URL after directory-index or clean-URL resolution.",
845
+ fix: "Rename or remove one artifact so every request route has one owner.",
850
846
  },
851
847
  publish_path_invalid: {
852
848
  summary: "A publish path is not a relative, normalized POSIX path.",
853
849
  fix: "Use forward-slash relative paths without traversal segments or control characters.",
854
850
  },
851
+ publish_reference_missing: {
852
+ summary: "Published HTML, CSS, or JavaScript references an internal path that is not in the version.",
853
+ fix: "Publish the missing artifact, or correct the reference to a route that this version serves.",
854
+ },
855
855
  publish_setup_failed: {
856
856
  summary: "Provisioning for this publish failed.",
857
857
  fix: "Retry the publish; if it persists, contact support with the requestId.",
@@ -924,10 +924,6 @@ export const ERROR_DOCS = {
924
924
  summary: "No signing key matching the token's key id was found.",
925
925
  fix: "Refresh the runtime JWKS; the signing keys may have rotated.",
926
926
  },
927
- runtime_logs_unavailable: {
928
- summary: "Server logs are not available because Spacefast serves your space as static files.",
929
- fix: "There is no running server process to log. Use the request logs in your dashboard to inspect recent traffic.",
930
- },
931
927
  runtime_management_unavailable: {
932
928
  summary: "The runtime management surface is unavailable for this site.",
933
929
  fix: "Retry shortly; if the site stays unreachable, contact support.",
@@ -984,10 +980,6 @@ export const ERROR_DOCS = {
984
980
  summary: "The site was already deleted.",
985
981
  fix: "No action needed; the site is gone.",
986
982
  },
987
- site_capacity_exceeded: {
988
- summary: "The site has reached its capacity and cannot take more content.",
989
- fix: "Retry shortly; the platform rebalances spaces onto new sites automatically.",
990
- },
991
983
  site_has_live_spaces: {
992
984
  summary: "The site still has live spaces assigned to it, so it cannot be deleted.",
993
985
  fix: "Delete the live spaces or move them to another site before deleting this site.",
@@ -1036,6 +1028,10 @@ export const ERROR_DOCS = {
1036
1028
  summary: "The space was already claimed; a claim can only succeed once.",
1037
1029
  fix: "If you are the agent that published this space, exchange your claim token once at POST /v1/anonymous-claim/exchange for a durable access token and keep publishing to the same spaceId. Otherwise ask the owner for access — do not publish a duplicate space.",
1038
1030
  },
1031
+ space_capacity_warming: {
1032
+ summary: "This space is waiting on serving capacity that is being provisioned in the background.",
1033
+ fix: "Wait for the Retry-After window, then send the same publish again. No version was created and no files were uploaded.",
1034
+ },
1039
1035
  space_claim_unavailable: {
1040
1036
  summary: "This space cannot be claimed.",
1041
1037
  fix: "Only anonymous, unexpired spaces with a valid claim token can be claimed.",
@@ -1080,6 +1076,10 @@ export const ERROR_DOCS = {
1080
1076
  summary: "The export was produced by an unsupported runtime schema version.",
1081
1077
  fix: "Re-export from a current runtime, or upgrade before exporting.",
1082
1078
  },
1079
+ space_move_would_strand_zero_data: {
1080
+ summary: "The Space runs Zero, whose database lives on the site the Space is placed on. Relocating it would create an empty database on the new site and leave every row behind, so the move is refused.",
1081
+ fix: "Nothing was moved and no data was lost. Migrating Zero data between sites is not implemented; contact support if the Space genuinely has to be relocated.",
1082
+ },
1083
1083
  space_moving: {
1084
1084
  summary: "The space is moving between sites, which blocks this operation.",
1085
1085
  fix: "Wait for the move to finish, then retry.",
@@ -1290,11 +1290,7 @@ export const ERROR_DOCS = {
1290
1290
  },
1291
1291
  upload_path_not_declared: {
1292
1292
  summary: "An uploaded path was not declared in the version's manifest.",
1293
- fix: "Declare every path up front, or use an open session for incremental uploads.",
1294
- },
1295
- upload_session_cap_exceeded: {
1296
- summary: "The open upload session exceeded its file or byte cap.",
1297
- fix: "Stay within the session caps, or declare a manifest for large publishes.",
1293
+ fix: "Declare every path up front.",
1298
1294
  },
1299
1295
  upload_size_mismatch: {
1300
1296
  summary: "An uploaded file's size does not match the declared size.",
@@ -1650,7 +1646,7 @@ export const ERROR_DOCS = {
1650
1646
  },
1651
1647
  zero_log_query_invalid: {
1652
1648
  summary: "The Zero log query parameters are invalid.",
1653
- fix: "Use valid cursor, limit, mutationName, and requestId parameters.",
1649
+ fix: "Use valid cursor, limit, handlerName, and requestId parameters.",
1654
1650
  },
1655
1651
  zero_method_not_allowed: {
1656
1652
  summary: "The request method is not allowed for this Zero endpoint.",
@@ -31,6 +31,17 @@ export type FingerprintPlan = {
31
31
  reason: FingerprintSkipReason;
32
32
  }>;
33
33
  };
34
+ export type StaticDocumentDependency = {
35
+ sourcePath: string;
36
+ targetPath: string;
37
+ };
38
+ /**
39
+ * Advisory-only dependency discovery used by finalize diagnostics. It shares
40
+ * the exact HTML/CSS tokenizer and URL resolver with asset fingerprinting, then
41
+ * adds conservative static JS imports and page links. It never rewrites bytes
42
+ * and never changes access automatically.
43
+ */
44
+ export declare function scanStaticDocumentDependencies(sourcePath: string, text: string): StaticDocumentDependency[];
34
45
  export declare function planAssetFingerprints(input: {
35
46
  files: readonly FingerprintCandidateFile[];
36
47
  /** sha256 as lowercase hex over UTF-8 bytes of `text`. */
@@ -48,6 +48,52 @@ const FINGERPRINT_ASSET_EXTENSIONS = new Set([
48
48
  // no whitespace. Anything else stays on the default lane.
49
49
  const SAFE_PATH_PATTERN = /^[A-Za-z0-9/_.-]+$/;
50
50
  const SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
51
+ const HTML_ANCHOR_HREF_PATTERN = /<a\b[^>]*\bhref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/giu;
52
+ const JS_STATIC_REFERENCE_PATTERN = /(?:\b(?:import|export)\s+(?:[^"'()]*?\s+from\s+)?|\bimport\s*\(|\bnew\s+URL\s*\()\s*["']([^"']+)["']/gu;
53
+ const SOURCE_MAP_REFERENCE_PATTERN = /[#@]\s*sourceMappingURL=([^\s*]+)/gu;
54
+ /**
55
+ * Advisory-only dependency discovery used by finalize diagnostics. It shares
56
+ * the exact HTML/CSS tokenizer and URL resolver with asset fingerprinting, then
57
+ * adds conservative static JS imports and page links. It never rewrites bytes
58
+ * and never changes access automatically.
59
+ */
60
+ export function scanStaticDocumentDependencies(sourcePath, text) {
61
+ const extension = pathExtensionOf(sourcePath);
62
+ const rawUrls = [];
63
+ if (extension === "html" || extension === "htm") {
64
+ const html = scanHtml(text);
65
+ rawUrls.push(...html.refs.map((ref) => ref.url));
66
+ for (const range of html.cssRanges) {
67
+ rawUrls.push(...scanCssRefs(range.css, range.offset).map((ref) => ref.url));
68
+ }
69
+ for (const match of text.matchAll(HTML_ANCHOR_HREF_PATTERN)) {
70
+ const url = match[1] ?? match[2] ?? match[3];
71
+ if (url)
72
+ rawUrls.push(url);
73
+ }
74
+ }
75
+ else if (extension === "css") {
76
+ rawUrls.push(...scanCssRefs(text, 0).map((ref) => ref.url));
77
+ }
78
+ else if (extension === "js" || extension === "mjs" || extension === "cjs") {
79
+ for (const match of text.matchAll(JS_STATIC_REFERENCE_PATTERN)) {
80
+ if (match[1])
81
+ rawUrls.push(match[1]);
82
+ }
83
+ for (const match of text.matchAll(SOURCE_MAP_REFERENCE_PATTERN)) {
84
+ if (match[1])
85
+ rawUrls.push(match[1]);
86
+ }
87
+ }
88
+ const baseDir = parentDir(sourcePath);
89
+ return [
90
+ ...new Set(rawUrls
91
+ .map((url) => resolveReference(baseDir, url))
92
+ .filter((targetPath) => targetPath !== null)),
93
+ ]
94
+ .toSorted()
95
+ .map((targetPath) => ({ sourcePath, targetPath }));
96
+ }
51
97
  export function planAssetFingerprints(input) {
52
98
  const covered = input.pathCoveredByUserCacheControl ?? (() => false);
53
99
  const excluded = input.excludePath ?? (() => false);
@@ -1,3 +1 @@
1
- export declare function sanitizeDashboardReturnTo(returnTo: string | null | undefined, options?: {
2
- apiOrigin?: string | null;
3
- }): string | undefined;
1
+ export declare function sanitizeDashboardReturnTo(returnTo: string | null | undefined): string | undefined;
@@ -17,29 +17,9 @@ function hasUnsafeReturnToChars(value) {
17
17
  }
18
18
  return false;
19
19
  }
20
- // The ONE absolute-URL exception to the same-origin returnTo policy
21
- // (access-plan X-41): the api-origin GET /v1/access/authorize URL exactly —
22
- // the sign-in leg of the visitor redirect chain. Everything else absolute is
23
- // an open-redirect surface and stays rejected.
24
- const API_AUTHORIZE_PATH = "/v1/access/authorize";
25
- export function sanitizeDashboardReturnTo(returnTo, options) {
20
+ export function sanitizeDashboardReturnTo(returnTo) {
26
21
  const normalized = returnTo?.trim();
27
22
  const decoded = normalized ? decodedReturnTo(normalized) : null;
28
- if (normalized && decoded && options?.apiOrigin) {
29
- try {
30
- const candidate = new URL(normalized);
31
- const apiOrigin = new URL(options.apiOrigin).origin;
32
- if (candidate.origin === apiOrigin &&
33
- candidate.pathname === API_AUTHORIZE_PATH &&
34
- !hasUnsafeReturnToChars(normalized) &&
35
- !hasUnsafeReturnToChars(decoded)) {
36
- return candidate.toString();
37
- }
38
- }
39
- catch {
40
- // Not an absolute URL — fall through to the same-origin path rules.
41
- }
42
- }
43
23
  if (!normalized ||
44
24
  !decoded ||
45
25
  !normalized.startsWith("/") ||
@@ -1,6 +1,8 @@
1
1
  export type BuildSettingsInput = {
2
2
  fileNames: Iterable<string>;
3
3
  packageJson?: string | null | undefined;
4
+ jekyllYaml?: string | null | undefined;
5
+ jekyllToml?: string | null | undefined;
4
6
  vercelJson?: string | null | undefined;
5
7
  netlifyToml?: string | null | undefined;
6
8
  wranglerToml?: string | null | undefined;