@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,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { appRoutePathSchema, EXECUTION_ENV_MAX_KEYS, executionBundleSchema, executionCapabilitiesSchema, executionEnvNameSchema, executionIdentifierSchema, executionInspectPolicySchema, executionLogEntrySchema, executionLogListQuerySchema, executionLogListResponseSchema, executionSha256Schema, executionStaticFileSchema, httpMethodSchema, LAKEBED_SERVER_ENV_FILE, PLATFORM_ROUTE_PREFIX, runtimeRealtimeModeSchema, SERVER_ENV_FILE, } from "./execution.js";
2
+ import { appRoutePathSchema, EXECUTION_ENV_MAX_KEYS, executionBundleSchema, executionCapabilitiesSchema, executionEnvNameSchema, executionIdentifierSchema, executionInspectPolicySchema, executionSha256Schema, executionStaticFileSchema, httpMethodSchema, LAKEBED_SERVER_ENV_FILE, PLATFORM_ROUTE_PREFIX, runtimeRealtimeModeSchema, SERVER_ENV_FILE, } from "./execution.js";
3
3
  /**
4
4
  * Spacefast Zero: capsules — schema, queries, mutations and endpoints that run
5
5
  * together inside one parent-owned transaction — executed by the native runner
@@ -12,6 +12,13 @@ import { appRoutePathSchema, EXECUTION_ENV_MAX_KEYS, executionBundleSchema, exec
12
12
  * for the narrow surface both products can host.
13
13
  */
14
14
  export const ZERO_SOURCE_METADATA_KEY = "statticZero";
15
+ /**
16
+ * The tag a compiled capsule artifact carries — in the finalize payload, the
17
+ * runtime config, the install profile, the client config the browser reads, and
18
+ * every realtime event — so PHP and the Rust runner can tell what they were
19
+ * handed. It is a property of the artifact the tree produced, not a kind a
20
+ * space declares: a publish can carry this beside a worker.
21
+ */
15
22
  export const ZERO_RUNTIME_KIND = "zero";
16
23
  export const ZERO_PLATFORM_ROUTE_PREFIX = `${PLATFORM_ROUTE_PREFIX}/zero`;
