@spacefast/common 0.0.5 → 0.0.7

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 (183) hide show
  1. package/brand-assets/spacefast-favicon.svg +16 -0
  2. package/brand-assets/spacefast-sf-full-bleed.svg +13 -0
  3. package/brand-assets/spacefast-wordmark.svg +5 -0
  4. package/dist/agents/connect-targets.d.ts +138 -0
  5. package/dist/agents/connect-targets.js +243 -0
  6. package/dist/brand-assets-build.d.ts +26 -0
  7. package/dist/brand-assets-build.js +81 -0
  8. package/dist/brand-assets.d.ts +42 -0
  9. package/dist/brand-assets.js +30 -0
  10. package/dist/brand.d.ts +1 -0
  11. package/dist/brand.js +5 -0
  12. package/dist/config/domains.d.ts +12 -6
  13. package/dist/config/domains.js +30 -38
  14. package/dist/contracts/access.d.ts +967 -124
  15. package/dist/contracts/access.js +804 -148
  16. package/dist/contracts/activity.d.ts +1 -1
  17. package/dist/contracts/activity.js +28 -2
  18. package/dist/contracts/annotations.d.ts +2 -4
  19. package/dist/contracts/api-keys.d.ts +126 -4
  20. package/dist/contracts/api-keys.js +74 -6
  21. package/dist/contracts/archives.d.ts +8 -2
  22. package/dist/contracts/archives.js +11 -4
  23. package/dist/contracts/billing.d.ts +0 -9
  24. package/dist/contracts/builds.d.ts +65 -21
  25. package/dist/contracts/builds.js +29 -0
  26. package/dist/contracts/common.d.ts +2 -0
  27. package/dist/contracts/common.js +4 -0
  28. package/dist/contracts/continuation.d.ts +0 -3
  29. package/dist/contracts/countries.d.ts +2 -0
  30. package/dist/contracts/countries.js +261 -0
  31. package/dist/contracts/deployments.d.ts +34 -34
  32. package/dist/contracts/device-auth.d.ts +4 -11
  33. package/dist/contracts/device-auth.js +4 -0
  34. package/dist/contracts/docs.d.ts +119 -0
  35. package/dist/contracts/docs.js +51 -0
  36. package/dist/contracts/domains.d.ts +96 -54
  37. package/dist/contracts/domains.js +26 -4
  38. package/dist/contracts/enums.d.ts +15 -16
  39. package/dist/contracts/enums.js +26 -14
  40. package/dist/contracts/error-code-meta.d.ts +184 -0
  41. package/dist/contracts/error-code-meta.js +124 -10
  42. package/dist/contracts/error-codes.d.ts +1 -1
  43. package/dist/contracts/error-codes.js +42 -0
  44. package/dist/contracts/events.d.ts +1 -1
  45. package/dist/contracts/feature-lifecycle-core.d.ts +36 -0
  46. package/dist/contracts/feature-lifecycle-core.js +220 -0
  47. package/dist/contracts/feature-lifecycle.d.ts +7 -0
  48. package/dist/contracts/feature-lifecycle.js +31 -0
  49. package/dist/contracts/features.d.ts +76 -6
  50. package/dist/contracts/features.js +178 -13
  51. package/dist/contracts/generated-feature-launch-entries.d.ts +2 -0
  52. package/dist/contracts/generated-feature-launch-entries.js +518 -0
  53. package/dist/contracts/git.d.ts +2 -8
  54. package/dist/contracts/ids.d.ts +9 -0
  55. package/dist/contracts/ids.js +13 -0
  56. package/dist/contracts/mcp.d.ts +8 -10
  57. package/dist/contracts/me.js +1 -1
  58. package/dist/contracts/oauth-resources.d.ts +19 -8
  59. package/dist/contracts/oauth-resources.js +44 -13
  60. package/dist/contracts/operations.d.ts +161 -1
  61. package/dist/contracts/operations.js +49 -1
  62. package/dist/contracts/platform.d.ts +6 -102
  63. package/dist/contracts/platform.js +6 -50
  64. package/dist/contracts/publishes.d.ts +130 -0
  65. package/dist/contracts/publishes.js +145 -0
  66. package/dist/contracts/push-new.d.ts +4 -4
  67. package/dist/contracts/quotas.d.ts +2 -0
  68. package/dist/contracts/quotas.js +8 -0
  69. package/dist/contracts/repository-connections.d.ts +9 -8
  70. package/dist/contracts/repository-connections.js +13 -0
  71. package/dist/contracts/resources.d.ts +99 -13
  72. package/dist/contracts/resources.js +36 -4
  73. package/dist/contracts/routes.d.ts +0 -2
  74. package/dist/contracts/runtime-api.d.ts +363 -39
  75. package/dist/contracts/runtime-api.js +276 -6
  76. package/dist/contracts/sf-config-v1.d.ts +75 -0
  77. package/dist/contracts/sf-config-v1.js +6 -0
  78. package/dist/contracts/sites.d.ts +19 -2
  79. package/dist/contracts/sites.js +21 -0
  80. package/dist/contracts/space-config.d.ts +201 -2
  81. package/dist/contracts/space-config.js +135 -5
  82. package/dist/contracts/spaces.d.ts +376 -196
  83. package/dist/contracts/spaces.js +62 -10
  84. package/dist/contracts/superadmin-emails.d.ts +4 -2
  85. package/dist/contracts/superadmin-emails.js +8 -0
  86. package/dist/contracts/superadmin-queues.d.ts +26 -26
  87. package/dist/contracts/superadmin-spaces.d.ts +172 -42
  88. package/dist/contracts/superadmin-tenants.d.ts +6 -6
  89. package/dist/contracts/superadmin-tenants.js +6 -11
  90. package/dist/contracts/superadmin.d.ts +6 -93
  91. package/dist/contracts/superadmin.js +6 -14
  92. package/dist/contracts/tags.d.ts +10 -9
  93. package/dist/contracts/tags.js +2 -1
  94. package/dist/contracts/teams.d.ts +26 -30
  95. package/dist/contracts/teams.js +11 -17
  96. package/dist/contracts/theme-json.d.ts +30 -0
  97. package/dist/contracts/theme-json.js +48 -0
  98. package/dist/contracts/variables.d.ts +0 -2
  99. package/dist/contracts/variables.js +0 -5
  100. package/dist/contracts/webhooks.d.ts +2 -0
  101. package/dist/contracts/webhooks.js +1 -1
  102. package/dist/contracts/zero.d.ts +5 -10
  103. package/dist/docs/agent-prose.d.ts +43 -3
  104. package/dist/docs/agent-prose.js +146 -7
  105. package/dist/docs/agent-setup.d.ts +51 -0
  106. package/dist/docs/agent-setup.js +211 -14
  107. package/dist/docs/agent-solutions.d.ts +5 -5
  108. package/dist/docs/agent-solutions.js +2 -2
  109. package/dist/docs/catalog.d.ts +650 -0
  110. package/dist/docs/catalog.js +758 -0
  111. package/dist/docs/error-docs.d.ts +0 -2
  112. package/dist/docs/error-docs.js +189 -35
  113. package/dist/docs/index-build.d.ts +17 -0
  114. package/dist/docs/index-build.js +24 -0
  115. package/dist/docs/search.d.ts +54 -0
  116. package/dist/docs/search.js +96 -0
  117. package/dist/docs/skill-distribution.d.ts +5 -3
  118. package/dist/docs/skill-distribution.js +8 -8
  119. package/dist/slug-policy/blocklist.d.ts +4 -0
  120. package/dist/slug-policy/blocklist.js +122 -0
  121. package/dist/slug-policy/index.d.ts +17 -0
  122. package/dist/slug-policy/index.js +86 -0
  123. package/dist/utils/access-match.d.ts +39 -0
  124. package/dist/utils/access-match.js +296 -0
  125. package/dist/utils/auth-redirect.d.ts +3 -1
  126. package/dist/utils/auth-redirect.js +21 -1
  127. package/dist/utils/build-settings.d.ts +6 -0
  128. package/dist/utils/build-settings.js +429 -46
  129. package/dist/utils/claim-token.d.ts +8 -0
  130. package/dist/utils/claim-token.js +23 -2
  131. package/dist/utils/concurrency.d.ts +1 -0
  132. package/dist/utils/concurrency.js +22 -0
  133. package/dist/utils/content-type.d.ts +1 -0
  134. package/dist/utils/content-type.js +1 -1
  135. package/dist/utils/credential-policy.d.ts +54 -0
  136. package/dist/utils/{access-policy.js → credential-policy.js} +28 -2
  137. package/dist/utils/email.d.ts +1 -0
  138. package/dist/utils/email.js +3 -0
  139. package/dist/utils/gate-theme.d.ts +61 -0
  140. package/dist/utils/gate-theme.js +217 -0
  141. package/dist/utils/git-repository.d.ts +0 -1
  142. package/dist/utils/git-repository.js +0 -3
  143. package/dist/utils/id-hints.d.ts +8 -0
  144. package/dist/utils/id-hints.js +61 -0
  145. package/dist/utils/local-space-state.d.ts +91 -0
  146. package/dist/utils/local-space-state.js +251 -0
  147. package/dist/utils/oauth-signed-query.d.ts +8 -0
  148. package/dist/utils/oauth-signed-query.js +26 -0
  149. package/dist/utils/publish-detection.d.ts +0 -8
  150. package/dist/utils/publish-detection.js +0 -93
  151. package/dist/utils/publish-policy.d.ts +6 -5
  152. package/dist/utils/publish-policy.js +71 -7
  153. package/dist/utils/query-keys.d.ts +16 -4
  154. package/dist/utils/query-keys.js +31 -4
  155. package/dist/utils/runtime-paths.d.ts +0 -1
  156. package/dist/utils/runtime-paths.js +0 -1
  157. package/dist/utils/runtime-upload-batch.d.ts +18 -0
  158. package/dist/utils/runtime-upload-batch.js +90 -0
  159. package/dist/utils/runtime-upload.d.ts +2 -0
  160. package/dist/utils/runtime-upload.js +5 -0
  161. package/dist/utils/sf-config-v1.d.ts +2 -0
  162. package/dist/utils/sf-config-v1.js +542 -0
  163. package/dist/utils/space-config.d.ts +4 -0
  164. package/dist/utils/space-config.js +10 -1
  165. package/dist/utils/space-theme.d.ts +2 -0
  166. package/dist/utils/space-theme.js +9 -0
  167. package/dist/utils/static-runtime-policy.d.ts +0 -21
  168. package/dist/utils/static-runtime-policy.js +19 -103
  169. package/dist/utils/upload-session.d.ts +1 -1
  170. package/dist/utils/wpcom-auth-redirects.d.ts +32 -2
  171. package/dist/utils/wpcom-auth-redirects.js +26 -10
  172. package/dist/vocabulary.d.ts +130 -30
  173. package/dist/vocabulary.js +77 -36
  174. package/package.json +35 -1
  175. package/dist/contracts/account.d.ts +0 -28
  176. package/dist/contracts/account.js +0 -54
  177. package/dist/contracts/intercom.d.ts +0 -6
  178. package/dist/contracts/intercom.js +0 -5
  179. package/dist/contracts/telemetry.d.ts +0 -2
  180. package/dist/contracts/telemetry.js +0 -1
  181. package/dist/utils/access-policy.d.ts +0 -39
  182. package/dist/utils/error-display.d.ts +0 -7
  183. package/dist/utils/error-display.js +0 -42
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { policyDocSchema } from "./access.js";
2
+ import { accessEventSchema, policyDocSchema } from "./access.js";
3
3
  import { conventionFilesSchema, manifestFileSchema } from "./internal.js";
