@aphexcms/cms-core 9.8.1 → 9.10.0

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 (259) hide show
  1. package/dist/api/organizations.d.ts +2 -1
  2. package/dist/api/organizations.d.ts.map +1 -1
  3. package/dist/api/organizations.js +2 -1
  4. package/dist/api/schemas/documents.d.ts +1 -0
  5. package/dist/api/schemas/documents.d.ts.map +1 -1
  6. package/dist/api/schemas/documents.js +1 -0
  7. package/dist/api/schemas/jobs.d.ts +15 -0
  8. package/dist/api/schemas/jobs.d.ts.map +1 -0
  9. package/dist/api/schemas/jobs.js +17 -0
  10. package/dist/api/schemas/user.d.ts.map +1 -1
  11. package/dist/api/schemas/user.js +6 -2
  12. package/dist/auth/account-deletion.d.ts +35 -0
  13. package/dist/auth/account-deletion.d.ts.map +1 -0
  14. package/dist/auth/account-deletion.js +65 -0
  15. package/dist/auth/bootstrap.d.ts +104 -0
  16. package/dist/auth/bootstrap.d.ts.map +1 -0
  17. package/dist/auth/bootstrap.js +164 -0
  18. package/dist/auth/instance-state.d.ts +13 -0
  19. package/dist/auth/instance-state.d.ts.map +1 -0
  20. package/dist/auth/instance-state.js +30 -0
  21. package/dist/auth/invitation-status.d.ts +25 -0
  22. package/dist/auth/invitation-status.d.ts.map +1 -0
  23. package/dist/auth/invitation-status.js +41 -0
  24. package/dist/auth/sign-up-policy.d.ts +62 -0
  25. package/dist/auth/sign-up-policy.d.ts.map +1 -0
  26. package/dist/auth/sign-up-policy.js +120 -0
  27. package/dist/components/AdminApp.svelte +83 -6
  28. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  29. package/dist/components/admin/ActivityView.svelte +263 -13
  30. package/dist/components/admin/ActivityView.svelte.d.ts +10 -1
  31. package/dist/components/admin/ActivityView.svelte.d.ts.map +1 -1
  32. package/dist/db/interfaces/document.d.ts +9 -0
  33. package/dist/db/interfaces/document.d.ts.map +1 -1
  34. package/dist/db/interfaces/events.d.ts +29 -2
  35. package/dist/db/interfaces/events.d.ts.map +1 -1
  36. package/dist/db/interfaces/index.d.ts +1 -0
  37. package/dist/db/interfaces/index.d.ts.map +1 -1
  38. package/dist/db/interfaces/index.js +1 -0
  39. package/dist/db/interfaces/instance.d.ts +29 -0
  40. package/dist/db/interfaces/instance.d.ts.map +1 -1
  41. package/dist/db/interfaces/instance.js +8 -1
  42. package/dist/events/built-in-consumers.d.ts +20 -0
  43. package/dist/events/built-in-consumers.d.ts.map +1 -0
  44. package/dist/events/built-in-consumers.js +49 -0
  45. package/dist/events/catalog.d.ts +16 -0
  46. package/dist/events/catalog.d.ts.map +1 -1
  47. package/dist/events/catalog.js +17 -0
  48. package/dist/events/consumer.d.ts +14 -0
  49. package/dist/events/consumer.d.ts.map +1 -1
  50. package/dist/events/consumer.js +1 -0
  51. package/dist/events/emit.d.ts +23 -0
  52. package/dist/events/emit.d.ts.map +1 -1
  53. package/dist/events/emit.js +32 -1
  54. package/dist/events/index.d.ts +2 -0
  55. package/dist/events/index.d.ts.map +1 -1
  56. package/dist/events/index.js +2 -0
  57. package/dist/field-validation/utils.d.ts +27 -4
  58. package/dist/field-validation/utils.d.ts.map +1 -1
  59. package/dist/field-validation/utils.js +78 -10
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +3 -0
  63. package/dist/jobs/run-batch.d.ts +7 -1
  64. package/dist/jobs/run-batch.d.ts.map +1 -1
  65. package/dist/jobs/run-batch.js +3 -1
  66. package/dist/lib/api/organizations.d.ts +2 -1
  67. package/dist/lib/api/organizations.d.ts.map +1 -1
  68. package/dist/lib/api/organizations.js +2 -1
  69. package/dist/lib/api/organizations.js.map +1 -1
  70. package/dist/lib/api/schemas/api-keys.d.ts +4 -4
  71. package/dist/lib/api/schemas/documents.d.ts +1 -0
  72. package/dist/lib/api/schemas/documents.d.ts.map +1 -1
  73. package/dist/lib/api/schemas/documents.js +1 -0
  74. package/dist/lib/api/schemas/documents.js.map +1 -1
  75. package/dist/lib/api/schemas/jobs.d.ts +15 -0
  76. package/dist/lib/api/schemas/jobs.d.ts.map +1 -0
  77. package/dist/lib/api/schemas/jobs.js +18 -0
  78. package/dist/lib/api/schemas/jobs.js.map +1 -0
  79. package/dist/lib/api/schemas/user.d.ts.map +1 -1
  80. package/dist/lib/api/schemas/user.js +6 -2
  81. package/dist/lib/api/schemas/user.js.map +1 -1
  82. package/dist/lib/auth/account-deletion.d.ts +35 -0
  83. package/dist/lib/auth/account-deletion.d.ts.map +1 -0
  84. package/dist/lib/auth/account-deletion.js +66 -0
  85. package/dist/lib/auth/account-deletion.js.map +1 -0
  86. package/dist/lib/auth/bootstrap.d.ts +104 -0
  87. package/dist/lib/auth/bootstrap.d.ts.map +1 -0
  88. package/dist/lib/auth/bootstrap.js +165 -0
  89. package/dist/lib/auth/bootstrap.js.map +1 -0
  90. package/dist/lib/auth/instance-state.d.ts +13 -0
  91. package/dist/lib/auth/instance-state.d.ts.map +1 -0
  92. package/dist/lib/auth/instance-state.js +31 -0
  93. package/dist/lib/auth/instance-state.js.map +1 -0
  94. package/dist/lib/auth/invitation-status.d.ts +25 -0
  95. package/dist/lib/auth/invitation-status.d.ts.map +1 -0
  96. package/dist/lib/auth/invitation-status.js +42 -0
  97. package/dist/lib/auth/invitation-status.js.map +1 -0
  98. package/dist/lib/auth/sign-up-policy.d.ts +62 -0
  99. package/dist/lib/auth/sign-up-policy.d.ts.map +1 -0
  100. package/dist/lib/auth/sign-up-policy.js +121 -0
  101. package/dist/lib/auth/sign-up-policy.js.map +1 -0
  102. package/dist/lib/db/interfaces/document.d.ts +9 -0
  103. package/dist/lib/db/interfaces/document.d.ts.map +1 -1
  104. package/dist/lib/db/interfaces/events.d.ts +29 -2
  105. package/dist/lib/db/interfaces/events.d.ts.map +1 -1
  106. package/dist/lib/db/interfaces/index.d.ts +1 -0
  107. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  108. package/dist/lib/db/interfaces/index.js +1 -0
  109. package/dist/lib/db/interfaces/index.js.map +1 -1
  110. package/dist/lib/db/interfaces/instance.d.ts +29 -0
  111. package/dist/lib/db/interfaces/instance.d.ts.map +1 -1
  112. package/dist/lib/db/interfaces/instance.js +8 -1
  113. package/dist/lib/db/interfaces/instance.js.map +1 -1
  114. package/dist/lib/events/built-in-consumers.d.ts +20 -0
  115. package/dist/lib/events/built-in-consumers.d.ts.map +1 -0
  116. package/dist/lib/events/built-in-consumers.js +50 -0
  117. package/dist/lib/events/built-in-consumers.js.map +1 -0
  118. package/dist/lib/events/catalog.d.ts +16 -0
  119. package/dist/lib/events/catalog.d.ts.map +1 -1
  120. package/dist/lib/events/catalog.js +17 -0
  121. package/dist/lib/events/catalog.js.map +1 -1
  122. package/dist/lib/events/consumer.d.ts +14 -0
  123. package/dist/lib/events/consumer.d.ts.map +1 -1
  124. package/dist/lib/events/consumer.js +1 -0
  125. package/dist/lib/events/consumer.js.map +1 -1
  126. package/dist/lib/events/emit.d.ts +23 -0
  127. package/dist/lib/events/emit.d.ts.map +1 -1
  128. package/dist/lib/events/emit.js +32 -1
  129. package/dist/lib/events/emit.js.map +1 -1
  130. package/dist/lib/events/index.d.ts +2 -0
  131. package/dist/lib/events/index.d.ts.map +1 -1
  132. package/dist/lib/events/index.js +2 -0
  133. package/dist/lib/events/index.js.map +1 -1
  134. package/dist/lib/field-validation/utils.d.ts +27 -4
  135. package/dist/lib/field-validation/utils.d.ts.map +1 -1
  136. package/dist/lib/field-validation/utils.js +78 -10
  137. package/dist/lib/field-validation/utils.js.map +1 -1
  138. package/dist/lib/index.d.ts +1 -0
  139. package/dist/lib/index.d.ts.map +1 -1
  140. package/dist/lib/index.js +3 -0
  141. package/dist/lib/index.js.map +1 -1
  142. package/dist/lib/jobs/run-batch.d.ts +7 -1
  143. package/dist/lib/jobs/run-batch.d.ts.map +1 -1
  144. package/dist/lib/jobs/run-batch.js +3 -1
  145. package/dist/lib/jobs/run-batch.js.map +1 -1
  146. package/dist/lib/local-api/collection-api.d.ts +48 -1
  147. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  148. package/dist/lib/local-api/collection-api.js +110 -11
  149. package/dist/lib/local-api/collection-api.js.map +1 -1
  150. package/dist/lib/local-api/index.d.ts +1 -1
  151. package/dist/lib/local-api/index.d.ts.map +1 -1
  152. package/dist/lib/local-api/index.js +1 -1
  153. package/dist/lib/local-api/index.js.map +1 -1
  154. package/dist/lib/plugins/resolver.d.ts.map +1 -1
  155. package/dist/lib/plugins/resolver.js +7 -1
  156. package/dist/lib/plugins/resolver.js.map +1 -1
  157. package/dist/lib/schema-utils/utils.d.ts +31 -1
  158. package/dist/lib/schema-utils/utils.d.ts.map +1 -1
  159. package/dist/lib/schema-utils/utils.js +68 -0
  160. package/dist/lib/schema-utils/utils.js.map +1 -1
  161. package/dist/lib/server/api/rate-limit.d.ts +38 -0
  162. package/dist/lib/server/api/rate-limit.d.ts.map +1 -0
  163. package/dist/lib/server/api/rate-limit.js +71 -0
  164. package/dist/lib/server/api/rate-limit.js.map +1 -0
  165. package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
  166. package/dist/lib/server/api/routes/documents-by-id.js +10 -1
  167. package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
  168. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
  169. package/dist/lib/server/api/routes/documents-publish.js +10 -0
  170. package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
  171. package/dist/lib/server/api/routes/documents.d.ts.map +1 -1
  172. package/dist/lib/server/api/routes/documents.js +11 -0
  173. package/dist/lib/server/api/routes/documents.js.map +1 -1
  174. package/dist/lib/server/api/routes/jobs.d.ts.map +1 -1
  175. package/dist/lib/server/api/routes/jobs.js +174 -20
  176. package/dist/lib/server/api/routes/jobs.js.map +1 -1
  177. package/dist/lib/server/api/routes/organizations-by-id.d.ts.map +1 -1
  178. package/dist/lib/server/api/routes/organizations-by-id.js +61 -3
  179. package/dist/lib/server/api/routes/organizations-by-id.js.map +1 -1
  180. package/dist/lib/server/api/routes/organizations-invitations.d.ts.map +1 -1
  181. package/dist/lib/server/api/routes/organizations-invitations.js +31 -2
  182. package/dist/lib/server/api/routes/organizations-invitations.js.map +1 -1
  183. package/dist/lib/server/api/routes/resolve-organization-names.d.ts +17 -0
  184. package/dist/lib/server/api/routes/resolve-organization-names.d.ts.map +1 -0
  185. package/dist/lib/server/api/routes/resolve-organization-names.js +26 -0
  186. package/dist/lib/server/api/routes/resolve-organization-names.js.map +1 -0
  187. package/dist/lib/server/api/routes/user.d.ts +0 -8
  188. package/dist/lib/server/api/routes/user.d.ts.map +1 -1
  189. package/dist/lib/server/api/routes/user.js +144 -0
  190. package/dist/lib/server/api/routes/user.js.map +1 -1
  191. package/dist/lib/server/index.d.ts +6 -1
  192. package/dist/lib/server/index.d.ts.map +1 -1
  193. package/dist/lib/server/index.js +9 -1
  194. package/dist/lib/server/index.js.map +1 -1
  195. package/dist/lib/type-gen.d.ts.map +1 -1
  196. package/dist/lib/type-gen.js +11 -5
  197. package/dist/lib/type-gen.js.map +1 -1
  198. package/dist/lib/types/capabilities.d.ts +14 -0
  199. package/dist/lib/types/capabilities.d.ts.map +1 -1
  200. package/dist/lib/types/capabilities.js +37 -18
  201. package/dist/lib/types/capabilities.js.map +1 -1
  202. package/dist/lib/types/events.d.ts +27 -4
  203. package/dist/lib/types/events.d.ts.map +1 -1
  204. package/dist/lib/types/filters.d.ts +31 -0
  205. package/dist/lib/types/filters.d.ts.map +1 -1
  206. package/dist/lib/types/schemas.d.ts +14 -0
  207. package/dist/lib/types/schemas.d.ts.map +1 -1
  208. package/dist/lib/utils/fetch-remote-file.d.ts.map +1 -1
  209. package/dist/lib/utils/fetch-remote-file.js +32 -3
  210. package/dist/lib/utils/fetch-remote-file.js.map +1 -1
  211. package/dist/local-api/collection-api.d.ts +48 -1
  212. package/dist/local-api/collection-api.d.ts.map +1 -1
  213. package/dist/local-api/collection-api.js +110 -11
  214. package/dist/local-api/index.d.ts +1 -1
  215. package/dist/local-api/index.d.ts.map +1 -1
  216. package/dist/local-api/index.js +1 -1
  217. package/dist/plugins/resolver.d.ts.map +1 -1
  218. package/dist/plugins/resolver.js +7 -1
  219. package/dist/schema-utils/utils.d.ts +31 -1
  220. package/dist/schema-utils/utils.d.ts.map +1 -1
  221. package/dist/schema-utils/utils.js +68 -0
  222. package/dist/server/api/rate-limit.d.ts +38 -0
  223. package/dist/server/api/rate-limit.d.ts.map +1 -0
  224. package/dist/server/api/rate-limit.js +70 -0
  225. package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
  226. package/dist/server/api/routes/documents-by-id.js +10 -1
  227. package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
  228. package/dist/server/api/routes/documents-publish.js +10 -0
  229. package/dist/server/api/routes/documents.d.ts.map +1 -1
  230. package/dist/server/api/routes/documents.js +11 -0
  231. package/dist/server/api/routes/jobs.d.ts.map +1 -1
  232. package/dist/server/api/routes/jobs.js +174 -20
  233. package/dist/server/api/routes/organizations-by-id.d.ts.map +1 -1
  234. package/dist/server/api/routes/organizations-by-id.js +61 -3
  235. package/dist/server/api/routes/organizations-invitations.d.ts.map +1 -1
  236. package/dist/server/api/routes/organizations-invitations.js +31 -2
  237. package/dist/server/api/routes/resolve-organization-names.d.ts +17 -0
  238. package/dist/server/api/routes/resolve-organization-names.d.ts.map +1 -0
  239. package/dist/server/api/routes/resolve-organization-names.js +25 -0
  240. package/dist/server/api/routes/user.d.ts +0 -8
  241. package/dist/server/api/routes/user.d.ts.map +1 -1
  242. package/dist/server/api/routes/user.js +144 -0
  243. package/dist/server/index.d.ts +6 -1
  244. package/dist/server/index.d.ts.map +1 -1
  245. package/dist/server/index.js +9 -1
  246. package/dist/type-gen.d.ts.map +1 -1
  247. package/dist/type-gen.js +11 -5
  248. package/dist/types/capabilities.d.ts +14 -0
  249. package/dist/types/capabilities.d.ts.map +1 -1
  250. package/dist/types/capabilities.js +37 -18
  251. package/dist/types/events.d.ts +27 -4
  252. package/dist/types/events.d.ts.map +1 -1
  253. package/dist/types/filters.d.ts +31 -0
  254. package/dist/types/filters.d.ts.map +1 -1
  255. package/dist/types/schemas.d.ts +14 -0
  256. package/dist/types/schemas.d.ts.map +1 -1
  257. package/dist/utils/fetch-remote-file.d.ts.map +1 -1
  258. package/dist/utils/fetch-remote-file.js +32 -3
  259. package/package.json +6 -6