17
24
  /**
@@ -35,11 +42,59 @@ export const ZERO_RUNTIME_STORAGE_ROOT = "__spacefast/zero";
35
42
  export const ZERO_RUNTIME_ARTIFACT_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/artifact.json`;
36
43
  export const ZERO_RUNTIME_CONFIG_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/config.json`;
37
44
  export const ZERO_RUNTIME_BINARY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/bin/stattic-runtime`;
38
- export const ZERO_RUNTIME_BINARY_COMPATIBILITY_TARGET = "wpcloud-linux-x86_64-gnu-v1";
45
+ export const ZERO_RUNTIME_BINARY_COMPATIBILITY_TARGET = "linux-x86_64-gnu-v1";
39
46
  export const ZERO_RUNTIME_BUNDLE_ROOT = `${ZERO_RUNTIME_STORAGE_ROOT}/bundles`;
40
- export const ZERO_RUNTIME_CLIENT_BUNDLE_PATH = `${ZERO_RUNTIME_BUNDLE_ROOT}/client.js`;
41
47
  export const ZERO_RUNTIME_SERVER_BUNDLE_PATH = `${ZERO_RUNTIME_BUNDLE_ROOT}/server.qjs.mjs`;
42
- export const ZERO_RUNTIME_BUNDLE_MAX_BYTES = 786_432;
48
+ /** The compiled capsule client, served at the app root. */
49
+ export const ZERO_PUBLIC_CLIENT_BUNDLE_PATH = "client.js";
50
+ /**
51
+ * Where platform-owned client bytes serve from: same origin as the space, one
52
+ * content-addressed directory per platform build.
53
+ *
54
+ * Same origin is the whole point. Browsers have partitioned the HTTP cache by
55
+ * top-level site since 2020, so a shared third-party CDN buys nothing a
56
+ * same-origin URL does not — and costs a `script-src` hole. What a stable,
57
+ * content-addressed URL does buy is real: the digest changes only when the
58
+ * platform bytes change, so publishing a capsule a hundred times re-downloads
59
+ * the capsule's own bundle a hundred times and the platform's exactly once.
60
+ *
61
+ * Underscore-prefixed by framework convention (`_next/static`, `_astro`), which
62
+ * is also how the runtime recognises it as immutable — see `immutable_path` in
63
+ * `crates/stattic-runtime-core/src/finalize.rs`.
64
+ */
65
+ export const ZERO_PLATFORM_ASSET_NAMESPACE = "_spacefast";
66
+ export const ZERO_PLATFORM_ASSET_ROOT = `${ZERO_PLATFORM_ASSET_NAMESPACE}/platform`;
67
+ /** The serving path of one file in the platform build identified by `digest`. */
68
+ export function zeroPlatformAssetPath(digest, fileName) {
69
+ return `${ZERO_PLATFORM_ASSET_ROOT}/${digest}/${fileName}`;
70
+ }
71
+ /**
72
+ * The compiled capsule server, which the QuickJS runner instantiates whole.
73
+ *
74
+ * 768 KiB is inherited, not measured: nobody has yet established what the
75
+ * runner actually tolerates, and DS77 keeps the number only until someone does.
76
+ * It binds a real resource — the runner holds the module graph in the site's
77
+ * PHP-worker memory before executing anything — so it stays low deliberately;
78
+ * server code is handlers, not an application.
79
+ */
80
+ export const ZERO_SERVER_BUNDLE_MAX_BYTES = 786_432;
81
+ /**
82
+ * The tenant client bundle, and every other file the compile ships as content.
83
+ *
84
+ * This measures what the tenant publishes, and only that: the SDK, the kit, the
85
+ * chart layer, preact, recharts and lucide are externals resolved through the
86
+ * shell's import map to {@link ZERO_PLATFORM_ASSET_ROOT}, so platform bytes are
87
+ * never weighed here (DS42). What remains is author code plus whatever npm the
88
+ * author chose to bundle.
89
+ *
90
+ * 8 MiB matches the Functions per-entry cap (DS77) because the same reasoning
91
+ * applies: a client bundle is static bytes to a browser, so nothing on the
92
+ * serving side binds it, and the cap exists to fail an accidental
93
+ * hundred-megabyte dependency in our tooling — where the build can say which
94
+ * modules are large — rather than at upload. It is a guardrail, not a budget;
95
+ * the size report is what an author should be reading.
96
+ */
97
+ export const ZERO_CLIENT_BUNDLE_MAX_BYTES = 8 * 1024 * 1024;
43
98
  /**
44
99
  * A capsule's compiled server travels as version metadata, not as content, so a
45
100
  * server-only change leaves the published app shell byte-identical — and the
@@ -60,10 +115,16 @@ export const ZERO_MANAGED_TABLE_COLUMNS = ["id", "createdAt", "updatedAt"];
60
115
  export const ZERO_RESERVED_APP_ROUTE_PATHS = [
61
116
  "/",
62
117
  "/index.html",
63
- "/client.js",
118
+ `/${ZERO_PUBLIC_CLIENT_BUNDLE_PATH}`,
64
119
  "/auth/callback",
65
120
  ];
66
- export const ZERO_RESERVED_APP_ROUTE_PREFIXES = ["/auth/"];
121
+ // The whole platform namespace is reserved, not just the one directory a build
122
+ // happens to write: an endpoint claiming a path under it would shadow bytes the
123
+ // shell's import map already told the browser to fetch.
124
+ export const ZERO_RESERVED_APP_ROUTE_PREFIXES = [
125
+ "/auth/",
126
+ `/${ZERO_PLATFORM_ASSET_NAMESPACE}/`,
127
+ ];
67
128
  const zeroNameSchema = executionIdentifierSchema;
68
129
  const zeroRoutePathSchema = appRoutePathSchema({
69
130
  subject: "Zero capsule routes",
@@ -76,7 +137,7 @@ export const zeroEndpointSchema = z
76
137
  path: zeroRoutePathSchema,
77
138
  })
78
139
  .strict();
79
- function zeroEndpointRouteMatchShape(path) {
140
+ function zeroEndpointRouteMatch(path) {
80
141
  const segments = [];
81
142
  let score = 0;
82
143
  let splat = false;
@@ -105,17 +166,17 @@ export function zeroEndpointRoutesAmbiguous(left, right) {
105
166
  (left.method === "HEAD" && right.method === "GET");
106
167
  if (!methodsOverlap)
107
168
  return false;
108
- const leftShape = zeroEndpointRouteMatchShape(left.path);
109
- const rightShape = zeroEndpointRouteMatchShape(right.path);
110
- if (leftShape.score !== rightShape.score)
169
+ const leftMatch = zeroEndpointRouteMatch(left.path);
170
+ const rightMatch = zeroEndpointRouteMatch(right.path);
171
+ if (leftMatch.score !== rightMatch.score)
111
172
  return false;
112
- if (!leftShape.splat && leftShape.segments.length < rightShape.segments.length)
173
+ if (!leftMatch.splat && leftMatch.segments.length < rightMatch.segments.length)
113
174
  return false;
114
- if (!rightShape.splat && rightShape.segments.length < leftShape.segments.length)
175
+ if (!rightMatch.splat && rightMatch.segments.length < leftMatch.segments.length)
115
176
  return false;
116
- return Array.from({ length: Math.min(leftShape.segments.length, rightShape.segments.length) }, (_, index) => index).every((index) => {
117
- const segment = leftShape.segments[index];
118
- const other = rightShape.segments[index];
177
+ return Array.from({ length: Math.min(leftMatch.segments.length, rightMatch.segments.length) }, (_, index) => index).every((index) => {
178
+ const segment = leftMatch.segments[index];
179
+ const other = rightMatch.segments[index];
119
180
  return segment === null || other === null || segment === other;
120
181
  });
121
182
  }
@@ -203,18 +264,21 @@ export const zeroTableSchema = z
203
264
  export const zeroDatabaseSchema = z.record(z.string(), zeroTableSchema);
204
265
  const zeroSha256Schema = executionSha256Schema;
205
266
  /**
206
- * Zero's bundles travel inline in the finalize payload a capsule's compiled
207
- * client and server fit comfortably under the ceiling, and inlining keeps the
267
+ * The compiled server travels inline in the finalize payload; inlining keeps the
208
268
  * whole version one atomic write. Functions bundles do the opposite and land
209
269
  * in the content store first; see `functionsBundleRefSchema`.
270
+ *
271
+ * The client never travels this way. It is content — the browser fetches it
272
+ * from the version tree like any other asset — so it ships as a static file.
210
273
  */
