@cosmicdrift/kumiko-samples 0.367.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 (385) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +16 -2
  3. package/packages/bundled-features/src/audit/handlers/details.query.ts +1 -1
  4. package/packages/bundled-features/src/audit/handlers/list.query.ts +1 -1
  5. package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +5 -5
  6. package/packages/bundled-features/src/auth-email-password/bootstrap.ts +1 -1
  7. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +10 -3
  8. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +10 -3
  9. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  10. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +6 -2
  11. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +1 -1
  12. package/packages/bundled-features/src/auth-email-password/seeding.ts +2 -2
  13. package/packages/bundled-features/src/auth-foundation/feature.ts +43 -34
  14. package/packages/bundled-features/src/auth-foundation/index.ts +1 -0
  15. package/packages/bundled-features/src/auth-mfa/db/queries.ts +5 -2
  16. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
  17. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  18. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +2 -2
  19. package/packages/bundled-features/src/auth-mfa/handlers/status.query.ts +1 -1
  20. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  21. package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +1 -1
  22. package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +1 -1
  23. package/packages/bundled-features/src/auth-mfa-user-data/index.ts +19 -10
  24. package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +1 -1
  25. package/packages/bundled-features/src/billing-foundation/feature.ts +138 -135
  26. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +1 -1
  27. package/packages/bundled-features/src/billing-foundation/projection.ts +3 -2
  28. package/packages/bundled-features/src/cap-counter/calendar-cap-usage-reservation.ts +52 -1
  29. package/packages/bundled-features/src/cap-counter/cap-reservation.ts +203 -15
  30. package/packages/bundled-features/src/cap-counter/changes.json +13 -0
  31. package/packages/bundled-features/src/cap-counter/feature.ts +84 -73
  32. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +3 -4
  33. package/packages/bundled-features/src/cap-counter/index.ts +9 -1
  34. package/packages/bundled-features/src/cap-counter/tables.ts +10 -3
  35. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -2
  36. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +6 -2
  37. package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +1 -1
  38. package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +1 -1
  39. package/packages/bundled-features/src/channel-in-app/handlers/mark-all-read.write.ts +1 -1
  40. package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +1 -1
  41. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +1 -1
  42. package/packages/bundled-features/src/channel-in-app/tables.ts +1 -1
  43. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +1 -1
  44. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +1 -1
  45. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +1 -2
  46. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +1 -1
  47. package/packages/bundled-features/src/compliance-profiles/seeding.ts +8 -4
  48. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +26 -17
  49. package/packages/bundled-features/src/config/db/queries/resolver.ts +1 -1
  50. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +2 -2
  51. package/packages/bundled-features/src/config/resolver.ts +1 -1
  52. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  53. package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
  54. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +9 -7
  55. package/packages/bundled-features/src/custom-fields/db/queries/field-access.ts +1 -1
  56. package/packages/bundled-features/src/custom-fields/db/queries/projection.ts +1 -1
  57. package/packages/bundled-features/src/custom-fields/db/queries/quota.ts +1 -1
  58. package/packages/bundled-features/src/custom-fields/db/queries/retention.ts +6 -2
  59. package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +1 -1
  60. package/packages/bundled-features/src/custom-fields/feature.ts +11 -14
  61. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +2 -2
  62. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +2 -2
  63. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +2 -2
  64. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +2 -2
  65. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +4 -4
  66. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  67. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +16 -10
  68. package/packages/bundled-features/src/delivery/address-opt-out.ts +5 -2
  69. package/packages/bundled-features/src/delivery/attempt-log-retention.ts +1 -1
  70. package/packages/bundled-features/src/delivery/channel-context.ts +1 -1
  71. package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +1 -1
  72. package/packages/bundled-features/src/delivery/db/queries/preferences.ts +1 -1
  73. package/packages/bundled-features/src/delivery/delivery-service.ts +16 -6
  74. package/packages/bundled-features/src/delivery/feature.ts +1 -1
  75. package/packages/bundled-features/src/delivery/handlers/log.query.ts +3 -2
  76. package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +1 -1
  77. package/packages/bundled-features/src/delivery/upsert-preference.ts +5 -2
  78. package/packages/bundled-features/src/derivatives-sharp/feature.ts +21 -12
  79. package/packages/bundled-features/src/derivatives-sharp/index.ts +1 -1
  80. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +112 -103
  81. package/packages/bundled-features/src/document-ingest-foundation/forget-extract-with-file-ref.ts +3 -3
  82. package/packages/bundled-features/src/document-ingest-foundation/index.ts +4 -1
  83. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  84. package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -5
  85. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  86. package/packages/bundled-features/src/file-derivatives/feature.ts +134 -129
  87. package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +1 -1
  88. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  89. package/packages/bundled-features/src/file-foundation/feature.ts +38 -29
  90. package/packages/bundled-features/src/file-foundation/index.ts +1 -0
  91. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +1 -1
  92. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +32 -21
  93. package/packages/bundled-features/src/file-provider-inmemory/index.ts +6 -1
  94. package/packages/bundled-features/src/file-provider-s3/changes.json +10 -1
  95. package/packages/bundled-features/src/file-provider-s3/env-feature.ts +62 -0
  96. package/packages/bundled-features/src/file-provider-s3/feature.ts +107 -73
  97. package/packages/bundled-features/src/file-provider-s3/index.ts +6 -1
  98. package/packages/bundled-features/src/file-provider-s3/lib/index.ts +3 -0
  99. package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/s3-provider.ts +19 -19
  100. package/packages/bundled-features/src/file-provider-s3-env/index.ts +7 -2
  101. package/packages/bundled-features/src/files-provider-s3/index.ts +11 -3
  102. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +1 -1
  103. package/packages/bundled-features/src/files-tenant-data/hooks.ts +1 -2
  104. package/packages/bundled-features/src/folders/feature.ts +8 -3
  105. package/packages/bundled-features/src/folders-user-data/index.ts +27 -18
  106. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
  107. package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +1 -1
  108. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +3 -2
  109. package/packages/bundled-features/src/form-draft/feature.ts +6 -1
  110. package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +2 -2
  111. package/packages/bundled-features/src/form-draft/index.ts +1 -1
  112. package/packages/bundled-features/src/form-draft/lookup.ts +1 -1
  113. package/packages/bundled-features/src/form-draft-user-data/index.ts +19 -10
  114. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +165 -154
  115. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +1 -2
  116. package/packages/bundled-features/src/inbound-mail-foundation/index.ts +1 -1
  117. package/packages/bundled-features/src/inbound-mail-foundation/oauth-access-token.ts +5 -2
  118. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +3 -2
  119. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
  120. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +22 -13
  121. package/packages/bundled-features/src/inbound-provider-imap/index.ts +6 -1
  122. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +20 -12
  123. package/packages/bundled-features/src/inbound-provider-inmemory/index.ts +1 -0
  124. package/packages/bundled-features/src/jobs/db/queries/retention.ts +1 -1
  125. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +1 -1
  126. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +1 -1
  127. package/packages/bundled-features/src/jobs/handlers/list.query.ts +7 -2
  128. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  129. package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +1 -1
  130. package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +1 -1
  131. package/packages/bundled-features/src/jobs/job-run-logger.ts +11 -10
  132. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  133. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  134. package/packages/bundled-features/src/ledger/feature.ts +6 -3
  135. package/packages/bundled-features/src/mail-foundation/feature.ts +57 -46
  136. package/packages/bundled-features/src/mail-foundation/index.ts +1 -0
  137. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +25 -17
  138. package/packages/bundled-features/src/mail-transport-inmemory/index.ts +6 -1
  139. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +91 -79
  140. package/packages/bundled-features/src/mail-transport-smtp/index.ts +1 -0
  141. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +1 -1
  142. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +1 -2
  143. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +1 -2
  144. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -4
  145. package/packages/bundled-features/src/metrics/compute.ts +1 -1
  146. package/packages/bundled-features/src/metrics/filters.ts +1 -1
  147. package/packages/bundled-features/src/metrics/validate.ts +1 -1
  148. package/packages/bundled-features/src/notes-history/feature.ts +6 -3
  149. package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
  150. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  151. package/packages/bundled-features/src/notes-history-user-data/index.ts +27 -18
  152. package/packages/bundled-features/src/personal-access-tokens/changes.json +6 -0
  153. package/packages/bundled-features/src/personal-access-tokens/feature.ts +17 -2
  154. package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
  155. package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -2
  156. package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
  157. package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
  158. package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -2
  159. package/packages/bundled-features/src/personal-access-tokens/roles.ts +8 -6
  160. package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -0
  161. package/packages/bundled-features/src/readiness/feature.ts +25 -16
  162. package/packages/bundled-features/src/readiness/index.ts +1 -1
  163. package/packages/bundled-features/src/secrets/db/queries/read.ts +1 -1
  164. package/packages/bundled-features/src/secrets/feature.ts +8 -3
  165. package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +2 -2
  166. package/packages/bundled-features/src/secrets/secrets-context.ts +4 -3
  167. package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +1 -1
  168. package/packages/bundled-features/src/sessions/handlers/detail.query.ts +1 -1
  169. package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -2
  170. package/packages/bundled-features/src/sessions/handlers/mine.query.ts +1 -1
  171. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +1 -1
  172. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
  173. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  174. package/packages/bundled-features/src/sessions/session-callbacks.ts +14 -7
  175. package/packages/bundled-features/src/sessions/testing.ts +1 -1
  176. package/packages/bundled-features/src/tags/feature.ts +6 -3
  177. package/packages/bundled-features/src/template-resolver/api.ts +1 -1
  178. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +1 -1
  179. package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +1 -1
  180. package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +1 -2
  181. package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
  182. package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -2
  183. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +1 -1
  184. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +1 -1
  185. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +1 -1
  186. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
  187. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +1 -1
  188. package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +1 -1
  189. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +1 -1
  190. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +1 -1
  191. package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +1 -1
  192. package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +1 -1
  193. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
  194. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +1 -1
  195. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +1 -1
  196. package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +1 -1
  197. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
  198. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +1 -1
  199. package/packages/bundled-features/src/template-resolver/seeding.ts +3 -3
  200. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +1 -1
  201. package/packages/bundled-features/src/template-resolver/template-preview.ts +1 -1
  202. package/packages/bundled-features/src/template-resolver/template-resources.ts +1 -1
  203. package/packages/bundled-features/src/template-resolver/testing.ts +1 -1
  204. package/packages/bundled-features/src/template-resolver-user-data/index.ts +23 -14
  205. package/packages/bundled-features/src/tenant/handlers/active-tenant-ids.query.ts +1 -1
  206. package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -2
  207. package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
  208. package/packages/bundled-features/src/tenant/handlers/invitations.query.ts +1 -1
  209. package/packages/bundled-features/src/tenant/handlers/me.query.ts +1 -1
  210. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
  211. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  212. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  213. package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -1
  214. package/packages/bundled-features/src/tenant/handlers/resolve-user-ids.query.ts +1 -1
  215. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  216. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
  217. package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -2
  218. package/packages/bundled-features/src/tenant/invited-membership.ts +2 -2
  219. package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -2
  220. package/packages/bundled-features/src/tenant/seeding.ts +12 -12
  221. package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +1 -2
  222. package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +1 -2
  223. package/packages/bundled-features/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +1 -1
  224. package/packages/bundled-features/src/tenant-lifecycle/lifecycle-gate.ts +1 -1
  225. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +3 -3
  226. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +10 -5
  227. package/packages/bundled-features/src/tenant-lifecycle/testing.ts +3 -3
  228. package/packages/bundled-features/src/tenant-settings/feature.ts +34 -29
  229. package/packages/bundled-features/src/tier-engine/feature.ts +426 -428
  230. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +2 -3
  231. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +5 -2
  232. package/packages/bundled-features/src/user/changes.json +6 -0
  233. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +1 -1
  234. package/packages/bundled-features/src/user/handlers/create.write.ts +1 -2
  235. package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +1 -1
  236. package/packages/bundled-features/src/user/handlers/list.query.ts +1 -1
  237. package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -1
  238. package/packages/bundled-features/src/user/index.ts +5 -1
  239. package/packages/bundled-features/src/user/invited-global-roles.ts +2 -2
  240. package/packages/bundled-features/src/user/principal-status.ts +13 -3
  241. package/packages/bundled-features/src/user/resolve-display-names.ts +1 -1
  242. package/packages/bundled-features/src/user/seeding.ts +5 -5
  243. package/packages/bundled-features/src/user-data-rights/audit-download.ts +2 -2
  244. package/packages/bundled-features/src/user-data-rights/db/queries/export-jobs.ts +1 -1
  245. package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +1 -1
  246. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +1 -1
  247. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +1 -1
  248. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +1 -1
  249. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -1
  250. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +1 -1
  251. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +1 -2
  252. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +3 -3
  253. package/packages/bundled-features/src/user-data-rights/lib/deny-if-target-outside-admin-tenant.ts +1 -1
  254. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +7 -2
  255. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +7 -3
  256. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +11 -5
  257. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +10 -5
  258. package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +1 -2
  259. package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
  260. package/packages/bundled-features/src/waitlist/lib.ts +5 -2
  261. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +1 -1
  262. package/packages/bundled-features/src/workflow-runner/feature.ts +58 -47
  263. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +1 -1
  264. package/packages/bundled-features/src/workflow-runner/index.ts +1 -1
  265. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +1 -1
  266. package/samples/apps/admin-console/src/run-config.ts +2 -2
  267. package/samples/apps/cap-billing-demo/package.json +3 -0
  268. package/samples/apps/cap-billing-demo/src/feature.ts +2 -2
  269. package/samples/apps/cap-billing-demo/src/run-config.ts +8 -8
  270. package/samples/apps/marketing-demo/src/app/seed.ts +1 -1
  271. package/samples/apps/marketing-demo/src/db/queries/seed-counts.ts +1 -1
  272. package/samples/apps/showcase/package.json +3 -0
  273. package/samples/apps/showcase/src/app/seed-items.ts +1 -1
  274. package/samples/apps/styleguide/src/app/seed.ts +2 -2
  275. package/samples/apps/styleguide/src/features/ai-settings/seed.ts +2 -2
  276. package/samples/apps/ui-walkthrough/scripts/emit-e2e-data.ts +1 -1
  277. package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +1 -1
  278. package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +2 -2
  279. package/samples/apps/ui-walkthrough/src/app/seed-vehicles.ts +1 -1
  280. package/samples/apps/ui-walkthrough/src/app/seed.ts +1 -1
  281. package/samples/apps/ui-walkthrough/src/db/queries/row-counts.ts +1 -1
  282. package/samples/apps/ui-walkthrough/src/db/queries/task-counts.ts +1 -1
  283. package/samples/apps/use-all-bundled/package.json +3 -0
  284. package/samples/apps/use-all-bundled/scripts/check-coverage.ts +2 -2
  285. package/samples/apps/use-all-bundled/src/app/auth-constants.ts +1 -1
  286. package/samples/apps/use-all-bundled/src/app/cap-overview-caps.ts +2 -2
  287. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +1 -1
  288. package/samples/apps/use-all-bundled/src/app/seed-documents.ts +1 -1
  289. package/samples/apps/use-all-bundled/src/app/seed.ts +11 -5
  290. package/samples/apps/use-all-bundled/src/run-config.ts +55 -56
  291. package/samples/apps/user-data-rights-demo/README.md +2 -2
  292. package/samples/apps/user-data-rights-demo/package.json +3 -0
  293. package/samples/apps/user-data-rights-demo/src/run-config.ts +7 -7
  294. package/samples/apps/workspaces/package.json +3 -0
  295. package/samples/recipes/access-control/package.json +3 -0
  296. package/samples/recipes/anonymous-access/package.json +3 -0
  297. package/samples/recipes/anonymous-access-multitenant/package.json +3 -0
  298. package/samples/recipes/apex-landing/package.json +1 -0
  299. package/samples/recipes/apex-surface-auth/package.json +3 -0
  300. package/samples/recipes/apex-surface-auth/src/feature.ts +2 -2
  301. package/samples/recipes/api-worker-split/package.json +3 -0
  302. package/samples/recipes/api-worker-split/src/feature.ts +1 -2
  303. package/samples/recipes/auth-claims/package.json +3 -0
  304. package/samples/recipes/auth-foundation-providers/src/feature.ts +1 -1
  305. package/samples/recipes/auth-mfa/package.json +3 -0
  306. package/samples/recipes/basic-entity/package.json +3 -0
  307. package/samples/recipes/chat-channels/package.json +3 -0
  308. package/samples/recipes/compliance-profiles-demo/package.json +3 -0
  309. package/samples/recipes/cross-feature-events/package.json +3 -1
  310. package/samples/recipes/cross-feature-events/src/feature.ts +1 -1
  311. package/samples/recipes/crypto-shredding-hr/package.json +3 -0
  312. package/samples/recipes/currencies-global/package.json +3 -0
  313. package/samples/recipes/currencies-per-tenant/package.json +3 -0
  314. package/samples/recipes/custom-fields-basic/package.json +3 -0
  315. package/samples/recipes/custom-handlers/package.json +3 -0
  316. package/samples/recipes/dashboard-stats/package.json +3 -0
  317. package/samples/recipes/delivery-notifications/package.json +3 -0
  318. package/samples/recipes/e2e-generator/package.json +3 -0
  319. package/samples/recipes/embedded/package.json +3 -0
  320. package/samples/recipes/embedded-entity-form/package.json +1 -0
  321. package/samples/recipes/encrypted-tenant-config/README.md +1 -1
  322. package/samples/recipes/encrypted-tenant-config/package.json +3 -0
  323. package/samples/recipes/error-contract/package.json +3 -0
  324. package/samples/recipes/event-sourcing/package.json +3 -1
  325. package/samples/recipes/event-sourcing/src/feature.ts +16 -20
  326. package/samples/recipes/event-sourcing/tsconfig.json +2 -6
  327. package/samples/recipes/feature-toggles/package.json +3 -0
  328. package/samples/recipes/field-access/package.json +3 -0
  329. package/samples/recipes/files-post-processing/package.json +1 -0
  330. package/samples/recipes/golden-path/README.md +30 -0
  331. package/samples/recipes/golden-path/package.json +11 -0
  332. package/samples/recipes/golden-path/src/feature.ts +70 -0
  333. package/samples/recipes/idempotency/package.json +3 -0
  334. package/samples/recipes/inbound-mail-triage/package.json +3 -0
  335. package/samples/recipes/lane-routing/package.json +3 -0
  336. package/samples/recipes/ledger-banking/package.json +3 -0
  337. package/samples/recipes/ledger-invoicing/package.json +3 -0
  338. package/samples/recipes/legal-pages/package.json +3 -0
  339. package/samples/recipes/lifecycle-hooks/package.json +3 -0
  340. package/samples/recipes/managed-config/package.json +3 -0
  341. package/samples/recipes/managed-pages/package.json +3 -0
  342. package/samples/recipes/notes-history-basic/package.json +3 -0
  343. package/samples/recipes/ownership/package.json +3 -0
  344. package/samples/recipes/pdf-audit-export/package.json +1 -0
  345. package/samples/recipes/pipeline-basics/package.json +3 -0
  346. package/samples/recipes/public-share-token/package.json +3 -0
  347. package/samples/recipes/public-share-token/src/feature.ts +1 -1
  348. package/samples/recipes/rate-limiting/package.json +3 -0
  349. package/samples/recipes/realtime-sse/package.json +3 -0
  350. package/samples/recipes/record-detail-layout/package.json +1 -0
  351. package/samples/recipes/reference-data/package.json +3 -0
  352. package/samples/recipes/relations/package.json +3 -0
  353. package/samples/recipes/screens-nav/package.json +3 -0
  354. package/samples/recipes/search/package.json +3 -0
  355. package/samples/recipes/secrets-demo/package.json +3 -0
  356. package/samples/recipes/security-baseline/src/feature.ts +2 -2
  357. package/samples/recipes/session-revocation/README.md +1 -1
  358. package/samples/recipes/session-revocation/package.json +3 -0
  359. package/samples/recipes/session-revocation/src/feature.ts +1 -1
  360. package/samples/recipes/state-machine/package.json +3 -1
  361. package/samples/recipes/state-machine/src/entities/invoice.ts +2 -2
  362. package/samples/recipes/state-machine/src/events.ts +19 -0
  363. package/samples/recipes/state-machine/src/feature.ts +25 -30
  364. package/samples/recipes/state-machine/src/handlers/_helpers.ts +13 -14
  365. package/samples/recipes/state-machine/src/handlers/create.ts +1 -1
  366. package/samples/recipes/state-machine/src/handlers/transitions.ts +129 -122
  367. package/samples/recipes/state-machine/src/reducer.ts +1 -1
  368. package/samples/recipes/state-machine/tsconfig.json +2 -6
  369. package/samples/recipes/tags-basic/package.json +3 -0
  370. package/samples/recipes/tenant-isolation/package.json +3 -0
  371. package/samples/recipes/tenant-settings/package.json +3 -0
  372. package/samples/recipes/tier-admin/package.json +3 -0
  373. package/samples/recipes/timezones/package.json +3 -0
  374. package/samples/recipes/tsconfig.base.json +1 -1
  375. package/samples/recipes/user-data-rights/package.json +3 -0
  376. package/samples/recipes/user-data-rights/src/feature.ts +6 -2
  377. package/samples/recipes/user-profile/package.json +3 -0
  378. package/samples/recipes/user-profile/src/feature.ts +2 -2
  379. package/samples/recipes/webhook-step/package.json +3 -0
  380. package/samples/recipes/wizard-form/package.json +1 -0
  381. package/samples/recipes/workflow-engine/package.json +3 -0
  382. package/samples/recipes/workflow-engine/src/db/queries/suspended-runs.ts +5 -2
  383. package/samples/recipes/writeform-section/package.json +1 -0
  384. package/packages/bundled-features/src/file-provider-s3-env/feature.ts +0 -58
  385. /package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/env-helper.ts +0 -0