@@ -0,0 +1,49 @@
1
+ import { userDeleted } from './catalog.js';
2
+ /** Extract the asset id from an avatar path, or null if it isn't one of ours. */
3
+ function avatarAssetId(image) {
4
+ return /^\/media\/([^/]+)\//.exec(image)?.[1] ?? null;
5
+ }
6
+ /**
7
+ * Erase a deleted user's avatar — the file, not just the row.
8
+ *
9
+ * Account deletion removes the user record, and with it the only pointer to the avatar
10
+ * asset. Without this the image survives in object storage indefinitely, reachable by
11
+ * anyone holding its URL and invisible to the media browser (avatars are marked
12
+ * `system`), so nothing would ever surface it for cleanup. That is precisely the
13
+ * "personal data with no way left to find or erase it" case a right-to-erasure request
14
+ * has to be able to answer.
15
+ *
16
+ * Idempotent, as every consumer must be: a missing asset is a completed erasure, so a
17
+ * redelivery finds nothing and succeeds. It throws only when the delete itself fails, so
18
+ * a transient storage outage retries with backoff instead of silently giving up — the
19
+ * one outcome that would leave the data behind while reporting success.
20
+ */
21
+ export const eraseUserAvatarConsumer = {
22
+ implements: 'aphex/event/consumer',
23
+ id: 'aphex.erase-user-avatar',
24
+ events: [userDeleted.type],
25
+ async handler({ event, assetService, logger }) {
26
+ const image = event.payload.image;
27
+ if (typeof image !== 'string' || !image)
28
+ return;
29
+ const assetId = avatarAssetId(image);
30
+ if (!assetId) {
31
+ // An external provider's avatar, or one of the absolute storage URLs written
32
+ // before avatars moved to `/media/<id>/`. Nothing of ours to delete, and no
33
+ // asset id recoverable from it — flag it so it can be cleared by hand.
34
+ logger.warn('[erase-user-avatar]', `User ${event.payload.userId} had a non-asset avatar (${image}); nothing to erase automatically.`);
35
+ return;
36
+ }
37
+ if (!assetService) {
38
+ // Throwing would retry forever against a host that has no asset service at
39
+ // all. Say so loudly once per attempt and let the delivery dead-letter.
40
+ throw new Error(`Cannot erase avatar asset ${assetId}: no asset service is configured on this host.`);
41
+ }
42
+ const deleted = await assetService.deleteAsset(event.organizationId, assetId);
43
+ logger.info('[erase-user-avatar]', deleted
44
+ ? `Erased avatar asset ${assetId} for deleted user ${event.payload.userId}`
45
+ : `Avatar asset ${assetId} was already gone for user ${event.payload.userId}`);
46
+ }
47
+ };
48
+ /** Every consumer core ships. Seeded into the part resolver ahead of plugin parts. */
49
+ export const BUILT_IN_EVENT_CONSUMERS = [eraseUserAvatarConsumer];
@@ -5,4 +5,20 @@ export declare const documentPublished: import("./define-event.js").EventDefinit
5
5
  documentType: z.ZodString;