211
274
  export const zeroRuntimeBundleSchema = executionBundleSchema({
212
275
  bundleRoot: ZERO_RUNTIME_BUNDLE_ROOT,
213
- maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
276
+ maxBytes: ZERO_SERVER_BUNDLE_MAX_BYTES,
214
277
  });
215
278
  export const zeroRuntimeStaticFileSchema = executionStaticFileSchema({
216
279
  storageRoot: ZERO_RUNTIME_STORAGE_ROOT,
217
- maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
280
+ maxBytes: ZERO_CLIENT_BUNDLE_MAX_BYTES,
281
+ platformAssetRoot: ZERO_PLATFORM_ASSET_ROOT,
218
282
  });
219
283
  export const zeroRuntimeRunSourceSchema = z
220
284
  .object({
@@ -472,7 +536,7 @@ export const zeroCapsuleArtifactSchema = z
472
536
  .strict(),
473
537
  db: z
474
538
  .object({
475
- backend: z.literal("wpcloud-mysql"),
539
+ backend: z.literal("mysql"),
476
540
  migrations: z.array(zeroMigrationOperationSchema).default([]),
477
541
  })
478
542
  .strict(),
@@ -493,7 +557,9 @@ export const zeroRuntimeFinalizePayloadSchema = z
493
557
  install: zeroRuntimeInstallProfileSchema,
494
558
  artifact: zeroCapsuleArtifactSchema,
495
559
  bundles: z.array(zeroRuntimeBundleSchema).max(8).default([]),
496
- staticFiles: z.array(zeroRuntimeStaticFileSchema).max(16).default([]),
560
+ // The shell, the client bundle, the utility stylesheet, and the platform
561
+ // build's own entries and shared chunks.
562
+ staticFiles: z.array(zeroRuntimeStaticFileSchema).max(64).default([]),
497
563
  endpointSources: z.array(zeroRuntimeEndpointSourceSchema).max(128).default([]),
498
564
  runSources: z.array(zeroRuntimeRunSourceSchema).max(128).default([]),
499
565
  migrations: zeroMigrationPlanSchema.nullable().default(null),
@@ -567,23 +633,24 @@ export const zeroDeployMetadataSchema = z
567
633
  })
568
634
  .strict();
569
635
  /**
570
- * What a live Zero capsule is, as the `app` member of a space's runtime status.
636
+ * What a live Zero capsule is, as the `capsule` member of a space's runtime
637
+ * status.
571
638
  *
572
639
  * There is no `versionId` here: this only ever describes the version the status
573
640
  * response already names as live, and repeating it would invite the two to
574
641
  * disagree. `artifactId` stays because it identifies the built capsule rather
575
- * than the publish that carries it.
642
+ * than the publish that carries it. There is no kind tag either — the member it
643
+ * rides in already says which product answered.
576
644
  *
577
645
  * Every field is derived from the version's own finalize metadata, which is
578
646
  * what makes this safe to answer for a space whose runtime is asleep,
579
647
  * mid-move, or failing: nothing here costs a call to the space's origin. It is
580
648
  * also why there are no counts of things listed here — a caller that wants
581
649
  * `tables.length` can take it — and why the database is not a field: a capsule
582
- * always owns one, so `runtimeKind: "zero"` already said so.
650
+ * always owns one, so its presence already said so.
583
651
  */
584
652
  export const zeroAppSchema = z
585
653
  .object({
586
- runtimeKind: z.literal(ZERO_RUNTIME_KIND),
587
654
  artifactId: z.string().min(1),
588
655
  appName: z.string().min(1),
589
656
  serverRuntime: z.literal("quickjs-rust"),
@@ -616,11 +683,6 @@ export const zeroAppSchema = z
616
683
  realtime: zeroRuntimePublicRealtimeConfigSchema,
617
684
  })
618
685
  .strict();
