@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
@@ -1,8 +1,20 @@
1
1
  import { z } from "zod";
2
2
  import { dataEnvelope } from "./common.js";
3
+ import { appRoutePathSchema, EXECUTION_ENV_MAX_KEYS, executionBundleSchema, executionCapabilitiesSchema, executionEnvNameSchema, executionIdentifierSchema, executionInspectPolicySchema, executionLogEntrySchema, executionLogListQuerySchema, executionLogListResponseSchema, executionSha256Schema, executionStaticFileSchema, httpMethodSchema, PLATFORM_ROUTE_PREFIX, } from "./execution.js";
4
+ /**
5
+ * Spacefast Zero: capsules — schema, queries, mutations and endpoints that run
6
+ * together inside one parent-owned transaction — executed by the native runner
7
+ * on a dedicated wp.cloud site, against that site's own MySQL.
8
+ *
9
+ * The transaction is what makes this a separate product rather than a
10
+ * placement option for `./functions.js`. A capsule handler's semantics depend
11
+ * on the transaction wrapped around it, and an isolate reaching the database
12
+ * over a relay cannot offer one. See `endpointIsPortable` in `./execution.js`
13
+ * for the narrow surface both products can host.
14
+ */
3
15
  export const ZERO_SOURCE_METADATA_KEY = "statticZero";
4
16
  export const ZERO_RUNTIME_KIND = "zero";
5
- export const ZERO_PLATFORM_ROUTE_PREFIX = "/__spacefast/zero";
17
+ export const ZERO_PLATFORM_ROUTE_PREFIX = `${PLATFORM_ROUTE_PREFIX}/zero`;
6
18
  export const ZERO_CLIENT_ENTRY = "client/index.tsx";
7
19
  export const ZERO_SERVER_ENTRY = "server/index.ts";