6
6
  publishedHash: z.ZodNullable<z.ZodString>;
7
7
  }, z.core.$strip>>;
8
+ /**
9
+ * Emitted when a user account is deleted, once per organization they belonged to — the
10
+ * erasure fan-out point. Consumers react by removing whatever that user left behind in
11
+ * *their* organization, so "delete my account" reaches per-org data without the deletion
12
+ * path having to know every consumer that cares.
13
+ *
14
+ * Carries `image` because it can't be looked up afterwards: the account row is gone by the
15
+ * time a consumer runs, taking the only pointer to the avatar asset with it. This is the
16
+ * one case where the payload holds a value rather than an identifier, and it's still not a
17
+ * secret — it's the same public CDN path the profile served.
18
+ */
19
+ export declare const userDeleted: import("./define-event.js").EventDefinition<"user.deleted", z.ZodObject<{
20
+ userId: z.ZodString;
21
+ email: z.ZodNullable<z.ZodString>;
22
+ image: z.ZodNullable<z.ZodString>;
23
+ }, z.core.$strip>>;
8
24
  //# sourceMappingURL=catalog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/lib/events/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB;;;;kBAO7B,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/lib/events/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB;;;;kBAO7B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW;;;;kBAQvB,CAAC"}
@@ -9,3 +9,20 @@ export const documentPublished = defineEvent('document.published', z.object({
9
9
  documentType: z.string(),
10
10
  publishedHash: z.string().nullable()
11
11
  }));