619
- // Both products emit the same log shape; `handlerName` carries the mutation
620
- // name here and the worker handler name on Functions.
621
- export const zeroLogListQuerySchema = executionLogListQuerySchema;
622
- export const zeroLogEntrySchema = executionLogEntrySchema;
623
- export const zeroLogListResponseSchema = executionLogListResponseSchema;
624
686
  export const zeroRealtimeEventIntakeResponseSchema = z
625
687
  .object({
626
688
  accepted: z.literal(true),
@@ -651,7 +713,7 @@ export function createZeroCapsuleArtifact(input) {
651
713
  appName: input.appName,
652
714
  serverRuntime: "quickjs-rust",
653
715
  client: {
654
- bundlePath: input.clientBundlePath ?? ZERO_RUNTIME_CLIENT_BUNDLE_PATH,
716
+ bundlePath: input.clientBundlePath ?? ZERO_PUBLIC_CLIENT_BUNDLE_PATH,
655
717
  basePathAware: true,
656
718
  },
657
719
  server: {
@@ -664,7 +726,7 @@ export function createZeroCapsuleArtifact(input) {
664
726
  sockets: input.sockets ?? [],
665
727
  },
666
728
  db: {
667
- backend: "wpcloud-mysql",
729
+ backend: "mysql",
668
730
  migrations: [],
669
731
  },
670
732
  realtime: {
@@ -4,7 +4,7 @@
4
4
  * Append-only: add a new top-level static dashboard route's first segment here
5
5
  * before its route module lands. A repository structural test enforces this.
6
6
  */
7
- export declare const TEAM_SLUG_ROUTE_RESERVATIONS: readonly ["accept-beta-invite", "accept-invitation", "account", "access", "agent", "claim", "device", "drop", "new-team", "oauth", "sign-in", "start", "terminal", "two-factor"];
7
+ export declare const TEAM_SLUG_ROUTE_RESERVATIONS: readonly ["accept-beta-invite", "accept-invitation", "account", "access", "agent", "claim", "device", "drop", "new-team", "oauth", "push", "sign-in", "start", "terminal", "two-factor"];
8
8
  /**
9
9
  * Dashboard route first-segments that cannot be used as space slugs.
10
10
  *
@@ -21,6 +21,7 @@ export const TEAM_SLUG_ROUTE_RESERVATIONS = [
21
21
  "drop",
22
22
  "new-team",
23
23
  "oauth",
24
+ "push",
24
25
  "sign-in",
25
26
  "start",
26
27
  "terminal",
@@ -6,6 +6,7 @@ export declare const ARCHIVE_SECRET_GLOBS: readonly [".env*", ".npmrc", ".netrc"
6
6
  export declare const SECRET_RULES_PROSE: string;
7
7
  export declare const POSITIONING_PROSE: string;
8
8
  export declare const EXPLAIN_TO_USER_PROSE: string;
9
+ export declare const FEEDBACK_PROSE = "With user approval, send feedback with `sf feedback`, MCP `execute` (search `send feedback`), or `POST /v1/feedback`. Never include credentials or private links.";
9
10
  export declare const FAILURE_CONDUCT_PROSE: string;
10
11
  export declare const LANE_PICKER_PROSE: string;
11
12
  export declare const HOW_TO_RESEARCH_PROSE: string;
@@ -40,7 +41,7 @@ export declare const SAVE_STATE_MCP_PROSE: string;
40
41
  export declare const UPDATE_SPACE_PROSE: string;
41
42
  /**
42
43
  * The CLAIM / CONTINUE verb: show the claim link, and after the user claims,
43
- * self-correct by exchanging the claim token once for a durable credential.
44
+ * self-correct by exchanging the space key once for a durable credential.
44
45
  */
45
46
  export declare const CONTINUE_AFTER_CLAIM_PROSE: string;
46
47
  /**
@@ -91,4 +92,3 @@ export declare const AGENT_PROSE: {
91
92
  readonly envNotes: string;
92
93
  readonly envNotesApi: string;
93
94
  };
94
- export type AgentProseKey = keyof typeof AGENT_PROSE;
@@ -4,7 +4,7 @@ import { serviceOrigin } from "../config/domains.js";
4
4
  //
5
5
  // - packages/cli/skill.template.md (the SKILL.md router + copies)
6
6
  // - packages/common/src/docs/agent-setup.ts (the /ai and /ai.txt page body)
7
- // - apps/www/src/lib/llmo.ts (the agent-card / discovery prose)
7
+ // - spacefast/www (the agent-card / discovery prose)
8
8
  //
9
9
  // Each surface re-stated the publish sequence, the secret rules, and the receipt
10
10
  // shape in its own words, so they drifted. These fragments are the one source of
@@ -16,7 +16,7 @@ import { serviceOrigin } from "../config/domains.js";
16
16
  // the receipt shape or secret handling changes, change it here once.
17
17
  const API_ORIGIN = serviceOrigin("api", "prod");
18
18
  const PUBLISH_ENDPOINT = `${API_ORIGIN}/v1/publish`;
19
- const EXCHANGE_ENDPOINT = `${API_ORIGIN}/v1/anonymous-claim/exchange`;
19
+ const EXCHANGE_ENDPOINT = `${API_ORIGIN}/v1/claim/exchange`;
20
20
  // Centralized secret/credential patterns excluded from a publish archive. The
21
21
  // `find` preflight and the `zip -x` exclusions are derived from the same list so
22
22
  // they can never disagree, and the no-install / skill copies stay identical.
@@ -38,6 +38,21 @@ export const ARCHIVE_SECRET_GLOBS = [
38
38
  "*.crt",
39
39
  "*id_rsa*",
40
40
  ];
41
+ const ARCHIVE_REJECTED_GLOBS = [
42
+ ...ARCHIVE_SECRET_GLOBS,
43
+ ".git",
44
+ ".spacefast",
45
+ ".ssh",
46
+ ".aws",
47
+ ".kube",
48
+ ".docker",
49
+ "node_modules",
50
+ ".next",
51
+ ".nuxt",
52
+ ".cache",
53
+ ".turbo",
54
+ "coverage",
55
+ ];
41
56
  function findExpr(globs) {
42
57
  return globs
43
58
  .map((glob) => (glob.includes("/") ? `-path "${glob}"` : `-name "${glob}"`))
@@ -48,21 +63,22 @@ function findExpr(globs) {
48
63
  * them out of logs and transcripts, and never echo them back.
49
64
  */
50
65
  export const SECRET_RULES_PROSE = [
51
- "Treat claim tokens, upload tokens, device codes, and API keys as credentials. Do not print",
66
+ "Treat space keys, upload tokens, device codes, and API keys as credentials. Do not print",
52
67
  "them, paste them into chat, commit them, archive them, or include them in shared logs. Avoid",
53
68
  "`set -x`, persistent shell history, CI log echoing, and command transcripts when secrets are",
54
69
  "present. On shared hosts, prefer one-off environment variables or restrictive temporary files,",
55
70
  "clear them after use, and avoid durable auth unless the user explicitly asks.",
56
71
  ].join("\n");
57
72
  export const POSITIONING_PROSE = [
58
- "Spacefast is a static host for AI-made web artifacts: permanent live URLs, immutable version",
59
- "URLs, anonymous publish with a claim link, and agent continuation after claim. It serves",
60
- "static files. It does not execute server code, run databases, or build-on-push on the",
61
- "anonymous lane.",
73
+ "Spacefast is the best place to share AI artifacts.",
74
+ "Spaces serve files directly; app code runs only through a declared Zero or Functions runtime.",
62
75
  "",
63
- "Honest comparisons an agent can relay: Vercel and Netlify are broader app platforms;",
64
- "Cloudflare Pages is edge-first static hosting; GitHub Pages is repository-native. Spacefast",
65
- "optimizes for agent-safe one-shot publish, claim, versioning, rollback, and continuation.",
76
+ "Do not claim that no-account publish followed by claim is unique to Spacefast. here.now and",
77
+ "Netlify offer native anonymous publish-and-claim flows; Cloudflare offers temporary accounts",
78
+ "and claim deployments; Vercel lets agents and platforms transfer deployments to users.",
79
+ "Spacefast's narrower lane is direct HTTP publishing with separate Access and Claim",
80
+ "authority, immutable versions, rollback, and agent continuation after claim. GitHub Pages",
81
+ "remains repository-native and has no equivalent anonymous ownership-handoff flow documented.",
66
82
  ].join("\n");
67
83
  export const EXPLAIN_TO_USER_PROSE = [
68
84
  "Present Access and Claim as the only actions. State anonymous expiry in user terms: the Space",
@@ -70,10 +86,12 @@ export const EXPLAIN_TO_USER_PROSE = [
70
86
  "Keep live and immutable Version addresses as receipt metadata. After claim, the agent key is named",
71
87
  "and revocable in the dashboard.",
72
88
  ].join("\n");
89
+ export const FEEDBACK_PROSE = "With user approval, send feedback with `sf feedback`, MCP `execute` (search `send feedback`), or `POST /v1/feedback`. Never include credentials or private links.";
73
90
  export const FAILURE_CONDUCT_PROSE = [
74
91
  "On failure, surface the problem document's `code`, `type`, and `requestId`, then stop.",
75
- "Do not invent undocumented endpoints. Do not read credentials out of auth files. Do not",
76
- "retry a one-shot operation without reusing its `Idempotency-Key`.",
92
+ "Do not invent undocumented endpoints. Do not read credentials out of auth files. Retrying a",
93
+ "failed publish with the same files is safe: it returns the Space the first attempt created.",
94
+ FEEDBACK_PROSE,
77
95
  ].join("\n");
78
96
  export const LANE_PICKER_PROSE = [
79
97
  "Pick the lane by environment: filesystem plus repeat work means CLI or On-Device MCP; no",
@@ -124,7 +142,7 @@ export const CHECK_BEFORE_PUBLISH_PROSE = [
124
142
  "",
125
143
  "If any of these finds a space, publish a new version to that `spaceId` (see the update",
126
144
  "instructions) instead of creating another space. Only create a new space when none exists",
127
- "and the user wants a new site.",
145
+ "and the user wants a new one.",
128
146
  ].join("\n");
129
147
  export const CHECK_BEFORE_PUBLISH_API_PROSE = [
130
148
  "Before creating a space, check whether this project already has one:",
@@ -140,7 +158,7 @@ export const CHECK_BEFORE_PUBLISH_API_PROSE = [
140
158
  "",
141
159
  "If any of these finds a space, publish a new version to that `spaceId` (see the update",
142
160
  "instructions) instead of creating another space. Only create a new space when none exists",
143
- "and the user wants a new site.",
161
+ "and the user wants a new one.",
144
162
  ].join("\n");
145
163
  export const CHECK_BEFORE_PUBLISH_MCP_PROSE = [
146
164
  "Before creating a space, check whether this project already has one:",
@@ -151,7 +169,7 @@ export const CHECK_BEFORE_PUBLISH_MCP_PROSE = [
151
169
  "- When authenticated, use `execute` to call the generated list-spaces operation.",
152
170
  "",
153
171
  "If any of these finds a space, publish a new version to that space instead of creating",
154
- "another. Only create a new space when none exists and the user wants a new site.",
172
+ "another. Only create a new space when none exists and the user wants a new one.",
155
173
  ].join("\n");
156
174
  /**
157
175
  * The SAVE verb: persist the space id and credential after a first publish so
@@ -186,16 +204,16 @@ export const SAVE_STATE_PROSE = [
186
204
  ].join("\n");
187
205
  /** Curl/API skill: no CLI/MCP required to continue in-session. */
188
206
  export const SAVE_STATE_API_PROSE = [
189
- "After the first publish, keep `data.space.id` and `data.claim.token` (when present) in agent",
207
+ "After the first publish, keep `data.space.id` and `data.claim.key` (when present) in agent",
190
208
  "memory for this session so later publishes update the same space. You may write non-secret",
191
209
  '`.spacefast/space.json` as `{"space":"<spc_id>"}` when helpful. Do not recreate credential',
192
- "state with shell redirections. Keep claim tokens and `.spacefast/state.json` out of publish",
210
+ "state with shell redirections. Keep space keys and `.spacefast/state.json` out of publish",
193
211
  "archives, commits, logs, and chat.",
194
212
  ].join("\n");
195
213
  export const SAVE_STATE_MCP_PROSE = [
196
214
  "After the first publish, On-Device MCP persists `.spacefast/` automatically so the next",
197
215
  "`publish` updates the same space. Hosted MCP has no local filesystem state; keep the space id",
198
- "in the current agent session or pass it explicitly. Never ask the user to paste claim tokens",
216
+ "in the current agent session or pass it explicitly. Never ask the user to paste space keys",
199
217
  "or access tokens into chat.",
200
218
  ].join("\n");
201
219
  /**
@@ -207,30 +225,30 @@ export const UPDATE_SPACE_PROSE = [
207
225
  "never re-run the first-publish recipe when saved state exists:",
208
226
  "",
209
227
  "```bash",
210
- 'curl -q -sS -H "Authorization: Bearer <claim-token-or-access-token>" \\',
228
+ 'curl -q -sS -H "Authorization: Bearer <space-key-or-access-token>" \\',
211
229
  " --form-string 'spaceId=<spc_id>' \\",
212
230
  ' -F "files=@index.html" \\',
213
231
  ` ${PUBLISH_ENDPOINT}`,
214
232
  "```",
215
233
  "",
216
- "Use the saved claim token for an unclaimed anonymous space, or an access token for owned",
217
- "spaces. Send a folder as `-F archive=@site.zip` exactly like a first publish; the receipt",
218
- "shape is identical.",
234
+ "Use the saved space key for an unclaimed anonymous space, or an access token for owned",
235
+ "spaces. Send a folder or project as `-F archive=@site.zip` exactly like a first publish.",
236
+ "Archive uploads return a durable Build receipt; follow `data.next` until the version is ready.",
219
237
  ].join("\n");
220
238
  /**
221
239
  * The CLAIM / CONTINUE verb: show the claim link, and after the user claims,
222
- * self-correct by exchanging the claim token once for a durable credential.
240
+ * self-correct by exchanging the space key once for a durable credential.
223
241
  */
224
242
  export const CONTINUE_AFTER_CLAIM_PROSE = [
225
- "Always show the user the claim link (`data.claim.url`) and its expiry (`data.claim.expiresAt`).",
226
- 'If the user says "claimed", check claim status and exchange the saved claim token; do not wait',
243
+ "Always show the user the claim link (`data.claim.claimUrl`) and its expiry (`data.claim.expiresAt`).",
244
+ 'If the user says "claimed", check claim status and exchange the saved space key; do not wait',
227
245
  "for a publish failure before continuing.",
228
- "After the user claims the space in the browser, the saved claim token stops authorizing",
246
+ "After the user claims the space in the browser, the saved space key stops authorizing",
229
247
  "publishes: the next publish fails with error code `space_claimed_credential_available`. That",
230
248
  "failure is the signal to upgrade your credential — call the exchange endpoint exactly once:",
231
249
  "",
232
250
  "```bash",
233
- 'curl -q -sS -X POST -H "Authorization: Bearer <claim-token>" \\',
251
+ 'curl -q -sS -X POST -H "Authorization: Bearer <space-key>" \\',
234
252
  ` ${EXCHANGE_ENDPOINT}`,
235
253
  "```",
236
254
  "",
@@ -311,8 +329,7 @@ export const PUBLISH_SEQUENCE_PROSE = [
311
329
  "Publish a single file after rejecting symbolic links in the file or any existing ancestor:",
312
330
  "Set `SPACEFAST_PUBLISH_TARGET` through the agent runtime/environment, not by interpolating",
313
331
  "a repository path into this source. The recipe passes it as a separately quoted argv element.",
314
- "Fresh serving capacity can take a moment; it replays only `space_capacity_warming` with one",
315
- "stable idempotency identity, follows `Retry-After`, and stops after ten attempts:",
332
+ "Fresh serving capacity can make the first request take longer while Spacefast provisions it:",
316
333
  "",
317
334
  "```bash",
318
335
  ': "${SPACEFAST_PUBLISH_TARGET:?set this through the runtime environment}"',
@@ -324,27 +341,9 @@ export const PUBLISH_SEQUENCE_PROSE = [
324
341
  '[ -f "$publish_target" ] || { printf "error: publish file is not a regular file\\n" >&2; exit 2; }',
325
342
  'escaped_path="${publish_target//\\\\/\\\\\\\\}"',
326
343
  'escaped_path="${escaped_path//\\"/\\\\\\"}"',
327
- "idempotency_key=\"publish-$(od -An -N16 -tx1 /dev/urandom | tr -d ' \\n')\"",
328
- "idempotency_principal=\"$(od -An -N32 -tx1 /dev/urandom | tr -d ' \\n')\"",
329
344
  'api_origin="${SPACEFAST_API_ORIGIN:-https://api.spacefast.com}"',
330
- 'headers_file="$(mktemp)"',
331
- "trap 'rm -f \"$headers_file\"' EXIT",
332
- "attempt=1",
333
- "while :; do",
334
- ' response="$(curl -q -sS -D "$headers_file" -F "files=@\\"$escaped_path\\"" \\',
335
- ' -H "Idempotency-Key: $idempotency_key" \\',
336
- ' -H "x-spacefast-idempotency-principal: $idempotency_principal" \\',
337
- ' "$api_origin/v1/publish")"',
338
- ' if ! printf \'%s\' "$response" | grep -Eq \'"code"[[:space:]]*:[[:space:]]*"space_capacity_warming"\'; then',
339
- " printf '%s\\n' \"$response\"",
340
- " break",
341
- " fi",
342
- ' [ "$attempt" -lt 10 ] || { printf \'%s\\n\' "$response"; exit 1; }',
343
- ' retry_after="$(awk \'tolower($1) == "retry-after:" { gsub("\\r", "", $2); print $2; exit }\' "$headers_file")"',
344
- ' case "$retry_after" in ""|*[!0-9]*) retry_after=20 ;; esac',
345
- " attempt=$((attempt + 1))",
346
- ' sleep "$retry_after"',
347
- "done",
345
+ 'curl -q -sS -F "files=@\\"$escaped_path\\"" \\',
346
+ ' "$api_origin/v1/publish"',
348
347
  "SPACEFAST_PUBLISH",
349
348
  "```",
350
349
  "",
@@ -361,14 +360,17 @@ export const PUBLISH_SEQUENCE_PROSE = [
361
360
  'publish_target="$1"',
362
361
  'case "$publish_target" in -*) publish_target="./$publish_target" ;; esac',
363
362
  ...LEXICAL_PUBLISH_PATH_PREFLIGHT,
364
- `find "$publish_target" \\( ${findExpr(ARCHIVE_SECRET_GLOBS)} \\) -print`,
363
+ '[ -d "$publish_target" ] || { printf "error: publish folder is not a directory\\n" >&2; exit 2; }',
364
+ `unsafe_path="$(find "$publish_target" \\( ${findExpr(ARCHIVE_REJECTED_GLOBS)} \\) -print -quit)"`,
365
+ '[ -z "$unsafe_path" ] || { printf "error: unsafe entry in publish root: %s\\n" "$unsafe_path" >&2; exit 2; }',
365
366
  '! find "$publish_target" -type l -print -quit | grep -q . || { printf "error: symbolic link in publish root\\n" >&2; exit 2; }',
366
367
  ...SECURE_ARCHIVE_RECIPE,
367
368
  "SPACEFAST_PUBLISH",
368
369
  "```",
369
370
  "",
370
- "If the preflight prints credential-like files, or the publish root contains a symbolic link,",
371
- "stop and choose a narrower generated output directory or remove the unsafe entry before uploading.",
371
+ "The preflight exits before upload when it finds a credential-like file, repository/auth state,",
372
+ "an unrelated build/cache directory, or a symbolic link. Choose a narrower generated output",
373
+ "directory or remove the unsafe entry before trying again.",
372
374
  ].join("\n");
373
375
  /**
374
376
  * What the JSON publish receipt contains and how to read it. The receipt is the
@@ -378,19 +380,21 @@ export const RECEIPT_SHAPE_PROSE = [
378
380
  "The JSON receipt is the source of truth:",
379
381
  "",
380
382
  "- `data.space.liveUrl` — the live URL.",
381
- "- `data.access.url` and `data.access.expiresAt` — reusable access; claim preserves the URL and changes its expiry to null.",
383
+ "- `data.access.url` and `data.access.expiresAt` — reusable access when present on an owned publish receipt.",
382
384
  " It is not a stable URL or recipient Link; clients must not persist it as Space state.",
383
385
  "- `data.version.immutableUrl` — the permanent address of the frozen Version. The bare URL",
384
386
  " carries no authority: use the receipt's Access URL for the author's browser or create a scoped",
385
387
  " Link for a recipient. It is reserved in the initial receipt. If the publish is still",
386
- " finalizing, poll `data.links.status` with the claim token until the status is `ready`.",
388
+ " finalizing, poll `data.links.status` with the space key until the status is `ready`.",
387
389
  "- `data.upload` — signed upload instructions for manifest publishes when file bytes were not sent",
388
390
  " with the request. Send each `data.upload.targets[]` instruction exactly as returned, treat",
389
391
  " authorization headers and upload tokens as secrets, then finalize.",
390
- "- `data.claim.url` and `data.claim.expiresAt` — the space is anonymous and expires unless claimed;",
392
+ "- `data.claim.claimUrl` and `data.claim.expiresAt` — the space is anonymous and expires unless claimed;",
391
393
  " always show the user the claim link and the deadline so the space becomes theirs.",
392
- "- `data.claim.token` — a secret capability. For anonymous spaces, use it as",
393
- " `Authorization: Bearer <claim-token>` when polling `data.links.status`, finalizing uploads,",
394
+ "- `data.claim.url` — the site door: the live URL carrying the key in `/__/<key>` form. Anonymous",
395
+ " receipts have no `data.access`; this is the link that opens the private site in a browser.",
396
+ "- `data.claim.key` — the space key, a secret capability. For anonymous spaces, use it as",
397
+ " `Authorization: Bearer <space-key>` when polling `data.links.status`, finalizing uploads,",
394
398
  " or updating the same `spaceId`. Save it to `.spacefast/state.json` so the next publish",
395
399
  " updates this space. After the user claims the space, exchange it once at",
396
400
  ` \`POST ${EXCHANGE_ENDPOINT}\` for a durable credential.`,
@@ -420,19 +424,8 @@ export const SIGNED_UPLOAD_PROSE = [
420
424
  "local file bytes for `target.path`. Then call `data.links.finalize` and share the final receipt.",
421
425
  "If the session expires or only a page of files is returned, follow `data.links.resume`.",
422
426
  "",
423
- "For importing an archive that already lives somewhere else, prefer the import-from-link API:",
424
- "",
425
- "```bash",
426
- "curl -q -sS https://api.spacefast.com/v1/spaces/{spaceId}/imports \\",
427
- ' -H "content-type: application/json" \\',
428
- ' -H "Authorization: Bearer $SPACEFAST_TOKEN" \\',
429
- ' -d \'{"source":{"kind":"url","url":"https://example.com/site.zip"}}\'',
430
- "```",
431
- "",
432
- "If the archive is only local to the agent, create an upload-sourced import, PUT the archive to",
433
- "`{archiveUpload.baseUrl}/{archiveUpload.files[0]}` with the returned bearer token, then finalize",
434
- "the import. If the token expires, fetch/resume the import for fresh `archiveUpload` instructions.",
435
- "Do not base64 large archives into chat or MCP tool arguments.",
427
+ "A manifest entry may name a `sourceUrl`, so bytes that already live on a public HTTPS URL never",
428
+ "have to round-trip through the agent. Do not base64 large archives into chat or MCP tool arguments.",
436
429
  ].join("\n");
437
430
  /**
438
431
  * Named fragments for the skill-template generator. The templates carry