@spacefast/common 0.0.24 → 0.2.1

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 (320) 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.d.ts +6 -146
  7. package/dist/agents/connect-targets.js +63 -295
  8. package/dist/agents/private-key-oauth.d.ts +31 -2
  9. package/dist/agents/private-key-oauth.js +166 -92
  10. package/dist/agents/registry/core.d.ts +292 -0
  11. package/dist/agents/registry/core.js +1388 -0
  12. package/dist/agents/registry/deeplink-probes.d.ts +23 -0
  13. package/dist/agents/registry/deeplink-probes.js +18 -0
  14. package/dist/agents/registry/node.d.ts +56 -0
  15. package/dist/agents/registry/node.js +339 -0
  16. package/dist/brand-assets-build.js +3 -6
  17. package/dist/brand-assets.d.ts +5 -15
  18. package/dist/brand-assets.js +12 -14
  19. package/dist/brand.d.ts +17 -0
  20. package/dist/brand.js +24 -4
  21. package/dist/config/domains.d.ts +79 -12
  22. package/dist/config/domains.js +128 -29
  23. package/dist/config/index.js +1 -2
  24. package/dist/contracts/abuse.js +9 -24
  25. package/dist/contracts/access-profiles.d.ts +86 -0
  26. package/dist/contracts/access-profiles.js +89 -0
  27. package/dist/contracts/access.d.ts +24 -30
  28. package/dist/contracts/access.js +33 -64
  29. package/dist/contracts/activity.d.ts +18 -1
  30. package/dist/contracts/activity.js +72 -26
  31. package/dist/contracts/analytics.js +8 -10
  32. package/dist/contracts/api-keys.d.ts +77 -52
  33. package/dist/contracts/api-keys.js +44 -24
  34. package/dist/contracts/application-journal.d.ts +216 -0
  35. package/dist/contracts/application-journal.js +167 -0
  36. package/dist/contracts/auth.d.ts +90 -17
  37. package/dist/contracts/auth.js +86 -17
  38. package/dist/contracts/beta.d.ts +9 -4
  39. package/dist/contracts/beta.js +20 -16
  40. package/dist/contracts/billing.d.ts +2 -1
  41. package/dist/contracts/billing.js +37 -11
  42. package/dist/contracts/bootstrap.d.ts +791 -0
  43. package/dist/contracts/bootstrap.js +51 -0
  44. package/dist/contracts/builds.d.ts +209 -18
  45. package/dist/contracts/builds.js +93 -27
  46. package/dist/contracts/channels.d.ts +43 -0
  47. package/dist/contracts/channels.js +25 -9
  48. package/dist/contracts/cli.d.ts +7 -0
  49. package/dist/contracts/cli.js +6 -0
  50. package/dist/contracts/collab-public.d.ts +1 -1
  51. package/dist/contracts/collab-public.js +5 -8
  52. package/dist/contracts/comments.d.ts +44 -34
  53. package/dist/contracts/comments.js +107 -77
  54. package/dist/contracts/commerce.d.ts +165 -0
  55. package/dist/contracts/commerce.js +146 -0
  56. package/dist/contracts/common.d.ts +3 -3
  57. package/dist/contracts/common.js +20 -31
  58. package/dist/contracts/content-contract-verification.d.ts +521 -0
  59. package/dist/contracts/content-contract-verification.js +320 -0
  60. package/dist/contracts/content-platform-fixture.d.ts +1278 -0
  61. package/dist/contracts/content-platform-fixture.js +44 -0
  62. package/dist/contracts/content-program.d.ts +994 -0
  63. package/dist/contracts/content-program.js +658 -0
  64. package/dist/contracts/content-sync.d.ts +290 -0
  65. package/dist/contracts/content-sync.js +167 -0
  66. package/dist/contracts/content.d.ts +432 -0
  67. package/dist/contracts/content.js +303 -0
  68. package/dist/contracts/continuation.d.ts +17 -1
  69. package/dist/contracts/continuation.js +23 -23
  70. package/dist/contracts/countries.js +3 -4
  71. package/dist/contracts/crons.d.ts +52 -0
  72. package/dist/contracts/crons.js +60 -0
  73. package/dist/contracts/dashboard-prefs.d.ts +56 -0
  74. package/dist/contracts/dashboard-prefs.js +51 -0
  75. package/dist/contracts/device-auth.d.ts +234 -37
  76. package/dist/contracts/device-auth.js +267 -53
  77. package/dist/contracts/docs.d.ts +1 -5
  78. package/dist/contracts/docs.js +7 -15
  79. package/dist/contracts/domains.d.ts +501 -93
  80. package/dist/contracts/domains.js +193 -55
  81. package/dist/contracts/email-preferences.d.ts +3 -3
  82. package/dist/contracts/email-preferences.js +6 -7
  83. package/dist/contracts/enums.d.ts +27 -26
  84. package/dist/contracts/enums.js +68 -61
  85. package/dist/contracts/error-code-meta.d.ts +283 -7
  86. package/dist/contracts/error-code-meta.js +97 -5
  87. package/dist/contracts/error-codes.d.ts +5 -5
  88. package/dist/contracts/error-codes.js +82 -17
  89. package/dist/contracts/events.d.ts +100 -20
  90. package/dist/contracts/events.js +107 -20
  91. package/dist/contracts/execution.d.ts +48 -64
  92. package/dist/contracts/execution.js +52 -62
  93. package/dist/contracts/feature-lifecycle.d.ts +73 -27
  94. package/dist/contracts/feature-lifecycle.js +86 -26
  95. package/dist/contracts/features.d.ts +68 -19
  96. package/dist/contracts/features.js +42 -41
  97. package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
  98. package/dist/contracts/frame-session.d.ts +192 -0
  99. package/dist/contracts/frame-session.js +164 -0
  100. package/dist/contracts/functions.d.ts +338 -164
  101. package/dist/contracts/functions.js +367 -198
  102. package/dist/contracts/git.d.ts +27 -33
  103. package/dist/contracts/git.js +10 -11
  104. package/dist/contracts/grant-copy.d.ts +43 -0
  105. package/dist/contracts/grant-copy.js +44 -0
  106. package/dist/contracts/grants.d.ts +62 -54
  107. package/dist/contracts/grants.js +124 -23
  108. package/dist/contracts/ids.d.ts +4 -1
  109. package/dist/contracts/ids.js +6 -3
  110. package/dist/contracts/internal.d.ts +8 -18
  111. package/dist/contracts/internal.js +13 -14
  112. package/dist/contracts/mcp.d.ts +28 -0
  113. package/dist/contracts/mcp.js +28 -0
  114. package/dist/contracts/me.d.ts +6 -1
  115. package/dist/contracts/me.js +12 -6
  116. package/dist/contracts/notifications.d.ts +27 -29
  117. package/dist/contracts/notifications.js +9 -4
  118. package/dist/contracts/oauth-resources.d.ts +112 -10
  119. package/dist/contracts/oauth-resources.js +116 -11
  120. package/dist/contracts/oauth-scope-actions.d.ts +90 -0
  121. package/dist/contracts/oauth-scope-actions.js +126 -0
  122. package/dist/contracts/operations.d.ts +27 -4
  123. package/dist/contracts/operations.js +12 -6
  124. package/dist/contracts/pages.d.ts +31 -7
  125. package/dist/contracts/pages.js +22 -5
  126. package/dist/contracts/partner-notifications.d.ts +3 -0
  127. package/dist/contracts/partner-notifications.js +65 -0
  128. package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
  129. package/dist/contracts/{platform.js → partner.js} +27 -40
  130. package/dist/contracts/plan-policy.js +1 -1
  131. package/dist/contracts/principal-assertion.d.ts +43 -0
  132. package/dist/contracts/principal-assertion.js +67 -0
  133. package/dist/contracts/principals.d.ts +73 -0
  134. package/dist/contracts/principals.js +59 -0
  135. package/dist/contracts/privacy.d.ts +11 -0
  136. package/dist/contracts/privacy.js +17 -0
  137. package/dist/contracts/problem-document.js +3 -4
  138. package/dist/contracts/publish-archive.d.ts +269 -161
  139. package/dist/contracts/publish-archive.js +11 -1
  140. package/dist/contracts/push-new.d.ts +8 -8
  141. package/dist/contracts/quotas.js +5 -5
  142. package/dist/contracts/realtime.d.ts +52 -0
  143. package/dist/contracts/realtime.js +54 -0
  144. package/dist/contracts/repository-connections.d.ts +44 -31
  145. package/dist/contracts/repository-connections.js +17 -5
  146. package/dist/contracts/resources.d.ts +105 -14
  147. package/dist/contracts/resources.js +150 -26
  148. package/dist/contracts/route-inventory.d.ts +358 -0
  149. package/dist/contracts/route-inventory.js +141 -0
  150. package/dist/contracts/runtime-api.d.ts +206 -82
  151. package/dist/contracts/runtime-api.js +131 -70
  152. package/dist/contracts/runtime-app.d.ts +13 -23
  153. package/dist/contracts/runtime-app.js +39 -24
  154. package/dist/contracts/runtime-components.d.ts +143 -0
  155. package/dist/contracts/runtime-components.js +199 -0
  156. package/dist/contracts/runtime-db.d.ts +49 -23
  157. package/dist/contracts/runtime-db.js +87 -22
  158. package/dist/contracts/runtime-purge.d.ts +8 -0
  159. package/dist/contracts/runtime-purge.js +5 -0
  160. package/dist/contracts/runtime-services.d.ts +43 -75
  161. package/dist/contracts/runtime-services.js +29 -49
  162. package/dist/contracts/runtime-storage.d.ts +15 -14
  163. package/dist/contracts/runtime-storage.js +30 -14
  164. package/dist/contracts/sf-config-v1.d.ts +48 -14
  165. package/dist/contracts/slugs.js +13 -4
  166. package/dist/contracts/space-config.d.ts +283 -19
  167. package/dist/contracts/space-config.js +430 -80
  168. package/dist/contracts/spaces.d.ts +376 -290
  169. package/dist/contracts/spaces.js +200 -135
  170. package/dist/contracts/superadmin-activity.d.ts +3 -43
  171. package/dist/contracts/superadmin-activity.js +6 -30
  172. package/dist/contracts/superadmin-emails.d.ts +1 -0
  173. package/dist/contracts/superadmin-emails.js +17 -1
  174. package/dist/contracts/superadmin-runtime.d.ts +199 -0
  175. package/dist/contracts/superadmin-runtime.js +141 -0
  176. package/dist/contracts/superadmin-search.d.ts +22 -2
  177. package/dist/contracts/superadmin-search.js +14 -6
  178. package/dist/contracts/superadmin-spaces.d.ts +438 -189
  179. package/dist/contracts/superadmin-spaces.js +131 -25
  180. package/dist/contracts/superadmin-teams.d.ts +5 -2
  181. package/dist/contracts/superadmin-teams.js +1 -2
  182. package/dist/contracts/superadmin-tenants.d.ts +627 -12
  183. package/dist/contracts/superadmin-tenants.js +32 -13
  184. package/dist/contracts/superadmin.d.ts +232 -37
  185. package/dist/contracts/superadmin.js +106 -22
  186. package/dist/contracts/tags.d.ts +85 -58
  187. package/dist/contracts/tags.js +47 -37
  188. package/dist/contracts/teams.d.ts +86 -26
  189. package/dist/contracts/teams.js +90 -31
  190. package/dist/contracts/tenants.d.ts +135 -0
  191. package/dist/contracts/tenants.js +120 -0
  192. package/dist/contracts/test-triggers.d.ts +70 -0
  193. package/dist/contracts/test-triggers.js +116 -0
  194. package/dist/contracts/theme-json.js +3 -8
  195. package/dist/contracts/transfers.d.ts +1 -0
  196. package/dist/contracts/transfers.js +3 -2
  197. package/dist/contracts/usage.d.ts +209 -0
  198. package/dist/contracts/usage.js +124 -12
  199. package/dist/contracts/variables.d.ts +2 -2
  200. package/dist/contracts/variables.js +9 -13
  201. package/dist/contracts/webhooks.d.ts +13 -5
  202. package/dist/contracts/webhooks.js +3 -1
  203. package/dist/contracts/zero.d.ts +72 -81
  204. package/dist/contracts/zero.js +80 -78
  205. package/dist/dashboard-paths/index.d.ts +24 -21
  206. package/dist/dashboard-paths/index.js +35 -47
  207. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
  208. package/dist/dashboard-paths/route-reservations.generated.js +36 -0
  209. package/dist/docs/agent-arrival.d.ts +92 -0
  210. package/dist/docs/agent-arrival.js +227 -0
  211. package/dist/docs/agent-output-policy.d.ts +6 -0
  212. package/dist/docs/agent-output-policy.js +22 -0
  213. package/dist/docs/agent-prose.d.ts +12 -18
  214. package/dist/docs/agent-prose.js +73 -51
  215. package/dist/docs/agent-setup.d.ts +72 -41
  216. package/dist/docs/agent-setup.js +339 -436
  217. package/dist/docs/catalog.d.ts +153 -95
  218. package/dist/docs/catalog.js +163 -48
  219. package/dist/docs/error-docs.d.ts +2098 -1
  220. package/dist/docs/error-docs.js +421 -144
  221. package/dist/docs/index-build.d.ts +0 -1
  222. package/dist/docs/index-build.js +2 -3
  223. package/dist/docs/page-context-prompt.d.ts +77 -0
  224. package/dist/docs/page-context-prompt.js +131 -0
  225. package/dist/docs/reference-urls.d.ts +46 -0
  226. package/dist/docs/reference-urls.js +79 -0
  227. package/dist/docs/search.d.ts +6 -8
  228. package/dist/docs/search.js +10 -13
  229. package/dist/docs/skill-distribution.d.ts +4 -1
  230. package/dist/docs/skill-distribution.js +10 -5
  231. package/dist/docs/skills.d.ts +120 -120
  232. package/dist/docs/skills.js +121 -73
  233. package/dist/docs/start-prompts.d.ts +45 -0
  234. package/dist/docs/start-prompts.js +62 -0
  235. package/dist/domain-exploration.js +9 -13
  236. package/dist/og-template.d.ts +56 -0
  237. package/dist/og-template.js +56 -0
  238. package/dist/slug-policy/index.js +5 -11
  239. package/dist/test-helpers/fetch-stub.js +1 -0
  240. package/dist/utils/browser-credential.d.ts +13 -6
  241. package/dist/utils/browser-credential.js +14 -7
  242. package/dist/utils/build-settings.d.ts +21 -1
  243. package/dist/utils/build-settings.js +133 -15
  244. package/dist/utils/canonical-json.d.ts +3 -5
  245. package/dist/utils/canonical-json.js +4 -5
  246. package/dist/utils/cast-transport.d.ts +5 -17
  247. package/dist/utils/cast-transport.js +6 -19
  248. package/dist/utils/claim-token.js +1 -2
  249. package/dist/utils/comment-avatars.js +4 -6
  250. package/dist/utils/concurrency.js +3 -3
  251. package/dist/utils/content-type.d.ts +7 -6
  252. package/dist/utils/content-type.js +73 -51
  253. package/dist/utils/credential-policy.d.ts +50 -6
  254. package/dist/utils/credential-policy.js +126 -59
  255. package/dist/utils/dns-instructions.js +9 -9
  256. package/dist/utils/egress-policy.fixtures.json +1 -1
  257. package/dist/utils/error-code.js +1 -0
  258. package/dist/utils/generate-space-name.d.ts +3 -8
  259. package/dist/utils/generate-space-name.js +3 -8
  260. package/dist/utils/grant-decision.fixtures.json +2 -2
  261. package/dist/utils/grants.d.ts +0 -1
  262. package/dist/utils/grants.js +7 -8
  263. package/dist/utils/gravatar.d.ts +2 -4
  264. package/dist/utils/gravatar.js +6 -12
  265. package/dist/utils/id-hints.js +14 -23
  266. package/dist/utils/idempotency.d.ts +3 -3
  267. package/dist/utils/idempotency.js +6 -7
  268. package/dist/utils/local-space-state.d.ts +23 -26
  269. package/dist/utils/local-space-state.js +46 -46
  270. package/dist/utils/oauth-signed-query.d.ts +3 -5
  271. package/dist/utils/oauth-signed-query.js +6 -9
  272. package/dist/utils/one-shot-replay.d.ts +7 -6
  273. package/dist/utils/one-shot-replay.js +3 -5
  274. package/dist/utils/page-colors.d.ts +15 -19
  275. package/dist/utils/page-colors.js +23 -45
  276. package/dist/utils/page-fonts.d.ts +1 -1
  277. package/dist/utils/page-fonts.js +8 -20
  278. package/dist/utils/page-preview.d.ts +0 -1
  279. package/dist/utils/page-preview.js +0 -1
  280. package/dist/utils/pages.d.ts +33 -3
  281. package/dist/utils/pages.js +83 -30
  282. package/dist/utils/privacy-regions.d.ts +19 -0
  283. package/dist/utils/privacy-regions.js +91 -0
  284. package/dist/utils/publish-form-data.d.ts +4 -5
  285. package/dist/utils/publish-form-data.js +2 -3
  286. package/dist/utils/publish-policy.d.ts +11 -17
  287. package/dist/utils/publish-policy.fixtures.json +11 -5
  288. package/dist/utils/publish-policy.js +65 -110
  289. package/dist/utils/query-client.d.ts +2 -0
  290. package/dist/utils/query-client.js +10 -1
  291. package/dist/utils/runtime-paths.d.ts +4 -4
  292. package/dist/utils/runtime-paths.js +6 -8
  293. package/dist/utils/runtime-upload.d.ts +9 -0
  294. package/dist/utils/runtime-upload.js +12 -0
  295. package/dist/utils/secure-local-file.d.ts +3 -3
  296. package/dist/utils/secure-local-file.js +23 -40
  297. package/dist/utils/space-config.d.ts +12 -15
  298. package/dist/utils/space-config.js +13 -16
  299. package/dist/utils/static-runtime-policy.d.ts +10 -7
  300. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  301. package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
  302. package/dist/utils/static-runtime-policy.generated.js +70 -0
  303. package/dist/utils/static-runtime-policy.js +31 -132
  304. package/dist/utils/storage-policy.js +1 -2
  305. package/dist/utils/upload-session.d.ts +4 -1
  306. package/dist/utils/upload-session.js +41 -19
  307. package/dist/utils/version-path.js +11 -19
  308. package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
  309. package/dist/utils/wpcom-auth-redirects.js +1 -4
  310. package/dist/vocabulary.d.ts +13 -13
  311. package/dist/vocabulary.js +52 -27
  312. package/package.json +15 -18
  313. package/dist/agents/client-registry.d.ts +0 -22
  314. package/dist/agents/client-registry.js +0 -41
  315. package/dist/docs/agent-handoff-document.d.ts +0 -15
  316. package/dist/docs/agent-handoff-document.js +0 -180
  317. package/dist/docs/agent-solutions.d.ts +0 -110
  318. package/dist/docs/agent-solutions.js +0 -183
  319. package/dist/utils/query-keys.d.ts +0 -84
  320. package/dist/utils/query-keys.js +0 -108
