@spacefast/common 0.0.26 → 0.2.2

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 (302) hide show
  1. package/dist/agents/connect-targets.d.ts +6 -146
  2. package/dist/agents/connect-targets.js +63 -295
  3. package/dist/agents/private-key-oauth.d.ts +31 -1
  4. package/dist/agents/private-key-oauth.js +124 -33
  5. package/dist/agents/registry/core.d.ts +292 -0
  6. package/dist/agents/registry/core.js +1388 -0
  7. package/dist/agents/registry/deeplink-probes.d.ts +23 -0
  8. package/dist/agents/registry/deeplink-probes.js +18 -0
  9. package/dist/agents/registry/node.d.ts +56 -0
  10. package/dist/agents/registry/node.js +339 -0
  11. package/dist/brand-assets-build.js +1 -2
  12. package/dist/brand-assets.js +4 -7
  13. package/dist/brand.d.ts +17 -0
  14. package/dist/brand.js +24 -4
  15. package/dist/config/domains.d.ts +55 -28
  16. package/dist/config/domains.js +85 -41
  17. package/dist/config/index.js +1 -2
  18. package/dist/contracts/abuse.js +9 -24
  19. package/dist/contracts/access-profiles.d.ts +86 -0
  20. package/dist/contracts/access-profiles.js +89 -0
  21. package/dist/contracts/access.d.ts +21 -27
  22. package/dist/contracts/access.js +33 -64
  23. package/dist/contracts/activity.d.ts +18 -1
  24. package/dist/contracts/activity.js +70 -26
  25. package/dist/contracts/analytics.js +8 -10
  26. package/dist/contracts/api-keys.d.ts +77 -52
  27. package/dist/contracts/api-keys.js +44 -24
  28. package/dist/contracts/application-journal.d.ts +216 -0
  29. package/dist/contracts/application-journal.js +167 -0
  30. package/dist/contracts/auth.d.ts +90 -17
  31. package/dist/contracts/auth.js +86 -17
  32. package/dist/contracts/beta.d.ts +9 -4
  33. package/dist/contracts/beta.js +20 -16
  34. package/dist/contracts/billing.js +7 -11
  35. package/dist/contracts/bootstrap.d.ts +791 -0
  36. package/dist/contracts/bootstrap.js +51 -0
  37. package/dist/contracts/builds.d.ts +192 -7
  38. package/dist/contracts/builds.js +84 -21
  39. package/dist/contracts/channels.d.ts +43 -0
  40. package/dist/contracts/channels.js +25 -9
  41. package/dist/contracts/cli.d.ts +7 -0
  42. package/dist/contracts/cli.js +6 -0
  43. package/dist/contracts/collab-public.d.ts +1 -1
  44. package/dist/contracts/collab-public.js +5 -8
  45. package/dist/contracts/comments.d.ts +45 -35
  46. package/dist/contracts/comments.js +107 -77
  47. package/dist/contracts/commerce.d.ts +165 -0
  48. package/dist/contracts/commerce.js +146 -0
  49. package/dist/contracts/common.d.ts +3 -3
  50. package/dist/contracts/common.js +18 -29
  51. package/dist/contracts/content-contract-verification.d.ts +521 -0
  52. package/dist/contracts/content-contract-verification.js +320 -0
  53. package/dist/contracts/content-platform-fixture.d.ts +1278 -0
  54. package/dist/contracts/content-platform-fixture.js +44 -0
  55. package/dist/contracts/content-program.d.ts +994 -0
  56. package/dist/contracts/content-program.js +658 -0
  57. package/dist/contracts/content-sync.d.ts +290 -0
  58. package/dist/contracts/content-sync.js +167 -0
  59. package/dist/contracts/content.d.ts +432 -0
  60. package/dist/contracts/content.js +303 -0
  61. package/dist/contracts/continuation.d.ts +17 -1
  62. package/dist/contracts/continuation.js +23 -23
  63. package/dist/contracts/countries.js +3 -4
  64. package/dist/contracts/crons.d.ts +17 -0
  65. package/dist/contracts/crons.js +33 -15
  66. package/dist/contracts/dashboard-prefs.d.ts +56 -0
  67. package/dist/contracts/dashboard-prefs.js +51 -0
  68. package/dist/contracts/device-auth.d.ts +234 -37
  69. package/dist/contracts/device-auth.js +267 -53
  70. package/dist/contracts/docs.d.ts +6 -10
  71. package/dist/contracts/docs.js +5 -13
  72. package/dist/contracts/domains.d.ts +499 -102
  73. package/dist/contracts/domains.js +169 -58
  74. package/dist/contracts/email-preferences.d.ts +3 -3
  75. package/dist/contracts/email-preferences.js +6 -7
  76. package/dist/contracts/enums.d.ts +26 -26
  77. package/dist/contracts/enums.js +61 -54
  78. package/dist/contracts/error-code-meta.d.ts +273 -7
  79. package/dist/contracts/error-code-meta.js +81 -5
  80. package/dist/contracts/error-codes.d.ts +5 -5
  81. package/dist/contracts/error-codes.js +79 -16
  82. package/dist/contracts/events.d.ts +100 -20
  83. package/dist/contracts/events.js +107 -20
  84. package/dist/contracts/execution.d.ts +47 -66
  85. package/dist/contracts/execution.js +51 -64
  86. package/dist/contracts/feature-lifecycle.d.ts +70 -14
  87. package/dist/contracts/feature-lifecycle.js +86 -15
  88. package/dist/contracts/features.d.ts +100 -37
  89. package/dist/contracts/features.js +21 -27
  90. package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
  91. package/dist/contracts/frame-session.d.ts +192 -0
  92. package/dist/contracts/frame-session.js +164 -0
  93. package/dist/contracts/functions.d.ts +218 -211
  94. package/dist/contracts/functions.js +273 -260
  95. package/dist/contracts/grant-copy.d.ts +43 -0
  96. package/dist/contracts/grant-copy.js +44 -0
  97. package/dist/contracts/grants.d.ts +64 -56
  98. package/dist/contracts/grants.js +124 -23
  99. package/dist/contracts/ids.d.ts +4 -1
  100. package/dist/contracts/ids.js +4 -1
  101. package/dist/contracts/internal.d.ts +5 -4
  102. package/dist/contracts/internal.js +12 -3
  103. package/dist/contracts/mcp.d.ts +17 -0
  104. package/dist/contracts/mcp.js +23 -0
  105. package/dist/contracts/me.d.ts +6 -1
  106. package/dist/contracts/me.js +12 -6
  107. package/dist/contracts/notifications.d.ts +27 -29
  108. package/dist/contracts/notifications.js +9 -4
  109. package/dist/contracts/oauth-resources.d.ts +121 -10
  110. package/dist/contracts/oauth-resources.js +130 -11
  111. package/dist/contracts/oauth-scope-actions.d.ts +90 -0
  112. package/dist/contracts/oauth-scope-actions.js +126 -0
  113. package/dist/contracts/operations.d.ts +27 -4
  114. package/dist/contracts/operations.js +11 -5
  115. package/dist/contracts/pages.d.ts +29 -5
  116. package/dist/contracts/pages.js +22 -5
  117. package/dist/contracts/partner-notifications.d.ts +3 -0
  118. package/dist/contracts/partner-notifications.js +65 -0
  119. package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
  120. package/dist/contracts/{platform.js → partner.js} +27 -40
  121. package/dist/contracts/plan-policy.d.ts +1 -1
  122. package/dist/contracts/principal-assertion.d.ts +43 -0
  123. package/dist/contracts/principal-assertion.js +67 -0
  124. package/dist/contracts/principals.d.ts +73 -0
  125. package/dist/contracts/principals.js +59 -0
  126. package/dist/contracts/privacy.d.ts +11 -0
  127. package/dist/contracts/privacy.js +17 -0
  128. package/dist/contracts/problem-document.js +3 -4
  129. package/dist/contracts/publish-archive.d.ts +116 -18
  130. package/dist/contracts/publish-archive.js +6 -3
  131. package/dist/contracts/push-new.d.ts +4 -4
  132. package/dist/contracts/quotas.js +3 -3
  133. package/dist/contracts/realtime.d.ts +52 -0
  134. package/dist/contracts/realtime.js +54 -0
  135. package/dist/contracts/repository-connections.d.ts +1 -1
  136. package/dist/contracts/repository-connections.js +6 -2
  137. package/dist/contracts/resources.d.ts +105 -14
  138. package/dist/contracts/resources.js +145 -21
  139. package/dist/contracts/route-inventory.d.ts +358 -0
  140. package/dist/contracts/route-inventory.js +141 -0
  141. package/dist/contracts/runtime-api.d.ts +112 -35
  142. package/dist/contracts/runtime-api.js +86 -66
  143. package/dist/contracts/runtime-app.d.ts +11 -21
  144. package/dist/contracts/runtime-app.js +39 -24
  145. package/dist/contracts/runtime-components.d.ts +143 -0
  146. package/dist/contracts/runtime-components.js +199 -0
  147. package/dist/contracts/runtime-db.d.ts +45 -19
  148. package/dist/contracts/runtime-db.js +85 -20
  149. package/dist/contracts/runtime-purge.js +3 -5
  150. package/dist/contracts/runtime-services.d.ts +43 -75
  151. package/dist/contracts/runtime-services.js +29 -49
  152. package/dist/contracts/runtime-storage.d.ts +14 -14
  153. package/dist/contracts/runtime-storage.js +28 -13
  154. package/dist/contracts/sf-config-v1.d.ts +14 -18
  155. package/dist/contracts/slugs.js +13 -4
  156. package/dist/contracts/space-config.d.ts +235 -28
  157. package/dist/contracts/space-config.js +246 -91
  158. package/dist/contracts/spaces.d.ts +360 -255
  159. package/dist/contracts/spaces.js +190 -122
  160. package/dist/contracts/superadmin-activity.d.ts +3 -43
  161. package/dist/contracts/superadmin-activity.js +6 -30
  162. package/dist/contracts/superadmin-emails.d.ts +1 -0
  163. package/dist/contracts/superadmin-emails.js +17 -1
  164. package/dist/contracts/superadmin-runtime.d.ts +199 -0
  165. package/dist/contracts/superadmin-runtime.js +141 -0
  166. package/dist/contracts/superadmin-search.d.ts +22 -2
  167. package/dist/contracts/superadmin-search.js +14 -6
  168. package/dist/contracts/superadmin-spaces.d.ts +435 -186
  169. package/dist/contracts/superadmin-spaces.js +131 -25
  170. package/dist/contracts/superadmin-teams.d.ts +3 -0
  171. package/dist/contracts/superadmin-teams.js +1 -2
  172. package/dist/contracts/superadmin-tenants.d.ts +627 -6
  173. package/dist/contracts/superadmin-tenants.js +32 -7
  174. package/dist/contracts/superadmin.d.ts +98 -16
  175. package/dist/contracts/superadmin.js +63 -10
  176. package/dist/contracts/tags.d.ts +85 -58
  177. package/dist/contracts/tags.js +44 -34
  178. package/dist/contracts/teams.d.ts +72 -9
  179. package/dist/contracts/teams.js +84 -25
  180. package/dist/contracts/tenants.d.ts +135 -0
  181. package/dist/contracts/tenants.js +120 -0
  182. package/dist/contracts/test-triggers.d.ts +70 -0
  183. package/dist/contracts/test-triggers.js +116 -0
  184. package/dist/contracts/theme-json.js +3 -8
  185. package/dist/contracts/transfers.d.ts +1 -0
  186. package/dist/contracts/transfers.js +1 -0
  187. package/dist/contracts/usage.d.ts +209 -0
  188. package/dist/contracts/usage.js +124 -12
  189. package/dist/contracts/variables.d.ts +2 -2
  190. package/dist/contracts/variables.js +9 -13
  191. package/dist/contracts/webhooks.d.ts +13 -5
  192. package/dist/contracts/webhooks.js +3 -1
  193. package/dist/contracts/zero.d.ts +57 -64
  194. package/dist/contracts/zero.js +68 -66
  195. package/dist/dashboard-paths/index.d.ts +24 -21
  196. package/dist/dashboard-paths/index.js +35 -47
  197. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
  198. package/dist/dashboard-paths/route-reservations.generated.js +36 -0
  199. package/dist/docs/agent-arrival.d.ts +92 -0
  200. package/dist/docs/agent-arrival.js +227 -0
  201. package/dist/docs/agent-output-policy.d.ts +6 -0
  202. package/dist/docs/agent-output-policy.js +22 -0
  203. package/dist/docs/agent-prose.d.ts +11 -17
  204. package/dist/docs/agent-prose.js +62 -37
  205. package/dist/docs/agent-setup.d.ts +72 -41
  206. package/dist/docs/agent-setup.js +336 -436
  207. package/dist/docs/catalog.d.ts +147 -89
  208. package/dist/docs/catalog.js +157 -42
  209. package/dist/docs/error-docs.d.ts +2102 -1
  210. package/dist/docs/error-docs.js +285 -16
  211. package/dist/docs/index-build.d.ts +0 -1
  212. package/dist/docs/index-build.js +2 -3
  213. package/dist/docs/page-context-prompt.d.ts +77 -0
  214. package/dist/docs/page-context-prompt.js +131 -0
  215. package/dist/docs/reference-urls.d.ts +46 -0
  216. package/dist/docs/reference-urls.js +79 -0
  217. package/dist/docs/search.d.ts +6 -8
  218. package/dist/docs/search.js +10 -13
  219. package/dist/docs/skill-distribution.d.ts +4 -1
  220. package/dist/docs/skill-distribution.js +10 -5
  221. package/dist/docs/skills.d.ts +117 -117
  222. package/dist/docs/skills.js +120 -72
  223. package/dist/docs/start-prompts.d.ts +45 -0
  224. package/dist/docs/start-prompts.js +62 -0
  225. package/dist/domain-exploration.js +9 -13
  226. package/dist/og-template.d.ts +56 -0
  227. package/dist/og-template.js +56 -0
  228. package/dist/slug-policy/index.js +5 -11
  229. package/dist/utils/browser-credential.d.ts +13 -6
  230. package/dist/utils/browser-credential.js +14 -7
  231. package/dist/utils/build-settings.d.ts +16 -0
  232. package/dist/utils/build-settings.js +63 -17
  233. package/dist/utils/canonical-json.d.ts +3 -5
  234. package/dist/utils/canonical-json.js +3 -5
  235. package/dist/utils/cast-transport.d.ts +5 -17
  236. package/dist/utils/cast-transport.js +6 -19
  237. package/dist/utils/claim-token.js +1 -2
  238. package/dist/utils/comment-avatars.js +4 -6
  239. package/dist/utils/concurrency.js +2 -3
  240. package/dist/utils/content-type.d.ts +7 -6
  241. package/dist/utils/content-type.js +73 -51
  242. package/dist/utils/credential-policy.d.ts +50 -6
  243. package/dist/utils/credential-policy.js +123 -57
  244. package/dist/utils/egress-policy.fixtures.json +1 -1
  245. package/dist/utils/generate-space-name.d.ts +3 -8
  246. package/dist/utils/generate-space-name.js +3 -8
  247. package/dist/utils/grants.d.ts +0 -1
  248. package/dist/utils/grants.js +4 -7
  249. package/dist/utils/gravatar.d.ts +2 -4
  250. package/dist/utils/gravatar.js +6 -12
  251. package/dist/utils/id-hints.js +14 -23
  252. package/dist/utils/idempotency.d.ts +3 -3
  253. package/dist/utils/idempotency.js +6 -7
  254. package/dist/utils/local-space-state.d.ts +15 -15
  255. package/dist/utils/local-space-state.js +34 -23
  256. package/dist/utils/oauth-signed-query.d.ts +3 -5
  257. package/dist/utils/oauth-signed-query.js +6 -9
  258. package/dist/utils/one-shot-replay.d.ts +3 -5
  259. package/dist/utils/one-shot-replay.js +3 -5
  260. package/dist/utils/page-colors.d.ts +4 -10
  261. package/dist/utils/page-colors.js +11 -35
  262. package/dist/utils/page-fonts.js +6 -11
  263. package/dist/utils/page-preview.d.ts +0 -1
  264. package/dist/utils/page-preview.js +0 -1
  265. package/dist/utils/pages.d.ts +22 -11
  266. package/dist/utils/pages.js +70 -30
  267. package/dist/utils/privacy-regions.d.ts +19 -0
  268. package/dist/utils/privacy-regions.js +91 -0
  269. package/dist/utils/publish-form-data.d.ts +4 -5
  270. package/dist/utils/publish-form-data.js +2 -3
  271. package/dist/utils/publish-policy.d.ts +10 -23
  272. package/dist/utils/publish-policy.js +63 -116
  273. package/dist/utils/query-client.d.ts +2 -0
  274. package/dist/utils/query-client.js +10 -1
  275. package/dist/utils/runtime-paths.d.ts +4 -4
  276. package/dist/utils/runtime-paths.js +6 -8
  277. package/dist/utils/runtime-upload.d.ts +4 -0
  278. package/dist/utils/runtime-upload.js +5 -0
  279. package/dist/utils/secure-local-file.d.ts +3 -3
  280. package/dist/utils/secure-local-file.js +18 -24
  281. package/dist/utils/space-config.d.ts +11 -14
  282. package/dist/utils/space-config.js +10 -16
  283. package/dist/utils/static-runtime-policy.d.ts +5 -8
  284. package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
  285. package/dist/utils/static-runtime-policy.generated.js +70 -0
  286. package/dist/utils/static-runtime-policy.js +17 -84
  287. package/dist/utils/storage-policy.js +1 -2
  288. package/dist/utils/upload-session.js +8 -14
  289. package/dist/utils/version-path.js +11 -19
  290. package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
  291. package/dist/utils/wpcom-auth-redirects.js +1 -4
  292. package/dist/vocabulary.d.ts +7 -7
  293. package/dist/vocabulary.js +30 -16
  294. package/package.json +14 -2
  295. package/dist/agents/client-registry.d.ts +0 -22
  296. package/dist/agents/client-registry.js +0 -41
  297. package/dist/docs/agent-handoff-document.d.ts +0 -15
  298. package/dist/docs/agent-handoff-document.js +0 -180
  299. package/dist/docs/agent-solutions.d.ts +0 -110
  300. package/dist/docs/agent-solutions.js +0 -183
  301. package/dist/utils/query-keys.d.ts +0 -84
  302. package/dist/utils/query-keys.js +0 -108
