@cosmicdrift/kumiko-samples 0.386.0 → 0.388.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 (530) hide show
  1. package/LICENSE +21 -57
  2. package/README.md +1 -1
  3. package/package.json +2 -2
  4. package/packages/bundled-features/package.json +9 -2
  5. package/packages/bundled-features/src/agent-tools/changes.json +6 -0
  6. package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
  7. package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +9 -9
  8. package/packages/bundled-features/src/audit/changes.json +12 -0
  9. package/packages/bundled-features/src/audit/handlers/audit-events.ts +1 -1
  10. package/packages/bundled-features/src/audit/screens.ts +1 -1
  11. package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
  12. package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
  13. package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
  14. package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
  15. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
  16. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
  17. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
  18. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  19. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
  20. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
  21. package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
  22. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
  23. package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
  24. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
  25. package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
  26. package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
  27. package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
  28. package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
  29. package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
  30. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
  31. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
  32. package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
  33. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
  34. package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
  35. package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
  36. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
  37. package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
  38. package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
  39. package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
  40. package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
  41. package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
  42. package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
  43. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
  44. package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
  45. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
  46. package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
  47. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
  48. package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
  49. package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
  50. package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
  51. package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
  52. package/packages/bundled-features/src/auth-mfa/changes.json +6 -0
  53. package/packages/bundled-features/src/auth-mfa/feature-exports.ts +2 -2
  54. package/packages/bundled-features/src/auth-mfa/feature.ts +6 -0
  55. package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
  56. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
  57. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
  58. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  59. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
  60. package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
  61. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  62. package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
  63. package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
  64. package/packages/bundled-features/src/auth-mfa/web/i18n.ts +9 -4
  65. package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
  66. package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
  67. package/packages/bundled-features/src/auth-mfa/web/mfa-code-or-recovery-field.tsx +68 -0
  68. package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +23 -13
  69. package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +23 -13
  70. package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +15 -6
  71. package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +71 -24
  72. package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
  73. package/packages/bundled-features/src/billing-foundation/changes.json +55 -0
  74. package/packages/bundled-features/src/billing-foundation/checkout-core.ts +32 -42
  75. package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +8 -2
  76. package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +2 -0
  77. package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +14 -3
  78. package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +3 -4
  79. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +12 -6
  80. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +35 -19
  81. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +12 -8
  82. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +14 -8
  83. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +5 -0
  84. package/packages/bundled-features/src/billing-foundation/consumer-protection/withdrawal-period.ts +8 -10
  85. package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
  86. package/packages/bundled-features/src/billing-foundation/events.ts +23 -21
  87. package/packages/bundled-features/src/billing-foundation/feature.ts +45 -44
  88. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
  89. package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +71 -6
  90. package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +19 -17
  91. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
  92. package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
  93. package/packages/bundled-features/src/billing-foundation/handlers/plan-switch-preview.query.ts +65 -0
  94. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +29 -22
  95. package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +44 -8
  96. package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +72 -82
  97. package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +14 -1
  98. package/packages/bundled-features/src/billing-foundation/i18n.ts +22 -0
  99. package/packages/bundled-features/src/billing-foundation/index.ts +2 -0
  100. package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +62 -27
  101. package/packages/bundled-features/src/billing-foundation/plan-switch.ts +84 -0
  102. package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
  103. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
  104. package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
  105. package/packages/bundled-features/src/billing-foundation/types.ts +144 -66
  106. package/packages/bundled-features/src/billing-foundation/validate-options.ts +19 -0
  107. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +123 -51
  108. package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +89 -42
  109. package/packages/bundled-features/src/billing-foundation/web/constants.ts +4 -0
  110. package/packages/bundled-features/src/billing-foundation/web/plan-price.ts +55 -0
  111. package/packages/bundled-features/src/billing-foundation/web/plan-switch-confirm-dialog.tsx +224 -0
  112. package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
  113. package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
  114. package/packages/bundled-features/src/cap-counter/cap-reservation.ts +5 -1
  115. package/packages/bundled-features/src/cap-counter/changes.json +18 -0
  116. package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
  117. package/packages/bundled-features/src/cap-counter/enforce-cap.ts +66 -68
  118. package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
  119. package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
  120. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
  121. package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
  122. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +9 -2
  123. package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
  124. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
  125. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  126. package/packages/bundled-features/src/channel-email/changes.json +6 -0
  127. package/packages/bundled-features/src/channel-email/feature.ts +1 -1
  128. package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
  129. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
  130. package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
  131. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
  132. package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
  133. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
  134. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
  135. package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
  136. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
  137. package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
  138. package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
  139. package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
  140. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
  141. package/packages/bundled-features/src/config/changes.json +12 -0
  142. package/packages/bundled-features/src/config/handlers/cascade.query.ts +4 -2
  143. package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
  144. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
  145. package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
  146. package/packages/bundled-features/src/config/handlers/values.query.ts +4 -2
  147. package/packages/bundled-features/src/config/resolver.ts +4 -4
  148. package/packages/bundled-features/src/config/table.ts +10 -10
  149. package/packages/bundled-features/src/config/write-helpers.ts +28 -9
  150. package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
  151. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +23 -21
  152. package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
  153. package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
  154. package/packages/bundled-features/src/custom-fields/events.ts +7 -8
  155. package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
  156. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
  157. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
  158. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
  159. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
  160. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
  161. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
  162. package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
  163. package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
  164. package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
  165. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
  166. package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
  167. package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
  168. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
  169. package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
  170. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
  171. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
  172. package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
  173. package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
  174. package/packages/bundled-features/src/data-retention/feature.ts +11 -18
  175. package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
  176. package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
  177. package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
  178. package/packages/bundled-features/src/data-retention/presets.ts +18 -23
  179. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  180. package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
  181. package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
  182. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
  183. package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
  184. package/packages/bundled-features/src/delivery/changes.json +30 -0
  185. package/packages/bundled-features/src/delivery/channel-context.ts +9 -3
  186. package/packages/bundled-features/src/delivery/db/queries/preferences.ts +2 -2
  187. package/packages/bundled-features/src/delivery/delivery-service.ts +35 -5
  188. package/packages/bundled-features/src/delivery/feature.ts +3 -3
  189. package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
  190. package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +20 -1
  191. package/packages/bundled-features/src/delivery/handlers/unsubscribe-page-chrome.query.ts +1 -1
  192. package/packages/bundled-features/src/delivery/tables.ts +9 -8
  193. package/packages/bundled-features/src/delivery/unsubscribe-link.ts +3 -1
  194. package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +1 -0
  195. package/packages/bundled-features/src/delivery/unsubscribe-page.ts +6 -0
  196. package/packages/bundled-features/src/delivery/unsubscribe.ts +40 -19
  197. package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
  198. package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
  199. package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
  200. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
  201. package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
  202. package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
  203. package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
  204. package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
  205. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  206. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
  207. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  208. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
  209. package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
  210. package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
  211. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  212. package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
  213. package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
  214. package/packages/bundled-features/src/file-foundation/index.ts +1 -0
  215. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -1
  216. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
  217. package/packages/bundled-features/src/file-provider-s3/env-named-feature.ts +0 -2
  218. package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
  219. package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
  220. package/packages/bundled-features/src/files/README.md +1 -1
  221. package/packages/bundled-features/src/files/feature.ts +6 -6
  222. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
  223. package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
  224. package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
  225. package/packages/bundled-features/src/folders/feature.ts +1 -1
  226. package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
  227. package/packages/bundled-features/src/folders/web/tree.ts +5 -5
  228. package/packages/bundled-features/src/form-draft/changes.json +6 -0
  229. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +3 -3
  230. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
  231. package/packages/bundled-features/src/form-draft/decrypt-draft.ts +4 -1
  232. package/packages/bundled-features/src/form-draft/entity.ts +3 -3
  233. package/packages/bundled-features/src/form-draft/feature.ts +4 -5
  234. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  235. package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
  236. package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
  237. package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
  238. package/packages/bundled-features/src/host-routing/README.md +1 -1
  239. package/packages/bundled-features/src/host-routing/changes.json +6 -0
  240. package/packages/bundled-features/src/host-routing/dispatch.ts +16 -17
  241. package/packages/bundled-features/src/host-routing/options.ts +2 -1
  242. package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
  243. package/packages/bundled-features/src/inbound-mail-foundation/changes.json +18 -0
  244. package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
  245. package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
  246. package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
  247. package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
  248. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
  249. package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
  250. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
  251. package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
  252. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
  253. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
  254. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
  255. package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
  256. package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +27 -15
  257. package/packages/bundled-features/src/inbound-mail-foundation/i18n.ts +0 -1
  258. package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
  259. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
  260. package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
  261. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
  262. package/packages/bundled-features/src/inbound-mail-foundation/screens.ts +0 -3
  263. package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
  264. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +70 -70
  265. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +101 -84
  266. package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
  267. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
  268. package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
  269. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
  270. package/packages/bundled-features/src/jobs/changes.json +13 -0
  271. package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
  272. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
  273. package/packages/bundled-features/src/jobs/events.ts +1 -1
  274. package/packages/bundled-features/src/jobs/feature.ts +20 -11
  275. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
  276. package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
  277. package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  278. package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
  279. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  280. package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +45 -40
  281. package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +63 -59
  282. package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
  283. package/packages/bundled-features/src/jobs/job-run-logger.ts +19 -19
  284. package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
  285. package/packages/bundled-features/src/jobs/screens.ts +1 -1
  286. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  287. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  288. package/packages/bundled-features/src/ledger/entity.ts +5 -5
  289. package/packages/bundled-features/src/ledger/feature.ts +3 -3
  290. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
  291. package/packages/bundled-features/src/ledger/recurring.ts +12 -12
  292. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  293. package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
  294. package/packages/bundled-features/src/ledger/web/index.ts +7 -7
  295. package/packages/bundled-features/src/legal-pages/README.md +1 -1
  296. package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
  297. package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
  298. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
  299. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
  300. package/packages/bundled-features/src/mail-foundation/changes.json +6 -0
  301. package/packages/bundled-features/src/mail-foundation/feature.ts +31 -30
  302. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
  303. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
  304. package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
  305. package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
  306. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
  307. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
  308. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
  309. package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
  310. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
  311. package/packages/bundled-features/src/managed-pages/table.ts +16 -15
  312. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
  313. package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
  314. package/packages/bundled-features/src/notes-history/entity.ts +4 -4
  315. package/packages/bundled-features/src/notes-history/feature.ts +2 -2
  316. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  317. package/packages/bundled-features/src/page-render/layout.ts +9 -9
  318. package/packages/bundled-features/src/page-render/markdown.ts +11 -11
  319. package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
  320. package/packages/bundled-features/src/personal-access-tokens/feature.ts +9 -6
  321. package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
  322. package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
  323. package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
  324. package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
  325. package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
  326. package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
  327. package/packages/bundled-features/src/renderer-pdf/changes.json +6 -0
  328. package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +27 -10
  329. package/packages/bundled-features/src/secrets/feature.ts +9 -9
  330. package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
  331. package/packages/bundled-features/src/seo/feature.ts +3 -3
  332. package/packages/bundled-features/src/sessions/constants.ts +1 -1
  333. package/packages/bundled-features/src/sessions/feature.ts +16 -11
  334. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
  335. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
  336. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  337. package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
  338. package/packages/bundled-features/src/sessions/screens.ts +2 -2
  339. package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
  340. package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
  341. package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
  342. package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +11 -1
  343. package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
  344. package/packages/bundled-features/src/shared/index.ts +1 -1
  345. package/packages/bundled-features/src/shared/mail-template-body.ts +10 -3
  346. package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
  347. package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
  348. package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
  349. package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
  350. package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
  351. package/packages/bundled-features/src/step-dispatcher/changes.json +6 -0
  352. package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -0
  353. package/packages/bundled-features/src/subscription-dodo/changes.json +14 -0
  354. package/packages/bundled-features/src/subscription-dodo/client.ts +45 -0
  355. package/packages/bundled-features/src/subscription-dodo/constants.ts +24 -0
  356. package/packages/bundled-features/src/subscription-dodo/feature.ts +207 -0
  357. package/packages/bundled-features/src/subscription-dodo/index.ts +16 -0
  358. package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +345 -0
  359. package/packages/bundled-features/src/subscription-dodo/runtime.ts +126 -0
  360. package/packages/bundled-features/src/subscription-dodo/verify-webhook.ts +262 -0
  361. package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
  362. package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
  363. package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
  364. package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
  365. package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
  366. package/packages/bundled-features/src/subscription-stripe/changes.json +12 -0
  367. package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
  368. package/packages/bundled-features/src/subscription-stripe/feature.ts +45 -43
  369. package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
  370. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
  371. package/packages/bundled-features/src/subscription-stripe/runtime.ts +9 -8
  372. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
  373. package/packages/bundled-features/src/tags/feature.ts +3 -3
  374. package/packages/bundled-features/src/tags/screens.ts +1 -1
  375. package/packages/bundled-features/src/template-resolver/api.ts +41 -14
  376. package/packages/bundled-features/src/template-resolver/changes.json +48 -0
  377. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -0
  378. package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
  379. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +3 -2
  380. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +27 -5
  381. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +3 -2
  382. package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +3 -2
  383. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +8 -7
  384. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +19 -20
  385. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +15 -5
  386. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
  387. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
  388. package/packages/bundled-features/src/template-resolver/handlers/tenant-override-counts.query.ts +9 -5
  389. package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +8 -6
  390. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +44 -5
  391. package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
  392. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
  393. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +37 -26
  394. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +7 -2
  395. package/packages/bundled-features/src/template-resolver/seeding.ts +36 -18
  396. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +22 -4
  397. package/packages/bundled-features/src/template-resolver/table.ts +13 -14
  398. package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +0 -11
  399. package/packages/bundled-features/src/template-resolver/template-meta.ts +12 -4
  400. package/packages/bundled-features/src/template-resolver/template-preview.ts +11 -3
  401. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
  402. package/packages/bundled-features/src/template-resolver/web/constants.ts +7 -5
  403. package/packages/bundled-features/src/template-resolver/web/index.ts +7 -0
  404. package/packages/bundled-features/src/template-resolver/web/mail-layout-constants.ts +8 -0
  405. package/packages/bundled-features/src/tenant/changes.json +6 -0
  406. package/packages/bundled-features/src/tenant/feature.ts +7 -7
  407. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +10 -4
  408. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  409. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  410. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  411. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +8 -5
  412. package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
  413. package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
  414. package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
  415. package/packages/bundled-features/src/tenant/screens.ts +1 -1
  416. package/packages/bundled-features/src/tenant/seeding.ts +19 -18
  417. package/packages/bundled-features/src/tenant/testing.ts +5 -6
  418. package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
  419. package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
  420. package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
  421. package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
  422. package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
  423. package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
  424. package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
  425. package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
  426. package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
  427. package/packages/bundled-features/src/tenant-lifecycle/changes.json +6 -0
  428. package/packages/bundled-features/src/tenant-lifecycle/constants.ts +5 -0
  429. package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
  430. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +7 -3
  431. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
  432. package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
  433. package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
  434. package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
  435. package/packages/bundled-features/src/tier-engine/changes.json +6 -0
  436. package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
  437. package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
  438. package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
  439. package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
  440. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
  441. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +12 -9
  442. package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
  443. package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
  444. package/packages/bundled-features/src/tier-engine/web/constants.ts +3 -3
  445. package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
  446. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
  447. package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
  448. package/packages/bundled-features/src/user/schema/user.ts +45 -44
  449. package/packages/bundled-features/src/user/seeding.ts +40 -40
  450. package/packages/bundled-features/src/user/testing.ts +3 -3
  451. package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
  452. package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
  453. package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
  454. package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
  455. package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
  456. package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
  457. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
  458. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
  459. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
  460. package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
  461. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
  462. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
  463. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
  464. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
  465. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
  466. package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
  467. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
  468. package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
  469. package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
  470. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
  471. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +169 -280
  472. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +87 -108
  473. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
  474. package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
  475. package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
  476. package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
  477. package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
  478. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
  479. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
  480. package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
  481. package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
  482. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
  483. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
  484. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
  485. package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
  486. package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
  487. package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
  488. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
  489. package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
  490. package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
  491. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
  492. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
  493. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
  494. package/packages/bundled-features/src/user-profile/index.ts +3 -3
  495. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
  496. package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
  497. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
  498. package/packages/bundled-features/src/waitlist/changes.json +18 -0
  499. package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +2 -1
  500. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +5 -5
  501. package/packages/bundled-features/src/waitlist/import.ts +5 -0
  502. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +22 -3
  503. package/packages/bundled-features/src/waitlist/link-on-signup.ts +20 -10
  504. package/packages/bundled-features/src/waitlist/options.ts +3 -0
  505. package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
  506. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
  507. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
  508. package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
  509. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
  510. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
  511. package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
  512. package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
  513. package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
  514. package/samples/apps/styleguide/src/features/widgets/i18n.ts +11 -0
  515. package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +24 -0
  516. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-constants.ts +5 -0
  517. package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +90 -15
  518. package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +16 -6
  519. package/samples/apps/use-all-bundled/feature-manifest.json +120 -3
  520. package/samples/apps/use-all-bundled/src/run-config.ts +9 -3
  521. package/samples/recipes/auth-mfa/README.md +5 -0
  522. package/samples/recipes/auth-mfa/package.json +5 -2
  523. package/samples/recipes/auth-mfa/src/web/confirmation-code-step.tsx +49 -0
  524. package/samples/recipes/auth-mfa/tsconfig.json +8 -0
  525. package/samples/recipes/env-composition/README.md +3 -1
  526. package/samples/recipes/env-composition/src/env.ts +2 -0
  527. package/samples/recipes/legal-pages/README.md +1 -1
  528. package/samples/recipes/rate-limiting/README.md +18 -0
  529. package/samples/recipes/rate-limiting/src/feature.ts +12 -0
  530. package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +0 -12