@@ -100,137 +100,142 @@ export function createFileDerivativesFeature(opts: FileDerivativesOptions = {}):
100
100
  );
101
101
  }
102
102
 
103
- return defineFeature(FEATURE_NAME, (r) => {
104
- r.describe(
105
- "Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: \"ip\"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: \"fileRef\"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.",
106
- );
107
- r.uiHints({
108
- displayLabel: "File Derivatives",
109
- category: "storage",
110
- recommended: false,
111
- });
112
- // Needs a storage provider to read the original + write the variant —
113
- // without file-foundation there's nothing to derive from or write to.
114
- r.requires({ features: ["file-foundation"] });
115
- // variant() reads fileRefsTable, which "files" (not file-foundation)
116
- // owns — without this, mounting file-derivatives + file-foundation
117
- // alone boots fine but fails at request-time with a SQL error the first
118
- // time variant() runs.
119
- r.requires({ features: ["files"] });
120
-
121
- r.extendsRegistrar(EXT_DERIVATIVE_RENDERER, {
122
- onRegister: () => {
123
- // No side-effects at register-time — resolution (exact MIME match,
124
- // then `<type>/*` wildcard) happens at request-time in
125
- // resolveRenderer, mirrors file-foundation's fileProvider point.
126
- },
127
- });
128
- r.extendsRegistrar(EXT_DERIVATIVE_PUBLIC_PREDICATE, {
129
- onRegister: () => {
130
- // No side-effects at register-time — resolution happens at
131
- // request-time in publicVariantQuery, keyed by the FileRef's
132
- // entityType.
133
- },
134
- });
135
- r.extendsRegistrar(EXT_DERIVATIVE_OVERLAY_RESOLVER, {
136
- onRegister: () => {
137
- // No side-effects at register-time — resolution happens in
138
- // variant(), keyed by the FileRef's entityType, before the spec
139
- // hash is computed.
140
- },
141
- });
142
-
143
- // Registered ONLY when resolveApexTenant is supplied — r.queryHandler
144
- // registers publicVariantQuery into the feature's dispatch table as a
145
- // side effect of being called, independent of what's done with its
146
- // return value. Calling it unconditionally would make `publicVariant`
147
- // (access: ["anonymous", ...]) reachable via the generic `/api` query
148
- // dispatch even when the httpRoute below isn't mounted, bypassing the
149
- // "tenantId comes from the host, never the payload" invariant that only
150
- // `resolveApexTenant` enforces.
151
- if (opts.resolveApexTenant) {
152
- const resolveApexTenant = opts.resolveApexTenant;
153
- const byFileRef = opts.publicTenantResolution === "fileRef";
154
- const routeQn = byFileRef ? PUBLIC_VARIANT_BY_FILE_REF_QN : PUBLIC_VARIANT_QN;
155
-
156
- r.queryHandler(publicVariantQuery);
157
- // publicVariantByFileRefQuery is the ONLY way "fileRef" mode is
158
- // reachable — registered ONLY in that mode for the same reason
159
- // publicVariantQuery is gated above: registering it unconditionally
160
- // would expose its unsafeRaw, cross-tenant FileRef lookup via the
161
- // generic `/api` query dispatch even in default "host" mode.
162
- if (byFileRef) {
163
- // The handler reads the FileRef-tenant's row to keep a blocked
164
- // tenant's public variants from staying reachable — require the
165
- // dependency so a missing mount fails boot, not the tenant check
166
- // silently no-op-ing at request time.
167
- r.requires({ features: ["tenant"] });
168
- r.queryHandler(publicVariantByFileRefQuery);
169
- }
170
-
171
- r.httpRoute({
172
- method: "GET",
173
- path: `${basePath}/:fileRefId/:variant`,
174
- anonymous: true,
175
- handler: async (c, { systemQuery }) => {
176
- // `param(...)` is string|undefined here — `path` is a computed
177
- // template, so Hono can't infer the param type from a literal.
178
- const fileRefId = c.req.param("fileRefId");
179
- const variant = c.req.param("variant");
180
- // 404, not 400 — a syntactically bad name and "doesn't exist" must
181
- // answer identically, no name-oracle. fileRefsTable.id is a UUID
182
- // column — a malformed id must fail here, not at the DB. Without
183
- // this, an anonymous, internet-facing caller can throw a Postgres
184
- // 22P02 on every request (Bun.SQL pools the failed connection), a
185
- // DoS primitive with no auth required.
186
- if (!fileRefId || !variant || !VARIANT_NAME_RE.test(variant) || !isUuid(fileRefId)) {
187
- return c.text("not found", 404);
188
- }
189
-
190
- const host = c.req.header("host") ?? new URL(c.req.url).host;
191
- const tenantId = await resolveApexTenant(host);
192
- if (!tenantId) return c.text("not found", 404);
193
-
194
- let result: PublicVariantQueryResult;
195
- try {
196
- // @cast-boundary engine-payload — shape comes from
197
- // publicVariantQuery's return type (publicVariantByFileRefQuery
198
- // returns exactly that, or null, never its own shape).
199
- result = (await systemQuery(
200
- routeQn,
201
- { fileRefId, variant },
202
- tenantId,
203
- )) as PublicVariantQueryResult;
204
- } catch (err) {
205
- if (err instanceof RateLimitError) {
206
- return c.text("rate limited", 429);
207
- }
208
- // biome-ignore lint/suspicious/noConsole: ops-visible fallback, no logger wired into HttpRouteHandlerDeps
209
- console.error(
210
- `file-derivatives: public-variant query failed for fileRefId="${fileRefId}" variant="${variant}"`,
211
- err,
212
- );
213
- return c.text("variant unavailable", 503);
214
- }
215
- if (!result) return c.text("not found", 404);
216
-
217
- const bytes = Buffer.from(result.dataBase64, "base64");
218
- const etag = computeRevisionEtag([tenantId, fileRefId, variant, result.revision]);
219
- return cachedResponse(c.req.raw, {
220
- body: bytes,
221
- etag,
222
- cache: { kind: "revalidate", maxAgeSeconds: 60 },
223
- // Explicit here, not left to the app-wide security-headers default, so the route stays safe standalone.
224
- headers: {
225
- "content-type": result.mimeType,
226
- vary: "Host",
227
- "x-content-type-options": "nosniff",
228
- },
229
- });
103
+ return defineFeature(
104
+ FEATURE_NAME,
105
+ (r) => {
106
+ r.describe(
107
+ "Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: \"ip\"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: \"fileRef\"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.",
108
+ );
109
+ r.uiHints({
110
+ displayLabel: "File Derivatives",
111
+ category: "storage",
112
+ recommended: false,
113
+ });
114
+ // Needs a storage provider to read the original + write the variant —
115
+ // without file-foundation there's nothing to derive from or write to.
116
+ r.requires({ features: ["file-foundation"] });
117
+ // variant() reads fileRefsTable, which "files" (not file-foundation)
118
+ // owns — without this, mounting file-derivatives + file-foundation
119
+ // alone boots fine but fails at request-time with a SQL error the first
120
+ // time variant() runs.
121
+ r.requires({ features: ["files"] });
122
+
123
+ r.extendsRegistrar(EXT_DERIVATIVE_RENDERER, {
124
+ onRegister: () => {
125
+ // No side-effects at register-time — resolution (exact MIME match,
126
+ // then `<type>/*` wildcard) happens at request-time in
127
+ // resolveRenderer, mirrors file-foundation's fileProvider point.
128
+ },
129
+ });
130
+ r.extendsRegistrar(EXT_DERIVATIVE_PUBLIC_PREDICATE, {
131
+ onRegister: () => {
132
+ // No side-effects at register-time — resolution happens at
133
+ // request-time in publicVariantQuery, keyed by the FileRef's
134
+ // entityType.
230
135
  },
231
136
  });
232
- }
233
- });
137
+ r.extendsRegistrar(EXT_DERIVATIVE_OVERLAY_RESOLVER, {
138
+ onRegister: () => {
139
+ // No side-effects at register-time — resolution happens in
140
+ // variant(), keyed by the FileRef's entityType, before the spec
141
+ // hash is computed.
142
+ },
143
+ });
144
+
145
+ // Registered ONLY when resolveApexTenant is supplied — r.queryHandler
146
+ // registers publicVariantQuery into the feature's dispatch table as a
147
+ // side effect of being called, independent of what's done with its
148
+ // return value. Calling it unconditionally would make `publicVariant`
149
+ // (access: ["anonymous", ...]) reachable via the generic `/api` query
150
+ // dispatch even when the httpRoute below isn't mounted, bypassing the
151
+ // "tenantId comes from the host, never the payload" invariant that only
152
+ // `resolveApexTenant` enforces.
153
+ if (opts.resolveApexTenant) {
154
+ const resolveApexTenant = opts.resolveApexTenant;
155
+ const byFileRef = opts.publicTenantResolution === "fileRef";
156
+ const routeQn = byFileRef ? PUBLIC_VARIANT_BY_FILE_REF_QN : PUBLIC_VARIANT_QN;
157
+
158
+ r.queryHandler(publicVariantQuery);
159
+ // publicVariantByFileRefQuery is the ONLY way "fileRef" mode is
160
+ // reachable — registered ONLY in that mode for the same reason
161
+ // publicVariantQuery is gated above: registering it unconditionally
162
+ // would expose its unsafeRaw, cross-tenant FileRef lookup via the
163
+ // generic `/api` query dispatch even in default "host" mode.
164
+ if (byFileRef) {
165
+ // The handler reads the FileRef-tenant's row to keep a blocked
166
+ // tenant's public variants from staying reachable — require the
167
+ // dependency so a missing mount fails boot, not the tenant check
168
+ // silently no-op-ing at request time.
169
+ r.requires({ features: ["tenant"] });
170
+ r.queryHandler(publicVariantByFileRefQuery);
171
+ }
172
+
173
+ r.httpRoute({
174
+ method: "GET",
175
+ path: `${basePath}/:fileRefId/:variant`,
176
+ anonymous: true,
177
+ handler: async (c, { systemQuery }) => {
178
+ // `param(...)` is string|undefined here — `path` is a computed
179
+ // template, so Hono can't infer the param type from a literal.
180
+ const fileRefId = c.req.param("fileRefId");
181
+ const variant = c.req.param("variant");
182
+ // 404, not 400 — a syntactically bad name and "doesn't exist" must
183
+ // answer identically, no name-oracle. fileRefsTable.id is a UUID
184
+ // column — a malformed id must fail here, not at the DB. Without
185
+ // this, an anonymous, internet-facing caller can throw a Postgres
186
+ // 22P02 on every request (Bun.SQL pools the failed connection), a
187
+ // DoS primitive with no auth required.
188
+ if (!fileRefId || !variant || !VARIANT_NAME_RE.test(variant) || !isUuid(fileRefId)) {
189
+ return c.text("not found", 404);
190
+ }
191
+
192
+ const host = c.req.header("host") ?? new URL(c.req.url).host;
193
+ const tenantId = await resolveApexTenant(host);
194
+ if (!tenantId) return c.text("not found", 404);
195
+
196
+ let result: PublicVariantQueryResult;
197
+ try {
198
+ // @cast-boundary engine-payload — shape comes from
199
+ // publicVariantQuery's return type (publicVariantByFileRefQuery
200
+ // returns exactly that, or null, never its own shape).
201
+ result = (await systemQuery(
202
+ routeQn,
203
+ { fileRefId, variant },
204
+ tenantId,
205
+ )) as PublicVariantQueryResult;
206
+ } catch (err) {
207
+ if (err instanceof RateLimitError) {
208
+ return c.text("rate limited", 429);
209
+ }
210
+ // biome-ignore lint/suspicious/noConsole: ops-visible fallback, no logger wired into HttpRouteHandlerDeps
211
+ console.error(
212
+ `file-derivatives: public-variant query failed for fileRefId="${fileRefId}" variant="${variant}"`,
213
+ err,
214
+ );
215
+ return c.text("variant unavailable", 503);
216
+ }
217
+ if (!result) return c.text("not found", 404);
218
+
219
+ const bytes = Buffer.from(result.dataBase64, "base64");
220
+ const etag = computeRevisionEtag([tenantId, fileRefId, variant, result.revision]);
221
+ return cachedResponse(c.req.raw, {
222
+ body: bytes,
223
+ etag,
224
+ cache: { kind: "revalidate", maxAgeSeconds: 60 },
225
+ // Explicit here, not left to the app-wide security-headers default, so the route stays safe standalone.
226
+ headers: {
227
+ "content-type": result.mimeType,
228
+ vary: "Host",
229
+ "x-content-type-options": "nosniff",
230
+ },
231
+ });
232
+ },
233
+ });
234
+ }
235
+ },
236
+ Object.keys(opts).length === 0 ? { dedupeOptions: {} } : undefined,
237
+ );
234
238
  }
235
239
 
240
+ /** @deprecated Use createFileDerivativesFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
236
241
  export const fileDerivativesFeature = createFileDerivativesFeature();
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import {
3
3
  createAnonymousUser,
4
4
  defineQueryHandler,
@@ -23,7 +23,7 @@
23
23
  // but this handler's own isPublic gate runs exactly the same either way.
24
24
 
25
25
  import { computeRevisionEtag } from "@cosmicdrift/kumiko-framework/api";
26
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
26
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
27
27
  import { resolveFieldVariant } from "@cosmicdrift/kumiko-framework/derivatives";
28
28
  import {
29
29
  defineQueryHandler,
@@ -37,36 +37,45 @@ export {
37
37
 
38
38
  const FEATURE_NAME = "file-foundation";
39
39
 
40
- export const fileFoundationFeature = defineFeature(FEATURE_NAME, (r) => {
41
- r.describe(
42
- "Defines the `fileProvider` extension point and a per-tenant `provider` config key that selects which registered storage plugin to use at runtime. Call `createFileProviderForTenant(ctx, tenantId)` to get a `FileStorageProvider` — use this feature together with at least one `file-provider-*` feature; the `files` feature builds on top of it for tracked `FileRef` entities with GDPR hooks.",
43
- );
44
- r.uiHints({
45
- displayLabel: "File Provider Foundation",
46
- category: "storage",
47
- recommended: false,
48
- });
49
- r.requires({ features: ["config"] });
40
+ export function createFileFoundationFeature() {
41
+ return defineFeature(
42
+ FEATURE_NAME,
43
+ (r) => {
44
+ r.describe(
45
+ "Defines the `fileProvider` extension point and a per-tenant `provider` config key that selects which registered storage plugin to use at runtime. Call `createFileProviderForTenant(ctx, tenantId)` to get a `FileStorageProvider` — use this feature together with at least one `file-provider-*` feature; the `files` feature builds on top of it for tracked `FileRef` entities with GDPR hooks.",
46
+ );
47
+ r.uiHints({
48
+ displayLabel: "File Provider Foundation",
49
+ category: "storage",
50
+ recommended: false,
51
+ });
52
+ r.requires({ features: ["config"] });
50
53
 
51
- r.extendsRegistrar(EXT_FILE_PROVIDER, {
52
- onRegister: () => {
53
- // No side-effects at register-time — registry stores the usage,
54
- // factory looks it up at request-time.
55
- },
56
- });
54
+ r.extendsRegistrar(EXT_FILE_PROVIDER, {
55
+ onRegister: () => {
56
+ // No side-effects at register-time — registry stores the usage,
57
+ // factory looks it up at request-time.
58
+ },
59
+ });
57
60
 
58
- const providerConfigKey = r.config(
59
- "provider",
60
- createTenantConfig("text", {
61
- default: "",
62
- env: FILE_STORAGE_PROVIDER_ENV,
63
- write: access.roles("TenantAdmin", "SystemAdmin"),
64
- read: access.roles("TenantAdmin", "SystemAdmin", "User"),
65
- }),
61
+ const providerConfigKey = r.config(
62
+ "provider",
63
+ createTenantConfig("text", {
64
+ default: "",
65
+ env: FILE_STORAGE_PROVIDER_ENV,
66
+ write: access.roles("TenantAdmin", "SystemAdmin"),
67
+ read: access.roles("TenantAdmin", "SystemAdmin", "User"),
68
+ }),
69
+ );
70
+ // Readiness gating: provider-plugins' required keys/secrets count only
71
+ // while their plugin is the one this key selects.
72
+ r.extensionSelector(EXT_FILE_PROVIDER, providerConfigKey);
73
+
74
+ return { providerConfigKey };
75
+ },
76
+ { dedupeOptions: {} },
66
77
  );
67
- // Readiness gating: provider-plugins' required keys/secrets count only
68
- // while their plugin is the one this key selects.
69
- r.extensionSelector(EXT_FILE_PROVIDER, providerConfigKey);
78
+ }
70
79
 
71
- return { providerConfigKey };
72
- });
80
+ /** @deprecated Use createFileFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
81
+ export const fileFoundationFeature = createFileFoundationFeature();
@@ -1,6 +1,7 @@
1
1
  // Public API of the file-foundation bundled-feature.
2
2
 
3
3
  export {
4
+ createFileFoundationFeature,
4
5
  createFileProviderForTenant,
5
6
  type FileProviderContext,
6
7
  type FileProviderPlugin,
@@ -1,5 +1,5 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import type { DbRunner, TenantDb } from "@cosmicdrift/kumiko-framework/db";
2
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { isUuid, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import {
5
5
  createFileContext,
@@ -58,27 +58,38 @@ export function clearStorage(tenantId: string): void {
58
58
  // =============================================================================
59
59
  // Feature-definition
60
60
  // =============================================================================
61
+ export function createFileProviderInMemoryFeature() {
62
+ return defineFeature(
63
+ FEATURE_NAME,
64
+ (r) => {
65
+ r.describe(
66
+ 'Registers an in-process `"inmemory"` provider for `file-foundation` that stores file bytes per tenant in a module-level Map. Use `listKeys(tenantId)` and `clearStorage(tenantId)` in demo apps and tests; not for production (data is lost on restart and grows without bound).',
67
+ );
68
+ r.uiHints({
69
+ displayLabel: "File Provider · In-Memory",
70
+ category: "storage",
71
+ recommended: false,
72
+ });
73
+ // Kein requires auf "config" oder "secrets" — der
74
+ // In-Memory-Provider hat keine Config + kein Secret. Nur die
75
+ // file-foundation muss da sein (Plugin-extension-point).
76
+ r.requires({ features: ["file-foundation"] });
61
77
 
62
- export const fileProviderInMemoryFeature = defineFeature(FEATURE_NAME, (r) => {
63
- r.describe(
64
- 'Registers an in-process `"inmemory"` provider for `file-foundation` that stores file bytes per tenant in a module-level Map. Use `listKeys(tenantId)` and `clearStorage(tenantId)` in demo apps and tests; not for production (data is lost on restart and grows without bound).',
78
+ const plugin: FileProviderPlugin = {
79
+ build: async (
80
+ _ctx: FileProviderContext,
81
+ tenantId: string,
82
+ ): Promise<FileStorageProvider> => {
83
+ // Returns the per-tenant storage. Identity-stable across calls so
84
+ // accumulated state is kept.
85
+ return getOrCreateProviderForTenant(tenantId);
86
+ }, // @wrapper-known semantic-alias
87
+ };
88
+ r.useExtension("fileProvider", "inmemory", plugin);
89
+ },
90
+ { dedupeOptions: {} },
65
91
  );
66
- r.uiHints({
67
- displayLabel: "File Provider · In-Memory",
68
- category: "storage",
69
- recommended: false,
70
- });
71
- // Kein requires auf "config" oder "secrets" — der
72
- // In-Memory-Provider hat keine Config + kein Secret. Nur die
73
- // file-foundation muss da sein (Plugin-extension-point).
74
- r.requires({ features: ["file-foundation"] });
92
+ }
75
93
 
76
- const plugin: FileProviderPlugin = {
77
- build: async (_ctx: FileProviderContext, tenantId: string): Promise<FileStorageProvider> => {
78
- // Returnt den per-tenant Storage. Identitätsstabil zwischen calls
79
- // damit accumulated state erhalten bleibt.
80
- return getOrCreateProviderForTenant(tenantId);
81
- }, // @wrapper-known semantic-alias
82
- };
83
- r.useExtension("fileProvider", "inmemory", plugin);
84
- });
94
+ /** @deprecated Use createFileProviderInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
95
+ export const fileProviderInMemoryFeature = createFileProviderInMemoryFeature();
@@ -1,3 +1,8 @@
1
1
  // Public API of the file-provider-inmemory bundled-feature.
2
2
 
3
- export { clearStorage, fileProviderInMemoryFeature, listKeys } from "./feature.js";
3
+ export {
4
+ clearStorage,
5
+ createFileProviderInMemoryFeature,
6
+ fileProviderInMemoryFeature,
7
+ listKeys,
8
+ } from "./feature.js";
@@ -1 +1,10 @@
1
- []
1
+ [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "breaking",
5
+ "title": "The S3 file providers merge into createFileProviderS3Feature({ fromEnv })",
6
+ "detail": "createFileProviderS3Feature() mounts the per-tenant config provider as before. createFileProviderS3Feature({ fromEnv: true }) mounts the env-configured provider (feature name, provider key \"s3-env\" and requires unchanged). The S3 client helpers (createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, S3ProviderConfig) move to the new subpath @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib.\n\nThe subpaths file-provider-s3-env and files-provider-s3 keep working as deprecated re-exports and are removed in the first release after 2026-10-29.\n\nold -> new:\n fileProviderS3EnvFeature from .../file-provider-s3-env -> createFileProviderS3Feature({ fromEnv: true }) from .../file-provider-s3\n fileProviderS3Feature -> createFileProviderS3Feature()\n @cosmicdrift/kumiko-bundled-features/files-provider-s3 -> @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib",
7
+ "migration": "Run `bun kumiko-upgrade --apply`. It rewrites the imports and the env feature mount, and reports `typeof fileProviderS3EnvFeature` and re-exports of it with file and line.",
8
+ "codemod": "scripts/codemod/s3-imports.ts"
9
+ }
10
+ ]
@@ -0,0 +1,62 @@
1
+ // file-provider-s3-env — S3 file provider configured entirely from
2
+ // process.env. ONE shared bucket for ALL tenants: wire it by setting the
3
+ // `S3_*` env vars + mounting — no per-tenant admin seeding and no
4
+ // `secrets`-feature dependency.
5
+ //
6
+ // **vs the default file-provider-s3:** the config-based `"s3"` provider owns per-tenant
7
+ // config keys + an encrypted `s3.secretAccessKey` secret (per-tenant
8
+ // buckets, admin-seeded). This `"s3-env"` provider reads one credential set
9
+ // from env and serves every tenant from one bucket — the
10
+ // Hetzner-Object-Storage / single-bucket deploy case. Tenant isolation
11
+ // still holds: file keys carry the tenant (export ZIPs:
12
+ // `exports/<tenantId>/<jobId>.zip`) or are globally-unique UUIDs (fileRefs).
13
+ //
14
+ // **Pattern-Vorbild:** mirrors file-provider-inmemory (zero admin seeding,
15
+ // only the file-foundation plugin-point required).
16
+ //
17
+ // **Env vars** (read by createS3ProviderFromEnv, prefix `S3_`):
18
+ // required — S3_BUCKET, S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY
19
+ // optional — S3_ENDPOINT (S3-compat stores incl. Hetzner Object Storage),
20
+ // S3_FORCE_PATH_STYLE
21
+ // Missing required vars throw on the FIRST file op (inside the export cron).
22
+ // The user-data-rights boot guard surfaces that at boot instead.
23
+
24
+ import type {
25
+ FileProviderContext,
26
+ FileProviderPlugin,
27
+ } from "@cosmicdrift/kumiko-bundled-features/file-foundation";
28
+ import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
29
+ import type { FileStorageProvider } from "@cosmicdrift/kumiko-framework/files";
30
+ import { createS3ProviderFromEnv } from "./lib/env-helper.js";
31
+
32
+ const FEATURE_NAME = "file-provider-s3-env";
33
+
34
+ export function createFileProviderS3EnvFeature() {
35
+ return defineFeature(
36
+ FEATURE_NAME,
37
+ (r) => {
38
+ r.describe(
39
+ 'Registers an `"s3-env"` provider for `file-foundation` that reads one S3 credential set from `process.env` (`S3_BUCKET`/`S3_REGION`/`S3_ACCESS_KEY`/`S3_SECRET_KEY`, optional `S3_ENDPOINT`/`S3_FORCE_PATH_STYLE`) and serves every tenant from one shared bucket — no per-tenant config or secret seeding. Use this for single-bucket S3-compatible deploys (e.g. Hetzner Object Storage); use `file-provider-s3` instead when each tenant needs its own bucket/credentials.',
40
+ );
41
+ r.uiHints({
42
+ displayLabel: "File Provider · S3 (env)",
43
+ category: "storage",
44
+ recommended: false,
45
+ });
46
+ // No requires on "config" or "secrets" — credentials come from
47
+ // env, not the per-tenant config + secrets store. Only the file-foundation
48
+ // plugin-extension-point must be mounted.
49
+ r.requires({ features: ["file-foundation"] });
50
+
51
+ const plugin: FileProviderPlugin = {
52
+ // tenantId ignored: one shared bucket serves all tenants (isolation via
53
+ // tenant-prefixed / UUID keys). Built fresh per call like file-provider-s3;
54
+ // the S3 client opens no connection at construction.
55
+ build: async (_ctx: FileProviderContext, _tenantId: string): Promise<FileStorageProvider> =>
56
+ createS3ProviderFromEnv(), // @wrapper-known semantic-alias
57
+ };
58
+ r.useExtension("fileProvider", "s3-env", plugin);
59
+ },
60
+ { dedupeOptions: {} },
61
+ );
62
+ }