@spacefast/common 0.0.12 → 0.0.17

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 (189) hide show
  1. package/dist/agents/client-registry.d.ts +22 -0
  2. package/dist/agents/client-registry.js +41 -0
  3. package/dist/agents/connect-targets.d.ts +51 -6
  4. package/dist/agents/connect-targets.js +93 -28
  5. package/dist/brand.d.ts +0 -11
  6. package/dist/brand.js +0 -20
  7. package/dist/config/domains.d.ts +15 -6
  8. package/dist/config/domains.js +24 -10
  9. package/dist/config/postgres-budget.d.ts +3 -0
  10. package/dist/config/postgres-budget.js +6 -1
  11. package/dist/config/postgres-budget.json +2 -1
  12. package/dist/contracts/abuse.js +1 -1
  13. package/dist/contracts/access.d.ts +486 -1196
  14. package/dist/contracts/access.js +323 -1054
  15. package/dist/contracts/activity.d.ts +1 -1
  16. package/dist/contracts/activity.js +11 -15
  17. package/dist/contracts/api-keys.d.ts +16 -0
  18. package/dist/contracts/api-keys.js +11 -9
  19. package/dist/contracts/archives.d.ts +1 -2
  20. package/dist/contracts/archives.js +15 -17
  21. package/dist/contracts/beta.js +1 -1
  22. package/dist/contracts/builds.js +14 -14
  23. package/dist/contracts/channels.js +2 -2
  24. package/dist/contracts/comments.d.ts +143 -99
  25. package/dist/contracts/comments.js +194 -79
  26. package/dist/contracts/common.d.ts +12 -12
  27. package/dist/contracts/common.js +33 -30
  28. package/dist/contracts/continuation.js +5 -5
  29. package/dist/contracts/countries.js +2 -7
  30. package/dist/contracts/data-source-routes.d.ts +20 -0
  31. package/dist/contracts/data-source-routes.js +15 -0
  32. package/dist/contracts/device-auth.d.ts +13 -9
  33. package/dist/contracts/device-auth.js +12 -12
  34. package/dist/contracts/docs.d.ts +10 -10
  35. package/dist/contracts/domains.js +39 -33
  36. package/dist/contracts/enums.d.ts +4 -14
  37. package/dist/contracts/enums.js +3 -10
  38. package/dist/contracts/error-code-meta.d.ts +122 -56
  39. package/dist/contracts/error-code-meta.js +43 -19
  40. package/dist/contracts/error-codes.d.ts +7 -4
  41. package/dist/contracts/error-codes.js +48 -24
  42. package/dist/contracts/events.d.ts +22 -15
  43. package/dist/contracts/events.js +33 -5
  44. package/dist/contracts/execution.d.ts +238 -0
  45. package/dist/contracts/execution.js +309 -0
  46. package/dist/contracts/feature-lifecycle.d.ts +39 -188
  47. package/dist/contracts/feature-lifecycle.js +52 -196
  48. package/dist/contracts/features.d.ts +13 -115
  49. package/dist/contracts/features.js +5 -35
  50. package/dist/contracts/functions.d.ts +597 -0
  51. package/dist/contracts/functions.js +475 -0
  52. package/dist/contracts/grants.d.ts +1175 -0
  53. package/dist/contracts/grants.js +783 -0
  54. package/dist/contracts/ids.d.ts +7 -5
  55. package/dist/contracts/ids.js +7 -7
  56. package/dist/contracts/internal.js +2 -2
  57. package/dist/contracts/mcp.d.ts +17 -556
  58. package/dist/contracts/mcp.js +9 -103
  59. package/dist/contracts/me.js +3 -4
  60. package/dist/contracts/notifications.d.ts +108 -0
  61. package/dist/contracts/notifications.js +54 -0
  62. package/dist/contracts/oauth-resources.d.ts +22 -5
  63. package/dist/contracts/oauth-resources.js +23 -2
  64. package/dist/contracts/operations.d.ts +0 -48
  65. package/dist/contracts/operations.js +0 -19
  66. package/dist/contracts/pages.d.ts +10 -14
  67. package/dist/contracts/pages.js +17 -21
  68. package/dist/contracts/plan-policy.d.ts +1 -8
  69. package/dist/contracts/plan-policy.js +1 -4
  70. package/dist/contracts/platform.d.ts +78 -30
  71. package/dist/contracts/platform.js +69 -20
  72. package/dist/contracts/problem-document.d.ts +14 -0
  73. package/dist/contracts/problem-document.js +35 -0
  74. package/dist/contracts/push-new.d.ts +41 -2
  75. package/dist/contracts/push-new.js +4 -0
  76. package/dist/contracts/quotas.d.ts +0 -1
  77. package/dist/contracts/quotas.js +0 -5
  78. package/dist/contracts/repository-connections.d.ts +1 -1
  79. package/dist/contracts/resources.d.ts +16 -71
  80. package/dist/contracts/resources.js +13 -16
  81. package/dist/contracts/runtime-api.d.ts +666 -303
  82. package/dist/contracts/runtime-api.js +272 -113
  83. package/dist/contracts/runtime-app.d.ts +168 -0
  84. package/dist/contracts/runtime-app.js +42 -0
  85. package/dist/contracts/runtime-db.d.ts +424 -0
  86. package/dist/contracts/runtime-db.js +108 -0
  87. package/dist/contracts/runtime-storage.d.ts +120 -0
  88. package/dist/contracts/runtime-storage.js +40 -0
  89. package/dist/contracts/sf-config-v1.d.ts +54 -1
  90. package/dist/contracts/sf-config-v1.js +2 -2
  91. package/dist/contracts/sites.d.ts +6 -0
  92. package/dist/contracts/sites.js +30 -11
  93. package/dist/contracts/space-config.d.ts +91 -121
  94. package/dist/contracts/space-config.js +464 -42
  95. package/dist/contracts/spaces.d.ts +300 -171
  96. package/dist/contracts/spaces.js +128 -98
  97. package/dist/contracts/superadmin-emails.d.ts +2 -2
  98. package/dist/contracts/superadmin-spaces.d.ts +26 -130
  99. package/dist/contracts/superadmin-spaces.js +22 -0
  100. package/dist/contracts/superadmin-tenants.js +4 -4
  101. package/dist/contracts/superadmin.d.ts +4 -0
  102. package/dist/contracts/superadmin.js +14 -1
  103. package/dist/contracts/tags.d.ts +6 -6
  104. package/dist/contracts/tags.js +1 -1
  105. package/dist/contracts/teams.d.ts +9 -9
  106. package/dist/contracts/teams.js +25 -16
  107. package/dist/contracts/theme-json.js +1 -1
  108. package/dist/contracts/transfers.d.ts +0 -1
  109. package/dist/contracts/transfers.js +4 -4
  110. package/dist/contracts/variables.js +3 -3
  111. package/dist/contracts/zero.d.ts +384 -596
  112. package/dist/contracts/zero.js +167 -299
  113. package/dist/dashboard-paths/index.d.ts +18 -3
  114. package/dist/dashboard-paths/index.js +19 -0
  115. package/dist/docs/agent-handoff-document.d.ts +2 -2
  116. package/dist/docs/agent-handoff-document.js +8 -7
  117. package/dist/docs/agent-prose.d.ts +22 -3
  118. package/dist/docs/agent-prose.js +227 -55
  119. package/dist/docs/agent-setup.d.ts +14 -11
  120. package/dist/docs/agent-setup.js +289 -61
  121. package/dist/docs/agent-solutions.d.ts +6 -6
  122. package/dist/docs/agent-solutions.js +24 -22
  123. package/dist/docs/catalog.d.ts +53 -98
  124. package/dist/docs/catalog.js +90 -117
  125. package/dist/docs/error-docs.js +304 -236
  126. package/dist/docs/skill-distribution.d.ts +2 -0
  127. package/dist/docs/skill-distribution.js +7 -4
  128. package/dist/docs/skills.d.ts +546 -0
  129. package/dist/docs/skills.js +340 -0
  130. package/dist/utils/auth-redirect.d.ts +1 -3
  131. package/dist/utils/auth-redirect.js +1 -21
  132. package/dist/utils/browser-credential.d.ts +19 -0
  133. package/dist/utils/browser-credential.js +62 -0
  134. package/dist/utils/build-settings.d.ts +2 -0
  135. package/dist/utils/build-settings.js +61 -9
  136. package/dist/utils/comment-avatars.d.ts +7 -0
  137. package/dist/utils/comment-avatars.js +42 -0
  138. package/dist/utils/content-type.d.ts +3 -3
  139. package/dist/utils/content-type.js +38 -61
  140. package/dist/utils/credential-policy.d.ts +1 -1
  141. package/dist/utils/credential-policy.js +4 -0
  142. package/dist/utils/domain-diagnostics.d.ts +5 -5
  143. package/dist/utils/domain-diagnostics.js +21 -10
  144. package/dist/utils/egress-policy.fixtures.json +1 -1
  145. package/dist/utils/grants.d.ts +53 -0
  146. package/dist/utils/grants.js +160 -0
  147. package/dist/utils/local-space-state.d.ts +78 -4
  148. package/dist/utils/local-space-state.js +384 -82
  149. package/dist/utils/one-shot-replay.d.ts +14 -0
  150. package/dist/utils/one-shot-replay.js +21 -0
  151. package/dist/utils/page-preview.d.ts +7 -0
  152. package/dist/utils/page-preview.js +9 -0
  153. package/dist/utils/pages.d.ts +2 -5
  154. package/dist/utils/pages.js +64 -33
  155. package/dist/utils/publish-form-data.d.ts +22 -0
  156. package/dist/utils/publish-form-data.js +26 -0
  157. package/dist/utils/publish-policy.d.ts +34 -4
  158. package/dist/utils/publish-policy.js +149 -62
  159. package/dist/utils/query-keys.d.ts +8 -10
  160. package/dist/utils/query-keys.js +14 -10
  161. package/dist/utils/runtime-paths.d.ts +3 -0
  162. package/dist/utils/runtime-paths.js +7 -0
  163. package/dist/utils/secure-local-file.d.ts +73 -0
  164. package/dist/utils/secure-local-file.js +1373 -0
  165. package/dist/utils/space-config.d.ts +17 -4
  166. package/dist/utils/space-config.js +151 -8
  167. package/dist/utils/static-runtime-policy.d.ts +5 -0
  168. package/dist/utils/static-runtime-policy.js +54 -10
  169. package/dist/utils/storage-policy.d.ts +20 -0
  170. package/dist/utils/storage-policy.fixtures.json +174 -0
  171. package/dist/utils/storage-policy.js +193 -0
  172. package/dist/utils/upload-session.d.ts +15 -1
  173. package/dist/utils/upload-session.js +68 -2
  174. package/dist/utils/version-file-browser.d.ts +13 -0
  175. package/dist/utils/version-file-browser.js +59 -0
  176. package/package.json +20 -1
  177. package/dist/contracts/mounts.d.ts +0 -142
  178. package/dist/contracts/mounts.js +0 -56
  179. package/dist/utils/access-grant.d.ts +0 -14
  180. package/dist/utils/access-grant.js +0 -88
  181. package/dist/utils/access-match.d.ts +0 -46
  182. package/dist/utils/access-match.fixtures.json +0 -513
  183. package/dist/utils/access-match.js +0 -312
  184. package/dist/utils/access-verdict.fixtures.json +0 -421
  185. package/dist/utils/asset-fingerprint.d.ts +0 -53
  186. package/dist/utils/asset-fingerprint.js +0 -574
  187. package/dist/utils/sf-config-v1.d.ts +0 -2
  188. package/dist/utils/sf-config-v1.fixtures.json +0 -9
  189. package/dist/utils/sf-config-v1.js +0 -551
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { accessRoleSchema, authorityReferenceSchema } from "./access.js";
2
3
  import { CursorPaginationSchema, cursorListQuerySchema } from "./common.js";