@@ -1,5 +1,5 @@
1
1
  // Public-Read of a derived FileRef variant — the anonymous counterpart to
2
- // GET /files/:id/variant/:name (#1950, auth-gated). Both routes resolve the
2
+ // GET /files/:id/variant/:name (auth-gated). Both routes resolve the
3
3
  // same way: the variant spec comes from the FileRef's field declaration
4
4
  // (`createImageField({ variants: {...} })`), not a fixed list — an app that
5
5
  // declares its own variant name gets it served here too. This route never
@@ -3,7 +3,7 @@ import type { VariantSpec } from "@cosmicdrift/kumiko-types/derivatives-types";
3
3
  // Ready-made specs to spread into a field's own `variants` declaration
4
4
  // (`createImageField({ variants: { thumb, full: { ...full, maxEdge: 4096 } } })`)
5
5
  // — not an allow-list. Which names a route serves is decided entirely by
6
- // what a field declares (#1985), these are just common defaults.
6
+ // what a field declares; these are just common defaults.
7
7
  export const thumb = { maxEdge: 160, fit: "cover", format: "webp" } as const satisfies VariantSpec;
8
8
  export const card = { maxEdge: 640, fit: "inside", format: "webp" } as const satisfies VariantSpec;
9
9
  export const hero = { maxEdge: 1600, fit: "inside", format: "webp" } as const satisfies VariantSpec;
