@cosmicdrift/kumiko-bundled-features 0.366.0 → 0.368.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 (365) hide show
  1. package/dist/audit/handlers/details.query.js +1 -1
  2. package/dist/audit/handlers/list.query.js +1 -1
  3. package/dist/audit/run-escape-hatch-retention.js +1 -1
  4. package/dist/auth-email-password/bootstrap.js +1 -1
  5. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +6 -3
  6. package/dist/auth-email-password/handlers/invite-accept.write.js +6 -3
  7. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  8. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +6 -3
  9. package/dist/auth-email-password/handlers/signup-confirm.write.js +1 -1
  10. package/dist/auth-email-password/seeding.js +2 -2
  11. package/dist/auth-foundation/feature.d.ts +4 -0
  12. package/dist/auth-foundation/feature.js +37 -33
  13. package/dist/auth-foundation/index.d.ts +1 -1
  14. package/dist/auth-foundation/index.js +1 -1
  15. package/dist/auth-mfa/db/queries.js +1 -2
  16. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
  17. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  18. package/dist/auth-mfa/handlers/reencrypt.job.js +2 -3
  19. package/dist/auth-mfa/handlers/status.query.js +1 -1
  20. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  21. package/dist/auth-mfa/mfa-code-verifier.js +1 -1
  22. package/dist/auth-mfa/mfa-status-checker.js +1 -1
  23. package/dist/auth-mfa-user-data/index.d.ts +4 -0
  24. package/dist/auth-mfa-user-data/index.js +13 -9
  25. package/dist/billing-foundation/billing-info-query.js +1 -1
  26. package/dist/billing-foundation/feature.d.ts +1 -0
  27. package/dist/billing-foundation/feature.js +5 -6
  28. package/dist/billing-foundation/handlers/create-portal-session.write.js +1 -1
  29. package/dist/billing-foundation/projection.js +1 -2
  30. package/dist/cap-counter/calendar-cap-usage-reservation.d.ts +7 -0
  31. package/dist/cap-counter/calendar-cap-usage-reservation.js +28 -2
  32. package/dist/cap-counter/cap-reservation.d.ts +16 -0
  33. package/dist/cap-counter/cap-reservation.js +144 -14
  34. package/dist/cap-counter/feature.d.ts +4 -0
  35. package/dist/cap-counter/feature.js +74 -68
  36. package/dist/cap-counter/handlers/increment-rolling.write.js +3 -4
  37. package/dist/cap-counter/index.d.ts +3 -2
  38. package/dist/cap-counter/index.js +3 -2
  39. package/dist/cap-counter/tables.js +10 -3
  40. package/dist/cap-overview/handlers/caps-usage.query.js +1 -2
  41. package/dist/cap-overview/handlers/tenant-caps-list.query.js +1 -2
  42. package/dist/cap-overview/handlers/tenant-options.query.js +1 -1
  43. package/dist/channel-email/email-channel.d.ts +5 -1
  44. package/dist/channel-email/email-channel.js +8 -2
  45. package/dist/channel-email/feature.js +1 -1
  46. package/dist/channel-in-app/handlers/inbox.query.js +1 -1
  47. package/dist/channel-in-app/handlers/mark-all-read.write.js +1 -1
  48. package/dist/channel-in-app/handlers/mark-read.write.js +1 -1
  49. package/dist/channel-in-app/handlers/unread-count.query.js +1 -1
  50. package/dist/channel-in-app/tables.js +1 -2
  51. package/dist/compliance-profiles/handlers/for-tenant.query.js +1 -1
  52. package/dist/compliance-profiles/handlers/needs-profile.query.js +1 -1
  53. package/dist/compliance-profiles/handlers/set-profile.write.js +1 -2
  54. package/dist/compliance-profiles/resolve-for-tenant.js +1 -1
  55. package/dist/compliance-profiles/seeding.js +3 -5
  56. package/dist/compliance-profiles-ops/index.d.ts +8 -0
  57. package/dist/compliance-profiles-ops/index.js +19 -15
  58. package/dist/config/db/queries/resolver.js +1 -1
  59. package/dist/config/handlers/reencrypt.job.js +2 -2
  60. package/dist/config/resolver.js +1 -1
  61. package/dist/config/write-helpers.js +1 -1
  62. package/dist/crypto-shredding/handlers/forget-subject.write.js +6 -3
  63. package/dist/custom-fields/db/queries/field-access.js +1 -1
  64. package/dist/custom-fields/db/queries/projection.js +1 -1
  65. package/dist/custom-fields/db/queries/quota.js +1 -1
  66. package/dist/custom-fields/db/queries/retention.js +1 -2
  67. package/dist/custom-fields/db/queries/user-data-rights.js +1 -1
  68. package/dist/custom-fields/feature.d.ts +20 -2
  69. package/dist/custom-fields/feature.js +9 -13
  70. package/dist/custom-fields/handlers/clear-custom-field.write.js +2 -2
  71. package/dist/custom-fields/handlers/delete-system-field.write.js +2 -2
  72. package/dist/custom-fields/handlers/delete-tenant-field.write.js +2 -2
  73. package/dist/custom-fields/handlers/set-custom-field.write.js +2 -2
  74. package/dist/custom-fields/wire-for-entity.js +4 -4
  75. package/dist/data-retention/resolve-for-tenant.js +1 -1
  76. package/dist/data-retention/run-retention-cleanup.js +17 -13
  77. package/dist/delivery/address-opt-out.js +1 -2
  78. package/dist/delivery/attempt-log-retention.js +1 -1
  79. package/dist/delivery/channel-context.js +2 -1
  80. package/dist/delivery/db/queries/address-opt-outs.js +1 -1
  81. package/dist/delivery/db/queries/preferences.js +1 -1
  82. package/dist/delivery/delivery-service.d.ts +2 -0
  83. package/dist/delivery/delivery-service.js +46 -11
  84. package/dist/delivery/feature.js +2 -2
  85. package/dist/delivery/handlers/log.query.js +2 -3
  86. package/dist/delivery/handlers/preferences.query.js +1 -1
  87. package/dist/delivery/handlers/unsubscribe-address.write.d.ts +6 -0
  88. package/dist/delivery/handlers/unsubscribe-address.write.js +8 -5
  89. package/dist/delivery/index.d.ts +3 -0
  90. package/dist/delivery/index.js +2 -0
  91. package/dist/delivery/testing.d.ts +2 -0
  92. package/dist/delivery/types.d.ts +2 -1
  93. package/dist/delivery/unsubscribe-link.d.ts +25 -0
  94. package/dist/delivery/unsubscribe-link.js +40 -0
  95. package/dist/delivery/unsubscribe-page-strings.d.ts +11 -0
  96. package/dist/delivery/unsubscribe-page-strings.js +15 -0
  97. package/dist/delivery/unsubscribe.d.ts +3 -0
  98. package/dist/delivery/unsubscribe.js +65 -29
  99. package/dist/delivery/upsert-preference.js +1 -2
  100. package/dist/derivatives-sharp/feature.d.ts +4 -0
  101. package/dist/derivatives-sharp/feature.js +15 -11
  102. package/dist/derivatives-sharp/index.d.ts +1 -1
  103. package/dist/derivatives-sharp/index.js +1 -1
  104. package/dist/document-ingest-foundation/feature.d.ts +7 -0
  105. package/dist/document-ingest-foundation/feature.js +94 -90
  106. package/dist/document-ingest-foundation/forget-extract-with-file-ref.js +3 -3
  107. package/dist/document-ingest-foundation/index.d.ts +1 -1
  108. package/dist/document-ingest-foundation/index.js +1 -1
  109. package/dist/feature-toggles/global-feature-state-table.js +1 -2
  110. package/dist/feature-toggles/handlers/set.write.js +3 -5
  111. package/dist/feature-toggles/toggle-runtime.js +1 -1
  112. package/dist/file-derivatives/feature.d.ts +1 -0
  113. package/dist/file-derivatives/feature.js +2 -1
  114. package/dist/file-derivatives/handlers/public-variant-by-file-ref.query.js +1 -1
  115. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  116. package/dist/file-foundation/feature.d.ts +6 -0
  117. package/dist/file-foundation/feature.js +29 -25
  118. package/dist/file-foundation/index.d.ts +1 -1
  119. package/dist/file-foundation/index.js +1 -1
  120. package/dist/file-foundation/read-file-ref-content.js +1 -1
  121. package/dist/file-provider-inmemory/feature.d.ts +4 -0
  122. package/dist/file-provider-inmemory/feature.js +24 -20
  123. package/dist/file-provider-inmemory/index.d.ts +1 -1
  124. package/dist/file-provider-inmemory/index.js +1 -1
  125. package/dist/file-provider-s3/env-feature.d.ts +3 -0
  126. package/dist/file-provider-s3/env-feature.js +46 -0
  127. package/dist/file-provider-s3/feature.d.ts +26 -0
  128. package/dist/file-provider-s3/feature.js +84 -72
  129. package/dist/file-provider-s3/index.d.ts +1 -1
  130. package/dist/file-provider-s3/index.js +1 -1
  131. package/dist/file-provider-s3/lib/index.d.ts +3 -0
  132. package/dist/file-provider-s3/lib/index.js +2 -0
  133. package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.js +19 -19
  134. package/dist/file-provider-s3-env/index.d.ts +8 -1
  135. package/dist/file-provider-s3-env/index.js +7 -2
  136. package/dist/files-provider-s3/index.d.ts +5 -3
  137. package/dist/files-provider-s3/index.js +5 -2
  138. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +1 -1
  139. package/dist/files-tenant-data/hooks.js +1 -2
  140. package/dist/folders/feature.d.ts +6 -2
  141. package/dist/folders/feature.js +4 -2
  142. package/dist/folders-user-data/index.d.ts +4 -0
  143. package/dist/folders-user-data/index.js +21 -17
  144. package/dist/form-draft/db/queries/cleanup.js +1 -1
  145. package/dist/form-draft/db/queries/draft-count.js +1 -1
  146. package/dist/form-draft/db/queries/owned-file-refs.js +1 -2
  147. package/dist/form-draft/feature.d.ts +4 -0
  148. package/dist/form-draft/feature.js +5 -1
  149. package/dist/form-draft/handlers/cleanup.job.js +2 -2
  150. package/dist/form-draft/index.d.ts +1 -1
  151. package/dist/form-draft/index.js +1 -1
  152. package/dist/form-draft/lookup.js +1 -1
  153. package/dist/form-draft-user-data/index.d.ts +4 -0
  154. package/dist/form-draft-user-data/index.js +13 -9
  155. package/dist/inbound-mail-foundation/feature.d.ts +4 -0
  156. package/dist/inbound-mail-foundation/feature.js +151 -147
  157. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -2
  158. package/dist/inbound-mail-foundation/index.d.ts +1 -1
  159. package/dist/inbound-mail-foundation/index.js +1 -1
  160. package/dist/inbound-mail-foundation/oauth-access-token.js +1 -2
  161. package/dist/inbound-mail-foundation/projection.js +1 -2
  162. package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
  163. package/dist/inbound-provider-imap/feature.d.ts +4 -0
  164. package/dist/inbound-provider-imap/feature.js +16 -12
  165. package/dist/inbound-provider-imap/index.d.ts +1 -1
  166. package/dist/inbound-provider-imap/index.js +1 -1
  167. package/dist/inbound-provider-inmemory/feature.d.ts +4 -0
  168. package/dist/inbound-provider-inmemory/feature.js +14 -10
  169. package/dist/inbound-provider-inmemory/index.d.ts +1 -1
  170. package/dist/inbound-provider-inmemory/index.js +1 -1
  171. package/dist/jobs/db/queries/retention.js +1 -1
  172. package/dist/jobs/db/queries/stale-run-sweep.js +1 -1
  173. package/dist/jobs/handlers/detail.query.js +1 -1
  174. package/dist/jobs/handlers/list.query.js +1 -2
  175. package/dist/jobs/handlers/retry.write.js +1 -1
  176. package/dist/jobs/handlers/tenant-failures.query.js +1 -1
  177. package/dist/jobs/handlers/tenant-runs.query.js +1 -1
  178. package/dist/jobs/job-run-logger.js +1 -2
  179. package/dist/jobs/tenant-job-failure-table.js +1 -2
  180. package/dist/jobs/tenant-job-run-table.js +1 -2
  181. package/dist/ledger/feature.d.ts +6 -2
  182. package/dist/ledger/feature.js +4 -2
  183. package/dist/mail-foundation/feature.d.ts +23 -1
  184. package/dist/mail-foundation/feature.js +76 -49
  185. package/dist/mail-foundation/index.d.ts +1 -1
  186. package/dist/mail-foundation/index.js +1 -1
  187. package/dist/mail-transport-inmemory/feature.d.ts +4 -0
  188. package/dist/mail-transport-inmemory/feature.js +20 -16
  189. package/dist/mail-transport-inmemory/index.d.ts +1 -1
  190. package/dist/mail-transport-inmemory/index.js +1 -1
  191. package/dist/mail-transport-smtp/feature.d.ts +16 -0
  192. package/dist/mail-transport-smtp/feature.js +85 -79
  193. package/dist/mail-transport-smtp/index.d.ts +1 -1
  194. package/dist/mail-transport-smtp/index.js +1 -1
  195. package/dist/managed-pages/handlers/by-slug.query.js +1 -1
  196. package/dist/managed-pages/handlers/by-tenant-published.query.js +1 -2
  197. package/dist/managed-pages/handlers/set.write.js +1 -2
  198. package/dist/managed-pages/seeding.js +3 -5
  199. package/dist/metrics/compute.d.ts +1 -1
  200. package/dist/metrics/filters.d.ts +1 -1
  201. package/dist/metrics/filters.js +1 -1
  202. package/dist/metrics/validate.js +1 -1
  203. package/dist/notes-history/feature.d.ts +7 -2
  204. package/dist/notes-history/feature.js +4 -2
  205. package/dist/notes-history/handlers/add-note.write.js +1 -1
  206. package/dist/notes-history-user-data/hooks.js +1 -1
  207. package/dist/notes-history-user-data/index.d.ts +4 -0
  208. package/dist/notes-history-user-data/index.js +21 -17
  209. package/dist/personal-access-tokens/feature.d.ts +4 -1
  210. package/dist/personal-access-tokens/feature.js +10 -2
  211. package/dist/personal-access-tokens/handlers/create.write.js +1 -1
  212. package/dist/personal-access-tokens/handlers/list.query.js +2 -2
  213. package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
  214. package/dist/personal-access-tokens/resolver.js +1 -1
  215. package/dist/personal-access-tokens/revoke-for-user.js +1 -1
  216. package/dist/personal-access-tokens/roles.js +3 -5
  217. package/dist/personal-access-tokens/screens.js +2 -0
  218. package/dist/readiness/feature.d.ts +8 -0
  219. package/dist/readiness/feature.js +18 -14
  220. package/dist/readiness/index.d.ts +1 -1
  221. package/dist/readiness/index.js +1 -1
  222. package/dist/secrets/db/queries/read.js +1 -1
  223. package/dist/secrets/feature.d.ts +3 -0
  224. package/dist/secrets/feature.js +3 -2
  225. package/dist/secrets/handlers/rotate.job.js +2 -3
  226. package/dist/secrets/secrets-context.js +3 -4
  227. package/dist/sessions/db/queries/cleanup.js +1 -1
  228. package/dist/sessions/handlers/detail.query.js +1 -1
  229. package/dist/sessions/handlers/list.query.js +2 -2
  230. package/dist/sessions/handlers/mine.query.js +1 -1
  231. package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
  232. package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
  233. package/dist/sessions/handlers/revoke.write.js +1 -1
  234. package/dist/sessions/session-callbacks.js +4 -6
  235. package/dist/sessions/testing.d.ts +1 -1
  236. package/dist/tags/feature.d.ts +6 -2
  237. package/dist/tags/feature.js +4 -2
  238. package/dist/template-resolver/api.js +1 -1
  239. package/dist/template-resolver/compile-document-body.js +47 -11
  240. package/dist/template-resolver/document-sanitizer.d.ts +2 -0
  241. package/dist/template-resolver/document-sanitizer.js +16 -1
  242. package/dist/template-resolver/document-schema.d.ts +2 -0
  243. package/dist/template-resolver/document-schema.js +31 -0
  244. package/dist/template-resolver/handlers/bundle-import.js +4 -3
  245. package/dist/template-resolver/handlers/by-slug.query.js +1 -1
  246. package/dist/template-resolver/handlers/by-tenant.query.js +1 -2
  247. package/dist/template-resolver/handlers/collection-item.query.js +1 -1
  248. package/dist/template-resolver/handlers/collection-list.query.js +1 -2
  249. package/dist/template-resolver/handlers/collection-set.write.js +1 -1
  250. package/dist/template-resolver/handlers/copy-locale.write.js +4 -3
  251. package/dist/template-resolver/handlers/diff-to-system.query.js +1 -1
  252. package/dist/template-resolver/handlers/export-bundle.query.js +1 -1
  253. package/dist/template-resolver/handlers/find-by-id.query.js +6 -2
  254. package/dist/template-resolver/handlers/layout-source.query.js +1 -1
  255. package/dist/template-resolver/handlers/list.query.js +4 -2
  256. package/dist/template-resolver/handlers/overview.query.js +5 -3
  257. package/dist/template-resolver/handlers/reset-to-system.write.js +1 -1
  258. package/dist/template-resolver/handlers/resource-remove.write.js +1 -1
  259. package/dist/template-resolver/handlers/set.write.js +1 -1
  260. package/dist/template-resolver/handlers/template-write.d.ts +2 -1
  261. package/dist/template-resolver/handlers/template-write.js +13 -2
  262. package/dist/template-resolver/handlers/tenant-overrides.query.js +1 -1
  263. package/dist/template-resolver/handlers/toggle-status.write.js +1 -1
  264. package/dist/template-resolver/handlers/usage.query.js +1 -1
  265. package/dist/template-resolver/handlers/validate.query.js +1 -1
  266. package/dist/template-resolver/index.d.ts +3 -2
  267. package/dist/template-resolver/index.js +3 -2
  268. package/dist/template-resolver/qualified-names.d.ts +1 -0
  269. package/dist/template-resolver/qualified-names.js +1 -0
  270. package/dist/template-resolver/seeding.d.ts +4 -0
  271. package/dist/template-resolver/seeding.js +43 -9
  272. package/dist/template-resolver/store-template-resource.js +1 -1
  273. package/dist/template-resolver/template-preview.js +3 -1
  274. package/dist/template-resolver/template-resources.js +1 -1
  275. package/dist/template-resolver/template-system-only.d.ts +8 -0
  276. package/dist/template-resolver/template-system-only.js +11 -0
  277. package/dist/template-resolver/template-validation.js +42 -28
  278. package/dist/template-resolver/testing.js +1 -1
  279. package/dist/template-resolver/web/i18n.js +1 -0
  280. package/dist/template-resolver-user-data/index.d.ts +4 -0
  281. package/dist/template-resolver-user-data/index.js +17 -13
  282. package/dist/tenant/handlers/active-tenant-ids.query.js +1 -1
  283. package/dist/tenant/handlers/add-member.write.js +1 -2
  284. package/dist/tenant/handlers/cancel-invitation.write.js +1 -1
  285. package/dist/tenant/handlers/invitations.query.js +1 -1
  286. package/dist/tenant/handlers/me.query.js +1 -1
  287. package/dist/tenant/handlers/member-directory.query.js +1 -1
  288. package/dist/tenant/handlers/members.query.js +1 -1
  289. package/dist/tenant/handlers/memberships.query.js +1 -1
  290. package/dist/tenant/handlers/remove-member.write.js +1 -2
  291. package/dist/tenant/handlers/resolve-user-ids.query.js +1 -1
  292. package/dist/tenant/handlers/team-list.query.js +1 -1
  293. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  294. package/dist/tenant/handlers/update-member-roles.write.js +1 -2
  295. package/dist/tenant/invited-membership.js +2 -3
  296. package/dist/tenant/last-tenant-admin.js +1 -2
  297. package/dist/tenant/seeding.js +12 -6
  298. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +1 -2
  299. package/dist/tenant-lifecycle/handlers/request-destruction.write.js +1 -2
  300. package/dist/tenant-lifecycle/lib/revoke-tenant-sessions.js +1 -1
  301. package/dist/tenant-lifecycle/lifecycle-gate.js +1 -1
  302. package/dist/tenant-lifecycle/run-tenant-destroy.js +3 -5
  303. package/dist/tenant-lifecycle/stages.js +10 -6
  304. package/dist/tenant-lifecycle/testing.d.ts +1 -1
  305. package/dist/tenant-lifecycle/testing.js +2 -2
  306. package/dist/tenant-settings/feature.d.ts +1 -0
  307. package/dist/tenant-settings/feature.js +2 -1
  308. package/dist/tier-engine/feature.d.ts +1 -8
  309. package/dist/tier-engine/feature.js +71 -78
  310. package/dist/tier-engine/handlers/get-tenant-tier.query.js +2 -3
  311. package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -2
  312. package/dist/user/db/queries/stream-tenant-backfill.js +1 -1
  313. package/dist/user/handlers/create.write.js +1 -2
  314. package/dist/user/handlers/find-for-auth.query.js +1 -1
  315. package/dist/user/handlers/list.query.js +1 -1
  316. package/dist/user/handlers/update-roles.js +1 -2
  317. package/dist/user/index.d.ts +1 -1
  318. package/dist/user/index.js +1 -1
  319. package/dist/user/invited-global-roles.js +2 -3
  320. package/dist/user/principal-status.d.ts +4 -0
  321. package/dist/user/principal-status.js +9 -3
  322. package/dist/user/resolve-display-names.js +1 -1
  323. package/dist/user/seeding.js +5 -6
  324. package/dist/user-data-rights/audit-download.js +2 -2
  325. package/dist/user-data-rights/db/queries/export-jobs.js +1 -1
  326. package/dist/user-data-rights/db/queries/forget-cleanup.js +1 -1
  327. package/dist/user-data-rights/handlers/download-by-job.query.js +1 -1
  328. package/dist/user-data-rights/handlers/download-by-token.query.js +1 -1
  329. package/dist/user-data-rights/handlers/export-status.query.js +1 -1
  330. package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
  331. package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
  332. package/dist/user-data-rights/handlers/request-export.write.js +1 -2
  333. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +3 -3
  334. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.d.ts +1 -1
  335. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.js +1 -1
  336. package/dist/user-data-rights/lib/update-user-lifecycle.d.ts +1 -0
  337. package/dist/user-data-rights/lib/update-user-lifecycle.js +3 -3
  338. package/dist/user-data-rights/run-export-jobs.js +2 -3
  339. package/dist/user-data-rights/run-forget-cleanup.js +9 -5
  340. package/dist/user-data-rights/run-user-export.js +9 -5
  341. package/dist/waitlist/handlers/invite.write.js +1 -2
  342. package/dist/waitlist/handlers/reject.write.js +1 -1
  343. package/dist/waitlist/lib.js +1 -2
  344. package/dist/workflow-runner/event-subscriber.js +1 -1
  345. package/dist/workflow-runner/feature.d.ts +4 -0
  346. package/dist/workflow-runner/feature.js +44 -40
  347. package/dist/workflow-runner/handlers/resume-run.write.js +1 -1
  348. package/dist/workflow-runner/index.d.ts +1 -1
  349. package/dist/workflow-runner/index.js +1 -1
  350. package/dist/workflow-runner/pending-projection.js +1 -1
  351. package/package.json +28 -11
  352. package/src/cap-counter/changes.json +13 -0
  353. package/src/channel-email/changes.json +6 -0
  354. package/src/crypto-shredding/changes.json +6 -0
  355. package/src/delivery/changes.json +12 -0
  356. package/src/file-provider-s3/changes.json +10 -1
  357. package/src/personal-access-tokens/changes.json +6 -0
  358. package/src/template-resolver/changes.json +25 -0
  359. package/src/user/changes.json +6 -0
  360. package/src/user-data-rights/changes.json +6 -0
  361. package/dist/file-provider-s3-env/feature.d.ts +0 -3
  362. package/dist/file-provider-s3-env/feature.js +0 -46
  363. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.d.ts +0 -0
  364. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.js +0 -0
  365. /package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.d.ts +0 -0