12
+ /**
13
+ * Emitted when a user account is deleted, once per organization they belonged to — the
14
+ * erasure fan-out point. Consumers react by removing whatever that user left behind in
15
+ * *their* organization, so "delete my account" reaches per-org data without the deletion
16
+ * path having to know every consumer that cares.
17
+ *
18
+ * Carries `image` because it can't be looked up afterwards: the account row is gone by the
19
+ * time a consumer runs, taking the only pointer to the avatar asset with it. This is the
20
+ * one case where the payload holds a value rather than an identifier, and it's still not a
21
+ * secret — it's the same public CDN path the profile served.
22
+ */
23
+ export const userDeleted = defineEvent('user.deleted', z.object({
24
+ userId: z.string(),
25
+ email: z.string().nullable(),
26
+ /** The profile image as stored, or null. `/media/<assetId>/<filename>` when it's ours. */
27
+ image: z.string().nullable()
28
+ }));
@@ -32,11 +32,23 @@ export interface ConsumerSettingsReader {
32
32
  /** Decrypted settings for `pluginId` in the event's organization ({} if never configured). */
33
33
  get(pluginId: string): Promise<Record<string, unknown>>;
34
34
  }
35
+ /**
36
+ * The asset operations a consumer may perform. Deliberately the *service*, not the database
37
+ * adapter: `databaseAdapter.deleteAsset` drops the row and leaves the file in object storage,
38
+ * which for an erasure consumer is the difference between deleting the pointer and deleting
39
+ * the data.
40
+ */
41
+ export interface ConsumerAssetService {
42
+ findAssetById(organizationId: string, id: string): Promise<unknown>;
43
+ deleteAsset(organizationId: string, id: string): Promise<boolean>;
44
+ }
35
45
  /** What an event-consumer handler receives. `databaseAdapter` is the live adapter (org-scoped calls take an org id). */