@@ -8,13 +8,13 @@
8
8
  // erasure hit the same store by construction. This feature re-exports the moved
9
9
  // symbols unchanged so existing imports keep working.
10
10
  //
11
- // **Pattern-Vorbild:** identisch zu `mail-foundation`. Foundation deklariert
12
- // extension-point `fileProvider`, Provider-Features (file-provider-s3, -inmemory,
13
- // -s3-env, später -gcs/-azure-blob) registrieren sich namentlich. Tenant wählt
14
- // zur Runtime via config-key `provider`.
11
+ // **Pattern reference:** identical to `mail-foundation`. The foundation declares
12
+ // the `fileProvider` extension point; provider features (file-provider-s3,
13
+ // -inmemory, -s3-env, later -gcs/-azure-blob) register themselves by name. The
14
+ // tenant selects one at runtime via the `provider` config key.
15
15
  //
16
- // **Boot-Dependencies:** config (für provider-selector). Kein secrets, weil
17
- // Foundation selbst keine Secrets hält.
16
+ // **Boot dependencies:** config (for the provider selector). No secrets, because
17
+ // the foundation itself does not hold any secrets.
18
18
 
19
19
  import {
20
20
  access,
@@ -10,6 +10,7 @@ export {
10
10
  export {
11
11
  type FileRefContent,
12
12
  FileRefTooLargeError,
13
+ FileStorageUnavailableError,
13
14
  fileContextForTenant,
14
15
  fileContextFromResolver,
15
16
  readFileRefContent,
@@ -53,6 +53,12 @@ export class FileRefTooLargeError extends Error {
53
53
  }
54
54
  }
55
55
 
56
+ export class FileStorageUnavailableError extends Error {
57
+ constructor() {
58
+ super("readFileRefContent: no file storage is available for the file's tenant");
59
+ }
60
+ }
61
+
56
62
  // fileName of the row is never used: it is personal data and may be a PII ciphertext.
57
63
  export async function readFileRefContent(args: {
58
64
  readonly db: DbRunner | TenantDb;
@@ -82,7 +88,7 @@ export async function readFileRefContent(args: {
82
88
  }
83
89
  const files = args.filesForTenant(row.tenantId);
84
90
  if (files === undefined) {
85
- throw new Error("readFileRefContent: no file storage is available for the file's tenant");
91
+ throw new FileStorageUnavailableError();
86
92
  }
87
93
  const content = await files.refFromFileRef(row).read();
88
94
  return { content, contentType: row.mimeType, tenantId: row.tenantId, size };
@@ -1,21 +1,21 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // file-provider-inmemory — In-Memory-FileProvider für die file-
4
- // foundation Plugin-API. Speichert Files in einem per-Tenant-Map
5
- // statt in S3/Hetzner-Object-Storage. Für Demos, Sample-Apps und
6
- // Tests ohne MinIO-Container.
3
+ // file-provider-inmemory — In-memory file provider for the file-
4
+ // foundation plugin API. Stores files in a per-tenant Map instead
5
+ // of S3/Hetzner object storage. Intended for demos, sample apps,
6
+ // and tests without a MinIO container.
7
7
  //
8
- // **Was diese Feature liefert:**
9
- // 1. Plugin-Registration via `r.useExtension("fileProvider",
8
+ // **What this feature provides:**
9
+ // 1. Plugin registration via `r.useExtension("fileProvider",
10
10
  // "inmemory", { build })`.
11
- // 2. **Pro-Tenant Storage.** Jeder Tenant kriegt einen eigenen
12
- // InMemoryFileProvider — Tenant-Isolation by-design, keine
13
- // Pfad-Konvention nötig.
11
+ // 2. **Per-tenant storage.** Each tenant gets its own
12
+ // InMemoryFileProvider, providing tenant isolation by design
13
+ // without requiring a path convention.
14
14
  //
15
- // **Pattern-Vorbild:** mirrors file-provider-s3.
15
+ // **Pattern reference:** mirrors file-provider-s3.
16
16
  //
17
- // **NICHT für Production.** Buffer ist Process-Memory, geht beim
18
- // Restart verloren + wächst monoton mit jedem write.
17
+ // **NOT for production.** The buffer is process memory, is lost on
18
+ // restart, and grows monotonically with every write.
19
19
 
20
20
  import type {
21
21
  FileProviderContext,
@@ -50,7 +50,7 @@ export function listKeys(tenantId: string): readonly string[] {
50
50
  return providersByTenant.get(tenantId)?.keys() ?? [];
51
51
  }
52
52
 
53
- /** Demo/Test-Helper: leere den Tenant-Storage. */
53
+ /** Demo/test helper: clears a tenant's storage. */
54
54
  export function clearStorage(tenantId: string): void {
55
55
  providersByTenant.get(tenantId)?.clear();
56
56
  }
@@ -70,9 +70,9 @@ export function createFileProviderInMemoryFeature() {
70
70
  category: "storage",
71
71
  recommended: false,
72
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).
73
+ // No requirement for "config" or "secrets": the
74
+ // in-memory provider has neither configuration nor secrets. Only
75
+ // file-foundation must be present as the plugin extension point.
76
76
  r.requires({ features: ["file-foundation"] });
77
77
 
78
78
  const plugin: FileProviderPlugin = {
@@ -13,8 +13,6 @@ export type NamedS3EnvProviderOptions = {
13
13
  readonly name: string;
14
14
  /** Env prefix of the credential set, e.g. `RELEASES_S3_`. */
15
15
  readonly envPrefix: string;
16
- /** Tolerate missing credentials at boot; the provider then fails on its first file operation. */
17
- readonly lazy?: boolean;
18
16
  };
19
17
 
20
18
  /** An additional S3 provider next to `"s3-env"`, reading its credentials from `<envPrefix>BUCKET` etc. */
@@ -1,22 +1,22 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // file-provider-s3 — concrete S3-implementation for the
4
- // file-foundation plugin-API.
3
+ // file-provider-s3 — concrete S3 implementation for the
4
+ // file-foundation plugin API.
5
5
  //
6
- // **Was diese Feature liefert:**
7
- // 1. Provider-spezifische Tenant-Config (bucket/region/endpoint/
8
- // forcePathStyle/accessKeyId) und Secret (s3.secretAccessKey).
9
- // Self-contained — file-foundation kennt diese nicht.
10
- // 2. Plugin-Registration via `r.useExtension("fileProvider", "s3",
11
- // { build })`. file-foundation's Factory findet den Plugin via
12
- // registry.
13
- // 3. build(ctx, tenantId) liest config + secret, ruft `createS3Provider`
14
- // aus ./lib auf. Der EINZIGE Cross-Feature-Import
15
- // des Plugins — bewusst lokal gehalten.
6
+ // **What this feature provides:**
7
+ // 1. Provider-specific tenant config (bucket/region/endpoint/
8
+ // forcePathStyle/accessKeyId) and secret (s3.secretAccessKey).
9
+ // Self-contained — file-foundation does not know about these.
10
+ // 2. Plugin registration via `r.useExtension("fileProvider", "s3",
11
+ // { build })`. file-foundation's factory finds the plugin through
12
+ // the registry.
13
+ // 3. build(ctx, tenantId) reads the config and secret, then calls
14
+ // `createS3Provider` from ./lib. This is the plugin's only
15
+ // cross-feature import, intentionally kept local.
16
16
  //
17
- // **Pattern-Vorbild:** mirrors mail-transport-smtp.
17
+ // **Pattern reference:** mirrors mail-transport-smtp.
18
18
  //
19
- // **Boot-Dependencies:** config + secrets + file-foundation.
19
+ // **Boot dependencies:** config + secrets + file-foundation.
20
20
 
21
21
  import type {
22
22
  FileProviderContext,
@@ -101,8 +101,8 @@ function createTenantConfigFileProviderS3Feature() {
101
101
  },
102
102
  });
103
103
 
104
- // Plugin-Registration. entityName "s3" ist was tenants in
105
- // file-foundation's `provider` config-key setzen.
104
+ // Plugin registration. The entityName "s3" is what tenants set in
105
+ // file-foundation's `provider` config key.
106
106
  const plugin: FileProviderPlugin = {
107
107
  build: async (ctx: FileProviderContext, tenantId: string) => buildS3Provider(ctx, tenantId), // @wrapper-known semantic-alias
108
108
  };
@@ -5,7 +5,7 @@ import {
5
5
  } from "@cosmicdrift/kumiko-framework/files";
6
6
 
7
7
  // =============================================================================
8
- // Operator-Pflicht-Setup (Multipart-Upload-Cleanup)
8
+ // Required operator setup (multipart-upload cleanup)
9
9
  // =============================================================================
10
10
  //
11
11
  // `writeStream` uses Bun's S3 writer for real multipart streaming. S3
@@ -15,7 +15,7 @@ import {
15
15
  // OPEN in S3 and bills storage for the parts already uploaded — until a
16
16
  // lifecycle rule aborts it.
17
17
  //
18
- // **Pflicht-Operator-Setup auf jedem Bucket:**
18
+ // **Required operator setup on every bucket:**
19
19
  //
20
20
  // {
21
21
  // "Rules": [{
@@ -31,7 +31,7 @@ import {
31
31
  // R2 and Minio support the same syntax.
32
32
  //
33
33
  // =============================================================================
34
- // Operator-Pflicht-Setup (IAM: list permission)
34
+ // Required operator setup (IAM: list permission)
35
35
  // =============================================================================
36
36
  //
37
37
  // GDPR-forget/tenant-destroy erasure (user-data-rights-defaults) calls
@@ -181,9 +181,9 @@ export function createS3Provider(config: S3ProviderConfig): FileStorageProvider
181
181
  options?: SignedUrlOptions,
182
182
  ): Promise<string> {
183
183
  assertSafeStorageKey(key);
184
- // contentDisposition wird von Bun als response-content-disposition
185
- // Query-Param signiert (Response-Override fuer den GET-Download) —
186
- // der Browser sieht den Original-Dateinamen statt des UUID-Keys.
184
+ // Bun signs contentDisposition as the response-content-disposition
185
+ // query parameter (a response override for the GET download) —
186
+ // the browser sees the original filename instead of the UUID key.
187
187
  return client.presign(key, {
188
188
  expiresIn: expiresInSeconds,
189
189
  method: "GET",
@@ -15,7 +15,7 @@ bewirtschaftet. Das öffnet die Tür für Cross-Feature-Hooks:
15
15
  ## Was es NICHT macht
16
16
 
17
17
  - **Keine Upload-/Download-Routes** — die bleiben in
18
- `framework/src/api/server.ts` via `options.files`-Bootstrap.
18
+ `framework/src/api/server-routes.ts` (`mountFileRoutes`).
19
19
  Multipart-Form-Body und Binary-Streaming passen nicht ins Write/Query-
20
20
  Handler-Pattern; ein Refactor zu `r.httpRoute` wäre orthogonal zu
21
21
  diesem Sprint.
@@ -1,7 +1,7 @@
1
- // files — full Event-Sourcing für File-Metadata. Die Implementierung (Entity,
2
- // files:event:*-Events, Inline-Projektion) lebt seit dem ES-Umbau im
3
- // Framework neben file-routes + fileRefsTable, weil file-routes hart davon
4
- // abhängt (appendDomainEventCore verlangt registrierte Events + Projektion).
5
- // Dieses Modul re-exportiert nur, damit der App-Import-Pfad
6
- // `@cosmicdrift/kumiko-bundled-features/files` stabil bleibt.
1
+ // files — complete event sourcing for file metadata. The implementation (entity,
2
+ // files:event:*-events, inline projection) lives in the framework alongside
3
+ // file-routes and fileRefsTable because file-routes depends on registered events
4
+ // and a projection, as required by appendDomainEventCore.
5
+ // This module only re-exports the feature to keep the app import path
6
+ // `@cosmicdrift/kumiko-bundled-features/files` stable.
7
7
  export { createFilesFeature, fileRefEntity } from "@cosmicdrift/kumiko-framework/files";
@@ -1,5 +1,5 @@
1
1
  // Backfill/GC job for derivatives orphaned by a forget/tenant-destroy that ran
2
- // before #2461 wired binary cleanup into those flows (#2474). Those older runs
2
+ // before binary cleanup was wired into those flows. Those older runs
3
3
  // left the FileRef row gone with no audit trail of what was ever forgotten —
4
4
  // so this sweep works forward from the deterministic derivative-key grammar
5
5
  // alone: for every key under a tenant's storage prefix that parses as a
@@ -8,8 +8,8 @@
8
8
  // a soft-deleted one sitting in trash — means the derivative is still
9
9
  // legitimate; only genuinely unreferenced derivatives are swept.
10
10
  //
11
- // Manual trigger only (no cron) — an operator runs this once after upgrading
12
- // past #2461, or on demand for spot-checks.
11
+ // Manual trigger only (no cron) — an operator runs this once after upgrading,
12
+ // or on demand for spot-checks.
13
13
  //
14
14
  // Row unit for runChunkedMigration is a discovered derivative CANDIDATE KEY,
15
15
  // not a tenant: one tenant's storage listing produces a variable number of
@@ -91,7 +91,7 @@ export async function sweepOrphanedDerivativesJob(
91
91
  }
92
92
  tenantCursor = tenants.at(-1)?.id;
93
93
  for (const tenant of tenants) {
94
- const tenantId = tenant.id as TenantId;
94
+ const tenantId = tenant.id;
95
95
  let provider: FileStorageProvider;
96
96
  try {
97
97
  provider = await resolver(tenantId);
@@ -131,7 +131,7 @@ export async function sweepOrphanedDerivativesJob(
131
131
  ): Promise<"migrated" | "skipped" | "failed"> {
132
132
  // No isDeleted filter: a soft-deleted (trashed, not yet forgotten) fileRef
133
133
  // still legitimately backs its derivatives — only an ABSENT row (forgotten,
134
- // or a tenant destroyed before #2461 with no row left at all) makes a
134
+ // or a tenant destroyed with no row left at all) makes a
135
135
  // derivative orphaned.
136
136
  const owners = await selectMany(
137
137
  db,
@@ -1,5 +1,5 @@
1
1
  // EXT_TENANT_DATA + EXT_STORAGE_PROVIDER destroy hooks for the `fileRef`
2
- // entity (#2474). Kept apart from the `files` feature (like folders-user-data
2
+ // entity. Kept apart from the `files` feature (like folders-user-data
3
3
  // does for EXT_USER_DATA) so file consumers without the tenant-lifecycle
4
4
  // pipeline don't pull a hard dependency — `files` stays usable standalone.
5
5
  //
@@ -10,18 +10,17 @@
10
10
  // isDeleted filter: tenant-destroy purges trashed rows too, a destroyed
11
11
  // tenant has no "restore from trash" future. ALSO sweeps, per row, any
12
12
  // storageKey that does NOT sit under one of this tenant's own
13
- // tenantStoragePrefixes() — the shape a tenant-handover (kumiko-
14
- // framework#3035) leaves behind: the fileRef row's tenantId moved to
15
- // this tenant, but the bytes stayed under the SOURCE tenant's prefix
16
- // (moving them would mean copying bytes, which the handover design
17
- // explicitly rejects). Must run here, not in the "files" stage below —
18
- // that stage's own prefix sweep only reaches keys under ITS tenant's
19
- // prefixes by construction, and by the time it runs this hook has
20
- // already forgotten (hard-deleted) the rows it would need to read the
21
- // storageKey off. Deleted by STEM prefix (storageKeyStemPrefix), not the
22
- // exact key: a derived variant (thumbnail, resized render) has no
23
- // `file_refs` row of its own, so only the stem reaches original +
24
- // derivatives together.
13
+ // tenantStoragePrefixes() — the shape a tenant-handover leaves behind:
14
+ // the fileRef row's tenantId moved to this tenant, but the bytes stayed
15
+ // under the SOURCE tenant's prefix (moving them would mean copying bytes,
16
+ // which the handover design explicitly rejects). Must run here, not in
17
+ // the "files" stage below — that stage's own prefix sweep only reaches
18
+ // keys under ITS tenant's prefixes by construction, and by the time it
19
+ // runs this hook has already forgotten (hard-deleted) the rows it would
20
+ // need to read the storageKey off. Deleted by STEM prefix
21
+ // (storageKeyStemPrefix), not the exact key: a derived variant
22
+ // (thumbnail, resized render) has no `file_refs` row of its own, so only
23
+ // the stem reaches original + derivatives together.
25
24
  // - fileRefStorageDestroyHook ("files" stage, EXT_STORAGE_PROVIDER): wipes
26
25
  // every BINARY (original + derivatives + anything else) under the
27
26
  // tenant's storage prefixes. A full prefix sweep per tenantStoragePrefixes()
@@ -32,19 +31,18 @@
32
31
  // (the provider's own list() prefix already scopes it). Still catches a
33
32
  // blob with no fileRef row at all (the orphan case the row-driven sweep
34
33
  // above cannot see) — REFINED, not replaced, to skip a key a FOREIGN
35
- // tenant's fileRef row still references (a tenant-handover, kumiko-
36
- // framework#3035, leaves the row's tenantId moved but the storageKey
37
- // under THIS tenant's prefix unchanged). By the time this stage runs,
38
- // the "app-data" stage (stages.ts DESTRUCTION_STAGES: "app-data" before
39
- // "files") has already hard-deleted every row THIS tenant owned, so any
40
- // surviving row a listed key still matches is, by construction, a
41
- // foreign tenant's — no tenant comparison needed, existence is enough.
42
- // The exception is computed from the SURVIVING row's storageKeyStemPrefix
43
- // (mirroring the deletion side above), not the listed key's exact match:
44
- // a derivative has no fileRef row of its own, so excluding only exact
45
- // matches would still delete it out from under the tenant that claimed
46
- // its original. Batched: one existence query per chunk of listed keys,
47
- // not one query per key.
34
+ // tenant's fileRef row still references (a tenant-handover leaves the
35
+ // row's tenantId moved but the storageKey under THIS tenant's prefix
36
+ // unchanged). By the time this stage runs, the "app-data" stage
37
+ // (stages.ts DESTRUCTION_STAGES: "app-data" before "files") has already
38
+ // hard-deleted every row THIS tenant owned, so any surviving row a listed
39
+ // key still matches is, by construction, a foreign tenant's — no tenant
40
+ // comparison needed, existence is enough. The exception is computed from
41
+ // the SURVIVING row's storageKeyStemPrefix (mirroring the deletion side
42
+ // above), not the listed key's exact match: a derivative has no fileRef row
43
+ // of its own, so excluding only exact matches would still delete it out
44
+ // from under the tenant that claimed its original. Batched: one existence
45
+ // query per chunk of listed keys, not one query per key.
48
46
 
49
47
  import { createEventStoreExecutor, selectMany } from "@cosmicdrift/kumiko-framework/db";
50
48
  import {
@@ -1,5 +1,5 @@
1
1
  // GDPR tenant-destroy + orphaned-derivative backfill coverage for the `files`
2
- // feature's `fileRef` entity (#2474). Kept apart from `files` — like
2
+ // feature's `fileRef` entity. Kept apart from `files` — like
3
3
  // folders-user-data does for EXT_USER_DATA — so file consumers without the
4
4
  // tenant-lifecycle pipeline don't pull a hard dependency; `files` stays usable
5
5
  // standalone (e.g. user-data-rights-demo mounts `files` + user-data-rights
@@ -127,7 +127,7 @@ export type FoldersFeatureOptions = {
127
127
  /** Row-level ownership on the folder-assignment rows themselves — orthogonal
128
128
  * to `access`, which only gates whether a caller may dispatch set/clear/list
129
129
  * at all. Not needed to keep a caller from reading assignments on host
130
- * entities they can't see: that gate is default-on since fw#2766 and derives
130
+ * entities they can't see: that gate is default-on and derives
131
131
  * from the entity's `parentRef`. Use `ownership.read` for an ADDITIONAL row
132
132
  * rule on the assignment row itself; it is AND-ed with the host-visibility
133
133
  * gate. Applies only to `folder-assignment`; the `folder` catalog stays
@@ -521,8 +521,8 @@ export function FolderManager({
521
521
 
522
522
  // The bucket itself must stay in the tree even when nothing is currently
523
523
  // unfiled — it's the only drop target to un-file a leaf back out of a
524
- // folder. Regression: #671/5 — an empty `unfiled` array made the bucket
525
- // vanish entirely, silently removing that escape hatch.
524
+ // folder. An empty `unfiled` array made the bucket vanish entirely, silently
525
+ // removing that escape hatch.
526
526
  const hasUnfiled = filing !== undefined;
527
527
  if (hasUnfiled) {
528
528
  out.push(bucketRow(stripeNext()));
@@ -47,11 +47,11 @@ export function buildFolderTree(rows: readonly FolderRow[]): readonly FolderNode
47
47
  return build(null, 0);
48
48
  }
49
49
 
50
- // "Immobilie Berlin / Person Müller" for a folder id, walking parentId up.
51
- // Empty string if the id is unknown. The row-count cap stops a (currently
52
- // impossible — no reparent yet) parent cycle from spinning forever — `< `,
53
- // not `<=` (658/4): a cycle of exactly rows.length nodes must stop AT the
54
- // cap, not run one iteration past it.
50
+ // Returns a path such as "Properties / Berlin" for a folder id by walking
51
+ // parentId upward, or an empty string if the id is unknown. The row-count cap
52
+ // stops a parent cycle (currently impossible, since there is no reparent yet)
53
+ // from spinning forever. Use `<`, not `<=`: a cycle of exactly rows.length
54
+ // nodes must stop at the cap, not run one iteration past it.
55
55
  export function folderPath(rows: readonly FolderRow[], id: string, separator = " / "): string {
56
56
  const byId = new Map(rows.map((r) => [r.id, r]));
57
57
  const names: string[] = [];
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "Encrypted drafts without a PII key service raise an error",
6
+ "detail": "Reading a ciphertext draft with no PII subject key service configured throws instead of returning an empty draft, so the stale-draft cleanup defers it and no longer releases its file refs as if it were empty."
7
+ },
2
8
  {
3
9
  "version": "0.379.0",
4
10
  "type": "breaking",
@@ -1,5 +1,5 @@
1
1
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
2
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
+ import { toPostgresArrayLiteral, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
5
5
  import { readStoredDraft } from "../../decrypt-draft.ts";
@@ -22,7 +22,7 @@ export type StaleDraftRow = {
22
22
  // once; a draft saved exactly once (create, never updated) has no
23
23
  // modified_at yet, so falls back to inserted_at.
24
24
  //
25
- // Reads the blob + tenantId BEFORE anything is deleted (issue #1915) — the
25
+ // Reads the blob + tenantId BEFORE anything is deleted — the
26
26
  // caller (cleanup.job.ts) walks each row's blob for FileRefs and releases
27
27
  // them per-tenant via ctx._fileProviderResolver, then deletes the batch
28
28
  // per-row via formDraftExecutor.delete (event-sourced, not raw SQL — a
@@ -48,7 +48,7 @@ export async function selectStaleDraftsBatch(
48
48
  AND NOT ("id"::text = ANY($3::text[]))
49
49
  ORDER BY COALESCE("modified_at", "inserted_at") ASC
50
50
  LIMIT $2`,
51
- [olderThanDays, batchSize, [...excludeIds]],
51
+ [olderThanDays, batchSize, toPostgresArrayLiteral([...excludeIds])],
52
52
  );
53
53
  return Promise.all(
54
54
  rows.map(async (row) => {
@@ -8,7 +8,7 @@ import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
8
8
  import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
9
9
 
10
10
  // Narrows a draft blob's raw FileRef-shaped storageKeys (collectDraftFileRefKeys
11
- // output — extracted from free-form, client-supplied JSON, issue #1889) down to
11
+ // output — extracted from free-form, client-supplied JSON) down to
12
12
  // the ones with a real, non-deleted file_refs row owned by this exact
13
13
  // (tenantId, ownerId). Without this, a crafted draft value like
14
14
  // { storageKey: "<someone-else's-real-key>" } would reach the storage
@@ -4,6 +4,7 @@ import {
4
4
  decryptPiiFieldValues,
5
5
  isPiiCiphertext,
6
6
  } from "@cosmicdrift/kumiko-framework/crypto";
7
+ import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
7
8
  import { type FormDraftBlob, formDraftBlobSchema } from "./schemas.ts";
8
9
 
9
10
  // Raw reads (fetchOne/selectMany/SQL) return the stored column, which is
@@ -13,7 +14,9 @@ import { type FormDraftBlob, formDraftBlobSchema } from "./schemas.ts";
13
14
  export async function readStoredDraft(stored: unknown): Promise<FormDraftBlob | null> {
14
15
  let plain = stored;
15
16
  const kms = configuredPiiSubjectKms();
16
- if (isPiiCiphertext(stored) && kms) {
17
+ if (isPiiCiphertext(stored)) {
18
+ // A silent null would make the stale-draft cleanup treat the draft as empty and leak its file refs.
19
+ if (!kms) throw new InternalError({ message: "form-draft: pii kms not configured" });
17
20
  const out = await decryptPiiFieldValues({ draft: stored }, ["draft"], kms, {
18
21
  requestId: requestContext.get()?.requestId ?? "form-draft:read",
19
22
  });
@@ -11,8 +11,8 @@ import { FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT } from "./w
11
11
  // (tenant, ownerId): the same key from two different users, or the same
12
12
  // user in two different tenants, is a different draft.
13
13
  //
14
- // Boundary (issue #1889): form-draft never holds anything that already
15
- // lives in a domain stream — it's a Zwischenstand BEFORE the domain entity
14
+ // Boundary: form-draft never holds anything that already
15
+ // lives in a domain stream — it's an intermediate state BEFORE the domain entity
16
16
  // is created. Consumers delete the draft (discard handler) once the real
17
17
  // submit succeeds; partially-created domain data past that point is the
18
18
  // consuming app's concern, not this feature's.
@@ -34,7 +34,7 @@ export const formDraftEntity = createEntity({
34
34
  personal: false,
35
35
  reason: "technical_reference",
36
36
  }),
37
- // The blob shape is fixed by issue #1889, not left to the caller:
37
+ // The blob shape is fixed, not left to the caller:
38
38
  // { values: Record<string, unknown>, stepIndex: number, savedAt: string }.
39
39
  // Free-form because `values` mirrors whatever fields the in-progress
40
40
  // form has, so it can carry arbitrary user-entered PII. Encrypted under
@@ -1,9 +1,8 @@
1
1
  // form-draft — a per-user, per-tenant working copy of an in-progress form,
2
- // saved BEFORE the real domain entity exists. Backing for wizard-mode resume
3
- // (kumiko-framework#1884/#1883): a caller-assigned draftKey (typically
4
- // screenId + optional hostEntityId) round-trips { values, stepIndex,
5
- // savedAt } through save/discard/get. See entity.ts for the ownership +
6
- // uniqueness model.
2
+ // saved BEFORE the real domain entity exists. Backing for wizard-mode resume.
3
+ // A caller-assigned draftKey (typically screenId + optional hostEntityId)
4
+ // round-trips { values, stepIndex, savedAt } through save/discard/get. See
5
+ // entity.ts for the ownership + uniqueness model.
7
6
 
8
7
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
9
8
  import { defineFeature, type FeatureRegistrar } from "@cosmicdrift/kumiko-framework/engine";
@@ -79,7 +79,7 @@ export const discardDraftWrite = defineWriteHandler({
79
79
  // Fail-closed erase of file_refs rows FIRST (outside the best-effort
80
80
  // storage-hygiene loop). releaseDraftFileRefs swallows per-key errors
81
81
  // by design — routing forget through it would report discarded:true
82
- // while leaving the row behind (#1922 / review #2009).
82
+ // while leaving the row behind.
83
83
  for (const ref of ownedRefs) {
84
84
  const forgetResult = await fileRefExecutor.forget({ id: ref.id }, event.user, ctx.db);
85
85
  if (!forgetResult.isSuccess) return forgetResult;
@@ -1,7 +1,7 @@
1
1
  import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
2
  import type { FormDraftBlob } from "./schemas.ts";
3
3
 
4
- // The draft blob's `values` is free-form by design (issue #1889: form-draft
4
+ // The draft blob's `values` is free-form by design: form-draft
5
5
  // never knows the consuming form's field schema, only { values, stepIndex,
6
6
  // savedAt }). A FileRef pointer is therefore recognised purely by shape —
7
7
  // any object anywhere in `values` carrying a non-empty string `storageKey`
@@ -48,11 +48,11 @@ export function collectDraftFileRefKeys(
48
48
  //
49
49
  // Takes an already-decided key list, not the draft blob — callers must run
50
50
  // collectDraftFileRefKeys() output through db/queries' owned-storage-key
51
- // filter first. `values` is free-form, client-supplied JSON (issue #1889);
52
- // releasing a key straight out of it without verifying a real, owned
53
- // file_refs row exists would let a crafted `{ storageKey: "<victim's key>" }`
54
- // delete someone else's file — the same ownership check file-routes.ts runs
55
- // before every read/delete (loadFileForTenant + FileAccessGuard).
51
+ // filter first. `values` is free-form, client-supplied JSON; releasing a key
52
+ // straight out of it without verifying a real, owned file_refs row exists
53
+ // would let a crafted `{ storageKey: "<victim's key>" }` delete someone
54
+ // else's file — the same ownership check file-routes.ts runs before every
55
+ // read/delete (loadFileForTenant + FileAccessGuard).
56
56
  export async function releaseDraftFileRefs(
57
57
  keys: readonly string[],
58
58
  deleteBinary: (storageKey: string) => Promise<void>,
@@ -17,9 +17,9 @@ const draftValuesSchema = z
17
17
  `values exceeds the ${FORM_DRAFT_VALUES_MAX_BYTES}-byte limit`,
18
18
  );
19
19
 
20
- // The draft blob shape — fixed by issue #1889 here, not left for consumers
20
+ // The draft blob shape — fixed here, not left for consumers
21
21
  // to invent per-app. `stepIndex` is in from the start so wizard-mode resume
22
- // (kumiko-framework#1884) doesn't need a later migration.
22
+ // doesn't need a later migration.
23
23
  export const formDraftBlobSchema = z.object({
24
24
  values: z.record(z.string(), z.unknown()),
25
25
  stepIndex: z.number().int().min(0),
@@ -41,7 +41,7 @@ export type SaveDraftPayload = z.infer<typeof saveDraftPayloadSchema>;
41
41
  // row right after the domain entity write already carries the same
42
42
  // storageKeys forward — releasing them here would destroy files the entity
43
43
  // now depends on. Only an actual abandon/abort flow should pass
44
- // releaseFiles: true (issue #1915's "explicit abort" case).
44
+ // releaseFiles: true (the "explicit abort" case).
45
45
  export const discardDraftPayloadSchema = z.object({
46
46
  draftKey: draftKeySchema,
47
47
  releaseFiles: z.boolean().optional(),
@@ -1,6 +1,4 @@
1
1
  // form-draft bundle constants — feature-name + qualified handler/query names.
2
- //
3
- // Part of CosmicDriftGameStudio/kumiko-framework#1883 (wizard mode), issue #1889.
4
2
 
5
3
  import type { AccessRule } from "@cosmicdrift/kumiko-framework/engine";
6
4
 
@@ -92,5 +92,5 @@ allowlists stay in the app: wrap the dispatch function and fall through to it.
92
92
 
93
93
  - `tenantBy: (host, db) => TenantId | null` resolves every host that is neither the apex nor a fixed host (profile subdomains, custom domains). The tenant must be enabled and active; null means 404 for pages and `tenant_required` for the API. `createHostTenantIdResolver(options, db)` exposes the same mapping for managed-pages' `resolveApexTenant`.
94
94
  - `tenantPathPrefix` is optional in host and resolver mode and serves `<prefix>/<key>` on the apex. The API half still takes the apex anchor there; an app that needs a path-named tenant on API calls resolves it itself.
95
- - `redirects: [{ from, to, host?, status? }]` run before host classification. `to` is configured, never derived from the request.
95
+ - `redirects: [{ from, to, host?, status? }]` run before host classification inside hostDispatch, i.e. only for requests that reach the HTML fallback (no static file, no API route); a `from` that matches a static file or `/api/...` never fires. `to` is configured, never derived from the request.
96
96
  - `apexAnonymousQueryAllowlist: { "example.com": ["feature:query:x"] }` limits the anonymous apex anchor to the listed query types on that host, for `/api/query` and `/api/stream`; other paths keep the anchor. `example.com` and `www.example.com` share one entry (a host without its own uses the other's). Combined with `tenantBy: "path"` it throws at boot, because the client names its tenant there (X-Tenant wins over the resolver) and would bypass the allowlist.
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "Redirects documented as hostDispatch-only",
6
+ "detail": "The redirects option and README state that redirects run inside hostDispatch, so only for requests that reach the HTML fallback; a from matching a static file or an API route never fires. The shared existence lookup of the host and resolver modes is one helper."
7
+ },
2
8
  {
3
9
  "version": "0.376.0",
4
10
  "type": "improvement",