8
20
  export const ZERO_RUNTIME_ROUTE_PATHS = {
@@ -18,7 +30,7 @@ export const ZERO_RUNTIME_ROUTE_PATHS = {
18
30
  export const ZERO_RUNTIME_STORAGE_ROOT = "__spacefast/zero";
19
31
  export const ZERO_RUNTIME_ARTIFACT_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/artifact.json`;
20
32
  export const ZERO_RUNTIME_CONFIG_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/config.json`;
21
- export const ZERO_RUNTIME_BINARY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/bin/stattic-zero-runner`;
33
+ export const ZERO_RUNTIME_BINARY_PATH = `${ZERO_RUNTIME_STORAGE_ROOT}/bin/stattic-runtime`;
22
34
  export const ZERO_RUNTIME_BINARY_COMPATIBILITY_TARGET = "wpcloud-linux-x86_64-gnu-v1";
23
35
  export const ZERO_RUNTIME_BUNDLE_ROOT = `${ZERO_RUNTIME_STORAGE_ROOT}/bundles`;
24
36
  export const ZERO_RUNTIME_CLIENT_BUNDLE_PATH = `${ZERO_RUNTIME_BUNDLE_ROOT}/client.js`;
@@ -27,110 +39,28 @@ export const ZERO_SOURCE_ENV_FILE = ".env.zero.server";
27
39
  export const ZERO_CONFIG_FILE = "zero.json";
28
40
  export const ZERO_DEPLOY_FILE = ".zero/deploy.json";
29
41
  export const ZERO_RUNTIME_BUNDLE_MAX_BYTES = 786_432;
30
- export const ZERO_ENV_MAX_KEYS = 64;
31
- export const ZERO_ENV_NAME_MAX_BYTES = 128;
32
- export const ZERO_ENV_VALUE_MAX_BYTES = 16 * 1024;
33
- export const ZERO_ENV_TOTAL_VALUE_MAX_BYTES = 64 * 1024;
34
- export const ZERO_ENV_RESERVED_PREFIXES = ["SPACEFAST_", "ZERO_"];
35
42
  export const ZERO_MANAGED_TABLE_COLUMNS = ["id", "createdAt", "updatedAt"];
43
+ /**
44
+ * Paths the Zero app shell itself answers, on top of the platform-reserved set
45
+ * in `./execution.js`. A capsule cannot claim these because its own client
46
+ * router and auth flow already do.
47
+ */
36
48
  export const ZERO_RESERVED_APP_ROUTE_PATHS = [
37
49
  "/",
38
50
  "/index.html",
39
51
  "/client.js",
40
52
  "/auth/callback",
41
- "/__spacefast",
42
- "/__span",
43
53
  ];
44
- export const ZERO_RESERVED_APP_ROUTE_PREFIXES = ["/auth/", "/__spacefast/", "/__span/"];
45
- export const zeroRuntimeKindSchema = z.enum(["static", "zero", "php", "node", "workers"]);
46
- const zeroNameSchema = z
47
- .string()
48
- .min(1)
49
- .max(128)
50
- .regex(/^[A-Za-z_][A-Za-z0-9_]*$/);
51
- const zeroEnvNameSchema = z
52
- .string()
53
- .min(1)
54
- .max(ZERO_ENV_NAME_MAX_BYTES)
55
- .regex(/^[A-Za-z_][A-Za-z0-9_]*$/)
56
- .refine((name) => !ZERO_ENV_RESERVED_PREFIXES.some((prefix) => name.toUpperCase().startsWith(prefix)), { message: "Zero env variable name uses a reserved prefix." });
57
- function hasWellFormedUnicode(value) {
58
- for (let index = 0; index < value.length; index++) {
59
- const codeUnit = value.charCodeAt(index);
60
- if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
61
- if (index + 1 >= value.length)
62
- return false;
63
- const next = value.charCodeAt(index + 1);
64
- if (next < 0xdc00 || next > 0xdfff)
65
- return false;
66
- index++;
67
- }
68
- else if (codeUnit >= 0xdc00 && codeUnit <= 0xdfff) {
69
- return false;
70
- }
71
- }
72
- return true;
73
- }
74
- function hasNoAsciiControlCharacters(value) {
75
- for (let index = 0; index < value.length; index++) {
76
- const codeUnit = value.charCodeAt(index);
77
- if (codeUnit <= 0x1f || codeUnit === 0x7f)
78
- return false;
79
- }
80
- return true;
81
- }
82
- const zeroRoutePathSchema = z
83
- .string()
84
- .min(1)
85
- .max(2048)
86
- .startsWith("/")
87
- .refine(hasWellFormedUnicode, {
88
- message: "Zero capsule routes must contain well-formed Unicode.",
89
- })
90
- .refine((path) => path.normalize("NFC") === path, {
91
- message: "Zero capsule routes must use NFC-normalized Unicode.",
92
- })
93
- .refine(hasNoAsciiControlCharacters, {
94
- message: "Zero capsule routes must not contain ASCII control characters.",
95
- })
96
- .refine((path) => !path.includes("//") &&
97
- !path.includes("\\") &&
98
- !path.includes("*") &&
99
- !path.includes("?") &&
100
- !path.includes("#") &&
101
- !path.endsWith("/") &&
102
- path
103
- .split("/")
104
- .every((segment, index, segments) => segment !== "." &&
105
- segment !== ".." &&
106
- segment !== ":" &&
107
- (segment !== ":splat" || index === segments.length - 1)), {
108
- message: "Zero capsule routes must be absolute app paths without empty, traversal, unnamed parameter, * wildcard, non-terminal splat, \\, ?, or # segments.",
109
- })
110
- .refine((path) => !ZERO_RESERVED_APP_ROUTE_PATHS.some((reservedPath) => path === reservedPath), {
111
- message: "Zero capsule route is reserved by the Zero app shell.",
112
- })
113
- .refine((path) => !ZERO_RESERVED_APP_ROUTE_PREFIXES.some((reservedPrefix) => path.startsWith(reservedPrefix)), {
114
- message: "Zero capsule route prefix is reserved by the Zero app shell.",
115
- })
116
- .refine((path) => !path.startsWith(ZERO_PLATFORM_ROUTE_PREFIX), {
117
- message: `Zero capsule routes cannot use ${ZERO_PLATFORM_ROUTE_PREFIX}.`,
118
- })
119
- .refine((path) => path !== "/__stattic" && !path.startsWith("/__stattic/"), {
120
- message: "Zero capsule routes cannot use Spacefast private control paths.",
54
+ export const ZERO_RESERVED_APP_ROUTE_PREFIXES = ["/auth/"];
55
+ const zeroNameSchema = executionIdentifierSchema;
56
+ const zeroRoutePathSchema = appRoutePathSchema({
57
+ subject: "Zero capsule routes",
58
+ reservedPaths: ZERO_RESERVED_APP_ROUTE_PATHS,
59
+ reservedPrefixes: ZERO_RESERVED_APP_ROUTE_PREFIXES,
121
60
  });
122
- export const zeroHttpMethodSchema = z.enum([
123
- "GET",
124
- "HEAD",
125
- "POST",
126
- "PUT",
127
- "PATCH",
128
- "DELETE",
129
- "OPTIONS",
130
- ]);
131
61
  export const zeroEndpointSchema = z
132
62
  .object({
133
- method: zeroHttpMethodSchema,
63
+ method: httpMethodSchema,
134
64
  path: zeroRoutePathSchema,
135
65
  })
136
66
  .strict();
@@ -227,46 +157,21 @@ export const zeroTableSchema = z
227
157
  })
228
158
  .strict();
229
159
  export const zeroDatabaseSchema = z.record(z.string(), zeroTableSchema);
230
- const zeroSha256Schema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
231
- const zeroBase64Schema = z
232
- .string()
233
- .regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);
234
- export const zeroRuntimeBundleSchema = z
235
- .object({
236
- path: z
237
- .string()
238
- .min(1)
239
- .startsWith(`${ZERO_RUNTIME_BUNDLE_ROOT}/`)
240
- .refine((bundlePath) => !bundlePath.split("/").includes(".."), {
241
- message: "Zero bundle paths cannot traverse outside the runtime bundle root.",
242
- }),
243
- sha256: zeroSha256Schema,
244
- size: z.number().int().nonnegative().max(ZERO_RUNTIME_BUNDLE_MAX_BYTES),
245
- contentBase64: zeroBase64Schema,
246
- })
247
- .strict();
248
- const zeroPublicStaticPathSchema = z
249
- .string()
250
- .min(1)
251
- .max(2048)
252
- .refine((path) => !path.startsWith("/") && !path.split("/").includes(".."), {
253
- message: "Zero static file paths must be relative and cannot traverse.",
254
- })
255
- .refine((path) => !path.startsWith(ZERO_RUNTIME_STORAGE_ROOT + "/"), {
256
- message: `Zero static files cannot use ${ZERO_RUNTIME_STORAGE_ROOT}.`,
257
- })
258
- .refine((path) => !path.startsWith("_") && !path.startsWith("."), {
259
- message: "Zero static file paths cannot use private root prefixes.",
160
+ const zeroSha256Schema = executionSha256Schema;
161
+ /**
162
+ * Zero's bundles travel inline in the finalize payload — a capsule's compiled
163
+ * client and server fit comfortably under the ceiling, and inlining keeps the
164
+ * whole version one atomic write. Functions bundles do the opposite and land
165
+ * in the content store first; see `functionsBundleRefSchema`.
166
+ */
167
+ export const zeroRuntimeBundleSchema = executionBundleSchema({
168
+ bundleRoot: ZERO_RUNTIME_BUNDLE_ROOT,
169
+ maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
170
+ });
171
+ export const zeroRuntimeStaticFileSchema = executionStaticFileSchema({
172
+ storageRoot: ZERO_RUNTIME_STORAGE_ROOT,
173
+ maxBytes: ZERO_RUNTIME_BUNDLE_MAX_BYTES,
260
174
  });
261
- export const zeroRuntimeStaticFileSchema = z
262
- .object({
263
- path: zeroPublicStaticPathSchema,
264
- contentType: z.string().min(1).max(255),
265
- sha256: zeroSha256Schema,
266
- size: z.number().int().nonnegative().max(ZERO_RUNTIME_BUNDLE_MAX_BYTES),
267
- contentBase64: zeroBase64Schema,
268
- })
269
- .strict();
270
175
  export const zeroRuntimeRunSourceSchema = z
271
176
  .object({
272
177
  runId: z.string().min(1).max(256),
@@ -275,23 +180,13 @@ export const zeroRuntimeRunSourceSchema = z
275
180
  .min(1)
276
181
  .max(2 * 1024 * 1024),
277
182
  schemaHash: z.string().min(1).max(256).optional(),
278
- capabilities: z
279
- .object({
280
- db: z.boolean().default(false),
281
- fetch: z.boolean().default(false),
282
- auth: z.boolean().default(false),
283
- env: z.boolean().default(false),
284
- realtime: z.boolean().default(false),
285
- logging: z.boolean().default(false),
286
- })
287
- .partial()
288
- .default({}),
183
+ capabilities: executionCapabilitiesSchema,
289
184
  db: z.record(z.string(), z.unknown()).optional(),
290
185
  })
291
186
  .strict();
292
187
  export const zeroRuntimeEndpointSourceSchema = z
293
188
  .object({
294
- method: zeroHttpMethodSchema,
189
+ method: httpMethodSchema,
295
190
  path: zeroRoutePathSchema,
296
191
  endpointId: z.string().min(1).max(256),
297
192
  source: z
@@ -375,7 +270,7 @@ const zeroRuntimePublicRealtimeCanonicalModeSchema = z.enum([
375
270
  ]);
376
271
  export const zeroRealtimeModeSchema = zeroRealtimeCanonicalModeSchema;
377
272
  export const zeroRuntimePublicRealtimeModeSchema = zeroRuntimePublicRealtimeCanonicalModeSchema;
378
- export const zeroInspectPolicySchema = z.enum(["private", "public"]);
273
+ export const zeroInspectPolicySchema = executionInspectPolicySchema;
379
274
  const zeroRuntimePublicPathSchema = z.string().min(1).startsWith("/");
380
275
  const zeroHttpUrlSchema = z
381
276
  .string()
@@ -500,7 +395,7 @@ export const zeroSourceManifestSchema = z
500
395
  env: z
501
396
  .object({
502
397
  file: z.literal(ZERO_SOURCE_ENV_FILE),
503
- names: z.array(zeroEnvNameSchema).max(ZERO_ENV_MAX_KEYS).default([]),
398
+ names: z.array(executionEnvNameSchema).max(EXECUTION_ENV_MAX_KEYS).default([]),
504
399
  })
505
400
  .nullable()
506
401
  .default(null),
@@ -643,38 +538,40 @@ export const zeroDeployMetadataSchema = z
643
538
  finalize: zeroRuntimeFinalizePayloadSchema,
644
539
  })
645
540
  .strict();
646
- export const zeroInspectResponseSchema = z
541
+ /**
542
+ * What a live Zero capsule is, as the `app` member of a space's runtime status.
543
+ *
544
+ * There is no `versionId` here: this only ever describes the version the status
545
+ * response already names as live, and repeating it would invite the two to
546
+ * disagree. `artifactId` stays because it identifies the built capsule rather
547
+ * than the publish that carries it.
548
+ */
549
+ export const zeroAppSchema = z
647
550
  .object({
648
- versionId: z.string().min(1).nullable(),
649
- artifactId: z.string().min(1).nullable(),
650
- data: z
551
+ runtimeKind: z.literal(ZERO_RUNTIME_KIND),
552
+ artifactId: z.string().min(1),
553
+ appName: z.string().min(1),
554
+ serverRuntime: z.literal("quickjs-rust"),
555
+ inspect: z
651
556
  .object({
652
- runtimeKind: z.literal(ZERO_RUNTIME_KIND),
653
- appName: z.string().min(1),
654
- serverRuntime: z.literal("quickjs-rust"),
655
- inspect: z
656
- .object({
657
- policy: zeroInspectPolicySchema,
658
- })
659
- .strict(),
660
- install: zeroRuntimeInstallProfileSchema,
661
- tables: z.array(z.string()).default([]),
662
- queries: z.array(z.string()).default([]),
663
- mutations: z.array(z.string()).default([]),
664
- endpoints: z.array(zeroEndpointSchema).default([]),
665
- sockets: z.array(z.string()).default([]),
666
- variables: z
667
- .object({
668
- source: z.literal("stattic-variables"),
669
- names: z.array(z.string()).default([]),
670
- })
671
- .strict(),
672
- realtime: zeroRuntimePublicRealtimeConfigSchema,
557
+ policy: zeroInspectPolicySchema,
558
+ })
559
+ .strict(),
560
+ install: zeroRuntimeInstallProfileSchema,
561
+ tables: z.array(z.string()).default([]),
562
+ queries: z.array(z.string()).default([]),
563
+ mutations: z.array(z.string()).default([]),
564
+ endpoints: z.array(zeroEndpointSchema).default([]),
565
+ sockets: z.array(z.string()).default([]),
566
+ variables: z
567
+ .object({
568
+ source: z.literal("stattic-variables"),
569
+ names: z.array(z.string()).default([]),
673
570
  })
674
- .nullable(),
571
+ .strict(),
572
+ realtime: zeroRuntimePublicRealtimeConfigSchema,
675
573
  })
676
574
  .strict();
677
- export const zeroInspectPublicResponseSchema = dataEnvelope(zeroInspectResponseSchema);
678
575
  export const zeroDbInspectResponseSchema = z
679
576
  .object({
680
577
  versionId: z.string().min(1).nullable(),
@@ -708,36 +605,11 @@ export const zeroDbDumpResponseSchema = z
708
605
  })
709
606
  .strict();
710
607
  export const zeroDbDumpPublicResponseSchema = dataEnvelope(zeroDbDumpResponseSchema);
711
- export const zeroLogListQuerySchema = z
712
- .object({
713
- limit: z.coerce.number().int().min(1).max(100).default(50),
714
- cursor: z.string().min(1).optional(),
715
- requestId: z.string().min(1).optional(),
716
- mutationName: z.string().min(1).optional(),
717
- })
718
- .strict();
719
- export const zeroLogEntrySchema = z
720
- .object({
721
- id: z.string().min(1),
722
- timestamp: z.string().datetime(),
723
- level: z.enum(["debug", "info", "warn", "error"]),
724
- requestId: z.string().min(1).nullable(),
725
- versionId: z.string().min(1).nullable(),
726
- mutationName: z.string().min(1).nullable(),
727
- message: z.string(),
728
- metadata: z.record(z.string(), z.unknown()).default({}),
729
- })
730
- .strict();
731
- export const zeroLogListResponseSchema = z
732
- .object({
733
- data: z.array(zeroLogEntrySchema),
734
- pagination: z
735
- .object({
736
- nextCursor: z.string().nullable(),
737
- })
738
- .strict(),
739
- })
740
- .strict();
608
+ // Both products emit the same log shape; `handlerName` carries the mutation
609
+ // name here and the worker handler name on Functions.
610
+ export const zeroLogListQuerySchema = executionLogListQuerySchema;
611
+ export const zeroLogEntrySchema = executionLogEntrySchema;
612
+ export const zeroLogListResponseSchema = executionLogListResponseSchema;
741
613
  export const zeroRealtimeEventIntakeResponseSchema = z
742
614
  .object({
743
615
  accepted: z.literal(true),
@@ -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", "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", "sign-in", "start", "terminal", "two-factor"];
8
8
  /**
9
9
  * Dashboard route first-segments that cannot be used as space slugs.
10
10
  *
@@ -18,7 +18,7 @@ export type SpaceSlugRouteReservation = (typeof SPACE_SLUG_ROUTE_RESERVATIONS)[n
18
18
  export declare const TEAM_SLUG_ROUTE_RESERVATION_SET: ReadonlySet<string>;
19
19
  export declare const SPACE_SLUG_ROUTE_RESERVATION_SET: ReadonlySet<string>;
20
20
  export type SpaceSettingsDestination = "access" | "advanced" | "builds" | "integrations" | "integrations/add" | "source-builds";
21
- export type TeamSettingsDestination = "access" | "audit" | "developer" | "developer/agents" | "developer/environment-variables" | "developer/handoffs" | "developer/service-tokens" | "developer/webhooks" | "integrations";
21
+ export type TeamSettingsDestination = "access" | "audit" | "developer" | "developer/agents" | "developer/environment-variables" | "developer/handoffs" | "developer/webhooks" | "integrations";
22
22
  export declare function teamPath(teamSlug: string): string;
23
23
  export declare function spacePath(teamSlug: string, spaceSlug: string): string;
24
24
  export declare function versionDetailPath(teamSlug: string, spaceSlug: string, versionRef: string): string;
@@ -8,6 +8,7 @@ export const TEAM_SLUG_ROUTE_RESERVATIONS = [
8
8
  "accept-beta-invite",
9
9
  "accept-invitation",
10
10
  "account",
11
+ "access",
11
12
  // Not a TanStack route module: /agent* is the edge-served handoff-document
12
13
  // surface (apps/my/public/_redirects + vite middleware, #417). Those rewrite
13
14
  // rules deliberately swallow every /agent-prefixed path, so a team named
@@ -79,9 +79,9 @@ export const POSITIONING_PROSE = [
79
79
  "optimizes for agent-safe one-shot publish, claim, versioning, rollback, and continuation.",
80
80
  ].join("\n");
81
81
  export const EXPLAIN_TO_USER_PROSE = [
82
- "Relay `data.shareBlurb` verbatim when present. State anonymous expiry in user terms:",
83
- "the space expires unless claimed by `data.claim.expiresAt`. After claim, the agent key is",
84
- "named and revocable in the dashboard.",
82
+ "Report the bare Live URL, repeatable expiring private Open URL, immutable Version URL, and Claim link",
83
+ "as separate actions. State anonymous expiry in user terms: the space expires unless claimed by",
84
+ "`data.claim.expiresAt`. After claim, the agent key is named and revocable in the dashboard.",
85
85
  ].join("\n");
86
86
  export const FAILURE_CONDUCT_PROSE = [
87
87
  "On failure, surface `error.code`, `error.docsUrl`, and `error.requestId`, then stop.",
@@ -181,7 +181,7 @@ export const CONTINUE_AFTER_CLAIM_PROSE = [
181
181
  "Save `data.credential.accessToken` into `.spacefast/state.json` (replace the `claimToken`",
182
182
  'field with `"accessToken"`), then retry the publish with the new bearer. The exchange works',
183
183
  "exactly once; if it returns `continuation_used` or `continuation_unavailable`, ask the user",
184
- "to mint an access token in the dashboard (Account → Access tokens).",
184
+ "to create an API key in the dashboard (Account → API keys).",
185
185
  ].join("\n");
186
186
  /**
187
187
  * The zero-install publish sequence: one curl for a file, a secret-preflighted
@@ -216,10 +216,12 @@ export const RECEIPT_SHAPE_PROSE = [
216
216
  "The JSON receipt is the source of truth:",
217
217
  "",
218
218
  "- `data.space.liveUrl` — the live URL.",
219
- "- `data.version.immutableUrl` — the permanent, frozen version URL; share it for reviews.",
220
- " It is reserved in the initial receipt. If the publish is still finalizing, poll `data.links.status`",
221
- " with the claim token until the status is `ready`.",
222
- "- `data.shareBlurb` a paste-ready one-liner with the URL and claim nudge; relay it verbatim when present.",
219
+ "- `data.open.url` and `data.open.expiresAt` a repeatable private author Link until expiry, claim, or revocation.",
220
+ " It is not a stable URL or recipient Link; clients must not persist it as Space state.",
221
+ "- `data.version.immutableUrl` — the permanent address of the frozen Version. The bare URL",
222
+ " carries no authority: use the receipt's Open URL for the author's browser or create a scoped",
223
+ " Link for a recipient. It is reserved in the initial receipt. If the publish is still",
224
+ " finalizing, poll `data.links.status` with the claim token until the status is `ready`.",
223
225
  "- `data.upload` — signed upload instructions for manifest publishes when file bytes were not sent",
224
226
  " with the request. Send each `data.upload.targets[]` instruction exactly as returned, treat",
225
227
  " authorization headers and upload tokens as secrets, then finalize.",
@@ -50,13 +50,13 @@ export declare function parseAgentHandoffUrl(value: string, expectedOrigin: stri
50
50
  }>;
51
51
  /** Connect targets whose handoff continues through the CLI stdin exchange. */
52
52
  export declare const AGENT_HANDOFF_CLI_TARGET_IDS: readonly ConnectTargetId[];
53
- export declare const AGENT_HANDOFF_PREAMBLE = "Talk to the user before installing tools or publishing. Confirm the file or folder they want to make public.";
53
+ export declare const AGENT_HANDOFF_PREAMBLE = "Talk to the user before installing tools or publishing. Confirm the file or folder they want to publish.";
54
54
  /** The fetch-safety contract: reading the document never consumes or leaks a handoff. */
55
55
  export declare const AGENT_HANDOFF_FETCH_SAFETY = "Keep the original handoff link private. Fetching this document did not use the link or send its fragment secret; the secret is spent only by one successful exchange. An expired, used, or revoked link fails safely, so ask the user for a fresh one from the dashboard.";
56
56
  export declare const AGENT_HANDOFF_FRAGMENT_HYGIENE = "Keep its fragment out of commands, request URLs, logs, and replies.";
57
57
  export declare const AGENT_HANDOFF_CLI_APPROVAL_GUIDANCE: string;
58
58
  export declare const AGENT_HANDOFF_BROWSER_APPROVAL_GUIDANCE = "When the client opens browser approval, ask the user to approve there before publishing.";
59
- export declare const AGENT_HANDOFF_PUBLISH_PROSE = "After approval, confirm the selected Space and permissions, then publish only the files the user approved. Share the live URL and immutable version URL from the receipt.";
59
+ export declare const AGENT_HANDOFF_PUBLISH_PROSE = "After approval, confirm the selected Space and permissions, then publish only the files the user approved. Report the bare Live and immutable Version addresses separately from the private Open URL; create a scoped Link when a recipient needs access.";
60
60
  /** One target's Connect prose: blurb, copyable setup blocks, deeplink/download lines. */
61
61
  export declare function agentHandoffConnectSections(target: ConnectTarget): string[];
62
62
  /** Builds every copy-ready handoff artifact from one validated URL and target catalog row. */
@@ -112,13 +112,13 @@ function validateMcpEndpoint(value) {
112
112
  */
113
113
  /** Connect targets whose handoff continues through the CLI stdin exchange. */
114
114
  export const AGENT_HANDOFF_CLI_TARGET_IDS = ["claude-code", "codex"];
115
- export const AGENT_HANDOFF_PREAMBLE = "Talk to the user before installing tools or publishing. Confirm the file or folder they want to make public.";
115
+ export const AGENT_HANDOFF_PREAMBLE = "Talk to the user before installing tools or publishing. Confirm the file or folder they want to publish.";
116
116
  /** The fetch-safety contract: reading the document never consumes or leaks a handoff. */
117
117
  export const AGENT_HANDOFF_FETCH_SAFETY = "Keep the original handoff link private. Fetching this document did not use the link or send its fragment secret; the secret is spent only by one successful exchange. An expired, used, or revoked link fails safely, so ask the user for a fresh one from the dashboard.";
118
118
  export const AGENT_HANDOFF_FRAGMENT_HYGIENE = "Keep its fragment out of commands, request URLs, logs, and replies.";
119
119
  export const AGENT_HANDOFF_CLI_APPROVAL_GUIDANCE = `Run \`sf setup agent\` to initiate the handoff exchange; if \`sf\` is missing, install it first (macOS/Linux: \`${spacefastInstallCurlCommand}\`; Windows PowerShell: \`${spacefastInstallPowerShellCommand}\`). When it asks for the handoff link on stdin, paste the original link into that prompt; never pass the link as an argv value. Ask the user to approve in the browser, then wait for the CLI's approval result before publishing.`;
120
120
  export const AGENT_HANDOFF_BROWSER_APPROVAL_GUIDANCE = "When the client opens browser approval, ask the user to approve there before publishing.";
121
- export const AGENT_HANDOFF_PUBLISH_PROSE = "After approval, confirm the selected Space and permissions, then publish only the files the user approved. Share the live URL and immutable version URL from the receipt.";
121
+ export const AGENT_HANDOFF_PUBLISH_PROSE = "After approval, confirm the selected Space and permissions, then publish only the files the user approved. Report the bare Live and immutable Version addresses separately from the private Open URL; create a scoped Link when a recipient needs access.";
122
122
  /** One target's Connect prose: blurb, copyable setup blocks, deeplink/download lines. */
123
123
  export function agentHandoffConnectSections(target) {
124
124
  const setupSections = [target.primary, target.config].flatMap((setup) => setup ? [[setup.label, `\`\`\`${setup.language}`, setup.value, "```"].join("\n")] : []);
@@ -250,7 +250,7 @@ export function aiInstructionsText() {
250
250
  "## Install the CLI (On-Device files, updates, versions, rollback, and the rest)",
251
251
  "",
252
252
  "The CLI is the full surface: incremental publishes, version history, rollback,",
253
- "passwords, domains, logs, and diagnostics. Install it when the user will keep",
253
+ "sharing, domains, logs, and diagnostics. Install it when the user will keep",
254
254
  "working on the space:",
255
255
  "",
256
256
  "```bash",
@@ -291,7 +291,8 @@ export function aiInstructionsText() {
291
291
  "Request `mcp:tools` plus the API scopes the tools need: `teams:read` for team context,",
292
292
  "`teams:create` for creating teams,",
293
293
  "`spaces:read` for status, versions, diffs, and logs, `spaces:write` for claim/create/update,",
294
- "`publish:write` for publish and rollback, and `domains:read`/`domains:write` for domain",
294
+ "`spaces:rename` for slug and managed-address renames, `publish:write` for publish and rollback,",
295
+ "and `domains:read`/`domains:write` for domain",
295
296
  "inventory, DNS diagnostics, assignment, verification, and mutation. Hosted MCP does not read",
296
297
  "local paths; its workspace tools operate on a durable virtual workspace attached to the MCP",
297
298
  "session.",
@@ -329,8 +330,10 @@ export function aiInstructionsText() {
329
330
  "",
330
331
  "## After publishing",
331
332
  "",
332
- "- Share the live URL, the immutable version URL when ready, and for anonymous spaces —",
333
- " the claim link with its expiry. If the receipt's immutable URL is null, poll the",
333
+ "- Report the bare Live URL, the immutable Version URL when ready, the private Open URL, and",
334
+ " — for anonymous spaces — the claim link with its expiry. Bare Live and Version URLs carry",
335
+ " no authority for a private Space; create a scoped Link when a recipient needs access.",
336
+ " If the receipt's immutable URL is null, poll the",
334
337
  " operation and version links with the claim token as bearer auth until the version is ready.",
335
338
  "- Never print access tokens, claim tokens, auth files, or `.spacefast/state.json`.",
336
339
  "",
@@ -342,7 +345,7 @@ export function aiInstructionsText() {
342
345
  "",
343
346
  "- `_redirects` — redirects, rewrites, SPA fallbacks, custom 404 rules, and external",
344
347
  " `200` proxy rules.",
345
- "- `_headers` — response headers and Basic Auth rules.",
348
+ "- `_headers` — supported response headers.",
346
349
  "- `404.html` — custom not-found page.",
347
350
  "- `sf.jsonc` — serving config (index, fallback, listing, meta) and the optional",
348
351
  " `space` link. JSON Schema: https://spacefast.com/schemas/sf.json",
@@ -350,8 +353,7 @@ export function aiInstructionsText() {
350
353
  " agent-readable too.",
351
354
  "- Plan limits surface as diagnostics, not failures you should guess at: publish the",
352
355
  " intended artifact, then read and report what the CLI or API says. When a feature",
353
- ' is plan-gated, say: "Not available on Free. Available on Personal and Work." For',
354
- " simple gated access, `sf password set` needs no plan and no `_headers` rule.",
356
+ ' is plan-gated, say: "Not available on Free. Available on Personal and Work."',
355
357
  "",
356
358
  "## Agent-aware routing",
357
359
  "",
@@ -22,7 +22,7 @@ function hostedMcpText(label, guideUrl) {
22
22
  "Transport: Streamable HTTP",
23
23
  "Resource: https://mcp.spacefast.com",
24
24
  "Minimum scope: mcp:tools",
25
- "Common scopes: teams:read teams:create spaces:read spaces:write publish:write domains:read domains:write",
25
+ "Common scopes: teams:read teams:create spaces:read spaces:write spaces:rename publish:write domains:read domains:write",
26
26
  "",
27
27
  "Hosted MCP is for cloud/browser agents. It does not read local paths; use the hosted workspace tools or signed uploads for artifacts.",
28
28
  `Guide: ${guideUrl}`,