36
46
  export interface EventConsumerContext {
37
47
  event: ConsumedEvent;
38
48
  databaseAdapter: DatabaseAdapter;
39
49
  logger: Logger;
50
+ /** Assets in the event's organization, file included. `null` when the host wired none. */
51
+ assetService: ConsumerAssetService | null;
40
52
  /** Read this plugin's own decrypted settings for the event's org (e.g. a webhook URL secret). */
41
53
  settings: ConsumerSettingsReader;
42
54
  /**
@@ -49,6 +61,8 @@ export interface EventConsumerContext {
49
61
  /** Runtime services the consumer wrapper injects into each delivery's context. */
50
62
  export interface ConsumerHandlerDeps {
51
63
  pluginSettingsService: PluginSettingsReader;
64
+ /** The app's asset service, passed through to consumers that erase or rewrite media. */
65
+ assetService?: ConsumerAssetService | null;
52
66
  /** The app's email adapter (or `null` if email isn't configured). Passed straight to the consumer. */
53
67
  emailAdapter?: EmailAdapter | null;
54
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/lib/events/consumer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChF;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACtC,8FAA8F;IAC9F,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxD;AAED,wHAAwH;AACxH,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;;;OAIG;IACH,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CAClC;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IACnC,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,sGAAsG;IACtG,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqBD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/E;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,mBAAmB,GACvB,UAAU,CAcZ"}
1
+ {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/lib/events/consumer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChF;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACtC,8FAA8F;IAC9F,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxD;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACpC,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,wHAAwH;AACxH,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,iGAAiG;IACjG,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;;;OAIG;IACH,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CAClC;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IACnC,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,wFAAwF;IACxF,YAAY,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC3C,sGAAsG;IACtG,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqBD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/E;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,mBAAmB,GACvB,UAAU,CAeZ"}
@@ -70,6 +70,7 @@ export function toConsumerJobHandler(handler, deps) {
70
70
  databaseAdapter,
71
71
  logger,
72
72
  settings,
73
+ assetService: deps.assetService ?? null,
73
74
  emailAdapter: deps.emailAdapter ?? null
74
75
  });
75
76
  };
@@ -8,4 +8,27 @@ import type { Document } from '../types/document.js';
8
8
  * whether a version snapshot was taken.
9
9
  */
10
10
  export declare function emitDocumentPublished(tx: DatabaseAdapter, organizationId: string, doc: Document): Promise<void>;
11
+ /** A user account at the moment it is deleted — the last chance to read these fields. */
12
+ export interface DeletedUser {
13
+ id: string;
14
+ email?: string | null;
15
+ image?: string | null;
16
+ }
17
+ /**
18
+ * Emit `user.deleted` once per organization the user belonged to.
19
+ *
20
+ * Fans out per-org because the event log is org-scoped and erasure is an org-level
21
+ * concern: each organization holds its own residue of a user (their avatar, and in time
22
+ * whatever else), and each consumer runs against the org it was delivered for. One event
23
+ * naming a single "home" org would leave the others untouched.
24
+ *
25
+ * MUST be called on a TRANSACTION handle, in the same transaction as the deletion itself
26
+ * — the transactional-outbox guarantee. An account erased without its events emitted is
27
+ * personal data stranded with nothing left to point at it, which is the exact failure this
28
+ * exists to prevent.
29
+ *
30
+ * `organizationIds` are the caller's — read them *before* the deletion removes the
31
+ * membership rows, or this fans out to nothing.
32
+ */
33
+ export declare function emitUserDeleted(tx: DatabaseAdapter, organizationIds: readonly string[], user: DeletedUser): Promise<void>;
11
34
  //# sourceMappingURL=emit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/lib/events/emit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,eAAe,EACnB,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,QAAQ,GACX,OAAO,CAAC,IAAI,CAAC,CAWf"}
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/lib/events/emit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,eAAe,EACnB,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,QAAQ,GACX,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACpC,EAAE,EAAE,eAAe,EACnB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,IAAI,EAAE,WAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -1,4 +1,4 @@
1
- import { documentPublished } from './catalog.js';
1
+ import { documentPublished, userDeleted } from './catalog.js';
2
2
  /**
3
3
  * Emit `document.published` (and its outbox row) for a freshly published document. MUST be
4
4
  * called on a TRANSACTION handle (from `withTransaction`) so the event commits atomically with
@@ -18,3 +18,34 @@ export async function emitDocumentPublished(tx, organizationId, doc) {
18
18
  createdBy: doc.updatedBy
19
19
  });
20
20
  }
21
+ /**
22
+ * Emit `user.deleted` once per organization the user belonged to.
23
+ *
24
+ * Fans out per-org because the event log is org-scoped and erasure is an org-level
25
+ * concern: each organization holds its own residue of a user (their avatar, and in time
26
+ * whatever else), and each consumer runs against the org it was delivered for. One event
27
+ * naming a single "home" org would leave the others untouched.
28
+ *
29
+ * MUST be called on a TRANSACTION handle, in the same transaction as the deletion itself
30
+ * — the transactional-outbox guarantee. An account erased without its events emitted is
31
+ * personal data stranded with nothing left to point at it, which is the exact failure this
32
+ * exists to prevent.
33
+ *
34
+ * `organizationIds` are the caller's — read them *before* the deletion removes the
35
+ * membership rows, or this fans out to nothing.
36
+ */
37
+ export async function emitUserDeleted(tx, organizationIds, user) {
38
+ const payload = userDeleted.parse({
39
+ userId: user.id,
40
+ email: user.email ?? null,
41
+ image: user.image ?? null
42
+ });
43
+ for (const organizationId of organizationIds) {
44
+ await tx.appendEvent({
45
+ organizationId,
46
+ type: userDeleted.type,
47
+ payload,
48
+ createdBy: user.id
49
+ });
50
+ }
51
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './define-event.js';
2
2
  export * from './catalog.js';
3
3
  export * from './consumer.js';
4
+ export * from './emit.js';
5
+ export * from './built-in-consumers.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,sBAAsB,CAAC"}
@@ -1,3 +1,5 @@
1
1
  export * from './define-event.js';
2
2
  export * from './catalog.js';
3
3
  export * from './consumer.js';
4
+ export * from './emit.js';
5
+ export * from './built-in-consumers.js';
@@ -2,13 +2,36 @@ import type { Field, SchemaType } from '../types/index.js';
2
2
  export interface ValidationError {
3
3
  level: 'error' | 'warning' | 'info';
4
4
  message: string;
5
+ /**
6
+ * Which of the two questions this error answers.
7
+ *
8
+ * `structural` — the data cannot be interpreted as the schema at all: wrong
9
+ * JSON shape for the field type, or a key the schema never declared. Never a
10
+ * legitimate work-in-progress state, so it's rejected on **every** write,
11
+ * drafts included. This is the class an agent or a bad client produces.
12
+ *
13
+ * `content` — the data is the right shape but isn't finished: required fields
14
+ * missing, ranges exceeded, cross-field invariants unmet. Perfectly legitimate
15
+ * mid-edit, so it's only enforced at publish.
16
+ *
17
+ * Defaults to `content` when unset — the conservative direction, since
18
+ * mislabelling a rule error as structural would block saving a draft.
19
+ */
20
+ kind?: 'structural' | 'content';
21
+ }
22
+ export interface FieldErrors {
23
+ field: string;
24
+ errors: string[];
25
+ kind: 'structural' | 'content';
5
26
  }
6
27
  export interface DocumentValidationResult {
7
28
  isValid: boolean;
8
- errors: Array<{
9
- field: string;
10
- errors: string[];
11
- }>;
29
+ errors: FieldErrors[];
30
+ /**
31
+ * The subset of `errors` that no draft may carry. Empty on a merely
32
+ * incomplete document; non-empty means the payload is malformed.
33
+ */
34
+ structuralErrors: FieldErrors[];
12
35
  normalizedData: Record<string, any>;
13
36
  }
14
37
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAKnF,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAUrD;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmC9E;AAwMD;;GAEG;AACH,wBAAsB,aAAa,CAClC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,GAAG,EACV,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC,CAsJD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAO/D;AAwCD;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC,wBAAwB,CAAC,CA0BnC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAKnF,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,YAAY,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;;OAGG;IACH,gBAAgB,EAAE,WAAW,EAAE,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAUrD;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA6C9E;AAiOD;;GAEG;AACH,wBAAsB,aAAa,CAClC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,GAAG,EACV,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC,CA0KD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAO/D;AAiED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC,wBAAwB,CAAC,CA2BnC"}
@@ -76,8 +76,20 @@ export function validateValueShape(field, value) {
76
76
  return Array.isArray(value) ? null : `expected an array, got ${describeValue(value)}`;
77
77
  case 'object':
78
78
  return isPlainObject(value) ? null : `expected an object, got ${describeValue(value)}`;
79
+ case 'number':
80
+ // `''` is the empty state of a cleared number input, not a value.
81
+ if (value === '')
82
+ return null;
83
+ return typeof value === 'number' && Number.isFinite(value)
84
+ ? null
85
+ : `expected a number, got ${describeValue(value)}`;
86
+ case 'boolean':
87
+ if (value === '')
88
+ return null;
89
+ return typeof value === 'boolean' ? null : `expected a boolean, got ${describeValue(value)}`;
79
90
  default:
80
- // number/boolean/date/datetime — left to existing auto-rules / user rules.
91
+ // date/datetime — shape is inseparable from format here, so the
92
+ // existing auto-rules own them.
81
93
  return null;
82
94
  }
83
95
  }
@@ -212,7 +224,8 @@ async function validateArrayItems(field, items, context) {
212
224
  field: itemPath,
213
225
  errors: [
214
226
  `has type "${gotType}", which is not one of the declared array item types: ${declared}`
215
- ]
227
+ ],
228
+ kind: 'structural'
216
229
  });