@@ -11,86 +11,98 @@
11
11
  // { build })`. file-foundation's Factory findet den Plugin via
12
12
  // registry.
13
13
  // 3. build(ctx, tenantId) liest config + secret, ruft `createS3Provider`
14
- // aus files-provider-s3 auf. Der EINZIGE Cross-Feature-Import
14
+ // aus ./lib auf. Der EINZIGE Cross-Feature-Import
15
15
  // des Plugins — bewusst lokal gehalten.
16
16
  //
17
17
  // **Pattern-Vorbild:** mirrors mail-transport-smtp.
18
18
  //
19
19
  // **Boot-Dependencies:** config + secrets + file-foundation.
20
- import { createS3Provider } from "@cosmicdrift/kumiko-bundled-features/files-provider-s3";
21
20
  import { requireDefined, requireNonEmpty, requireSecretSet, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
22
21
  import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
23
22
  import { access, createTenantConfig, defineFeature } from "@cosmicdrift/kumiko-framework/engine";
23
+ import { createFileProviderS3EnvFeature } from "./env-feature.js";
24
+ import { createS3Provider } from "./lib/s3-provider.js";
24
25
  const FEATURE_NAME = "file-provider-s3";
25
26
  // =============================================================================
26
27
  // Feature-definition
27
28
  // =============================================================================
28
- export const fileProviderS3Feature = defineFeature(FEATURE_NAME, (r) => {
29
- r.describe('Registers itself as the `"s3"` provider for `file-foundation` and owns the per-tenant config keys (`bucket`, `region`, `endpoint`, `forcePathStyle`, `accessKeyId`) and the encrypted `s3.secretAccessKey` secret. Compatible with any S3-compatible object store (AWS S3, Hetzner Object Storage); set credentials via the admin UI or a seed handler before the first file operation.');
30
- r.uiHints({
31
- displayLabel: "File Provider · S3",
32
- category: "storage",
33
- recommended: false,
34
- });
35
- r.requires({ features: ["config"] });
36
- r.requires({ features: ["secrets"] });
37
- r.requires({ features: ["file-foundation"] });
38
- const secretAccessKey = r.secret("s3.secretAccessKey", {
39
- label: { en: "S3 secret access key" },
40
- hint: {
41
- en: "Private half of the S3 key pair. Hetzner calls it 'Secret Key', AWS calls it 'Secret Access Key'.",
42
- },
43
- redact: (plaintext) => {
44
- if (plaintext.length < 8)
45
- return "•".repeat(plaintext.length);
46
- return `${plaintext.slice(0, 4)}...${plaintext.slice(-4)}`;
47
- },
48
- scope: "tenant",
49
- // required: true ↔ the missing-secret throw in readSecretAccessKey — keep in sync.
50
- required: true,
51
- });
52
- // required: true ↔ the requireNonEmpty calls in buildS3Provider — keep in sync.
53
- const configKeys = r.config({
54
- keys: {
55
- bucket: createTenantConfig("text", {
56
- required: true,
57
- default: "",
58
- write: access.roles("TenantAdmin", "SystemAdmin"),
59
- read: access.roles("TenantAdmin", "SystemAdmin"),
60
- }),
61
- region: createTenantConfig("text", {
62
- required: true,
63
- default: "",
64
- write: access.roles("TenantAdmin", "SystemAdmin"),
65
- read: access.roles("TenantAdmin", "SystemAdmin"),
66
- }),
67
- endpoint: createTenantConfig("text", {
68
- default: "",
69
- write: access.roles("TenantAdmin", "SystemAdmin"),
70
- read: access.roles("TenantAdmin", "SystemAdmin"),
71
- }),
72
- forcePathStyle: createTenantConfig("boolean", {
73
- default: false,
74
- write: access.roles("TenantAdmin", "SystemAdmin"),
75
- }),
76
- accessKeyId: createTenantConfig("text", {
77
- required: true,
78
- default: "",
79
- write: access.roles("TenantAdmin", "SystemAdmin"),
80
- read: access.roles("TenantAdmin", "SystemAdmin"),
81
- }),
82
- },
83
- });
84
- // Plugin-Registration. entityName "s3" ist was tenants in
85
- // file-foundation's `provider` config-key setzen.
86
- const plugin = {
87
- build: async (ctx, tenantId) => buildS3Provider(ctx, tenantId), // @wrapper-known semantic-alias
88
- };
89
- r.useExtension("fileProvider", "s3", plugin);
90
- return { configKeys, secretAccessKey };
91
- });
29
+ function createTenantConfigFileProviderS3Feature() {
30
+ return defineFeature(FEATURE_NAME, (r) => {
31
+ r.describe('Registers itself as the `"s3"` provider for `file-foundation` and owns the per-tenant config keys (`bucket`, `region`, `endpoint`, `forcePathStyle`, `accessKeyId`) and the encrypted `s3.secretAccessKey` secret. Compatible with any S3-compatible object store (AWS S3, Hetzner Object Storage); set credentials via the admin UI or a seed handler before the first file operation.');
32
+ r.uiHints({
33
+ displayLabel: "File Provider · S3",
34
+ category: "storage",
35
+ recommended: false,
36
+ });
37
+ r.requires({ features: ["config"] });
38
+ r.requires({ features: ["secrets"] });
39
+ r.requires({ features: ["file-foundation"] });
40
+ const secretAccessKey = r.secret("s3.secretAccessKey", {
41
+ label: { en: "S3 secret access key" },
42
+ hint: {
43
+ en: "Private half of the S3 key pair. Hetzner calls it 'Secret Key', AWS calls it 'Secret Access Key'.",
44
+ },
45
+ redact: (plaintext) => {
46
+ if (plaintext.length < 8)
47
+ return "•".repeat(plaintext.length);
48
+ return `${plaintext.slice(0, 4)}...${plaintext.slice(-4)}`;
49
+ },
50
+ scope: "tenant",
51
+ // required: true ↔ the missing-secret throw in readSecretAccessKey — keep in sync.
52
+ required: true,
53
+ });
54
+ // required: true ↔ the requireNonEmpty calls in buildS3Provider — keep in sync.
55
+ const configKeys = r.config({
56
+ keys: {
57
+ bucket: createTenantConfig("text", {
58
+ required: true,
59
+ default: "",
60
+ write: access.roles("TenantAdmin", "SystemAdmin"),
61
+ read: access.roles("TenantAdmin", "SystemAdmin"),
62
+ }),
63
+ region: createTenantConfig("text", {
64
+ required: true,
65
+ default: "",
66
+ write: access.roles("TenantAdmin", "SystemAdmin"),
67
+ read: access.roles("TenantAdmin", "SystemAdmin"),
68
+ }),
69
+ endpoint: createTenantConfig("text", {
70
+ default: "",
71
+ write: access.roles("TenantAdmin", "SystemAdmin"),
72
+ read: access.roles("TenantAdmin", "SystemAdmin"),
73
+ }),
74
+ forcePathStyle: createTenantConfig("boolean", {
75
+ default: false,
76
+ write: access.roles("TenantAdmin", "SystemAdmin"),
77
+ }),
78
+ accessKeyId: createTenantConfig("text", {
79
+ required: true,
80
+ default: "",
81
+ write: access.roles("TenantAdmin", "SystemAdmin"),
82
+ read: access.roles("TenantAdmin", "SystemAdmin"),
83
+ }),
84
+ },
85
+ });
86
+ // Plugin-Registration. entityName "s3" ist was tenants in
87
+ // file-foundation's `provider` config-key setzen.
88
+ const plugin = {
89
+ build: async (ctx, tenantId) => buildS3Provider(ctx, tenantId), // @wrapper-known semantic-alias
90
+ };
91
+ r.useExtension("fileProvider", "s3", plugin);
92
+ return { configKeys, secretAccessKey };
93
+ }, { dedupeOptions: {} });
94
+ }
95
+ export function createFileProviderS3Feature(options = {}) {
96
+ return options.fromEnv === true
97
+ ? createFileProviderS3EnvFeature()
98
+ : createTenantConfigFileProviderS3Feature();
99
+ }
100
+ /** @deprecated Use createFileProviderS3Feature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
101
+ export const fileProviderS3Feature = createFileProviderS3Feature();
102
+ // Typed config/secret handles are identical across instances, so one module-level instance serves them.
103
+ const tenantConfigFeature = createTenantConfigFileProviderS3Feature();
92
104
  /** Typed handle for the S3 secret-access-key. */
93
- export const S3_SECRET_ACCESS_KEY = fileProviderS3Feature.exports.secretAccessKey;
105
+ export const S3_SECRET_ACCESS_KEY = tenantConfigFeature.exports.secretAccessKey;
94
106
  // =============================================================================
95
107
  // Internal: build the FileStorageProvider from tenant config + secret
96
108
  // =============================================================================
@@ -100,12 +112,12 @@ async function buildS3Provider(ctx, tenantId) {
100
112
  throw new Error(`${FEATURE_NAME}: ctx.config is missing — feature requires the config-feature mounted in the registry`);
101
113
  }
102
114
  const FILE_HINT = "Set via tenant-admin UI or seed-handler before reading or writing files.";
103
- const bucket = requireNonEmpty(await ctxConfig(fileProviderS3Feature.exports.configKeys.bucket), FEATURE_NAME, "bucket", FILE_HINT);
104
- const region = requireNonEmpty(await ctxConfig(fileProviderS3Feature.exports.configKeys.region), FEATURE_NAME, "region", FILE_HINT);
105
- const endpointRaw = requireDefined(await ctxConfig(fileProviderS3Feature.exports.configKeys.endpoint), FEATURE_NAME, "endpoint"); // @cast-boundary engine-payload
115
+ const bucket = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.bucket), FEATURE_NAME, "bucket", FILE_HINT);
116
+ const region = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.region), FEATURE_NAME, "region", FILE_HINT);
117
+ const endpointRaw = requireDefined(await ctxConfig(tenantConfigFeature.exports.configKeys.endpoint), FEATURE_NAME, "endpoint"); // @cast-boundary engine-payload
106
118
  const endpoint = endpointRaw.length > 0 ? endpointRaw : undefined;