@@ -1,12 +1,21 @@
1
1
  import { z } from "zod";
2
- // Channels READ surface (the platform spec "Channels"): a read-only
3
- // projection over the existing `channels` table and the `channel.promoted`
4
- // activity log. No writes, no new storage — promotion stays owned by the
5
- // publish/version lifecycle. Additive only.
6
- // One row of the channel list: where each named channel points right now.
2
+ // Channels READ surface (the platform spec "Channels"): a projection over the
3
+ // `channels` table and the `channel.promoted` activity log. No writes:
4
+ // promotion stays owned by the publish/version lifecycle.
5
+ // How a channel pointer moved: a fresh publish going live, a forward promote,
6
+ // or a rollback to an older version. Recorded on the `channel.promoted` event
7
+ // at write time; null on events that predate kind recording.
8
+ export const channelChangeKindSchema = z.enum(["publish", "promote", "rollback"]);
9
+ // The channel's most recent pointer move, straight from the promotion log.
10
+ export const channelLastChangeSchema = z.object({
11
+ kind: channelChangeKindSchema
12
+ .nullable()
13
+ .describe("How the pointer moved, or null when the log entry predates kind recording."),
14
+ at: z.string().datetime().describe("Instant the pointer moved, from the promotion log."),
15
+ });
7
16
  // `currentVersionId` is the channel's version pointer (`channels.versionId`).