217
230
  continue;
218
231
  }
@@ -222,7 +235,10 @@ async function validateArrayItems(field, items, context) {
222
235
  // branch below and get full field validation already; this is the one shape the rest of
223
236
  // this function never checked.
224
237
  if (typeRef.type === 'block') {
225
- results.push(...validatePortableTextBlock(item, itemPath));
238
+ // Every block check is a shape check.
239
+ for (const err of validatePortableTextBlock(item, itemPath)) {
240
+ results.push({ ...err, kind: 'structural' });
241
+ }
226
242
  continue;
227
243
  }
228
244
  if (typeRef.type === 'reference') {
@@ -231,7 +247,8 @@ async function validateArrayItems(field, items, context) {
231
247
  field: itemPath,
232
248
  errors: [
233
249
  `expected a reference object { _type: 'reference', _ref: '<documentId>' }, got ${describeValue(item)}`
234
- ]
250
+ ],
251
+ kind: 'structural'
235
252
  });
236
253
  }
237
254
  continue;
@@ -240,7 +257,8 @@ async function validateArrayItems(field, items, context) {
240
257
  if (!isPlainObject(item)) {
241
258
  results.push({
242
259
  field: itemPath,
243
- errors: [`expected an object, got ${describeValue(item)}`]
260
+ errors: [`expected an object, got ${describeValue(item)}`],
261
+ kind: 'structural'
244
262
  });
245
263
  continue;
246
264
  }
@@ -248,7 +266,11 @@ async function validateArrayItems(field, items, context) {
248
266
  for (const err of nested) {
249
267
  for (const rawMessage of err.errors) {
250
268
  const { path, reason } = splitFieldMessage(rawMessage);
251
- results.push({ field: `${itemPath}.${path ?? err.field}`, errors: [reason] });
269
+ results.push({
270
+ field: `${itemPath}.${path ?? err.field}`,
271
+ errors: [reason],
272
+ kind: err.kind
273
+ });
252
274
  }
253
275
  }
254
276
  }
@@ -273,15 +295,34 @@ export async function validateField(field, value, context = {}) {
273
295
  if (shapeError) {
274
296
  return {
275
297
  isValid: false,
276
- errors: [{ level: 'error', message: `Field "${field.name}" ${shapeError}` }]
298
+ errors: [
299
+ { level: 'error', message: `Field "${field.name}" ${shapeError}`, kind: 'structural' }
300
+ ]
277
301
  };
278
302
  }
303
+ // Object fields were previously never recursed into: the shape check above only
304
+ // confirms the value IS an object, so a required field nested inside one was
305
+ // silently unenforced and an undeclared key inside one was never seen.
306
+ if (field.type === 'object' && isPlainObject(value) && Array.isArray(field.fields)) {
307
+ const nested = await validateFieldSet(field.fields, value, context);
308
+ for (const err of nested) {
309
+ allErrors.push({
310
+ level: 'error',
311
+ message: `Field "${field.name}.${err.field}" ${err.errors.join('; ')}`,
312
+ kind: err.kind
313
+ });
314
+ }
315
+ }
279
316
  // Array items are never validated by the shape check above (it only confirms
280
317
  // the value IS an array) — recurse into each item against `field.of` here.
281
318
  if (field.type === 'array' && Array.isArray(value)) {
282
319
  const itemErrors = await validateArrayItems(field, value, context);
283
320
  for (const err of itemErrors) {
284
- allErrors.push({ level: 'error', message: `Field "${err.field}" ${err.errors.join('; ')}` });
321
+ allErrors.push({
322
+ level: 'error',
323
+ message: `Field "${err.field}" ${err.errors.join('; ')}`,
324
+ kind: err.kind
325
+ });
285
326
  }
286
327
  }
287
328
  // Add automatic validation for date/datetime/url fields based on type
@@ -399,6 +440,27 @@ export function getValidationClasses(hasErrors) {
399
440
  */
400
441
  async function validateFieldSet(fields, data, context) {
401
442
  const validationErrors = [];
443
+ // Keys present in the data but absent from the schema.
444
+ //
445
+ // Everything below walks the *schema's* fields and reads `data[field.name]`,
446
+ // so without this pass an undeclared key is never looked at — it validates
447
+ // clean and is persisted verbatim. That's how an agent writing invented field
448
+ // names silently corrupts a document.
449
+ //
450
+ // Underscore-prefixed keys are structural metadata (`_type`, `_key`, `_ref`),
451
+ // not content, so they're never "unknown".
452
+ const declared = new Set(fields.map((field) => field.name));
453
+ for (const key of Object.keys(data ?? {})) {
454
+ if (key.startsWith('_'))
455
+ continue;
456
+ if (declared.has(key))
457
+ continue;
458
+ validationErrors.push({
459
+ field: key,
460
+ errors: [`Unknown field "${key}" — not declared in the schema`],
461
+ kind: 'structural'
462
+ });
463
+ }
402
464
  for (const field of fields) {
403
465
  const value = data[field.name];
404
466
  const result = await validateField(field, value, {
@@ -406,11 +468,16 @@ async function validateFieldSet(fields, data, context) {
406
468
  document: context.document !== undefined ? context.document : data
407
469
  });
408
470
  if (!result.isValid) {
409
- const errorMessages = result.errors.filter((e) => e.level === 'error').map((e) => e.message);
471
+ const errorEntries = result.errors.filter((e) => e.level === 'error');
472
+ const errorMessages = errorEntries.map((e) => e.message);
410
473
  if (errorMessages.length > 0) {
411
474
  validationErrors.push({
412
475
  field: field.name,
413
- errors: errorMessages
476
+ errors: errorMessages,
477
+ // One structural error makes the whole field structural: the value
478
+ // can't be interpreted, so any content rules reported alongside it
479
+ // are noise anyway.
480
+ kind: errorEntries.some((e) => e.kind === 'structural') ? 'structural' : 'content'
414
481
  });
415
482
  }
416
483
  }
@@ -449,6 +516,7 @@ export async function validateDocumentData(schema, data, context = {}) {
449
516
  return {
450
517
  isValid: validationErrors.length === 0,
451
518
  errors: validationErrors,
519
+ structuralErrors: validationErrors.filter((e) => e.kind === 'structural'),
452
520
  normalizedData
453
521
  };
454
522
  }
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from './forms/index.js';
9
9
  export * from './theme/index.js';
10
10
  export * from './plugins/index.js';
11
11
  export * from './utils/index.js';
12
+ export * from './auth/invitation-status.js';
12
13
  export * from './api/index.js';
13
14
  export type { ApiResponse } from './api/index.js';
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAkBA,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGjG,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AAGzC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,cAAc,sBAAsB,CAAC;AAIrC,cAAc,gBAAgB,CAAC;AAI/B,cAAc,eAAe,CAAC;AAG9B,cAAc,eAAe,CAAC;AAI9B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAG9B,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAkBA,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGjG,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AAGzC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,cAAc,sBAAsB,CAAC;AAIrC,cAAc,gBAAgB,CAAC;AAI/B,cAAc,eAAe,CAAC;AAG9B,cAAc,eAAe,CAAC;AAI9B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAI9B,cAAc,0BAA0B,CAAC;AAGzC,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -36,6 +36,9 @@ export * from './theme/index.js';
36
36
  export * from './plugins/index.js';
37
37
  // General utility functions (logger, image URL builder, etc)
38
38
  export * from './utils/index.js';
39
+ // Invitation state predicates. Plain functions over a plain type — the one
40
+ // definition of "pending"/"expired" shared by cms-core, @aphexcms/auth and apps.
41
+ export * from './auth/invitation-status.js';
39
42
  // Unified API client
40
43
  export * from './api/index.js';
41
44
  // NOTE: The following are intentionally NOT re-exported from this root
@@ -6,7 +6,7 @@ import type { LocalAPI } from '../local-api/index.js';
6
6
  import type { PartResolver } from '../plugins/resolver.js';
7
7
  import { type RunDueJobsResult } from './run-due-jobs.js';
8
8
  import { type RelayOutboxResult } from './relay.js';
9
- import { type PluginSettingsReader } from '../events/consumer.js';
9
+ import { type ConsumerAssetService, type PluginSettingsReader } from '../events/consumer.js';
10
10
  /**
11
11
  * The slice of the CMS service container the runner needs. Structurally a subset
12
12
  * of `CMSInstances`, so callers can pass `event.locals.aphexCMS` (or `c.var.aphexCMS`)
@@ -22,6 +22,12 @@ export interface JobRunnerServices {
22
22
  pluginSettingsService: PluginSettingsReader;
23
23
  /** Handed to event consumers that send notifications; `null`/absent when email isn't configured. */
24
24
  emailAdapter?: EmailAdapter | null;
25
+ /**
26
+ * Handed to event consumers that erase or rewrite media — notably the built-in
27
+ * `user.deleted` avatar erasure, which needs the file gone from object storage and not
28
+ * merely the row gone from the table.
29
+ */
30
+ assetService?: ConsumerAssetService | null;
25
31
  }
26
32
  export interface RunJobsBatchOptions {
27
33
  /** Lease-owner label written to `cms_jobs.lease_owner` (crash-recovery visibility). */
@@ -1 +1 @@
1
- {"version":3,"file":"run-batch.d.ts","sourceRoot":"","sources":["../../src/lib/jobs/run-batch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,iGAAiG;IACjG,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,oGAAoG;IACpG,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IACnC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC3D,4EAA4E;IAC5E,KAAK,EAAE,iBAAiB,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CACjC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAqC7B"}
1
+ {"version":3,"file":"run-batch.d.ts","sourceRoot":"","sources":["../../src/lib/jobs/run-batch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAGN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,iGAAiG;IACjG,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,oGAAoG;IACpG,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB;IACnC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC3D,4EAA4E;IAC5E,KAAK,EAAE,iBAAiB,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CACjC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAuC7B"}
@@ -29,6 +29,7 @@ import { consumerJobType, toConsumerJobHandler } from '../events/consumer.js';
29
29
  export async function runJobsBatch(services, options = {}) {
30
30
  const { config, databaseAdapter, logger, localAPI, partResolver, pluginSettingsService } = services;
31
31
  const emailAdapter = services.emailAdapter ?? null;
32
+ const assetService = services.assetService ?? null;
32
33
  const relay = await relayOutbox(services, {
33
34
  organizationId: options.organizationId,
34
35
  batchSize: config.jobs?.relayBatchSize
@@ -40,7 +41,8 @@ export async function runJobsBatch(services, options = {}) {
40
41
  for (const consumer of partResolver.eventConsumers()) {
41
42
  consumerHandlers[consumerJobType(consumer.id)] = toConsumerJobHandler(consumer.handler, {
42
43
  pluginSettingsService,
43
- emailAdapter
44
+ emailAdapter,
45
+ assetService
44
46
  });
45
47
  }
46
48
  const jobs = await runDueJobs({
@@ -65,7 +65,8 @@ export declare class OrganizationsApi {
65
65
  success: boolean;
66
66
  }>>;
67
67
  /**
68
- * Delete an organization (super_admin only)
68
+ * Delete an organization, its media, and every membership in it. Owners only
69
+ * enforced by the route, not here.
69
70
  */
70
71
  static remove(id: string): Promise<ApiResponse<{
71
72
  success: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../../../src/lib/api/organizations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EACX,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAC3D,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE3D,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACzD,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,gBAAgB;IAC5B;;OAEG;WACU,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAIjE;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIxF;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAIhG;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIpE;;OAEG;WACU,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAY5D;;OAEG;WACU,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAIrE;;OAEG;WACU,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAI9F;;OAEG;WACU,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAIhG;;OAEG;WACU,gBAAgB,CAC5B,IAAI,EAAE,uBAAuB,GAC3B,OAAO,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAI3C;;OAEG;WACU,MAAM,CAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,yBAAyB,GAC7B,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIrC;;OAEG;WACU,gBAAgB,CAC5B,IAAI,EAAE,uBAAuB,GAC3B,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAI7C;;OAEG;WACU,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAG3E;AAGD,eAAO,MAAM,aAAa;;;;;;;;;;;;;CAazB,CAAC"}
1
+ {"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../../../src/lib/api/organizations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EACX,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAC3D,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE3D,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACzD,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,gBAAgB;IAC5B;;OAEG;WACU,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAIjE;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIxF;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAIhG;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIpE;;OAEG;WACU,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAY5D;;OAEG;WACU,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAIrE;;OAEG;WACU,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAI9F;;OAEG;WACU,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAIhG;;OAEG;WACU,gBAAgB,CAC5B,IAAI,EAAE,uBAAuB,GAC3B,OAAO,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAI3C;;OAEG;WACU,MAAM,CAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,yBAAyB,GAC7B,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAIrC;;OAEG;WACU,gBAAgB,CAC5B,IAAI,EAAE,uBAAuB,GAC3B,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAI7C;;;OAGG;WACU,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAG3E;AAGD,eAAO,MAAM,aAAa;;;;;;;;;;;;;CAazB,CAAC"}
@@ -76,7 +76,8 @@ export class OrganizationsApi {
76
76
  return apiClient.delete('/organizations/invitations', data);
77
77
  }
78
78
  /**
79
- * Delete an organization (super_admin only)
79
+ * Delete an organization, its media, and every membership in it. Owners only
80
+ * enforced by the route, not here.
80
81
  */
81
82
  static async remove(id) {
82
83
  return apiClient.delete(`/organizations/${id}`);
@@ -1 +1 @@
1
- {"version":3,"file":"organizations.js","sourceRoot":"","sources":["../../../src/lib/api/organizations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"organizations.js","sourceRoot":"","sources":["../../../src/lib/api/organizations.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,25 @@
1
1
  import { z } from 'zod';
2
2
  export declare const apiKeyPermissionSchema: z.ZodEnum<{
3
- read: "read";
4
3
  write: "write";
4
+ read: "read";
5
5
  }>;
6
6
  export declare const apiKeyCapabilitySchema: z.ZodString;
7
7
  export declare const createApiKeyRequest: z.ZodPipe<z.ZodObject<{
8
8
  name: z.ZodString;
9
9
  permissions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
10
- read: "read";
11
10
  write: "write";
11
+ read: "read";
12
12
  }>>>;
13
13
  capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
14
  expiresInDays: z.ZodOptional<z.ZodNumber>;
15
15
  }, z.core.$strip>, z.ZodTransform<{
16
- permissions: ("read" | "write")[] | undefined;
16
+ permissions: ("write" | "read")[] | undefined;
17
17
  capabilities: string[] | undefined;
18
18
  name: string;
19
19
  expiresInDays?: number | undefined;
20
20
  }, {
21
21
  name: string;
22
- permissions?: ("read" | "write")[] | undefined;
22
+ permissions?: ("write" | "read")[] | undefined;
23
23
  capabilities?: string[] | undefined;
24
24
  expiresInDays?: number | undefined;
25
25
  }>>;
@@ -43,6 +43,7 @@ export declare const listDocumentsQuery: z.ZodObject<{
43
43
  type: z.ZodOptional<z.ZodString>;
44
44
  docType: z.ZodOptional<z.ZodString>;
45
45
  status: z.ZodOptional<z.ZodString>;
46
+ search: z.ZodOptional<z.ZodString>;
46
47
  page: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
47
48
  pageSize: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
48
49
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;