107
- const forcePathStyle = requireDefined(await ctxConfig(fileProviderS3Feature.exports.configKeys.forcePathStyle), FEATURE_NAME, "forcePathStyle"); // @cast-boundary engine-payload
108
- const accessKeyId = requireNonEmpty(await ctxConfig(fileProviderS3Feature.exports.configKeys.accessKeyId), FEATURE_NAME, "accessKeyId", FILE_HINT);
119
+ const forcePathStyle = requireDefined(await ctxConfig(tenantConfigFeature.exports.configKeys.forcePathStyle), FEATURE_NAME, "forcePathStyle"); // @cast-boundary engine-payload
120
+ const accessKeyId = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.accessKeyId), FEATURE_NAME, "accessKeyId", FILE_HINT);
109
121
  const secretAccessKey = await readSecretAccessKey(ctx, tenantId);
110
122
  return createS3Provider({
111
123
  bucket,
@@ -1 +1 @@
1
- export { fileProviderS3Feature, S3_SECRET_ACCESS_KEY } from "./feature.js";
1
+ export { createFileProviderS3Feature, type FileProviderS3FeatureOptions, fileProviderS3Feature, S3_SECRET_ACCESS_KEY, } from "./feature.js";
@@ -1,2 +1,2 @@
1
1
  // Public API of the file-provider-s3 bundled-feature.
2
- export { fileProviderS3Feature, S3_SECRET_ACCESS_KEY } from "./feature.js";
2
+ export { createFileProviderS3Feature, fileProviderS3Feature, S3_SECRET_ACCESS_KEY, } from "./feature.js";
@@ -0,0 +1,3 @@
1
+ export { createS3ProviderFromEnv, parseS3EnvConfig } from "./env-helper.js";
2
+ export type { S3ProviderConfig } from "./s3-provider.js";
3
+ export { createS3Provider, resolveForcePathStyle } from "./s3-provider.js";
@@ -0,0 +1,2 @@
1
+ export { createS3ProviderFromEnv, parseS3EnvConfig } from "./env-helper.js";
2
+ export { createS3Provider, resolveForcePathStyle } from "./s3-provider.js";
@@ -3,12 +3,12 @@ import { assertSafeStorageKey, } from "@cosmicdrift/kumiko-framework/files";
3
3
  // Operator-Pflicht-Setup (Multipart-Upload-Cleanup)
4
4
  // =============================================================================
5
5
  //
6
- // `writeStream` nutzt Bun's S3-Writer fuer echtes multipart-streaming. S3
7
- // created dabei eine Multipart-Upload-Session mit einer Upload-ID; bei
8
- // normaler Completion wird sie geschlossen. Wird der Export-Worker mid-write
9
- // gecancelt (Pod-Restart, K8s-OOM-Kill, Process-Signal), bleibt die Session
10
- // in S3 OFFEN und berechnet Storage-Kosten fuer die bereits hochgeladenen
11
- // Parts — bis sie via Lifecycle-Rule abgebrochen werden.
6
+ // `writeStream` uses Bun's S3 writer for real multipart streaming. S3
7
+ // creates a multipart-upload session with an upload ID for it; on normal
8
+ // completion the session is closed. If the export worker is cancelled
9
+ // mid-write (pod restart, K8s OOM kill, process signal), the session stays
10
+ // OPEN in S3 and bills storage for the parts already uploaded — until a
11
+ // lifecycle rule aborts it.
12
12
  //
13
13
  // **Pflicht-Operator-Setup auf jedem Bucket:**
14
14
  //
@@ -21,9 +21,9 @@ import { assertSafeStorageKey, } from "@cosmicdrift/kumiko-framework/files";
21
21
  // }]
22
22
  // }
23
23
  //
24
- // AWS-CLI: `aws s3api put-bucket-lifecycle-configuration --bucket <name>
25
- // --lifecycle-configuration file://lifecycle.json`. Hetzner Object Storage
26
- // + R2 + Minio supporten dieselbe Syntax.
24
+ // AWS CLI: `aws s3api put-bucket-lifecycle-configuration --bucket <name>
25
+ // --lifecycle-configuration file://lifecycle.json`. Hetzner Object Storage,
26
+ // R2 and Minio support the same syntax.
27
27
  //
28
28
  // =============================================================================
29
29
  // Operator-Pflicht-Setup (IAM: list permission)
@@ -82,11 +82,11 @@ export function createS3Provider(config) {
82
82
  },
83
83
  async writeStream(key, source, options) {
84
84
  assertSafeStorageKey(key);
85
- // Echtes multipart-streaming via Bun's S3-Writer — partSize steuert die
86
- // Part-Boundary intern (AWS/R2 verlangen non-final Parts >= 5 MiB,
87
- // sonst EntityTooSmall beim CompleteMultipartUpload). Manuelles flush()
88
- // hier wuerde genau diese Garantie brechen, sobald die Source-Chunks
89
- // nicht auf partSize aufgehen.
85
+ // Real multipart streaming via Bun's S3 writer — partSize controls the
86
+ // part boundary internally (AWS/R2 require non-final parts >= 5 MiB,
87
+ // otherwise EntityTooSmall on CompleteMultipartUpload). A manual flush()
88
+ // here would break exactly that guarantee as soon as the source chunks
89
+ // do not line up with partSize.
90
90
  const writer = client.file(key).writer({
91
91
  ...(options?.mimeType !== undefined && { type: options.mimeType }),
92
92
  retry: 3,
@@ -94,8 +94,8 @@ export function createS3Provider(config) {
94
94
  partSize: STREAM_PART_SIZE,
95
95
  });
96
96
  for await (const chunk of source) {
97
- // Await applies Backpressure und bounded die in-flight Queue auf
98
- // queueSize, statt unbegrenzt zu puffern.
97
+ // Await applies backpressure and bounds the in-flight queue to
98
+ // queueSize instead of buffering without limit.
99
99
  await writer.write(chunk);
100
100
  }
101
101
  await writer.end();
@@ -106,9 +106,9 @@ export function createS3Provider(config) {
106
106
  },
107
107
  readStream(key) {
108
108
  assertSafeStorageKey(key);
109
- // Lazy: erst beim ersten chunk-pull wird der GET-Request abgesetzt.
110
- // Existiert der Key nicht, faellt der Error genau dort (nicht beim
111
- // readStream-Aufruf) — gleiches Lazy-Verhalten wie inmemory + local.
109
+ // Lazy: the GET request is only sent on the first chunk pull. If the key
110
+ // does not exist, the error surfaces right there (not on the readStream
111
+ // call) — same lazy behavior as inmemory + local.
112
112
  return {
113
113
  async *[Symbol.asyncIterator]() {
114
114
  for await (const chunk of client.file(key).stream()) {
@@ -1 +1,8 @@
1
- export { fileProviderS3EnvFeature } from "./feature.js";
1
+ /**
2
+ * @deprecated Use createFileProviderS3Feature({ fromEnv: true }) from
3
+ * `@cosmicdrift/kumiko-bundled-features/file-provider-s3`. Run `bun kumiko-upgrade --apply`.
4
+ * Removed in the first release after 2026-10-29.
5
+ */
6
+ export declare const fileProviderS3EnvFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
7
+ readonly exports: void;
8
+ };
@@ -1,2 +1,7 @@
1
- // Public API of the file-provider-s3-env bundled-feature.
2
- export { fileProviderS3EnvFeature } from "./feature.js";
1
+ import { createFileProviderS3Feature } from "../file-provider-s3/index.js";
2
+ /**
3
+ * @deprecated Use createFileProviderS3Feature({ fromEnv: true }) from
4
+ * `@cosmicdrift/kumiko-bundled-features/file-provider-s3`. Run `bun kumiko-upgrade --apply`.
5
+ * Removed in the first release after 2026-10-29.
6
+ */
7
+ export const fileProviderS3EnvFeature = createFileProviderS3Feature({ fromEnv: true });
@@ -1,3 +1,5 @@
1
- export { createS3ProviderFromEnv, parseS3EnvConfig } from "./env-helper.js";
2
- export type { S3ProviderConfig } from "./s3-provider.js";
3
- export { createS3Provider, resolveForcePathStyle } from "./s3-provider.js";
1
+ /**
2
+ * @deprecated Moved to `@cosmicdrift/kumiko-bundled-features/file-provider-s3/lib`. Run `bun kumiko-upgrade --apply`
3
+ * to rewrite imports. Removed in the first release after 2026-10-29.
4
+ */
5
+ export { createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, type S3ProviderConfig, } from "../file-provider-s3/lib/index.js";
@@ -1,2 +1,5 @@
1
- export { createS3ProviderFromEnv, parseS3EnvConfig } from "./env-helper.js";
2
- export { createS3Provider, resolveForcePathStyle } from "./s3-provider.js";
1
+ /**
2
+ * @deprecated Moved to `@cosmicdrift/kumiko-bundled-features/file-provider-s3/lib`. Run `bun kumiko-upgrade --apply`
3
+ * to rewrite imports. Removed in the first release after 2026-10-29.
4
+ */
5
+ export { createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, } from "../file-provider-s3/lib/index.js";
@@ -17,7 +17,7 @@
17
17
  // were a tenant. nextBatch pages tenants internally and buffers their
18
18
  // candidates into a flat queue so the shared deadline/circuit-breaker/signal
19
19
  // handling still applies per-key.
20
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
20
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
21
21
  import { parseDerivativeKey } from "@cosmicdrift/kumiko-framework/derivatives";
22
22
  import { assertSafeStorageKey, fileRefsTable, } from "@cosmicdrift/kumiko-framework/files";
23
23
  import * as z from "zod";
@@ -45,8 +45,7 @@
45
45
  // matches would still delete it out from under the tenant that claimed
46
46
  // its original. Batched: one existence query per chunk of listed keys,
47
47
  // not one query per key.
48
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
49
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
48
+ import { createEventStoreExecutor, selectMany } from "@cosmicdrift/kumiko-framework/db";
50
49
  import { createSystemUser, parseTenantId, } from "@cosmicdrift/kumiko-framework/engine";
51
50
  import { assertSafeStorageKey, fileRefEntity, fileRefsTable, storageKeyStemPrefix, tenantStoragePrefixes, } from "@cosmicdrift/kumiko-framework/files";
52
51
  import { runChunkedMigration } from "../shared/index.js";
@@ -2,7 +2,7 @@ import { type AccessRule, type EntityDefinition } from "@cosmicdrift/kumiko-fram
2
2
  type FoldersToggleable = {
3
3
  readonly default: boolean;
4
4
  };
5
- export declare const foldersFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
5
+ declare const defaultFoldersFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
6
6
  readonly exports: void;
7
7
  };
8
8
  export type FoldersFeatureOptions = {
@@ -41,5 +41,9 @@ export type FoldersFeatureOptions = {
41
41
  * otherwise considers every registered entity as a candidate host. */
42
42
  readonly parents?: readonly string[];
43
43
  };
44
- export declare function createFoldersFeature(opts?: FoldersFeatureOptions): typeof foldersFeature;
44
+ export declare function createFoldersFeature(opts?: FoldersFeatureOptions): typeof defaultFoldersFeature;
45
+ /** @deprecated Use createFoldersFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
46
+ export declare const foldersFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
47
+ readonly exports: void;
48
+ };
45
49
  export {};
@@ -62,7 +62,7 @@ function registerFolders(r, access, toggleable, ownership, parents) {
62
62
  description: "Lists the folder-membership rows of the caller's tenant; filter on entityId to learn which folder one entity sits in, or on folderId to list everything filed into a folder.",
63
63
  }));
64
64
  }
65
- export const foldersFeature = defineFeature(FOLDERS_FEATURE_NAME, (r) => registerFolders(r, DEFAULT_FOLDER_ACCESS, undefined, undefined, undefined));
65
+ const defaultFoldersFeature = defineFeature(FOLDERS_FEATURE_NAME, (r) => registerFolders(r, DEFAULT_FOLDER_ACCESS, undefined, undefined, undefined));
66
66
  function resolveAccess(opts) {
67
67
  if (opts.access !== undefined)
68
68
  return opts.access;
@@ -78,7 +78,7 @@ export function createFoldersFeature(opts = {}) {
78
78
  opts.toggleable === undefined &&
79
79
  opts.ownership === undefined &&
80
80
  opts.parents === undefined) {
81
- return foldersFeature;
81
+ return defaultFoldersFeature;
82
82
  }
83
83
  assertNoWhereRuleInOwnershipWrite("createFoldersFeature", opts.ownership?.write);
84
84
  if (opts.parents !== undefined && opts.parents.length === 0) {
@@ -90,3 +90,5 @@ export function createFoldersFeature(opts = {}) {
90
90
  const access = resolveAccess(opts);
91
91
  return defineFeature(FOLDERS_FEATURE_NAME, (r) => registerFolders(r, access, opts.toggleable, opts.ownership, opts.parents));
92
92
  }
93
+ /** @deprecated Use createFoldersFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
94
+ export const foldersFeature = createFoldersFeature();
@@ -1,3 +1,7 @@
1
+ export declare function createFoldersUserDataFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: void;
3
+ };
4
+ /** @deprecated Use createFoldersUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
5
  export declare const foldersUserDataFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
6
  readonly exports: void;
3
7
  };
@@ -5,20 +5,24 @@
5
5
  // folders stays usable without the user-data-rights stack. Mirrors credit-user-data.
6
6
  import { defineFeature, EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { folderAssignmentDeleteHook, folderAssignmentExportHook, folderDeleteHook, folderExportHook, } from "./hooks.js";
8
- export const foldersUserDataFeature = defineFeature("folders-user-data", (r) => {
9
- r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `folders` feature's `folder` + `folder-assignment` entities. Mounts the EXT_USER_DATA export + delete hooks so a tenant's folder tree and its entity-to-folder assignments are included in the user-data export bundle and erased on a tenant-scoped forget (single-user tenants only; multi-user + anonymize are no-ops since folder rows carry no per-user PII). Kept separate from `folders` so folder consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `folders`.");
10
- // user-data-rights is the hard dependency (EXT_USER_DATA host). `folders` is
11
- // OPTIONAL: if it's mounted toggleable(default=false) (e.g. per-tenant via
12
- // tier), a hard r.requires would throw an "effectively disabled" boot
13
- // warning even though the folder entities exist and the hooks work fine.
14
- r.requires({ features: ["user-data-rights"] });
15
- r.optionalRequires("folders");
16
- r.useExtension(EXT_USER_DATA, "folder", {
17
- export: folderExportHook,
18
- delete: folderDeleteHook,
19
- });
20
- r.useExtension(EXT_USER_DATA, "folder-assignment", {
21
- export: folderAssignmentExportHook,
22
- delete: folderAssignmentDeleteHook,
23
- });
24
- });
8
+ export function createFoldersUserDataFeature() {
9
+ return defineFeature("folders-user-data", (r) => {
10
+ r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `folders` feature's `folder` + `folder-assignment` entities. Mounts the EXT_USER_DATA export + delete hooks so a tenant's folder tree and its entity-to-folder assignments are included in the user-data export bundle and erased on a tenant-scoped forget (single-user tenants only; multi-user + anonymize are no-ops since folder rows carry no per-user PII). Kept separate from `folders` so folder consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `folders`.");
11
+ // user-data-rights is the hard dependency (EXT_USER_DATA host). `folders` is
12
+ // OPTIONAL: if it's mounted toggleable(default=false) (e.g. per-tenant via
13
+ // tier), a hard r.requires would throw an "effectively disabled" boot
14
+ // warning even though the folder entities exist and the hooks work fine.
15
+ r.requires({ features: ["user-data-rights"] });
16
+ r.optionalRequires("folders");
17
+ r.useExtension(EXT_USER_DATA, "folder", {
18
+ export: folderExportHook,
19
+ delete: folderDeleteHook,
20
+ });
21
+ r.useExtension(EXT_USER_DATA, "folder-assignment", {
22
+ export: folderAssignmentExportHook,
23
+ delete: folderAssignmentDeleteHook,
24
+ });
25
+ }, { dedupeOptions: {} });
26
+ }
27
+ /** @deprecated Use createFoldersUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
28
+ export const foldersUserDataFeature = createFoldersUserDataFeature();
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
3
3
  // COALESCE(modified_at, inserted_at) — a draft's "last touched" timestamp is
4
4
  // modified_at once the upsert path (save.write.ts) has updated it at least
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  // COUNT(*), not selectMany(...).length — save.write.ts checks this on every
3
3
  // create, and a draft's `values` blob can be up to FORM_DRAFT_VALUES_MAX_BYTES
4
4
  // (64KB); loading up to FORM_DRAFT_MAX_PER_OWNER full rows just to count them
@@ -1,5 +1,4 @@
1
- import { instantToTimestamptzParam, unsafeReadRetrying, } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { toPostgresArrayLiteral } from "@cosmicdrift/kumiko-framework/db";
1
+ import { instantToTimestamptzParam, toPostgresArrayLiteral, unsafeReadRetrying, } from "@cosmicdrift/kumiko-framework/db";
3
2
  // Narrows a draft blob's raw FileRef-shaped storageKeys (collectDraftFileRefKeys
4
3
  // output — extracted from free-form, client-supplied JSON, issue #1889) down to
5
4
  // the ones with a real, non-deleted file_refs row owned by this exact
@@ -1,3 +1,7 @@
1
+ export declare function createFormDraftFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: void;
3
+ };
4
+ /** @deprecated Use createFormDraftFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
5
  export declare const formDraftFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
6
  readonly exports: void;
3
7
  };
@@ -41,4 +41,8 @@ function registerFormDraft(r) {
41
41
  handler: (payload, ctx) => cleanupDraftsJob(payload, ctx, ctx.db.unsafeRaw()),
42
42
  });
43
43
  }
44
- export const formDraftFeature = defineFeature(FORM_DRAFT_FEATURE_NAME, registerFormDraft);
44
+ export function createFormDraftFeature() {
45
+ return defineFeature(FORM_DRAFT_FEATURE_NAME, registerFormDraft, { dedupeOptions: {} });
46
+ }
47
+ /** @deprecated Use createFormDraftFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
48
+ export const formDraftFeature = createFormDraftFeature();
@@ -37,7 +37,7 @@ async function releaseRowFileRefs(row, db, fileProviderResolver, log) {
37
37
  const isCreateMode = row.draftKey.includes(":new:");
38
38
  const ownedRefs = await filterOwnedFileRefs(db, row.tenantId, row.ownerId, keys, row.insertedAt, isCreateMode);
39
39
  const systemUser = createSystemUser(row.tenantId);
40
- const tenantDb = createTenantDb(db, row.tenantId, "system");
40
+ const tenantDb = createTenantDb({ db, tenantId: row.tenantId, mode: "system" });
41
41
  for (const ref of ownedRefs) {
42
42
  const forgetResult = await fileRefExecutor.forget({ id: ref.id }, systemUser, tenantDb);
43
43
  if (!forgetResult.isSuccess) {
@@ -78,7 +78,7 @@ export async function deleteStaleDraftsBatch(batch, db, retentionDays, log) {
78
78
  const byId = new Map(batch.map((row) => [row.id, row]));
79
79
  for (const [tenantId, ids] of groupStaleDraftIdsByTenant(batch)) {
80
80
  const systemUser = createSystemUser(tenantId);
81
- const tenantDb = createTenantDb(db, tenantId, "system");
81
+ const tenantDb = createTenantDb({ db, tenantId, mode: "system" });
82
82
  for (const id of ids) {
83
83
  // Race: user may have saved between select and here — skip if no longer stale.
84
84
  if (!(await isDraftStillStale(db, tenantId, id, retentionDays))) {
@@ -1,7 +1,7 @@
1
1
  export { FORM_DRAFT_ACCESS, FORM_DRAFT_FEATURE_NAME, FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT, FormDraftHandlers, FormDraftQueries, } from "./constants.js";
2
2
  export { formDraftEntity } from "./entity.js";
3
3
  export { formDraftExecutor, formDraftTable } from "./executor.js";
4
- export { formDraftFeature } from "./feature.js";
4
+ export { createFormDraftFeature, formDraftFeature } from "./feature.js";
5
5
  export { discardDraftWrite } from "./handlers/discard.write.js";
6
6
  export { type GetDraftResult, getDraftQuery } from "./handlers/get.query.js";
7
7
  export { type ListDraftsResult, listDraftsQuery } from "./handlers/list.query.js";
@@ -1,7 +1,7 @@
1
1
  export { FORM_DRAFT_ACCESS, FORM_DRAFT_FEATURE_NAME, FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT, FormDraftHandlers, FormDraftQueries, } from "./constants.js";
2
2
  export { formDraftEntity } from "./entity.js";
3
3
  export { formDraftExecutor, formDraftTable } from "./executor.js";
4
- export { formDraftFeature } from "./feature.js";
4
+ export { createFormDraftFeature, formDraftFeature } from "./feature.js";
5
5
  export { discardDraftWrite } from "./handlers/discard.write.js";
6
6
  export { getDraftQuery } from "./handlers/get.query.js";
7
7
  export { listDraftsQuery } from "./handlers/list.query.js";
@@ -1,4 +1,4 @@
1
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { formDraftTable } from "./executor.js";
3
3
  // Shared by save (upsert lookup + race re-lookup), discard, and get — always
4
4
  // scoped by tenantId + ownerId + draftKey, tenantId included explicitly
@@ -1,3 +1,7 @@
1
+ export declare function createFormDraftUserDataFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: void;
3
+ };
4
+ /** @deprecated Use createFormDraftUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
5
  export declare const formDraftUserDataFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
6
  readonly exports: void;
3
7
  };
@@ -6,12 +6,16 @@
6
6
  // pull a hard dependency. Mirrors notes-history-user-data.
7
7
  import { defineFeature, EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
8
8
  import { formDraftDeleteHook, formDraftExportHook } from "./hooks.js";
9
- export const formDraftUserDataFeature = defineFeature("form-draft-user-data", (r) => {
10
- r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `form-draft` feature's `form-draft` entity. Mounts the EXT_USER_DATA export hook so a user's saved drafts are included in the user-data export bundle, and a delete hook that physically removes the user's own draft rows on forget. Kept separate from `form-draft` so form-draft consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `form-draft`.");
11
- r.requires({ features: ["user-data-rights"] });
12
- r.optionalRequires("form-draft");
13
- r.useExtension(EXT_USER_DATA, "form-draft", {
14
- export: formDraftExportHook,
15
- delete: formDraftDeleteHook,
16
- });
17
- });
9
+ export function createFormDraftUserDataFeature() {
10
+ return defineFeature("form-draft-user-data", (r) => {
11
+ r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `form-draft` feature's `form-draft` entity. Mounts the EXT_USER_DATA export hook so a user's saved drafts are included in the user-data export bundle, and a delete hook that physically removes the user's own draft rows on forget. Kept separate from `form-draft` so form-draft consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `form-draft`.");
12
+ r.requires({ features: ["user-data-rights"] });
13
+ r.optionalRequires("form-draft");
14
+ r.useExtension(EXT_USER_DATA, "form-draft", {
15
+ export: formDraftExportHook,
16
+ delete: formDraftDeleteHook,
17
+ });
18
+ }, { dedupeOptions: {} });
19
+ }
20
+ /** @deprecated Use createFormDraftUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
21
+ export const formDraftUserDataFeature = createFormDraftUserDataFeature();
@@ -1,3 +1,7 @@
1
+ export declare function createInboundMailFoundationFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: void;
3
+ };
4
+ /** @deprecated Use createInboundMailFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
5
  export declare const inboundMailFoundationFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
6
  readonly exports: void;
3
7
  };