8
17
  export const channelListItemSchema = z.object({
9
- name: z.string().describe("Channel name; `live` is the default channel."),
18
+ name: z.string().describe("Channel name; `live` is the default."),
10
19
  currentVersionId: z
11
20
  .string()
12
21
  .nullable()
@@ -22,10 +31,13 @@ export const channelListItemSchema = z.object({
22
31
  .optional()
23
32
  .describe("Last version this channel served before the current pointer (rollback target)."),
24
33
  updatedAt: z.string().datetime().describe("Instant when this channel pointer last moved."),
34
+ lastChange: channelLastChangeSchema
35
+ .nullable()
36
+ .optional()
37
+ .describe("The most recent pointer move from the promotion log, or null when none exists."),
25
38
  });
26
39
  // One entry of a channel's promotion history (the deploy log): a single
27
- // `channel.promoted` event, newest first. This is the audit trail of every
28
- // pointer move on the channel.
40
+ // `channel.promoted` event, newest first.
29
41
  export const channelHistoryEntrySchema = z.object({
30
42
  versionId: z.string().describe("Version the channel was promoted to."),
31
43
  channel: z.string().describe("Channel that moved."),
@@ -35,11 +47,15 @@ export const channelHistoryEntrySchema = z.object({
35
47
  .optional()
36
48
  .describe("Version the channel served immediately before this promotion."),
37
49
  actorType: z
38
- .enum(["user", "api_key", "oauth_client", "anonymous_claim", "system"])
50
+ .enum(["user", "api_key", "partner_token", "oauth_client", "anonymous_claim", "system"])
39
51
  .nullable()
40
52
  .optional()
41
53
  .describe("Kind of actor that performed the promotion."),
42
54
  actorId: z.string().nullable().optional().describe("Identifier of the promoting actor."),
55
+ kind: channelChangeKindSchema
56
+ .nullable()
57
+ .optional()
58
+ .describe("How the pointer moved, or null when the entry predates kind recording."),
43
59
  at: z.string().datetime().describe("Instant when the promotion happened."),
44
60
  });
45
61
  export const channelListResponseSchema = z.object({
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  export declare const CLI_EXIT_CODES: {
2
3
  readonly ok: 0;
3
4
  readonly validation: 2;
@@ -8,3 +9,9 @@ export declare const CLI_EXIT_CODES: {
8
9
  readonly timeout: 50;
9
10
  readonly unknown: 1;
10
11
  };
12
+ export declare const cliWarningSchema: z.ZodObject<{
13
+ code: z.ZodString;
14
+ message: z.ZodString;
15
+ hint: z.ZodString;
16
+ }, z.core.$strip>;
17
+ export type CliWarning = z.infer<typeof cliWarningSchema>;
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  export const CLI_EXIT_CODES = {
2
3
  ok: 0,
3
4
  validation: 2,
@@ -8,3 +9,8 @@ export const CLI_EXIT_CODES = {
8
9
  timeout: 50,
9
10
  unknown: 1,
10
11
  };
12
+ export const cliWarningSchema = z.object({
13
+ code: z.string().min(1),
14
+ message: z.string().min(1),
15
+ hint: z.string().min(1),
16
+ });
@@ -6,7 +6,7 @@ export declare const publicActorSchema: z.ZodObject<{
6
6
  avatar_url: z.ZodOptional<z.ZodString>;
7
7
  }, z.core.$strip>;
8
8
  export type PublicActor = z.infer<typeof publicActorSchema>;
9
- /** A thread as a list renders it the body is an excerpt, the anchor is gone. */
9
+ /** A thread as a list renders it. The body is an excerpt, the anchor is gone. */
10
10
  export declare const publicThreadSchema: z.ZodObject<{
11
11
  id: z.ZodString;
12
12
  path: z.ZodString;
@@ -1,10 +1,7 @@
1
- // The Collab public types — the sanitized shapes every collab surface emits or
2
- // renders (collab-public-api.html §5). One home: the SDK, the overlay, the
3
- // dashboard bridge, the control-plane projection and any published layout all
4
- // import from here. Re-exported nowhere.
5
- //
6
- // Sanitized means sanitized: no emails, no raw authority refs, no anchors. A
7
- // custom layout can restyle everything these carry and escalate nothing.
1
+ // The sanitized shapes every collab surface emits or renders
2
+ // (collab-public-api.html §5). One home, imported directly, re-exported nowhere.
3
+ // Sanitized means no emails, no raw authority refs, no anchors: a custom layout
4
+ // can restyle everything these carry and escalate nothing.
8
5
  import { z } from "zod";
9
6
  /** A person, as everyone else may see them. Identity colors are not themeable. */
10
7
  export const publicActorSchema = z.object({
@@ -12,7 +9,7 @@ export const publicActorSchema = z.object({
12
9
  color: z.string().min(1).max(32),
13
10
  avatar_url: z.string().url().max(2048).optional(),
14
11
  });
15
- /** A thread as a list renders it the body is an excerpt, the anchor is gone. */
12
+ /** A thread as a list renders it. The body is an excerpt, the anchor is gone. */
16
13
  export const publicThreadSchema = z.object({
17
14
  id: z.string().min(1).max(128),
18
15
  path: z.string().min(1).max(2048),
@@ -4,6 +4,17 @@ export declare const commentThreadStatusSchema: z.ZodEnum<{
4
4
  open: "open";
5
5
  archived: "archived";
6
6
  }>;
7
+ /**
8
+ * What a moderator may ask a thread to become. Spam is not a stored status —
9
+ * Cast holds it as the thread's moderation state — so "spam" is a verdict the
10
+ * wire accepts, and reading a thread back always reports `open` or `archived`
11
+ * with `moderationState` beside it.
12
+ */
13
+ export declare const commentThreadStatusPatchSchema: z.ZodEnum<{
14
+ open: "open";
15
+ spam: "spam";
16
+ archived: "archived";
17
+ }>;
7
18
  export declare const COMMENT_SEARCH_QUERY_MAX_LENGTH = 160;
8
19
  export declare function normalizeCommentSearchQuery(value: string | undefined): string | undefined;
9
20
  export declare const COMMENT_PAGE_PATH_MAX_LENGTH = 2048;
@@ -41,12 +52,10 @@ export declare const collaborationPublicProfileSchema: z.ZodObject<{
41
52
  }, z.core.$strict>;
42
53
  export type CollaborationPublicProfile = z.infer<typeof collaborationPublicProfileSchema>;
43
54
  /**
44
- * Where the browser holding this ticket is.
45
- *
46
- * "embed" is a third-party site the owner allowlisted, and it is its own state
47
- * precisely so nothing pretends a foreign origin is a published Spacefast host:
48
- * the room an embed ticket names is origin-scoped, and both the mint and Cast
49
- * refuse the pairing in either direction.
55
+ * Where the browser holding this ticket is. "embed" is a third-party site the
56
+ * owner allowlisted, kept a separate state so no foreign origin passes as a
57
+ * published host: an embed ticket's room is origin-scoped, and both the mint
58
+ * and Cast refuse the pairing in either direction.
50
59
  */
51
60
  export declare const collaborationSurfaceSchema: z.ZodEnum<{
52
61
  preview: "preview";
@@ -63,9 +72,9 @@ export declare const collaborationTicketClaimsSchema: z.ZodObject<{
63
72
  avatar_url: z.ZodNullable<z.ZodURL>;
64
73
  }, z.core.$strict>>;
65
74
  role: z.ZodEnum<{
75
+ editor: "editor";
66
76
  viewer: "viewer";
67
77
  commenter: "commenter";
68
- editor: "editor";
69
78
  manager: "manager";
70
79
  }>;
71
80
  actorKind: z.ZodEnum<{
@@ -97,6 +106,8 @@ export declare const collaborationTicketClaimsSchema: z.ZodObject<{
97
106
  iss: z.ZodLiteral<"spacefast-api">;
98
107
  aud: z.ZodString;
99
108
  }, z.core.$strip>;
109
+ /** Where a team without the collab.comments feature applies for access. */
110
+ export declare const COMMENTS_WAITLIST_URL = "https://spacefast.com/waitlists/collab";
100
111
  export declare const commentsSurfaceSchema: z.ZodEnum<{
101
112
  off: "off";
102
113
  previews: "previews";
@@ -104,13 +115,11 @@ export declare const commentsSurfaceSchema: z.ZodEnum<{
104
115
  }>;
105
116
  export declare const COMMENTS_EMBED_ORIGINS_MAX = 20;
106
117
  /**
107
- * A site the Space owner allows the one-line Collab insert to run on.
108
- *
109
- * Exactly one https origin scheme, host, and port, nothing else. No
110
- * wildcards: on a foreign site this list IS the entitlement, and `*.example.com`
111
- * hands it to every subdomain the site ever loses control of. An off-shape
112
- * value is refused rather than normalized, so what the owner typed and what the
113
- * server matches are the same string.
118
+ * A site the Space owner allows the one-line Collab insert to run on. Exactly
119
+ * one https origin, nothing else: on a foreign site this list IS the
120
+ * entitlement, and `*.example.com` hands it to every subdomain the site ever
121
+ * loses control of. An off-shape value is refused rather than normalized, so
122
+ * the owner's string and the matched string are the same.
114
123
  */
115
124
  export declare const commentsEmbedOriginSchema: z.ZodString;
116
125
  export declare const collaborationSettingsSchema: z.ZodObject<{
@@ -167,11 +176,9 @@ export declare const collaborationUpdateSchema: z.ZodObject<{
167
176
  }, z.core.$strict>;
168
177
  }, z.core.$strip>;
169
178
  /**
170
- * The overlay's whole configuration, in one shape.
171
- *
172
- * Both lanes carry this: the Space's own origins get it from the runtime's
173
- * same-origin exchange, a third-party site fetches it over CORS keyed by
174
- * `data-space`. Only the transport differs — the SDK parses one shape.
179
+ * The overlay's whole configuration. Both lanes carry it: the Space's own
180
+ * origins from the runtime's same-origin exchange, a third-party site over CORS
181
+ * keyed by `data-space`. Only the transport differs.
175
182
  */
176
183
  export declare const collabOverlayConfigSchema: z.ZodObject<{
177
184
  enabled: z.ZodBoolean;
@@ -247,11 +254,9 @@ export declare const realtimeTokenResponseSchema: z.ZodObject<{
247
254
  }, z.core.$strip>;
248
255
  }, z.core.$strip>;
249
256
  /**
250
- * A Space-level fact worth interrupting someone for. It travels as a `notice`
251
- * on the Space's notice room never as an event in a page room because it
252
- * is not conversation content: every open surface needs it regardless of which
253
- * page it happens to be sitting on, including surfaces (the dashboard) that
254
- * are in no page room at all.
257
+ * A Space-level fact worth interrupting someone for. It travels on the Space's
258
+ * notice room, never as a page-room event: every open surface needs it whatever
259
+ * page it is on, including the dashboard, which is in no page room at all.
255
260
  */
256
261
  export declare const noticePublishSchema: z.ZodObject<{
257
262
  versionId: z.ZodOptional<z.ZodString>;
@@ -261,8 +266,8 @@ export declare const noticePublishSchema: z.ZodObject<{
261
266
  level: z.ZodDefault<z.ZodEnum<{
262
267
  info: "info";
263
268
  success: "success";
264
- error: "error";
265
269
  warning: "warning";
270
+ error: "error";
266
271
  }>>;
267
272
  payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
268
273
  }, z.core.$strip>;
@@ -296,14 +301,13 @@ export declare const commentAuthorSchema: z.ZodObject<{
296
301
  }, z.core.$strip>;
297
302
  export declare const commentTargetSchema: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
298
303
  /**
299
- * How many attachments one thread or reply may carry. Mirrors Cast's own
300
- * `@attachment_limit`: Cast is the authority that enforces it on write, this
301
- * bound is what REST readers can rely on.
304
+ * How many attachments one thread or reply may carry. Mirrors Cast's
305
+ * `@attachment_limit`: Cast enforces it on write, this is what REST readers get.
302
306
  */
303
307
  export declare const COMMENT_ATTACHMENT_MAX_COUNT = 10;
304
308
  /**
305
309
  * A pointer to a storage object on the Space's own runtime plus the descriptor
306
- * needed to render it never a URL. Cast stores exactly this (snake_case) under
310
+ * needed to render it, never a URL. Cast stores exactly this (snake_case) under
307
311
  * `metadata.attachments`; the id is a bare 32-hex object id.
308
312
  */
309
313
  export declare const commentAttachmentSchema: z.ZodObject<{
@@ -324,9 +328,8 @@ export declare const commentAttachmentSchema: z.ZodObject<{
324
328
  }, z.core.$strip>>;
325
329
  }, z.core.$strip>;
326
330
  /**
327
- * What a REST reader gets: the stored attachment plus a freshly composed read
328
- * URL. `url` is null when the runtime's revocable read key cannot be resolved
329
- * an honest degraded read rather than a dead link or a dropped attachment.
331
+ * The stored attachment plus a freshly composed read URL. `url` is null when the
332
+ * runtime's revocable read key cannot be resolved.
330
333
  */
331
334
  export declare const commentAttachmentViewSchema: z.ZodObject<{
332
335
  id: z.ZodString;
@@ -490,9 +493,6 @@ export declare const commentListQuerySchema: z.ZodObject<{
490
493
  author: z.ZodOptional<z.ZodString>;
491
494
  unread: z.ZodOptional<z.ZodCodec<z.ZodString, z.ZodBoolean>>;
492
495
  }, z.core.$strip>;
493
- export declare const commentSpamFeedbackSchema: z.ZodDefault<z.ZodObject<{
494
- commentId: z.ZodOptional<z.ZodString>;
495
- }, z.core.$strip>>;
496
496
  export declare const commentCreateSchema: z.ZodObject<{
497
497
  pagePath: z.ZodDefault<z.ZodString>;
498
498
  body: z.ZodString;
@@ -503,11 +503,20 @@ export declare const commentReplySchema: z.ZodObject<{
503
503
  body: z.ZodString;
504
504
  idempotencyKey: z.ZodOptional<z.ZodString>;
505
505
  }, z.core.$strip>;
506
+ export declare const commentReplyResponseSchema: z.ZodObject<{
507
+ status: z.ZodEnum<{
508
+ inserted: "inserted";
509
+ existing: "existing";
510
+ }>;
511
+ comment: z.ZodObject<{}, z.core.$loose>;
512
+ }, z.core.$loose>;
506
513
  export declare const commentPatchSchema: z.ZodObject<{
507
514
  status: z.ZodOptional<z.ZodEnum<{
508
515
  open: "open";
516
+ spam: "spam";
509
517
  archived: "archived";
510
518
  }>>;
519
+ spamCommentId: z.ZodOptional<z.ZodString>;
511
520
  }, z.core.$strip>;
512
521
  export declare const commentExportQuerySchema: z.ZodObject<{
513
522
  format: z.ZodDefault<z.ZodEnum<{
@@ -614,5 +623,6 @@ export type CollaborationUpdate = z.infer<typeof collaborationUpdateSchema>;
614
623
  export type CommentsSurface = z.infer<typeof commentsSurfaceSchema>;
615
624
  export type CollabVersionUrl = z.infer<typeof collabVersionUrlSchema>;
616
625
  export type CommentThread = z.infer<typeof commentThreadSchema>;
626
+ export type CommentThreadStatusPatch = z.infer<typeof commentThreadStatusPatchSchema>;
617
627
  export type CommentAttachment = z.infer<typeof commentAttachmentSchema>;
618
628
  export type CommentAttachmentView = z.infer<typeof commentAttachmentViewSchema>;
@@ -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),