3
4
  export const commentThreadStatusSchema = z.enum(["open", "archived"]);
4
5
  export const COMMENT_SEARCH_QUERY_MAX_LENGTH = 160;
@@ -6,28 +7,147 @@ export function normalizeCommentSearchQuery(value) {
6
7
  const trimmed = value?.trim();
7
8
  return trimmed ? trimmed.slice(0, COMMENT_SEARCH_QUERY_MAX_LENGTH) : undefined;
8
9
  }
9
- // The space access levels capability follows (SPACEFAST-CAST-PLAN D-2). Invited
10
- // reviewers are space invitees with one of these levels; the on-page overlay and
11
- // inbox re-evaluate the effective level server-side at join — this is only the
12
- // stored grant the dashboard manages.
13
- export const collaborationReviewerLevelSchema = z.enum(["viewer", "commenter", "editor"]);
14
10
  export const COMMENT_PAGE_PATH_MAX_LENGTH = 2_048;
15
- // An invited reviewer: request input projected into the access lane's canonical
16
- // `cast_reviewer` managed block. It is never mirrored into collaboration settings.
17
- export const collaborationInvitedReviewerSchema = z.object({
18
- email: z.string().email(),
19
- level: collaborationReviewerLevelSchema,
11
+ const COMMENT_CAPABILITIES = ["page.view", "comments.read", "comments.write"];
12
+ export const commentCapabilitiesSchema = z
13
+ .array(z.enum(COMMENT_CAPABILITIES))
14
+ .min(2)
15
+ .max(3)
16
+ .refine((capabilities) => new Set(capabilities).size === capabilities.length, {
17
+ message: "comment capabilities must be unique",
18
+ })
19
+ .superRefine((capabilities, context) => {
20
+ if (capabilities.includes("comments.write") && !capabilities.includes("comments.read")) {
21
+ context.addIssue({
22
+ code: "custom",
23
+ message: "comments.write requires comments.read",
24
+ });
25
+ }
26
+ if (capabilities.includes("comments.read") && !capabilities.includes("page.view")) {
27
+ context.addIssue({
28
+ code: "custom",
29
+ message: "comments.read requires page.view",
30
+ });
31
+ }
32
+ });
33
+ export const collaborationGuestProjectionSchema = z.object({
34
+ 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.
37
+ name: z
38
+ .string()
39
+ .trim()
40
+ .min(1)
41
+ .max(160)
42
+ .regex(/^[^\p{Cc}\p{Cf}]+$/u),
43
+ namedByUser: z.boolean(),
44
+ grantId: z.string().min(1).max(128),
45
+ admittedBy: z.union([
46
+ z.literal("anyone"),
47
+ z.templateLiteral(["link:", z.string().regex(/^[A-Za-z0-9_.-]+$/)]),
48
+ z.templateLiteral(["password:", z.string().regex(/^[A-Za-z0-9_.-]+$/)]),
49
+ ]),
50
+ emailVerified: z.boolean().default(false),
51
+ capabilities: commentCapabilitiesSchema,
52
+ });
53
+ // The identity a browser asserts when requesting a guest ticket — the
54
+ // self-asserted subset of the guest projection.
55
+ export const commentsGuestIdentitySchema = collaborationGuestProjectionSchema.pick({
56
+ anonymousId: true,
57
+ name: true,
58
+ namedByUser: true,
59
+ });
60
+ export function commentCapabilitiesOf(capabilities) {
61
+ return capabilities.filter((capability) => COMMENT_CAPABILITIES.includes(capability));
62
+ }
63
+ // The only account metadata exposed to Comments clients. Keep this shape
64
+ // deliberately smaller than the private account record carried server-side.
65
+ export const collaborationPublicProfileSchema = z
66
+ .object({
67
+ name: z.string().trim().min(1).max(120).nullable(),
68
+ username: z.string().trim().min(1).max(160).nullable(),
69
+ avatar_url: z
70
+ .url({ protocol: /^https?$/ })
71
+ .max(2_048)
72
+ .nullable(),
73
+ })
74
+ .strict();
75
+ export const collaborationTicketClaimsSchema = z
76
+ .object({
77
+ sub: z.string().min(1),
78
+ email: z.string().email().optional(),
79
+ profile: collaborationPublicProfileSchema.optional(),
80
+ role: accessRoleSchema,
81
+ // The session's principal, never the class of authority that admitted it:
82
+ // a signed-in account is "user" even when a share Link carried it in.
83
+ actorKind: z.enum(["user", "guest"]),
84
+ authorities: z.array(authorityReferenceSchema).max(16).optional(),
85
+ capabilities: commentCapabilitiesSchema,
86
+ anonymousId: z.string().min(8).max(160).optional(),
87
+ grantId: z.string().min(1).max(128).optional(),
88
+ namedByUser: z.boolean().optional(),
89
+ admittedBy: z
90
+ .union([
91
+ z.literal("anyone"),
92
+ z.templateLiteral(["link:", z.string().regex(/^[A-Za-z0-9_.-]+$/)]),
93
+ z.templateLiteral(["password:", z.string().regex(/^[A-Za-z0-9_.-]+$/)]),
94
+ ])
95
+ .optional(),
96
+ emailVerified: z.boolean().optional(),
97
+ room: z.string().min(1).max(4_096),
98
+ scope: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH),
99
+ surface: z.enum(["published", "preview"]),
100
+ nonce: z.string().min(1).max(160),
101
+ iat: z.number().int(),
102
+ nbf: z.number().int(),
103
+ exp: z.number().int(),
104
+ iss: z.literal("spacefast-api"),
105
+ aud: z.string().min(1),
106
+ })
107
+ .superRefine((claims, context) => {
108
+ if (claims.actorKind !== "guest")
109
+ return;
110
+ // A guest ticket names an anonymous browser identity, and one grant always
111
+ // admitted it: the guest projection the mint builds carries all five of
112
+ // these or it is not a guest at all. Capabilities still come from the union
113
+ // of every authority the session holds — the admitting grant describes the
114
+ // admission, not the reach.
115
+ for (const field of [
116
+ "anonymousId",
117
+ "grantId",
118
+ "namedByUser",
119
+ "admittedBy",
120
+ "emailVerified",
121
+ ]) {
122
+ if (claims[field] === undefined) {
123
+ context.addIssue({
124
+ code: "custom",
125
+ path: [field],
126
+ message: `${field} is required for a guest ticket`,
127
+ });
128
+ }
129
+ }
130
+ // Identity never follows from an authority, but the reverse still holds:
131
+ // an anonymous principal can only ever have acquired credential-class
132
+ // authorities. Account-class references on a guest ticket are a forgery.
133
+ for (const [index, authority] of (claims.authorities ?? []).entries()) {
134
+ if (!authority.startsWith("link:") && !authority.startsWith("password:")) {
135
+ context.addIssue({
136
+ code: "custom",
137
+ path: ["authorities", index],
138
+ message: "a guest ticket carries only link or password authorities",
139
+ });
140
+ }
141
+ }
20
142
  });
21
143
  export const collaborationSettingsSchema = z
22
144
  .object({
23
- anonymousReviewers: z.boolean().optional(),
24
- publishedAnonymousCommenters: z.boolean().optional(),
25
145
  spamFilterEnabled: z.boolean().optional(),
26
- invitedReviewers: z.array(collaborationInvitedReviewerSchema).optional(),
27
146
  // Whether comments are surfaced on the live/published host (vs preview-only).
28
147
  // The published loader (SPACEFAST-CAST-PLAN §4.2) mounts the orb on a live
29
148
  // host only when this is true; toggling it never requires a republish — the
30
- // always-injected inert tag reads behavior from the ETag'd overlay-config.
149
+ // always-injected inert tag re-reads it through the runtime's same-origin
150
+ // Comments config exchange on every load.
31
151
  publishedComments: z.boolean().optional(),
32
152
  notificationPreferences: z
33
153
  .object({
@@ -39,8 +159,23 @@ export const collaborationSettingsSchema = z
39
159
  .optional(),
40
160
  })
41
161
  .strict();
162
+ const collaborationSettingsPatchSchema = z
163
+ .object({
164
+ spamFilterEnabled: z.boolean().optional(),
165
+ publishedComments: z.boolean().optional(),
166
+ notificationPreferences: z
167
+ .object({
168
+ newThreads: z.boolean().optional(),
169
+ newReplies: z.boolean().optional(),
170
+ statusChanges: z.boolean().optional(),
171
+ })
172
+ .strict()
173
+ .optional(),
174
+ })
175
+ .strict();
42
176
  export const collaborationSchema = z.object({
43
177
  spaceId: z.string(),
178
+ revision: z.number().int().nonnegative(),
44
179
  enabled: z.boolean(),
45
180
  castResourceId: z.string().nullable(),
46
181
  castResourceKey: z.string().nullable(),
@@ -48,17 +183,23 @@ export const collaborationSchema = z.object({
48
183
  createdAt: z.string().datetime().nullable(),
49
184
  updatedAt: z.string().datetime().nullable(),
50
185
  });
51
- export const collaborationUpdateSchema = z.object({
52
- enabled: z.boolean(),
53
- settings: collaborationSettingsSchema.optional(),
186
+ export const collaborationUpdateSchema = z
187
+ .object({
188
+ expectedRevision: z.number().int().nonnegative(),
189
+ enabled: z.boolean().optional(),
190
+ settings: collaborationSettingsPatchSchema.optional(),
191
+ })
192
+ .refine((update) => update.enabled !== undefined || update.settings !== undefined, {
193
+ message: "At least one collaboration field is required",
54
194
  });
55
- export const collaborationTokenRequestSchema = z.object({
56
- versionId: z.string().min(1).optional(),
195
+ export const commentsTicketRequestSchema = z.object({
196
+ spaceId: z.string().min(1),
57
197
  pagePath: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH).default("/"),
58
- anonymousId: z.string().min(1).max(160).optional(),
59
- displayName: z.string().min(1).max(120).optional(),
198
+ origin: z.string().url(),
199
+ versionId: z.string().min(1).optional(),
200
+ identity: commentsGuestIdentitySchema.optional(),
60
201
  });
61
- export const collaborationTokenResponseSchema = z.object({
202
+ export const commentsTicketResponseSchema = z.object({
62
203
  token: z.string(),
63
204
  expiresAt: z.string().datetime(),
64
205
  cast: z.object({
@@ -66,18 +207,6 @@ export const collaborationTokenResponseSchema = z.object({
66
207
  room: z.string(),
67
208
  }),
68
209
  });
69
- export const collaborationHandoffRequestSchema = z.object({
70
- versionId: z.string().min(1),
71
- pagePath: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH).default("/"),
72
- });
73
- export const collaborationHandoffResponseSchema = z.object({
74
- handoffToken: z.string(),
75
- expiresAt: z.string().datetime(),
76
- url: z.string().url().nullable(),
77
- });
78
- export const collaborationHandoffExchangeSchema = z.object({
79
- handoffToken: z.string().min(16),
80
- });
81
210
  export const realtimeTokenRequestSchema = z.object({
82
211
  versionId: z.string().optional(),
83
212
  scope: z.enum(["space", "version"]).default("space"),
@@ -105,52 +234,9 @@ export const noticePublishResponseSchema = z.object({
105
234
  event: z.record(z.string(), z.unknown()).nullable(),
106
235
  broadcast: z.record(z.string(), z.unknown()).nullable(),
107
236
  });
108
- export const collabOverlayConfigQuerySchema = z.object({
109
- path: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH).optional(),
110
- versionId: z.string().min(1).optional(),
111
- host: z.string().min(1).optional(),
112
- });
113
- // Snake case is intentional: the injected Collab SDK consumes this alongside
114
- // Cast's snake-case join payload without a remapping layer.
115
- export const collabOverlayConfigSchema = z.object({
116
- enabled: z.boolean(),
117
- anonymous_commenters: z.boolean(),
118
- resource_key: z.string().nullable(),
119
- room_key: z.string().nullable(),
120
- version: z.object({
121
- id: z.string().nullable(),
122
- current: z.string().nullable(),
123
- // The viewed version's immutable URL; null when unknown (live context).
124
- url: z.string().nullable(),
125
- }),
126
- // The space's canonical live/published URL; null when comments-on-live is the
127
- // current context (you're already there) or no live URL exists.
128
- space: z.object({
129
- live_url: z.string().nullable(),
130
- }),
131
- ws_url: z.string().nullable(),
132
- endpoints: z.object({
133
- token: z.string().url(),
134
- handoff_exchange: z.string().url(),
135
- auth_bridge: z.string().url(),
136
- screenshots: z.string().url(),
137
- }),
138
- features: z.object({
139
- drawing: z.boolean(),
140
- capture: z.boolean(),
141
- notices: z.boolean(),
142
- }),
143
- });
144
- // Cross-version navigation directory (§5 "versions are native"): the SDK asks
145
- // for the immutable URLs of the version ids present in a room's threads so
146
- // "Open this comment on v12" is a real link. Gated exactly like the overlay
147
- // config — disabled comments never leak version URLs.
237
+ // Cross-version navigation directory: the Comments overlay asks for the
238
+ // immutable URLs of version ids present in a room's threads.
148
239
  export const COLLAB_VERSION_URLS_MAX_IDS = 50;
149
- export const collabVersionUrlsQuerySchema = collabOverlayConfigQuerySchema.extend({
150
- // Comma-separated version ids; the route caps the lookup at
151
- // COLLAB_VERSION_URLS_MAX_IDS ids.
152
- ids: z.string().min(1).max(4_096),
153
- });
154
240
  export const collabVersionUrlSchema = z.object({
155
241
  id: z.string(),
156
242
  url: z.string(),
@@ -162,10 +248,28 @@ export const collabVersionUrlSchema = z.object({
162
248
  export const commentAuthorSchema = z.object({
163
249
  kind: z.string().nullable(),
164
250
  id: z.string().nullable(),
251
+ profileId: z.string().nullable(),
165
252
  name: z.string().nullable(),
253
+ username: z.string().max(160).nullable(),
254
+ avatarUrl: z
255
+ .url({ protocol: /^https?$/ })
256
+ .max(2_048)
257
+ .nullable(),
166
258
  color: z.string().max(64).nullable(),
167
259
  });
168
260
  export const commentTargetSchema = z.record(z.string(), z.unknown()).nullable();
261
+ export const commentReactionActorSchema = z.object({
262
+ name: z.string().nullable(),
263
+ });
264
+ export const commentReactionEntrySchema = z.object({
265
+ count: z.number().int().min(0),
266
+ actors: z.record(z.string(), commentReactionActorSchema),
267
+ });
268
+ export const COMMENT_REACTION_EMOJIS = ["👍", "❤️", "🎉", "👀", "🚀", "🙏"];
269
+ export const commentReactionUpdateSchema = z.object({
270
+ emoji: z.enum(COMMENT_REACTION_EMOJIS),
271
+ op: z.enum(["add", "remove"]),
272
+ });
169
273
  export const commentThreadSchema = z.object({
170
274
  id: z.string(),
171
275
  castThreadId: z.string(),
@@ -182,6 +286,7 @@ export const commentThreadSchema = z.object({
182
286
  body: z.string().nullable(),
183
287
  author: commentAuthorSchema.nullable(),
184
288
  target: commentTargetSchema,
289
+ reactions: z.record(z.string(), commentReactionEntrySchema),
185
290
  comments: z.array(z.record(z.string(), z.unknown())),
186
291
  permalink: z.string().nullable(),
187
292
  updatedAt: z.string().datetime().nullable(),
@@ -218,6 +323,16 @@ export const commentScreenshotSchema = z.object({
218
323
  url: z.string().url(),
219
324
  expiresAt: z.string().datetime(),
220
325
  });
326
+ export const commentScreenshotRefreshSchema = z.object({
327
+ versionId: z.string().min(1),
328
+ pagePath: z.string().min(1).max(COMMENT_PAGE_PATH_MAX_LENGTH).default("/"),
329
+ key: z.string().min(1).max(2_048),
330
+ });
331
+ export const commentScreenshotRefreshResponseSchema = z.object({
332
+ key: z.string(),
333
+ url: z.string().url(),
334
+ expiresAt: z.string().datetime(),
335
+ });
221
336
  export const commentReplySchema = z.object({
222
337
  body: z.string().min(1).max(16_000),
223
338
  idempotencyKey: z.string().min(1).max(320).optional(),
@@ -102,19 +102,19 @@ export declare const requiredActionsSchema: z.ZodArray<z.ZodDiscriminatedUnion<[
102
102
  type: z.ZodLiteral<"renew">;
103
103
  domainId: z.ZodString;
104
104
  }, z.core.$strip>], "type">>;
105
- export declare const ApiErrorResponseSchema: z.ZodObject<{
106
- error: z.ZodObject<{
107
- code: z.ZodString;
108
- message: z.ZodString;
109
- param: z.ZodOptional<z.ZodString>;
110
- docsUrl: z.ZodString;
111
- details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
112
- suggestions: z.ZodOptional<z.ZodArray<z.ZodString>>;
113
- next: z.ZodOptional<z.ZodArray<z.ZodString>>;
114
- requestId: z.ZodOptional<z.ZodString>;
115
- }, z.core.$strip>;
105
+ export declare const ProblemDetailsSchema: z.ZodObject<{
106
+ type: z.ZodString;
107
+ title: z.ZodString;
108
+ status: z.ZodNumber;
109
+ detail: z.ZodString;
110
+ code: z.ZodString;
111
+ pointer: z.ZodOptional<z.ZodString>;
112
+ details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
113
+ suggestions: z.ZodOptional<z.ZodArray<z.ZodString>>;
114
+ next: z.ZodOptional<z.ZodArray<z.ZodString>>;
115
+ requestId: z.ZodString;
116
116
  }, z.core.$strip>;
117
- export type ApiErrorResponse = z.infer<typeof ApiErrorResponseSchema>;
117
+ export type ProblemDetails = z.infer<typeof ProblemDetailsSchema>;
118
118
  export declare function dataEnvelope<T extends z.ZodType>(data: T): z.ZodObject<{
119
119
  data: T;
120
120
  }, z.core.$strip>;
@@ -18,7 +18,7 @@ export const baseDiagnosticSchema = z.object({
18
18
  path: z
19
19
  .string()
20
20
  .nullish()
21
- .describe('Artifact path the diagnostic points at, e.g. "_headers:12", when one exists.'),
21
+ .describe('Artifact path the diagnostic points at, for example "_headers:12", when one exists.'),
22
22
  provider: diagnosticProvider
23
23
  .nullish()
24
24
  .describe("Upstream system the diagnostic originated from, when not Spacefast itself."),
@@ -30,7 +30,7 @@ export const baseDiagnosticSchema = z.object({
30
30
  retryable: z
31
31
  .boolean()
32
32
  .nullish()
33
- .describe("Whether retrying the same operation may resolve this diagnostic without the caller changing anything."),
33
+ .describe("Whether retrying the same operation can resolve this diagnostic without the caller changing anything."),
34
34
  });
35
35
  // Canonical DnsInstruction (internal-docs/platform.md L2500-2506): provider vocabulary
36
36
  // never leaks into `purpose`.
@@ -64,31 +64,34 @@ export const requiredActionSchema = z.discriminatedUnion("type", [
64
64
  export const requiredActionsSchema = z
65
65
  .array(requiredActionSchema)
66
66
  .describe("Concrete user steps that unblock this resource, using the one shared vocabulary.");
67
- // The error envelope (internal-docs/platform.md "Global API Conventions"): `docsUrl` is
68
- // mandatory and derived from `code` (see contracts/error-codes.ts); `param` is a
69
- // JSON-path-lite pointer into the failing request field on validation failures.
70
- export const ApiErrorResponseSchema = z.object({
71
- error: z.object({
72
- code: z.string().describe("Stable snake_case error code naming the failed public contract."),
73
- message: z.string().describe("Human-readable failure explanation."),
74
- param: z
75
- .string()
76
- .optional()
77
- .describe('JSON-path-lite pointer into the failing request field, e.g. "files[37].path", on validation failures.'),
78
- docsUrl: z
79
- .string()
80
- .describe("Always present; derived mechanically from `code` against the docs origin."),
81
- details: AnyObjectSchema.optional().describe("Machine-readable context for the error code."),
82
- suggestions: z
83
- .array(z.string())
84
- .optional()
85
- .describe("Actionable recovery steps safe to show in dashboards, SDKs, and CLI output."),
86
- next: z
87
- .array(z.string())
88
- .optional()
89
- .describe("Copy-pasteable commands or API requests an agent can run next."),
90
- requestId: z.string().optional().describe("Request id to quote when contacting support."),
91
- }),
67
+ // The error shape (internal-docs/platform.md "Global API Conventions"): every 4xx/5xx body
68
+ // is one RFC 9457 problem details document served as `application/problem+json`. `type` and
69
+ // `title` are derived mechanically from `code` (see contracts/error-codes.ts); `code`,
70
+ // `pointer` (RFC 6901), `details`, `suggestions`, `next`, and `requestId` are extension members.
71
+ export const ProblemDetailsSchema = z.object({
72
+ type: z
73
+ .string()
74
+ .describe("Problem type URI. It resolves to the error docs page. The server derives it mechanically from `code` against the docs origin."),
75
+ title: z
76
+ .string()
77
+ .describe("Short human-readable summary of the problem type. The server derives it mechanically from `code`."),
78
+ status: z.number().int().describe("HTTP status code of this response, repeated in the body."),
79
+ detail: z.string().describe("Human-readable failure explanation for this occurrence."),
80
+ code: z.string().describe("Stable snake_case error code naming the failed public contract."),
81
+ pointer: z
82
+ .string()
83
+ .optional()
84
+ .describe('RFC 6901 JSON Pointer into the failing request field, for example "/files/37/path", on validation failures.'),
85
+ details: AnyObjectSchema.optional().describe("Machine-readable context for the error code."),
86
+ suggestions: z
87
+ .array(z.string())
88
+ .optional()
89
+ .describe("Actionable recovery steps safe to show in dashboards, SDKs, and CLI output."),
90
+ next: z
91
+ .array(z.string())
92
+ .optional()
93
+ .describe("Copy-pasteable commands or API requests an agent can run next."),
94
+ requestId: z.string().describe("The request id to quote when contacting support."),
92
95
  });
93
96
  // Success envelope (internal-docs/platform.md "Global API Conventions"): `{ data: T }` for
94
97
  // single resources and mutations, `{ data: T[], pagination }` for lists. Mutations whose work
@@ -98,7 +101,7 @@ export function dataEnvelope(data) {
98
101
  }
99
102
  export const ApiUploadInstructionSchema = z
100
103
  .object({
101
- id: z.string().describe("Upload session id (`upl_…`)."),
104
+ id: z.string().describe("The upload session id (`upl_…`)."),
102
105
  expiresAt: z.string().datetime(),
103
106
  method: z.literal("PUT"),
104
107
  url: z
@@ -114,7 +117,7 @@ export const CursorPaginationSchema = z.object({
114
117
  nextCursor: z
115
118
  .string()
116
119
  .nullable()
117
- .describe("Opaque cursor for the next page; pass as `?cursor=`. Null on the last page."),
120
+ .describe("Opaque cursor for the next page; null when there are no more results."),
118
121
  hasMore: z.boolean().describe("Whether another page exists after this one."),
119
122
  });
120
123
  export const CURSOR_MAX_LENGTH = 4_096;
@@ -133,7 +136,7 @@ export const cursorListQuerySchema = z.object({
133
136
  .min(1)
134
137
  .max(CURSOR_MAX_LENGTH)
135
138
  .optional()
136
- .describe("Opaque cursor from a previous page's `pagination.nextCursor`."),
139
+ .describe("Opaque cursor from the previous page's `nextCursor`."),
137
140
  });
138
141
  // The operator-only offset list-response shape (superadmin surfaces): the named
139
142
  // items array, plus `total`/`limit`/`offset` and the offset `pagination` block.
@@ -13,7 +13,7 @@ import { AnyObjectSchema } from "./common.js";
13
13
  // generalized resume endpoint once the human step is done.
14
14
  export const RequiresActionTypeSchema = z
15
15
  .enum(["device_authorization"])
16
- .describe("Stable identifier for the out-of-band step a flow is blocked on. New blocking steps are added HERE so resume stays one generalized contract.");
16
+ .describe("Stable identifier for the out-of-band step that blocks the flow. Add new blocking steps here so resume stays one generalized contract.");
17
17
  export const RequiresActionSchema = z
18
18
  .object({
19
19
  actionType: RequiresActionTypeSchema,
@@ -29,7 +29,7 @@ export const RequiresActionSchema = z
29
29
  continuationToken: z
30
30
  .string()
31
31
  .min(1)
32
- .describe("Short-lived, single-use-on-completion, principal-scoped capability the agent presents to POST /v1/actions/resume to poll and complete this exact flow. Treat as a secret; never log it."),
32
+ .describe("Short-lived, principal-scoped capability for this exact flow. Present it to POST /v1/actions/resume to poll and complete the flow. The token is single-use on completion. Treat it as a secret. Never log it."),
33
33
  pollAfterSeconds: z
34
34
  .number()
35
35
  .int()
@@ -38,7 +38,7 @@ export const RequiresActionSchema = z
38
38
  expiresAt: z
39
39
  .string()
40
40
  .datetime()
41
- .describe("Instant by which the human step must be completed the originating flow's own deadline. Resume after this returns a terminal `expired` status (the token survives a short grace past this so resume can report that), but the flow can no longer be redeemed."),
41
+ .describe("Instant when the human step deadline is reached for the originating flow. Resume after this returns terminal `expired`. The token survives for a short grace so resume can report `expired`, but the flow can no longer be redeemed."),
42
42
  })
43
43
  .strict();
44
44
  /** The canonical `{ requiresAction }` envelope, additive alongside `{ data }` / `{ error }`. */
@@ -70,7 +70,7 @@ export const ActionResumeResponseSchema = z
70
70
  .object({
71
71
  status: z.literal("completed"),
72
72
  actionType: RequiresActionTypeSchema,
73
- result: AnyObjectSchema.describe("The flow's success payload, redeemed exactly once. For device_authorization this carries the one-time `apiKey` and any `claimedSpaceId`."),
73
+ result: AnyObjectSchema.describe("Flow success payload, redeemed exactly once. For device_authorization, this carries the one-time `apiKey` and any `claimedSpaceId`."),
74
74
  })
75
75
  .strict(),
76
76
  z
@@ -88,4 +88,4 @@ export const ActionResumeResponseSchema = z
88
88
  })
89
89
  .strict(),
90
90
  ])
91
- .describe("Consistent resume result across flows: keep polling on `pending`, read the one-time payload on `completed`, stop on `denied`/`expired`.");
91
+ .describe("Consistent resume result across flows. Keep polling on `pending`. Read the one-time payload on `completed`. Stop on `denied` or `expired`.");
@@ -1,10 +1,5 @@
1
- // ISO 3166-1 alpha-2 country codes the vocabulary of the firewall card's
2
- // country section (contracts/access.ts `firewallCountriesSchema`, access-plan
3
- // §5.6). The rule `match.country` is an exact-equality matcher against the
4
- // edge-supplied country header, so "allow only these countries" compiles to
5
- // one deny/challenge rule per code in the COMPLEMENT of this list — which is
6
- // why the list itself is a contract: the compiler and the projection must
7
- // agree on the universe.
1
+ // ISO 3166-1 alpha-2 country codes used by Grant network constraints. The
2
+ // runtime compares them with the edge-supplied country header.
8
3
  //
9
4
  // Officially assigned codes only (no exceptionally-reserved / user-assigned
10
5
  // ranges). Display names are a UI concern (`Intl.DisplayNames`), never stored.
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ export declare const dataSourceListItemSchema: z.ZodObject<{
3
+ kind: z.ZodLiteral<"wordpress">;
4
+ url: z.ZodString;
5
+ name: z.ZodString;
6
+ default: z.ZodBoolean;
7
+ }, z.core.$strict>;
8
+ export type DataSourceListItem = z.infer<typeof dataSourceListItemSchema>;
9
+ export declare const dataSourceListResponseSchema: z.ZodObject<{
10
+ data: z.ZodObject<{
11
+ dataSources: z.ZodArray<z.ZodObject<{
12
+ kind: z.ZodLiteral<"wordpress">;
13
+ url: z.ZodString;
14
+ name: z.ZodString;
15
+ default: z.ZodBoolean;
16
+ }, z.core.$strict>>;
17
+ defaultDataSource: z.ZodNullable<z.ZodString>;
18
+ }, z.core.$strip>;
19
+ }, z.core.$strip>;
20
+ export type DataSourceListResponse = z.infer<typeof dataSourceListResponseSchema>;
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { dataEnvelope } from "./common.js";
3
+ import { dataSourceNameSchema, wordpressDataSourceSchema } from "./space-config.js";
4
+ export const dataSourceListItemSchema = wordpressDataSourceSchema
5
+ .extend({
6
+ name: dataSourceNameSchema,
7
+ default: z.boolean().describe("Whether this source is the effective default."),
8
+ })
9
+ .strict();
10
+ export const dataSourceListResponseSchema = dataEnvelope(z.object({
11
+ dataSources: z.array(dataSourceListItemSchema),
12
+ defaultDataSource: dataSourceNameSchema
13
+ .nullable()
14
+ .describe("Configured default source, or the first source in bytewise name order; null when no sources are configured."),
15
+ }));