@@ -2,6 +2,13 @@ import { z } from "zod";
2
2
  import { accessRoleSchema, authorityReferenceSchema } from "./access.js";
3
3
  import { CursorPaginationSchema, cursorListQuerySchema } from "./common.js";
4
4
  export const commentThreadStatusSchema = z.enum(["open", "archived"]);
5
+ /**
6
+ * What a moderator may ask a thread to become. Spam is not a stored status —
7
+ * Cast holds it as the thread's moderation state — so "spam" is a verdict the
8
+ * wire accepts, and reading a thread back always reports `open` or `archived`
9
+ * with `moderationState` beside it.
10
+ */
11
+ export const commentThreadStatusPatchSchema = z.enum(["open", "archived", "spam"]);
5
12
  export const COMMENT_SEARCH_QUERY_MAX_LENGTH = 160;
6
13
  export function normalizeCommentSearchQuery(value) {
7
14
  const trimmed = value?.trim();
@@ -32,8 +39,7 @@ export const commentCapabilitiesSchema = z
32
39
  });
33
40
  export const collaborationGuestProjectionSchema = z.object({
34
41
  anonymousId: z.string().min(8).max(160),
35
- // No control or format characters: newlines, bidi overrides, and zero-width
36
- // joiners in a self-asserted display name are only ever spoofing material.
42
+ // Control and format characters in a self-asserted name are spoofing material.
37
43
  name: z
38
44
  .string()
39
45
  .trim()
@@ -50,8 +56,7 @@ export const collaborationGuestProjectionSchema = z.object({
50
56
  emailVerified: z.boolean().default(false),
51
57
  capabilities: commentCapabilitiesSchema,
52
58
  });
53
- // The identity a browser asserts when requesting a guest ticket — the
54
- // self-asserted subset of the guest projection.
59
+ // What a browser may assert about itself when requesting a guest ticket.
55
60
  export const commentsGuestIdentitySchema = collaborationGuestProjectionSchema.pick({
56
61
  anonymousId: true,
57
62
  name: true,
@@ -60,8 +65,7 @@ export const commentsGuestIdentitySchema = collaborationGuestProjectionSchema.pi
60
65
  export function commentCapabilitiesOf(capabilities) {
61
66
  return capabilities.filter((capability) => COMMENT_CAPABILITIES.includes(capability));
62
67
  }
63
- // The only account metadata exposed to Comments clients. Keep this shape
64
- // deliberately smaller than the private account record carried server-side.
68
+ // The only account metadata exposed to Comments clients.
65
69
  export const collaborationPublicProfileSchema = z
66
70
  .object({
67
71
  name: z.string().trim().min(1).max(120).nullable(),
@@ -73,12 +77,10 @@ export const collaborationPublicProfileSchema = z
73
77
  })
74
78
  .strict();
75
79
  /**
76
- * Where the browser holding this ticket is.
77
- *
78
- * "embed" is a third-party site the owner allowlisted, and it is its own state
79
- * precisely so nothing pretends a foreign origin is a published Spacefast host:
80
- * the room an embed ticket names is origin-scoped, and both the mint and Cast
81
- * refuse the pairing in either direction.
80
+ * Where the browser holding this ticket is. "embed" is a third-party site the
81
+ * owner allowlisted, kept a separate state so no foreign origin passes as a
82
+ * published host: an embed ticket's room is origin-scoped, and both the mint
83
+ * and Cast refuse the pairing in either direction.
82
84
  */
83
85
  export const collaborationSurfaceSchema = z.enum(["published", "preview", "embed"]);
84
86
  export const collaborationTicketClaimsSchema = z
@@ -116,11 +118,9 @@ export const collaborationTicketClaimsSchema = z
116
118
  .superRefine((claims, context) => {
117
119
  if (claims.actorKind !== "guest")
118
120
  return;
119
- // A guest ticket names an anonymous browser identity, and one grant always
120
- // admitted it: the guest projection the mint builds carries all five of
121
- // these or it is not a guest at all. Capabilities still come from the union
122
- // of every authority the session holds — the admitting grant describes the
123
- // admission, not the reach.
121
+ // The mint's guest projection carries all five or it is not a guest. The
122
+ // admitting grant describes the admission; capabilities come from the union
123
+ // of every authority the session holds.
124
124
  for (const field of [
125
125
  "anonymousId",
126
126
  "grantId",
@@ -136,9 +136,8 @@ export const collaborationTicketClaimsSchema = z
136
136
  });
137
137
  }
138
138
  }
139
- // Identity never follows from an authority, but the reverse still holds:
140
- // an anonymous principal can only ever have acquired credential-class
141
- // authorities. Account-class references on a guest ticket are a forgery.
139
+ // An anonymous principal can only ever have acquired credential-class
140
+ // authorities, so an account-class reference on a guest ticket is a forgery.
142
141
  for (const [index, authority] of (claims.authorities ?? []).entries()) {
143
142
  if (!authority.startsWith("link:") && !authority.startsWith("password:")) {
144
143
  context.addIssue({
@@ -149,21 +148,20 @@ export const collaborationTicketClaimsSchema = z
149
148
  }
150
149
  }
151
150
  });
152
- // Where comments are reachable. One escalating axis, not two booleans: "off"
153
- // means nowhere, "previews" means the immutable Version hosts only, and
154
- // "everywhere" adds the published Space. Moving between them never requires a
155
- // republish — the always-injected inert tag re-reads the surface through the
156
- // runtime's same-origin Comments config exchange on every load.
151
+ // Where comments are reachable, as one escalating axis: "off" is nowhere,
152
+ // "previews" is the immutable Version hosts only, "everywhere" adds the
153
+ // published Space. Moving between them never requires a republish: the inert
154
+ // tag re-reads the surface through the runtime's config exchange on every load.
155
+ /** Where a team without the collab.comments feature applies for access. */
156
+ export const COMMENTS_WAITLIST_URL = "https://spacefast.com/waitlists/collab";
157
157
  export const commentsSurfaceSchema = z.enum(["off", "previews", "everywhere"]);
158
158
  export const COMMENTS_EMBED_ORIGINS_MAX = 20;
159
159
  /**
160
- * A site the Space owner allows the one-line Collab insert to run on.
161
- *
162
- * Exactly one https origin scheme, host, and port, nothing else. No
163
- * wildcards: on a foreign site this list IS the entitlement, and `*.example.com`
164
- * hands it to every subdomain the site ever loses control of. An off-shape
165
- * value is refused rather than normalized, so what the owner typed and what the
166
- * server matches are the same string.
160
+ * A site the Space owner allows the one-line Collab insert to run on. Exactly
161
+ * one https origin, nothing else: on a foreign site this list IS the
162
+ * entitlement, and `*.example.com` hands it to every subdomain the site ever
163
+ * loses control of. An off-shape value is refused rather than normalized, so
164
+ * the owner's string and the matched string are the same.
167
165
  */
168
166
  export const commentsEmbedOriginSchema = z
169
167
  .string()
@@ -182,9 +180,8 @@ export const collaborationSettingsSchema = z
182
180
  .object({
183
181
  spamFilterEnabled: z.boolean().optional(),
184
182
  surface: commentsSurfaceSchema.default("previews"),
185
- // Non-empty is the embed toggle there is no fourth `surface` state. An
186
- // embed origin sees the Space at its "previews" tier and never the
187
- // published Space itself.
183
+ // Non-empty is the embed toggle; there is no fourth `surface` state. An embed
184
+ // origin sees the Space at its "previews" tier, never the published Space.
188
185
  embedOrigins: z.array(commentsEmbedOriginSchema).max(COMMENTS_EMBED_ORIGINS_MAX).default([]),
189
186
  notificationPreferences: z
190
187
  .object({
@@ -225,11 +222,9 @@ export const collaborationUpdateSchema = z.object({
225
222
  settings: collaborationSettingsPatchSchema,
226
223
  });
227
224
  /**
228
- * The overlay's whole configuration, in one shape.
229
- *
230
- * Both lanes carry this: the Space's own origins get it from the runtime's
231
- * same-origin exchange, a third-party site fetches it over CORS keyed by
232
- * `data-space`. Only the transport differs — the SDK parses one shape.
225
+ * The overlay's whole configuration. Both lanes carry it: the Space's own
226
+ * origins from the runtime's same-origin exchange, a third-party site over CORS
227
+ * keyed by `data-space`. Only the transport differs.
233
228
  */
234
229
  export const collabOverlayConfigSchema = z.object({
235
230
  enabled: z.boolean(),
@@ -252,9 +247,8 @@ export const collabOverlayConfigSchema = z.object({
252
247
  notices: z.boolean(),
253
248
  }),
254
249
  });
255
- // What a third-party page may assert about itself. The display name only — the
256
- // anonymous id is the server's to own, and a browser that could choose one
257
- // could wear another visitor's identity.
250
+ // What a third-party page may assert about itself: the display name only. A
251
+ // browser that could choose its anonymous id could wear another visitor's.
258
252
  export const commentsEmbedIdentitySchema = collaborationGuestProjectionSchema.pick({
259
253
  name: true,
260
254
  namedByUser: true,
@@ -290,9 +284,8 @@ export const commentsTicketResponseSchema = z.object({
290
284
  }),
291
285
  /**
292
286
  * The same session, bound to the Space's notice room. Cast binds a ticket to
293
- * exactly one room, so an overlay that also wants Space-level notices needs
294
- * a second ticket — never a second access decision. Null when this Space has
295
- * notices switched off.
287
+ * exactly one room, so Space-level notices need a second ticket, never a
288
+ * second access decision. Null when this Space has notices switched off.
296
289
  */
297
290
  notice: z
298
291
  .object({
@@ -311,11 +304,9 @@ export const realtimeTokenResponseSchema = z.object({
311
304
  }),
312
305
  });
313
306
  /**
314
- * A Space-level fact worth interrupting someone for. It travels as a `notice`
315
- * on the Space's notice room never as an event in a page room because it
316
- * is not conversation content: every open surface needs it regardless of which
317
- * page it happens to be sitting on, including surfaces (the dashboard) that
318
- * are in no page room at all.
307
+ * A Space-level fact worth interrupting someone for. It travels on the Space's
308
+ * notice room, never as a page-room event: every open surface needs it whatever
309
+ * page it is on, including the dashboard, which is in no page room at all.
319
310
  */
320
311
  export const noticePublishSchema = z.object({
321
312
  versionId: z.string().optional(),
@@ -340,8 +331,7 @@ export const COLLAB_VERSION_URLS_MAX_IDS = 50;
340
331
  export const collabVersionUrlSchema = z.object({
341
332
  id: z.string(),
342
333
  url: z.string(),
343
- // number/createdAt let clients order versions by real recency instead of
344
- // comparing opaque ids.
334
+ // Ordering by real recency, instead of comparing opaque ids.
345
335
  number: z.number().int().nullable(),
346
336
  createdAt: z.string().nullable(),
347
337
  });
@@ -359,14 +349,13 @@ export const commentAuthorSchema = z.object({
359
349
  });
360
350
  export const commentTargetSchema = z.record(z.string(), z.unknown()).nullable();
361
351
  /**
362
- * How many attachments one thread or reply may carry. Mirrors Cast's own
363
- * `@attachment_limit`: Cast is the authority that enforces it on write, this
364
- * bound is what REST readers can rely on.
352
+ * How many attachments one thread or reply may carry. Mirrors Cast's
353
+ * `@attachment_limit`: Cast enforces it on write, this is what REST readers get.
365
354
  */
366
355
  export const COMMENT_ATTACHMENT_MAX_COUNT = 10;
367
356
  /**
368
357
  * A pointer to a storage object on the Space's own runtime plus the descriptor
369
- * needed to render it never a URL. Cast stores exactly this (snake_case) under
358
+ * needed to render it, never a URL. Cast stores exactly this (snake_case) under
370
359
  * `metadata.attachments`; the id is a bare 32-hex object id.
371
360
  */
372
361
  export const commentAttachmentSchema = z.object({
@@ -385,9 +374,8 @@ export const commentAttachmentSchema = z.object({
385
374
  .optional(),
386
375
  });
387
376
  /**
388
- * What a REST reader gets: the stored attachment plus a freshly composed read
389
- * URL. `url` is null when the runtime's revocable read key cannot be resolved
390
- * an honest degraded read rather than a dead link or a dropped attachment.
377
+ * The stored attachment plus a freshly composed read URL. `url` is null when the
378
+ * runtime's revocable read key cannot be resolved.
391
379
  */
392
380
  export const commentAttachmentViewSchema = commentAttachmentSchema.extend({
393
381
  url: z.string().nullable(),
@@ -435,19 +423,36 @@ export const commentThreadSchema = z.object({
435
423
  updatedAt: z.string().datetime().nullable(),
436
424
  });
437
425
  export const commentListQuerySchema = cursorListQuerySchema.extend({
438
- versionId: z.string().optional(),
439
- status: commentThreadStatusSchema.optional(),
440
- filter: z.enum(["open", "archived", "spam"]).optional(),
441
- pagePath: z.string().max(COMMENT_PAGE_PATH_MAX_LENGTH).optional(),
442
- q: z.string().trim().max(COMMENT_SEARCH_QUERY_MAX_LENGTH).optional(),
443
- author: z.string().trim().max(160).optional(),
444
- unread: z.stringbool().optional(),
445
- });
446
- export const commentSpamFeedbackSchema = z
447
- .object({
448
- commentId: z.string().min(1).optional(),
449
- })
450
- .default({});
426
+ versionId: z.string().optional().describe("Return only threads anchored to this version."),
427
+ status: commentThreadStatusSchema
428
+ .optional()
429
+ .describe("Return only threads in this lifecycle state."),
430
+ filter: z
431
+ .enum(["open", "archived", "spam"])
432
+ .optional()
433
+ .describe("Named view. `open` and `archived` select a lifecycle state and win over `status`; `spam` lists the moderation-held threads, which requires comment-moderator access."),
434
+ pagePath: z
435
+ .string()
436
+ .max(COMMENT_PAGE_PATH_MAX_LENGTH)
437
+ .optional()
438
+ .describe("Return only threads anchored to this page path, for example `/pricing`."),
439
+ q: z
440
+ .string()
441
+ .trim()
442
+ .max(COMMENT_SEARCH_QUERY_MAX_LENGTH)
443
+ .optional()
444
+ .describe("Free-text search across thread and comment bodies."),
445
+ author: z
446
+ .string()
447
+ .trim()
448
+ .max(160)
449
+ .optional()
450
+ .describe("Return only threads started by this author name."),
451
+ unread: z
452
+ .stringbool()
453
+ .optional()
454
+ .describe("Return only threads that have unread comments for the caller."),
455
+ });
451
456
  export const commentCreateSchema = z.object({
452
457
  pagePath: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH).default("/"),
453
458
  body: z.string().min(1).max(16_000),
@@ -458,12 +463,37 @@ export const commentReplySchema = z.object({
458
463
  body: z.string().min(1).max(16_000),
459
464
  idempotencyKey: z.string().min(1).max(320).optional(),
460
465
  });
461
- export const commentPatchSchema = z.object({
462
- status: commentThreadStatusSchema.optional(),
466
+ export const commentReplyResponseSchema = z.looseObject({
467
+ status: z.enum(["inserted", "existing"]),
468
+ comment: z.looseObject({}),
469
+ });
470
+ export const commentPatchSchema = z
471
+ .object({
472
+ status: commentThreadStatusPatchSchema.optional(),
473
+ /**
474
+ * The held reply the verdict is about; the thread itself when absent. It
475
+ * only means something next to a spam verdict, so it is refused elsewhere
476
+ * rather than silently dropped.
477
+ */
478
+ spamCommentId: z.string().min(1).optional(),
479
+ })
480
+ .superRefine((patch, context) => {
481
+ if (patch.spamCommentId && patch.status !== "spam" && patch.status !== "open") {
482
+ context.addIssue({
483
+ code: "custom",
484
+ path: ["spamCommentId"],
485
+ message: "spamCommentId requires status open or spam",
486
+ });
487
+ }
463
488
  });
464
489
  export const commentExportQuerySchema = z.object({
465
- format: z.enum(["markdown", "json"]).default("markdown"),
466
- status: commentThreadStatusSchema.optional(),
490
+ format: z
491
+ .enum(["markdown", "json"])
492
+ .default("markdown")
493
+ .describe("Export shape: `markdown` to read, `json` to process."),
494
+ status: commentThreadStatusSchema
495
+ .optional()
496
+ .describe("Export only threads in this lifecycle state."),
467
497
  });
468
498
  export const commentListResponseSchema = z.object({
469
499
  data: z.array(commentThreadSchema),
@@ -0,0 +1,165 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Partner commerce contracts (companion spec `2026-08-23-partner-commerce-design.md`
4
+ * §2 usage, §3 entitlements, and §4 principal lifecycle.
5
+ *
6
+ * This is the single home for the commercial layer: the principal lifecycle
7
+ * status/actor vocabulary, the per-tenant plan catalog declared in the
8
+ * system-space manifest, and the imperative plan-assignment request. The
9
+ * principal directory shape (`principals.ts`) and the manifest schema
10
+ * (`space-config.ts`) both import from here, so the vocabulary has one owner.
11
+ */
12
+ export declare const PRINCIPAL_LIFECYCLE_STATUSES: readonly ["active", "suspended", "closed"];
13
+ export declare const principalLifecycleStatusSchema: z.ZodEnum<{
14
+ active: "active";
15
+ suspended: "suspended";
16
+ closed: "closed";
17
+ }>;
18
+ export type PrincipalLifecycleStatus = z.infer<typeof principalLifecycleStatusSchema>;
19
+ export declare const PRINCIPAL_STATUS_ACTORS: readonly ["partner", "spacefast"];
20
+ export declare const principalStatusActorSchema: z.ZodEnum<{
21
+ spacefast: "spacefast";
22
+ partner: "partner";
23
+ }>;
24
+ export type PrincipalStatusActor = z.infer<typeof principalStatusActorSchema>;
25
+ export declare const PLAN_CATALOG_CAPS: {
26
+ /** Max distinct plans a tenant may declare. */
27
+ readonly plans: 64;
28
+ /** Max plan-name length (also the assigned-plan and defaultPlan bound). */
29
+ readonly planNameChars: 64;
30
+ /** A plan can grant at most every known feature key. */
31
+ readonly features: number;
32
+ };
33
+ export declare const QUOTA_ENFORCEMENT_POLICIES: readonly ["warn", "block"];
34
+ export declare const quotaEnforcementPolicySchema: z.ZodEnum<{
35
+ warn: "warn";
36
+ block: "block";
37
+ }>;
38
+ export type QuotaEnforcementPolicy = z.infer<typeof quotaEnforcementPolicySchema>;
39
+ export declare const planCatalogEntrySchema: z.ZodObject<{
40
+ features: z.ZodArray<z.ZodEnum<{
41
+ zero: "zero";
42
+ "plans.paid.available": "plans.paid.available";
43
+ "anonymous.publishing": "anonymous.publishing";
44
+ "beta.enrollment_gate": "beta.enrollment_gate";
45
+ "domains.search": "domains.search";
46
+ "domains.registration": "domains.registration";
47
+ "domains.dns_management": "domains.dns_management";
48
+ "domains.wpcom_dns": "domains.wpcom_dns";
49
+ "domains.domain_connect": "domains.domain_connect";
50
+ "domains.proxy_bindings": "domains.proxy_bindings";
51
+ "collab.notices": "collab.notices";
52
+ "collab.comments": "collab.comments";
53
+ "content.managed": "content.managed";
54
+ "sites.dedicated_runtime": "sites.dedicated_runtime";
55
+ "collab.drawing": "collab.drawing";
56
+ tags: "tags";
57
+ functions: "functions";
58
+ "spaces.slug_rename": "spaces.slug_rename";
59
+ "pages.templates": "pages.templates";
60
+ "branding.hide": "branding.hide";
61
+ }>>;
62
+ quotas: z.ZodObject<{
63
+ spaces: z.ZodOptional<z.ZodNumber>;
64
+ storageBytes: z.ZodOptional<z.ZodNumber>;
65
+ buildMinutesPerMonth: z.ZodOptional<z.ZodNumber>;
66
+ customDomains: z.ZodOptional<z.ZodNumber>;
67
+ }, z.core.$strict>;
68
+ quotaPolicy: z.ZodOptional<z.ZodEnum<{
69
+ warn: "warn";
70
+ block: "block";
71
+ }>>;
72
+ }, z.core.$strict>;
73
+ export type PlanCatalogEntry = z.infer<typeof planCatalogEntrySchema>;
74
+ export declare const planCatalogSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
75
+ features: z.ZodArray<z.ZodEnum<{
76
+ zero: "zero";
77
+ "plans.paid.available": "plans.paid.available";
78
+ "anonymous.publishing": "anonymous.publishing";
79
+ "beta.enrollment_gate": "beta.enrollment_gate";
80
+ "domains.search": "domains.search";
81
+ "domains.registration": "domains.registration";
82
+ "domains.dns_management": "domains.dns_management";
83
+ "domains.wpcom_dns": "domains.wpcom_dns";
84
+ "domains.domain_connect": "domains.domain_connect";
85
+ "domains.proxy_bindings": "domains.proxy_bindings";
86
+ "collab.notices": "collab.notices";
87
+ "collab.comments": "collab.comments";
88
+ "content.managed": "content.managed";
89
+ "sites.dedicated_runtime": "sites.dedicated_runtime";
90
+ "collab.drawing": "collab.drawing";
91
+ tags: "tags";
92
+ functions: "functions";
93
+ "spaces.slug_rename": "spaces.slug_rename";
94
+ "pages.templates": "pages.templates";
95
+ "branding.hide": "branding.hide";
96
+ }>>;
97
+ quotas: z.ZodObject<{
98
+ spaces: z.ZodOptional<z.ZodNumber>;
99
+ storageBytes: z.ZodOptional<z.ZodNumber>;
100
+ buildMinutesPerMonth: z.ZodOptional<z.ZodNumber>;
101
+ customDomains: z.ZodOptional<z.ZodNumber>;
102
+ }, z.core.$strict>;
103
+ quotaPolicy: z.ZodOptional<z.ZodEnum<{
104
+ warn: "warn";
105
+ block: "block";
106
+ }>>;
107
+ }, z.core.$strict>>;
108
+ export type PlanCatalog = z.infer<typeof planCatalogSchema>;
109
+ export declare const defaultPlanNameSchema: z.ZodString;
110
+ export declare const materializedPlanCatalogSchema: z.ZodObject<{
111
+ plans: z.ZodRecord<z.ZodString, z.ZodObject<{
112
+ features: z.ZodArray<z.ZodEnum<{
113
+ zero: "zero";
114
+ "plans.paid.available": "plans.paid.available";
115
+ "anonymous.publishing": "anonymous.publishing";
116
+ "beta.enrollment_gate": "beta.enrollment_gate";
117
+ "domains.search": "domains.search";
118
+ "domains.registration": "domains.registration";
119
+ "domains.dns_management": "domains.dns_management";
120
+ "domains.wpcom_dns": "domains.wpcom_dns";
121
+ "domains.domain_connect": "domains.domain_connect";
122
+ "domains.proxy_bindings": "domains.proxy_bindings";
123
+ "collab.notices": "collab.notices";
124
+ "collab.comments": "collab.comments";
125
+ "content.managed": "content.managed";
126
+ "sites.dedicated_runtime": "sites.dedicated_runtime";
127
+ "collab.drawing": "collab.drawing";
128
+ tags: "tags";
129
+ functions: "functions";
130
+ "spaces.slug_rename": "spaces.slug_rename";
131
+ "pages.templates": "pages.templates";
132
+ "branding.hide": "branding.hide";
133
+ }>>;
134
+ quotas: z.ZodObject<{
135
+ spaces: z.ZodOptional<z.ZodNumber>;
136
+ storageBytes: z.ZodOptional<z.ZodNumber>;
137
+ buildMinutesPerMonth: z.ZodOptional<z.ZodNumber>;
138
+ customDomains: z.ZodOptional<z.ZodNumber>;
139
+ }, z.core.$strict>;
140
+ quotaPolicy: z.ZodOptional<z.ZodEnum<{
141
+ warn: "warn";
142
+ block: "block";
143
+ }>>;
144
+ }, z.core.$strict>>;
145
+ defaultPlan: z.ZodNullable<z.ZodString>;
146
+ }, z.core.$strict>;
147
+ export type MaterializedPlanCatalog = z.infer<typeof materializedPlanCatalogSchema>;
148
+ export declare const PRINCIPAL_STATUS_REASON_CHARS = 512;
149
+ export declare const principalSuspendSchema: z.ZodObject<{
150
+ reason: z.ZodOptional<z.ZodString>;
151
+ }, z.core.$strict>;
152
+ export type PrincipalSuspend = z.infer<typeof principalSuspendSchema>;
153
+ export declare const principalUnsuspendSchema: z.ZodObject<{
154
+ reason: z.ZodOptional<z.ZodString>;
155
+ }, z.core.$strict>;
156
+ export type PrincipalUnsuspend = z.infer<typeof principalUnsuspendSchema>;
157
+ export declare const principalCloseSchema: z.ZodObject<{
158
+ reason: z.ZodOptional<z.ZodString>;
159
+ force: z.ZodOptional<z.ZodBoolean>;
160
+ }, z.core.$strict>;
161
+ export type PrincipalClose = z.infer<typeof principalCloseSchema>;
162
+ export declare const principalPlanAssignSchema: z.ZodObject<{
163
+ plan: z.ZodString;
164
+ }, z.core.$strict>;
165
+ export type PrincipalPlanAssign = z.infer<typeof principalPlanAssignSchema>;
@@ -0,0 +1,146 @@
1
+ import { z } from "zod";
2
+ import { FEATURE_KEYS, featureKeySchema } from "./features.js";
3
+ /**
4
+ * Partner commerce contracts (companion spec `2026-08-23-partner-commerce-design.md`
5
+ * §2 usage, §3 entitlements, and §4 principal lifecycle.
6
+ *
7
+ * This is the single home for the commercial layer: the principal lifecycle
8
+ * status/actor vocabulary, the per-tenant plan catalog declared in the
9
+ * system-space manifest, and the imperative plan-assignment request. The
10
+ * principal directory shape (`principals.ts`) and the manifest schema
11
+ * (`space-config.ts`) both import from here, so the vocabulary has one owner.
12
+ */
13
+ // Principal lifecycle status (§4). `active` is the default; `suspended` is
14
+ // reversible (spaces serve the suspended page, mutations rejected); `closed` is
15
+ // terminal (retention window then deletion).
16
+ export const PRINCIPAL_LIFECYCLE_STATUSES = ["active", "suspended", "closed"];
17
+ export const principalLifecycleStatusSchema = z
18
+ .enum(PRINCIPAL_LIFECYCLE_STATUSES)
19
+ .describe("Principal lifecycle status: active, suspended (reversible), or closed (terminal).");
20
+ // Who applied the current status. `partner` is the tenant's own management key;
21
+ // `spacefast` is a platform-applied (legal/abuse) action the partner cannot
22
+ // lift. The status surface distinguishes the actor so a Spacefast suspension is
23
+ // visibly unliftable by the partner (§4).
24
+ export const PRINCIPAL_STATUS_ACTORS = ["partner", "spacefast"];
25
+ export const principalStatusActorSchema = z
26
+ .enum(PRINCIPAL_STATUS_ACTORS)
27
+ .describe("Actor that applied the current status: the partner, or Spacefast.");
28
+ // Bounds for the plan catalog. Self-contained (not in SPACE_CONFIG_CAPS) so the
29
+ // manifest schema imports from commerce, never the reverse. A plan may grant at
30
+ // most every known feature; plan names are short arbitrary per-tenant strings.
31
+ export const PLAN_CATALOG_CAPS = {
32
+ /** Max distinct plans a tenant may declare. */
33
+ plans: 64,
34
+ /** Max plan-name length (also the assigned-plan and defaultPlan bound). */
35
+ planNameChars: 64,
36
+ /** A plan can grant at most every known feature key. */
37
+ features: FEATURE_KEYS.length,
38
+ };
39
+ const planNameSchema = z.string().trim().min(1).max(PLAN_CATALOG_CAPS.planNameChars);
40
+ // How a tripped quota is enforced (companion spec §3c). `block` rejects the
41
+ // triggering mutation with a typed problem naming the quota; `warn` records an
42
+ // event and lets the mutation through. Serving is NEVER cut by quota — only by
43
+ // suspension (§4). Omitted = `block`.
44
+ export const QUOTA_ENFORCEMENT_POLICIES = ["warn", "block"];
45
+ export const quotaEnforcementPolicySchema = z
46
+ .enum(QUOTA_ENFORCEMENT_POLICIES)
47
+ .describe("How a tripped quota is enforced: warn (event only) or block (reject).");
48
+ const quotaLimitSchema = z.number().int().safe().nonnegative();
49
+ // One plan's entitlements: feature keys plus mutation-time quotas. Feature
50
+ // names are validated against the live `FEATURE_KEYS` vocabulary.
51
+ export const planCatalogEntrySchema = z
52
+ .object({
53
+ features: z
54
+ .array(featureKeySchema)
55
+ .max(PLAN_CATALOG_CAPS.features)
56
+ .describe("Feature keys this plan grants. Each must be a known Spacefast feature key."),
57
+ quotas: z
58
+ .object({
59
+ spaces: z
60
+ .number()
61
+ .int()
62
+ .nonnegative()
63
+ .optional()
64
+ .describe("Max spaces a principal on this plan may own. Omitted = no space-count cap."),
65
+ storageBytes: quotaLimitSchema
66
+ .optional()
67
+ .describe("Max measured bytes stored by the principal. Omitted = no storage cap."),
68
+ buildMinutesPerMonth: quotaLimitSchema
69
+ .optional()
70
+ .describe("Max build minutes in one UTC month. Omitted = no monthly build cap."),
71
+ customDomains: quotaLimitSchema
72
+ .optional()
73
+ .describe("Max active custom domains. Omitted = no custom-domain cap."),
74
+ })
75
+ .strict()
76
+ .describe("Quotas that the platform checks at the mutation that can exceed each limit."),
77
+ quotaPolicy: quotaEnforcementPolicySchema
78
+ .optional()
79
+ .describe("Enforcement policy for this plan's quotas. Omitted = block."),
80
+ })
81
+ .strict()
82
+ .describe("Entitlements for one plan: granted features and enforced quotas.");
83
+ // The per-tenant plan catalog: plan name → entitlements. Plan NAMES are
84
+ // arbitrary per-tenant strings (the reseller's own vocabulary); feature keys
85
+ // inside each plan are the fixed Spacefast vocabulary.
86
+ export const planCatalogSchema = z
87
+ .record(planNameSchema, planCatalogEntrySchema)
88
+ .refine((plans) => Object.keys(plans).length <= PLAN_CATALOG_CAPS.plans, `at most ${PLAN_CATALOG_CAPS.plans} plans`)
89
+ .describe("Per-tenant plan catalog declared in the system-space manifest.");
90
+ // The plan unassigned principals fall back to. A bare name here; the manifest
91
+ // schema cross-checks it against the declared `plans` keys.
92
+ export const defaultPlanNameSchema = planNameSchema.describe("Name of the plan unassigned principals fall back to. Must be a key in `plans`.");
93
+ // What the plan-catalog materializer freezes onto the tenant: the declared
94
+ // catalog paired with the manifest's `defaultPlan` (null when the manifest
95
+ // declared `plans` without a default). Entitlement resolution reads this one
96
+ // blob — the assigned plan resolves against `plans`, and an unassigned or
97
+ // stale principal falls back to `defaultPlan`.
98
+ export const materializedPlanCatalogSchema = z
99
+ .object({
100
+ plans: planCatalogSchema,
101
+ defaultPlan: defaultPlanNameSchema.nullable(),
102
+ })
103
+ .strict()
104
+ .describe("Materialized per-tenant plan catalog: the declared plans plus the default plan name.");
105
+ // The free-text reason a lifecycle transition records on the principal
106
+ // (`external_principals.status_reason`, bounded by the column). Optional on
107
+ // every transition; surfaced back on the principal so an operator sees why.
108
+ export const PRINCIPAL_STATUS_REASON_CHARS = 512;
109
+ const statusReasonSchema = z
110
+ .string()
111
+ .trim()
112
+ .min(1)
113
+ .max(PRINCIPAL_STATUS_REASON_CHARS)
114
+ .describe("Free-text reason recorded with the status change.");
115
+ // Suspend a principal (§4): reversibly darken its spaces (402 suspended page)
116
+ // and reject its mutations. Idempotent.
117
+ export const principalSuspendSchema = z
118
+ .object({ reason: statusReasonSchema.optional() })
119
+ .strict()
120
+ .describe("Suspend an external principal: its spaces serve the suspended page and writes are blocked.");
121
+ // Lift a suspension (§4). A partner may only lift a suspension it applied; a
122
+ // Spacefast-applied (legal/abuse) suspension is not liftable by the partner.
123
+ export const principalUnsuspendSchema = z
124
+ .object({ reason: statusReasonSchema.optional() })
125
+ .strict()
126
+ .describe("Lift a principal suspension and restore its spaces.");
127
+ // Close a principal (§4): terminal. Refused while the principal still owns
128
+ // spaces unless `force` tombstones them in the same call. Idempotent.
129
+ export const principalCloseSchema = z
130
+ .object({
131
+ reason: statusReasonSchema.optional(),
132
+ force: z
133
+ .boolean()
134
+ .optional()
135
+ .describe("Tombstone the principal's remaining spaces instead of refusing the close."),
136
+ })
137
+ .strict()
138
+ .describe("Close an external principal (terminal). Requires no owned spaces, or `force` to tombstone them.");
139
+ // Imperative plan assignment (§3b): `PUT /v1/principals/{type}/{id}/plan` with a
140
+ // plan name from the live manifest. Runtime state, not manifest config.
141
+ export const principalPlanAssignSchema = z
142
+ .object({
143
+ plan: planNameSchema.describe("Plan name from the live system-space manifest to assign to this principal."),
144
+ })
145
+ .strict()
146
+ .describe("Assign a principal to a plan from the tenant's live plan catalog.");
@@ -16,7 +16,7 @@ export declare const baseDiagnosticSchema: z.ZodObject<{
16
16
  path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
17
17
  provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
18
18
  registrar: "registrar";
19
- wpcloud: "wpcloud";
19
+ infra: "infra";
20
20
  dns: "dns";
21
21
  runtime: "runtime";
22
22
  }>>>;
@@ -183,7 +183,7 @@ export declare const AsyncOperationSchema: z.ZodObject<{
183
183
  path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
184
184
  provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
185
185
  registrar: "registrar";
186
- wpcloud: "wpcloud";
186
+ infra: "infra";
187
187
  dns: "dns";
188
188
  runtime: "runtime";
189
189
  }>>>;
@@ -227,7 +227,7 @@ export declare function mutationEnvelope<T extends z.ZodType>(data: T): z.ZodObj
227
227
  path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
228
228
  provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
229
229
  registrar: "registrar";
230
- wpcloud: "wpcloud";
230
+ infra: "infra";
231
231
  dns: "dns";
232
232
  runtime: "runtime";
233
233
  }>>>;