4
4
  const runtimeConventionFilesSchema = conventionFilesSchema.omit({ routes: true }).strict();
5
5
  const hostCanonicalRedirectSchema = z.object({
@@ -111,15 +111,62 @@ const runtimeRouteConfigSchema = z.object({
111
111
  // alike. Carries platform + file + cloud rules (platform prepended, always
112
112
  // wins). Explicit null clears the stored policy; absence leaves it untouched.
113
113
  policy: policyDocSchema.nullable().optional(),
114
- // Serving-secret map (name -> value) the policy's password rules reference by
115
- // `auth.password.ref` = "secret:<name>". Carries the space-password bcrypt
116
- // verifier hash the runtime resolves and `password_verify`s. Explicit null
117
- // clears stored secrets; absence leaves them untouched.
114
+ // Serving-secret map (name -> value) the policy's password acquires
115
+ // reference by `ref` = "secret:<name>". Carries the space-password bcrypt
116
+ // verifier hash (and the compiled `_headers` basicAuth credential hashes)
117
+ // the runtime resolves and `password_verify`s. Explicit null clears stored
118
+ // secrets; absence leaves them untouched.
118
119
  secrets: z.record(z.string().min(1), z.string().min(1)).nullable().optional(),
120
+ // Space session version (access-plan §3.1): the runtime rejects a visitor
121
+ // token whose `sv` claim mismatches this, and derives the space-local `pw:`
122
+ // key from the password secret + this value. Absent = 0.
123
+ session_version: z.number().int().nonnegative().nullable().optional(),
119
124
  // Anonymous claim-window countdown (ISO timestamp), compiled into serving
120
125
  // state so the runtime can render the expiry-rescue banner for visitors
121
126
  // holding the claim-link viewer session. Null/absent once claimed.
122
127
  anonymous_expires_at: z.string().nullable().optional(),
128
+ // Serve-time content-type allowlist. Generic serving policy: the engine has
129
+ // no notion of WHY a space is restricted — it refuses (403, blocked_message
130
+ // body) any file whose stored Content-Type matches no pattern. Patterns are
131
+ // exact types or `prefix/*` wildcards ("text/*"). The control plane pushes
132
+ // it for unclaimed anonymous spaces (no opaque binaries pre-claim); explicit
133
+ // null clears the stored policy — route config is rebuilt wholesale, so a
134
+ // claim clears it structurally on the next sync.
135
+ content_types: z
136
+ .object({
137
+ allowed: z.array(z.string().min(1)),
138
+ blocked_message: z.string().optional(),
139
+ })
140
+ .nullable()
141
+ .optional(),
142
+ // Per-space admission-control override (plan §5/§25; contract A1): the
143
+ // in-flight concurrency limit the engine enforces on uncacheable requests
144
+ // for this space, superseding SPACEFAST_UNCACHEABLE_CONC_PER_SPACE. Ops-only
145
+ // in V1 (set via the superadmin admission endpoint); absent means the
146
+ // env-knob default applies.
147
+ admission: z.object({ concurrency: z.number().int().positive() }).optional(),
148
+ // Durable revocation SET (access-plan revocation hardening): every
149
+ // currently-revoked link:/invite:/svc: grant id, computed from the
150
+ // control-plane's Postgres projection (access/resolve.ts
151
+ // `revocationsForSpace`). The runtime REPLACES its revocations store's
152
+ // grant bucket with exactly this set on every sync — the backstop that
153
+ // converges even when the instant best-effort revoke_grant/unrevoke_grant
154
+ // call was dropped. `subs` (JWT-subject revocations) are left untouched.
155
+ // Absence leaves the stored set untouched.
156
+ revocations: z.array(z.string().min(1)).optional(),
157
+ // Serve-time plan entitlements (proxy-routes.md: "the rule stays in your
158
+ // config and activates the moment you upgrade — no redeploy needed"). Stored
159
+ // per space beside `policy`; a `planGated` compiled proxy rule
160
+ // (packages/routing plan.ts) is checked against this doc at REQUEST time by
161
+ // runtime/redirects.php, never baked into the compiled artifact. Explicit
162
+ // null clears the stored doc (falls back to fail-closed); absence leaves it
163
+ // untouched.
164
+ entitlements: z
165
+ .object({
166
+ externalProxy: z.boolean(),
167
+ })
168
+ .nullable()
169
+ .optional(),
123
170
  });
124
171
  // Compiled SpaceConfig serving primitives (spec "Serving resolution"): the finalize
125
172
  // compiler resolves content defaults -> sf.jsonc -> space overlay into this shape;
@@ -140,6 +187,10 @@ const runtimeServingConfigSchema = z.object({
140
187
  })
141
188
  .nullable()
142
189
  .optional(),
190
+ clean_urls: z
191
+ .boolean()
192
+ .optional()
193
+ .describe("Serve flat `<name>.html` files at their extensionless URLs (W7.1). Absent = default: on unless the fallback is the 200-status SPA shape."),
143
194
  listing: z
144
195
  .boolean()
145
196
  .optional()
@@ -157,6 +208,32 @@ const runtimeServingConfigSchema = z.object({
157
208
  .nullable()
158
209
  .optional()
159
210
  .describe("Finalize-resolved listing/viewer/OG metadata (effective SpaceConfig meta); wins over session metadata."),
211
+ // Gate-page presentation (access-plan §5.7, X-16): finalize-compiled theme
212
+ // tokens (tier 1) plus the plan-gated white-label flag (tier 2). The runtime
213
+ // reads this shape defensively from the version's serving_config and defaults
214
+ // per-field; platform-LANE pages (tombstones, plan expiry, claim, invariant
215
+ // errors) never consume it (X-17).
216
+ pages: z
217
+ .object({
218
+ theme: z
219
+ .object({
220
+ accent: z.string().max(64).optional(),
221
+ background: z.string().max(64).optional(),
222
+ logo: z.string().max(2000).optional(),
223
+ name: z.string().max(120).optional(),
224
+ // Free tier ("basic color scheme + fonts"): a validated font-family
225
+ // stack, same grammar as pages.theme.accent/background.
226
+ fontFamily: z.string().max(256).optional(),
227
+ })
228
+ .optional(),
229
+ // Additive theme.json palette/font-family CSS custom properties
230
+ // (access-plan §8 tier 3 middle rung): exposes the full WP-compatible
231
+ // palette to custom 401.html/403.html/layout.html authors beyond the
232
+ // flat accent/background tokens above.
233
+ theme_vars: z.string().max(8192).optional(),
234
+ white_label: z.boolean().optional(),
235
+ })
236
+ .optional(),
160
237
  // Hidden experimental build-pipeline flag: absent on every version finalized
161
238
  // without it (byte-identical payload to today). Only ever sent as true.
162
239
  experimental_gutenberg: z.boolean().optional(),
@@ -194,6 +271,7 @@ const runtimeZeroEndpointCapabilitiesSchema = z
194
271
  auth: z.boolean().optional(),
195
272
  env: z.boolean().optional(),
196
273
  realtime: z.boolean().optional(),
274
+ logging: z.boolean().optional(),
197
275
  })
198
276
  .default({});
199
277
  const runtimeZeroEndpointSchema = z.object({
@@ -218,8 +296,14 @@ const runtimeZeroRunSchema = z.object({
218
296
  capabilities: runtimeZeroEndpointCapabilitiesSchema.optional(),
219
297
  db: z.record(z.string(), z.unknown()).optional(),
220
298
  });
299
+ // Gated-activation mode (plan §9, Placement V2): whether a version/import
300
+ // installs as immediately live ("active") or staged pending an explicit
301
+ // activation call ("activating", the engine's own fail-safe default when
302
+ // absent). Shared by finalize and import — do not re-inline this enum.
303
+ export const runtimeZeroModeSchema = z.enum(["active", "activating"]);
221
304
  export const runtimeVersionFinalizeRequestSchema = z.object({
222
305
  upload_id: z.string().min(1),
306
+ zero_mode: runtimeZeroModeSchema.optional(),
223
307
  // The version's authoritative ready timestamp (epoch seconds), passed by the
224
308
  // control plane when the version already reached ready (re-finalize, import
225
309
  // re-materialization, provider migration). The engine stamps it ONCE into the
@@ -266,6 +350,46 @@ export const runtimeVersionFinalizeRequestSchema = z.object({
266
350
  })
267
351
  .optional()
268
352
  .describe("Channel-variant template contents, keyed by runtime route name."),
353
+ // Publish-baked custom gate pages (access-plan §5.7 tier 3, X-35): the
354
+ // finalize compiler validates the version's 401.html/403.html slot element
355
+ // (`<div data-sf="challenge">` / `<div data-sf="deny">`), replaces the slot's
356
+ // contents with the opaque v1 marker comment, and ships the baked document
357
+ // here. The engine stores each under the version root as
358
+ // `access-pages/{challenge,deny}.html` (sibling of serving.php — never a
359
+ // publicly served path) and unlinks stale ones on re-finalize; serving is a
360
+ // single str_replace of the marker with the runtime-owned functional
361
+ // fragment. A version finalized without a key here has no override — the
362
+ // default platform page renders.
363
+ access_pages: z
364
+ .object({
365
+ challenge: z
366
+ .string()
367
+ .max(2 * 1024 * 1024)
368
+ .optional()
369
+ .describe("Baked 401.html carrying <!--spacefast:slot:challenge:v1-->."),
370
+ deny: z
371
+ .string()
372
+ .max(2 * 1024 * 1024)
373
+ .optional()
374
+ .describe("Baked 403.html carrying <!--spacefast:slot:deny:v1-->."),
375
+ })
376
+ .optional(),
377
+ // Custom gate-page chrome (access-plan §8 tier 2): the finalize compiler
378
+ // validates `.spacefast/templates/layout.html`'s `<div data-sf="content">`
379
+ // slot, replaces its contents with the opaque v1 marker comment, and ships
380
+ // the baked document here. The engine stores it as
381
+ // `access-pages/layout.html` (sibling of the challenge/deny overrides,
382
+ // never a publicly served path) and unlinks it when a re-finalize omits it.
383
+ // Serving wraps the runtime-owned gate-page content (brand row + heading +
384
+ // functional fragment) in the layout's content slot with one str_replace;
385
+ // a missing/invalid layout falls back to the platform default chrome. Only
386
+ // consulted when no full custom 401.html/403.html override wins for that
387
+ // page (tier 1 > tier 2).
388
+ layout_template: z
389
+ .string()
390
+ .max(2 * 1024 * 1024)
391
+ .optional()
392
+ .describe("Baked .spacefast/templates/layout.html carrying <!--spacefast:slot:layout-content:v1-->."),
269
393
  serving: z
270
394
  .object({
271
395
  headers_exact: z.record(z.string(), z.array(z.record(z.string(), z.unknown()))).default({}),
@@ -308,6 +432,9 @@ export const runtimeVersionFinalizeResponseSchema = z.object({
308
432
  space_id: z.string(),
309
433
  version_id: z.string(),
310
434
  status: z.literal("ready"),
435
+ // Runtime-compiled truth from zero/endpoints-index.json. Optional so older
436
+ // runtimes remain parseable during rolling deploys.
437
+ zero_endpoint_count: z.number().int().nonnegative().optional(),
311
438
  // Open sessions: the manifest derived from what was actually uploaded
312
439
  // (path, size, streaming sha256). Absent for declared sessions.
313
440
  manifest: z.array(manifestFileSchema).optional(),
@@ -323,11 +450,22 @@ export const runtimeRouteUpdateRequestSchema = z.object({
323
450
  host_canonical_redirects: runtimeRouteIntentSchema.shape.host_canonical_redirects,
324
451
  proxy_host_routes: runtimeRouteIntentSchema.shape.proxy_host_routes,
325
452
  });
453
+ export const runtimeHostnameIntentUpdateRequestSchema = z.object({
454
+ production_hostnames: runtimeRouteIntentSchema.shape.production_hostnames,
455
+ noindex_production_hostnames: runtimeRouteIntentSchema.shape.noindex_production_hostnames,
456
+ version_hostnames: runtimeRouteIntentSchema.shape.version_hostnames,
457
+ host_canonical_redirects: runtimeRouteIntentSchema.shape.host_canonical_redirects,
458
+ proxy_host_routes: runtimeRouteIntentSchema.shape.proxy_host_routes,
459
+ });
326
460
  export const runtimeRouteUpdateResponseSchema = z.object({
327
461
  space_id: z.string(),
328
462
  route_name: z.string(),
329
463
  version_id: z.string(),
330
464
  });
465
+ export const runtimeHostnameIntentUpdateResponseSchema = z.object({
466
+ space_id: z.string(),
467
+ route_count: z.number().int().nonnegative(),
468
+ });
331
469
  export const runtimeTombstonesUpdateRequestSchema = z.object({
332
470
  hostnames: runtimeRouteIntentSchema.shape.production_hostnames,
333
471
  mode: z.enum(["replace", "add", "remove"]).default("replace"),
@@ -342,6 +480,31 @@ export const runtimeTombstonesUpdateResponseSchema = z.object({
342
480
  space_id: z.string(),
343
481
  tombstone_count: z.number().int().nonnegative(),
344
482
  });
483
+ // Retention/pruning policy artifact (Placement V2 tiering, plan §8/§26): the
484
+ // control plane computes prunable version ids; the engine stores the list and
485
+ // its housekeeping tick prunes trees after re-checking live route pointers.
486
+ // An empty list clears the policy.
487
+ export const runtimeRetentionPolicyUpdateRequestSchema = z.object({
488
+ prunable_version_ids: z.array(z.string()),
489
+ });
490
+ export const runtimeRetentionPolicyUpdateResponseSchema = z.object({
491
+ space_id: z.string(),
492
+ prunable_count: z.number().int().nonnegative(),
493
+ });
494
+ // Instant per-grant tombstone (access-plan revocation hardening): the
495
+ // control plane's best-effort synchronous call at revoke/unrevoke time,
496
+ // hitting the SAME `revocations.json` the durable `config.revocations` full
497
+ // replace (above) also converges. `grant` must be a `link:`/`invite:`/`svc:`
498
+ // row id — the runtime rejects anything else.
499
+ export const runtimeGrantRevocationRequestSchema = z.object({
500
+ grant: z.string().min(1),
501
+ });
502
+ export const runtimeGrantRevocationResponseSchema = z.object({
503
+ space_id: z.string(),
504
+ target_type: z.literal("grant"),
505
+ grant: z.string(),
506
+ revoked: z.boolean(),
507
+ });
345
508
  export const runtimeSpaceDeleteResponseSchema = z.object({
346
509
  space_id: z.string(),
347
510
  status: z.literal("deleted"),
@@ -391,14 +554,21 @@ export const runtimeSpaceExportResponseSchema = z.object({
391
554
  export const runtimeSpaceImportStartRequestSchema = z
392
555
  .object({
393
556
  version_id_map: z.record(z.string(), z.string()).optional(),
557
+ // Plan §9 gated activation, extended to import (I-4): shares
558
+ // runtimeZeroModeSchema with runtimeVersionFinalizeRequestSchema.
559
+ // Absent/anything other than 'active' is the engine's own fail-safe
560
+ // 'activating'.
561
+ zero_mode: runtimeZeroModeSchema.optional(),
394
562
  })
395
563
  .strict();
396
564
  // Deferred version-id mapping: control-plane-driven uploads land on the
397
565
  // runtime before the control plane has read the archive, so the freshly
398
- // minted target ids are supplied here before the first step.
566
+ // minted target ids (and, for upload-sourced imports, zero_mode) are
567
+ // supplied here before the first step.
399
568
  export const runtimeSpaceImportMapRequestSchema = z
400
569
  .object({
401
570
  version_id_map: z.record(z.string(), z.string()),
571
+ zero_mode: runtimeZeroModeSchema.optional(),
402
572
  })
403
573
  .strict();
404
574
  export const runtimeSpaceImportResponseSchema = z.object({
@@ -414,6 +584,42 @@ export const runtimeSpaceImportResponseSchema = z.object({
414
584
  updated_at: z.string(),
415
585
  completed_at: z.string().optional(),
416
586
  });
587
+ const runtimeTransferBundleFileSchema = z.object({
588
+ path: z.string().min(1),
589
+ content_b64: z.string(),
590
+ });
591
+ export const runtimeTransferBundleSourceRequestSchema = z.object({
592
+ space_id: z.string().min(1),
593
+ version_ids: z.array(z.string().min(1)),
594
+ cursor: z.string().nullable(),
595
+ });
596
+ export const runtimeTransferBundleTargetRequestSchema = z.object({
597
+ space_id: z.string().min(1),
598
+ store: z.literal(true),
599
+ files: z.array(runtimeTransferBundleFileSchema),
600
+ done: z.boolean(),
601
+ });
602
+ export const runtimeTransferBundleResponseSchema = z.object({
603
+ chunk: z.object({ files: z.array(runtimeTransferBundleFileSchema) }),
604
+ next_cursor: z.string().nullable(),
605
+ });
606
+ export const runtimeTransferBundleStoredResponseSchema = z.object({
607
+ stored: z.literal(true),
608
+ });
609
+ export const runtimeTransferCommitRequestSchema = z.object({
610
+ space_id: z.string().min(1),
611
+ version_ids: z.array(z.string().min(1)),
612
+ live_version_id: z.string().nullable(),
613
+ });
614
+ export const runtimeTransferCommitResponseSchema = z.object({
615
+ installed: z.literal(true),
616
+ });
617
+ export const runtimeTransferAbortRequestSchema = z.object({
618
+ space_id: z.string().min(1),
619
+ });
620
+ export const runtimeTransferAbortResponseSchema = z.object({
621
+ aborted: z.boolean().optional(),
622
+ });
417
623
  // Per-space generation state reported by the authed state endpoint. The
418
624
  // reconciliation sweep compares this against control-plane expectations
419
625
  // (space liveVersionId vs the runtime's route pointers) and repairs targeted
@@ -511,3 +717,67 @@ export const runtimeEventsDrainResponseSchema = z.object({
511
717
  }))
512
718
  .optional(),
513
719
  });
720
+ // Engine job runner (plan §22, Placement V2): the box-local job runner behind
721
+ // the two-lane tick. The control plane creates a job, drives it with repeated
722
+ // ticks (kick-on-enqueue; the site-cron watchdog ticks the same route), and
723
+ // reads status from either the tick response or a direct GET. Field names
724
+ // mirror the engine's job record (§22 "Storage layout & job record").
725
+ export const runtimeEngineJobLaneSchema = z.enum(["interactive", "bulk"]);
726
+ export const runtimeEngineJobStatusSchema = z.enum(["pending", "running", "complete", "failed"]);
727
+ export const runtimeEngineJobErrorSchema = z.object({
728
+ code: z.string().min(1),
729
+ message: z.string().min(1),
730
+ });
731
+ export const runtimeEngineJobRecordSchema = z.object({
732
+ id: z.string().min(1),
733
+ type: z.string().min(1),
734
+ lane: runtimeEngineJobLaneSchema,
735
+ space_id: z.string().nullable().optional(),
736
+ operation_id: z.string().nullable().optional(),
737
+ status: runtimeEngineJobStatusSchema,
738
+ attempt: z.number().int().nonnegative().default(0),
739
+ max_attempts: z.number().int().positive().optional(),
740
+ progress: z
741
+ .object({
742
+ done: z.number().nonnegative().default(0),
743
+ total: z.number().nonnegative().default(0),
744
+ })
745
+ .optional(),
746
+ result: z.record(z.string(), z.unknown()).nullable().optional(),
747
+ error: runtimeEngineJobErrorSchema.nullable().optional(),
748
+ created_at: z.string().optional(),
749
+ updated_at: z.string().optional(),
750
+ });
751
+ export const runtimeEngineJobCreateRequestSchema = z.object({
752
+ type: z.string().min(1),
753
+ payload: z.record(z.string(), z.unknown()).default({}),
754
+ // Unique per (type, space, operation) — create is upsert-by-key (§22).
755
+ idempotency_key: z.string().min(1),
756
+ });
757
+ export const runtimeEngineJobResponseSchema = z.object({
758
+ job: runtimeEngineJobRecordSchema,
759
+ });
760
+ // The tick response carries the ticked job's fresh state when one was
761
+ // claimed/advanced this call, so a driver loop can usually avoid a follow-up
762
+ // GET; `job` is absent/null when the lane had nothing eligible to run.
763
+ export const runtimeEngineJobTickResponseSchema = z.object({
764
+ lane: runtimeEngineJobLaneSchema,
765
+ job: runtimeEngineJobRecordSchema.nullable().optional(),
766
+ drained: z.boolean().optional(),
767
+ });
768
+ // The management pull action for the Views panel (access-plan §5.6b, X-37):
769
+ // `GET /access-events?file&offset&limit` — a cursor-resumed read of the
770
+ // runtime's own per-hostname NDJSON access-event journal. `cursor` is the
771
+ // position after the last returned event (feed it back verbatim); `done` is
772
+ // false only when the response was truncated by `limit`; `dropped` totals the
773
+ // writer's `.dropped` sidecars (events skipped past the per-file byte cap).
774
+ export const runtimeAccessEventsCursorSchema = z.object({
775
+ file: z.string().min(1).nullable(),
776
+ offset: z.number().int().nonnegative(),
777
+ });
778
+ export const runtimeAccessEventsResponseSchema = z.object({
779
+ events: z.array(accessEventSchema).default([]),
780
+ cursor: runtimeAccessEventsCursorSchema,
781
+ done: z.boolean(),
782
+ dropped: z.number().int().nonnegative().default(0),
783
+ });
@@ -0,0 +1,75 @@
1
+ export declare const SF_CONFIG_V1_CANONICAL_FILE = "sf.jsonc";
2
+ export declare const SF_CONFIG_V1_FILES: readonly ["sf.jsonc", "spacefast.jsonc", "spacefast.json", "sf.json", ".sf/sf.json", ".sf/config.jsonc", ".sf/config.json"];
3
+ /** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
4
+ export declare const SF_CONFIG_V1_SCHEMA_URL: `${string}/schemas/sf.v1.json`;
5
+ export type SfConfigV1 = {
6
+ $schema?: typeof SF_CONFIG_V1_SCHEMA_URL;
7
+ version: 1;
8
+ build?: {
9
+ installRoot?: string;
10
+ installCommand?: string;
11
+ command?: string;
12
+ output?: string;
13
+ timeoutSeconds?: number;
14
+ };
15
+ serve?: {
16
+ index?: string | false;
17
+ spaFallback?: string;
18
+ cleanUrls?: boolean;
19
+ directoryListing?: boolean;
20
+ };
21
+ metadata?: {
22
+ title?: string;
23
+ description?: string;
24
+ image?: string;
25
+ };
26
+ substitute?: {
27
+ files: string[];
28
+ };
29
+ };
30
+ export type EffectiveConfigV1 = {
31
+ version: 1;
32
+ build?: NonNullable<SfConfigV1["build"]> & {
33
+ installRoot: string;
34
+ timeoutSeconds: number;
35
+ };
36
+ serve: {
37
+ index: string | false;
38
+ spaFallback?: string;
39
+ cleanUrls: boolean;
40
+ directoryListing: boolean;
41
+ };
42
+ metadata?: SfConfigV1["metadata"];
43
+ substitute?: SfConfigV1["substitute"];
44
+ };
45
+ export type SfConfigV1Issue = {
46
+ code: "config_alias" | "config_conflict" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "serve_index_required" | "template_syntax_retired";
47
+ severity: "error" | "warning";
48
+ path: string;
49
+ line: number;
50
+ column: number;
51
+ message: string;
52
+ suggestion?: string;
53
+ };
54
+ export type SfConfigV1Location = Pick<SfConfigV1Issue, "line" | "column">;
55
+ type SfConfigV1CompileResultBase = {
56
+ issues: SfConfigV1Issue[];
57
+ locations: ReadonlyMap<string, SfConfigV1Location>;
58
+ };
59
+ export type SfConfigV1CompileResult = SfConfigV1CompileResultBase & ({
60
+ success: true;
61
+ config: SfConfigV1;
62
+ effective: EffectiveConfigV1;
63
+ } | {
64
+ success: false;
65
+ config: null;
66
+ effective: null;
67
+ });
68
+ export type CompileSfConfigV1Options = {
69
+ artifactPaths?: readonly string[];
70
+ templateSources?: readonly {
71
+ path: string;
72
+ source: string;
73
+ }[];
74
+ };
75
+ export {};
@@ -0,0 +1,6 @@
1
+ import { BRAND } from "../brand.js";
2
+ import { SPACE_CONFIG_ACCEPTED_FILES, SPACE_CONFIG_CANONICAL_FILE, } from "./space-config.js";
3
+ export const SF_CONFIG_V1_CANONICAL_FILE = SPACE_CONFIG_CANONICAL_FILE;
4
+ export const SF_CONFIG_V1_FILES = SPACE_CONFIG_ACCEPTED_FILES;
5
+ /** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
6
+ export const SF_CONFIG_V1_SCHEMA_URL = `${BRAND.websiteOrigin}/schemas/sf.v1.json`;
@@ -5,6 +5,19 @@ export declare const SiteCapacitySchema: z.ZodObject<{
5
5
  storageBytes: z.ZodOptional<z.ZodNumber>;
6
6
  }, z.core.$strip>;
7
7
  export type SiteCapacity = z.infer<typeof SiteCapacitySchema>;
8
+ export declare const SitePressureSchema: z.ZodObject<{
9
+ ewmaLimitedPct: z.ZodOptional<z.ZodNumber>;
10
+ ewma429: z.ZodOptional<z.ZodNumber>;
11
+ ewma429PerMin: z.ZodOptional<z.ZodNumber>;
12
+ ewmaWorkersMax: z.ZodOptional<z.ZodNumber>;
13
+ ewmaCpuPct: z.ZodOptional<z.ZodNumber>;
14
+ lastSampleAt: z.ZodOptional<z.ZodString>;
15
+ consecutivePressured: z.ZodOptional<z.ZodNumber>;
16
+ consecutiveClean: z.ZodOptional<z.ZodNumber>;
17
+ pressureHoldUntil: z.ZodOptional<z.ZodString>;
18
+ lastBulkLaneActivityAt: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$loose>;
20
+ export type SitePressure = z.infer<typeof SitePressureSchema>;
8
21
  export declare const SiteSchema: z.ZodObject<{
9
22
  id: z.ZodString;
10
23
  tenantId: z.ZodString;
@@ -272,8 +285,10 @@ export declare const SuperadminSiteSchema: z.ZodObject<{
272
285
  createdAt: z.ZodString;
273
286
  updatedAt: z.ZodString;
274
287
  class: z.ZodEnum<{
275
- anonymous_pool: "anonymous_pool";
288
+ shared: "shared";
289
+ dedicated: "dedicated";
276
290
  shared_org: "shared_org";
291
+ anonymous_pool: "anonymous_pool";
277
292
  dedicated_space: "dedicated_space";
278
293
  }>;
279
294
  providerClientId: z.ZodNullable<z.ZodString>;
@@ -359,8 +374,10 @@ export declare const SuperadminSiteListSchema: z.ZodObject<{
359
374
  createdAt: z.ZodString;
360
375
  updatedAt: z.ZodString;
361
376
  class: z.ZodEnum<{
362
- anonymous_pool: "anonymous_pool";
377
+ shared: "shared";
378
+ dedicated: "dedicated";
363
379
  shared_org: "shared_org";
380
+ anonymous_pool: "anonymous_pool";
364
381
  dedicated_space: "dedicated_space";
365
382
  }>;
366
383
  providerClientId: z.ZodNullable<z.ZodString>;
@@ -26,6 +26,27 @@ export const SiteCapacitySchema = z
26
26
  .describe("Storage budget for the site in bytes."),
27
27
  })
28
28
  .describe("Capacity accounting for shared-pool sites.");
29
+ export const SitePressureSchema = z
30
+ .object({
31
+ ewmaLimitedPct: z.number().nonnegative().optional(),
32
+ ewma429: z.number().nonnegative().optional(),
33
+ ewma429PerMin: z.number().nonnegative().optional(),
34
+ ewmaWorkersMax: z.number().nonnegative().optional(),
35
+ ewmaCpuPct: z.number().nonnegative().optional(),
36
+ lastSampleAt: z.string().datetime().optional(),
37
+ consecutivePressured: z.number().int().nonnegative().optional(),
38
+ consecutiveClean: z.number().int().nonnegative().optional(),
39
+ // Provenance stamp for the sampler's automatic hold: set on trip to the
40
+ // exact hold instant it wrote, so release only clears holds the pressure
41
+ // pipeline itself set — never an operator-set placement hold.
42
+ pressureHoldUntil: z.string().datetime().optional(),
43
+ // Last time a bulk-lane engine job on this site reported activity via the
44
+ // job callbacks (runtime/callback-events.ts); the sampler discounts the
45
+ // CPU signal while this is within the sampling window.
46
+ lastBulkLaneActivityAt: z.string().datetime().optional(),
47
+ })
48
+ .passthrough()
49
+ .describe("Placement pressure signals computed outside the request path.");
29
50
  // A Site is THE placement unit (internal-docs/platform.md "Site", `site_`):
30
51
  // one WP.Cloud site per row. Spaces are placed onto a site via `space.siteId`.
31
52
  // Provider linkage (`providerClientId`, `providerRef`) is operator-only and