@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,4 +1,34 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "Preferences query reports renamed notification types under the current name",
6
+ "detail": "Rows stored under a former notification name are returned with the current name and collapsed per channel with the delivery precedence (current-name row wins, otherwise any disabled row disables), so settings screens show the effective state."
7
+ },
8
+ {
9
+ "version": "0.388.0",
10
+ "type": "fix",
11
+ "title": "Inline mail image retries on transient storage errors",
12
+ "detail": "Only a missing file storage for the file's tenant sends the mail without the inline image; any other read error (timeout, provider failure, DB) is rethrown so the send job retries instead of mailing without the logo."
13
+ },
14
+ {
15
+ "version": "0.388.0",
16
+ "type": "fix",
17
+ "title": "Unsubscribe tenant origin resolved once per notify call",
18
+ "detail": "The app's tenantOrigin callback runs once per notify call and tenant instead of once per recipient and channel, so a newsletter no longer causes one lookup and one fallback warning per address. The docs state the callback must only return verified, active domains."
19
+ },
20
+ {
21
+ "version": "0.388.0",
22
+ "type": "fix",
23
+ "title": "One-click unsubscribe POST keeps the JSON rejection",
24
+ "detail": "RFC 8058 one-click POSTs (form body List-Unsubscribe=One-Click) answer an invalid or expired token with the JSON 400 again and skip the branding lookup; only browser form submits get the HTML page."
25
+ },
26
+ {
27
+ "version": "0.388.0",
28
+ "type": "fix",
29
+ "title": "Resubscribe limit page has its own text",
30
+ "detail": "A browser that hits the resubscribe limit sees that the address cannot be subscribed again here, instead of the generic \"try again later\" error (new key mail.unsubscribe.resubscribeLimitReached in en, de, es, fr, it)."
31
+ },
2
32
  {
3
33
  "version": "0.383.0",
4
34
  "type": "fix",
@@ -5,7 +5,11 @@ import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
5
5
  import type { FileContext } from "@cosmicdrift/kumiko-framework/files";
6
6
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
7
7
  import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
8
- import { type FileRefContent, readFileRefContent } from "../file-foundation/index.ts";
8
+ import {
9
+ type FileRefContent,
10
+ FileStorageUnavailableError,
11
+ readFileRefContent,
12
+ } from "../file-foundation/index.ts";
9
13
  import {
10
14
  collectRendererPlugins,
11
15
  createRendererFoundationApi,
@@ -86,7 +90,8 @@ function createPdfRenderer(
86
90
  };
87
91
  }
88
92
 
89
- // A decorative inline image (logo) that cannot be read must not fail the whole mail.
93
+ // A decorative inline image (logo) of a tenant without file storage must not fail the whole mail;
94
+ // transient read errors rethrow so the send job retries.
90
95
  async function readInlineImageOrNull(
91
96
  fileRefId: string,
92
97
  read: () => Promise<FileRefContent | null>,
@@ -94,9 +99,10 @@ async function readInlineImageOrNull(
94
99
  try {
95
100
  return await read();
96
101
  } catch (err) {
102
+ if (!(err instanceof FileStorageUnavailableError)) throw err;
97
103
  createFallbackLogger("delivery").warn("inline image could not be read, sending without it", {
98
104
  fileRefId,
99
- errorName: err instanceof Error ? err.name : typeof err,
105
+ errorName: err.name,
100
106
  });
101
107
  return null;
102
108
  }
@@ -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
 
5
5
  export type NotificationPreferenceRow = {
@@ -27,6 +27,6 @@ export async function selectNotificationPreferences(
27
27
  OR (notification_type = '*' AND channel = $4)
28
28
  OR (notification_type = ANY($3::text[]) AND channel = '*')
29
29
  )`,
30
- [tenantId, userId, notificationTypeNames, channelName],
30
+ [tenantId, userId, toPostgresArrayLiteral(notificationTypeNames), channelName],
31
31
  );
32
32
  }
@@ -484,9 +484,37 @@ export function createDeliveryService(options: DeliveryServiceOptions): Delivery
484
484
  }
485
485
  }
486
486
 
487
+ // The app's tenantOrigin callback typically hits the DB: once per run and tenant, not per recipient.
488
+ const unsubscribeOriginsByRun = new WeakMap<NotifyRun, Map<TenantId, Promise<string>>>();
489
+
490
+ function unsubscribeOriginOnce(
491
+ run: NotifyRun,
492
+ links: UnsubscribeLinkConfig,
493
+ channelCtx: ChannelContext,
494
+ notificationType: string,
495
+ ): Promise<string> {
496
+ let originsByTenant = unsubscribeOriginsByRun.get(run);
497
+ if (originsByTenant === undefined) {
498
+ originsByTenant = new Map();
499
+ unsubscribeOriginsByRun.set(run, originsByTenant);
500
+ }
501
+ let origin = originsByTenant.get(channelCtx.tenantId);
502
+ if (origin === undefined) {
503
+ origin = unsubscribeLinkOrigin(links, channelCtx, (reason) =>
504
+ logError.warn(`unsubscribe link falls back to the app origin: ${reason}`, {
505
+ tenantId: channelCtx.tenantId,
506
+ notificationType,
507
+ }),
508
+ );
509
+ originsByTenant.set(channelCtx.tenantId, origin);
510
+ }
511
+ return origin;
512
+ }
513
+
487
514
  // A caller-supplied unsubscribeUrl wins; the recipient comes from the server-side notify
488
515
  // context, never from the notification data.
489
516
  async function withUnsubscribeUrl(
517
+ run: NotifyRun,
490
518
  message: ChannelMessage,
491
519
  channelName: string,
492
520
  recipient: UnsubscribeLinkRecipient,
@@ -498,11 +526,11 @@ export function createDeliveryService(options: DeliveryServiceOptions): Delivery
498
526
  }
499
527
  const supplied = message.data?.["unsubscribeUrl"];
500
528
  if (typeof supplied === "string" && supplied !== "") return message;
501
- const origin = await unsubscribeLinkOrigin(unsubscribeLinks, channelCtx, (reason) =>
502
- logError.warn(`unsubscribe link falls back to the app origin: ${reason}`, {
503
- tenantId: channelCtx.tenantId,
504
- notificationType: message.notificationType,
505
- }),
529
+ const origin = await unsubscribeOriginOnce(
530
+ run,
531
+ unsubscribeLinks,
532
+ channelCtx,
533
+ message.notificationType,
506
534
  );
507
535
  const unsubscribeUrl = await buildUnsubscribeUrl(unsubscribeLinks, origin, recipient, {
508
536
  tenantId: channelCtx.tenantId,
@@ -811,6 +839,7 @@ export function createDeliveryService(options: DeliveryServiceOptions): Delivery
811
839
  channel,
812
840
  address,
813
841
  message: await withUnsubscribeUrl(
842
+ run,
814
843
  message,
815
844
  channel.name,
816
845
  { kind: "user", userId },
@@ -914,6 +943,7 @@ export function createDeliveryService(options: DeliveryServiceOptions): Delivery
914
943
  channel,
915
944
  address,
916
945
  message: await withUnsubscribeUrl(
946
+ run,
917
947
  message,
918
948
  channel.name,
919
949
  { kind: "address", address },
@@ -46,7 +46,7 @@ import {
46
46
  export type DeliveryFeatureOptions = {
47
47
  // Access gate for the delivery-log screen and the `log` query it reads —
48
48
  // both move together so the nav entry a role sees always matches a
49
- // callable handler (#2033). Default access.admin includes TenantAdmin,
49
+ // callable handler. Default access.admin includes TenantAdmin,
50
50
  // who in a line-of-business app is the operator, not the platform — pass
51
51
  // access.systemAdmin to keep this platform-only and out of their nav.
52
52
  readonly access?: readonly string[];
@@ -99,10 +99,10 @@ export function createDeliveryFeature(options?: DeliveryFeatureOptions): Feature
99
99
  // boot-validator accepts the projection below because at least one
100
100
  // apply-key is a registered domain-event (DELIVERY_ATTEMPT_EVENT).
101
101
  // recipientAddress is the real PII (email address); recipientId stays
102
- // plaintext — pseudonymous fk, same line as config.userId (#821).
102
+ // plaintext — pseudonymous fk, same line as config.userId.
103
103
  // recipientId is nullable (system-triggered sends to non-users), so the
104
104
  // address falls back to the tenant key instead of the plaintext it used
105
- // to be — still shreddable, one tenant wide (fw#2776).
105
+ // to be — still shreddable, one tenant wide.
106
106
  r.defineEvent("attempt", deliveryAttemptSchema, {
107
107
  piiFields: {
108
108
  recipientAddress: { personal: { of: "recipientId", whenAbsent: "tenant" } },
@@ -208,7 +208,7 @@ export const logQuery = definePagedQueryHandler({
208
208
  const nextCursor =
209
209
  rows.length === limit && lastRow ? encodeSortCursor(sortColumn, lastRow) : null;
210
210
 
211
- // recipientAddress is stored encrypted under the recipient's DEK (#799)
211
+ // recipientAddress is stored encrypted under the recipient's DEK
212
212
  // — decrypt for the admin log view; forgotten subjects show [[erased]].
213
213
  // The notificationType/recipientAddress → type/recipient rename happens
214
214
  // here, not in the client: a projectionList screen has no entity to
@@ -2,6 +2,7 @@ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import * as z from "zod";
5
+ import { currentNotificationType } from "../notification-type-aliases.ts";
5
6
  import { notificationPreferencesTable } from "../tables.ts";
6
7
 
7
8
  export const preferencesQuery = defineQueryHandler({
@@ -37,6 +38,24 @@ export const preferencesQuery = defineQueryHandler({
37
38
  userId: query.user.id,
38
39
  });
39
40
 
40
- return { rows };
41
+ // Rows stored under a former notification name are reported under the current
42
+ // one, collapsed with the same precedence as delivery: an exact row wins,
43
+ // otherwise any disabled former-name row disables.
44
+ const collapsed = new Map<string, { row: (typeof rows)[number]; isExact: boolean }>();
45
+ for (const row of rows) {
46
+ const notificationType = currentNotificationType(ctx.registry, row.notificationType);
47
+ const key = `${notificationType}\u0000${row.channel}`;
48
+ const isExact = row.notificationType === notificationType;
49
+ const existing = collapsed.get(key);
50
+ if (existing?.isExact) continue;
51
+ const formerNameRowDisablesAlready =
52
+ existing !== undefined &&
53
+ !isExact &&
54
+ (existing.row.enabled === false || row.enabled !== false);
55
+ if (formerNameRowDisablesAlready) continue;
56
+ collapsed.set(key, { row: { ...row, notificationType }, isExact });
57
+ }
58
+
59
+ return { rows: [...collapsed.values()].map((entry) => entry.row) };
41
60
  },
42
61
  });
@@ -33,7 +33,7 @@ export const unsubscribePageChromeQuery = defineQueryHandler({
33
33
  // or createUnsubscribePageChromeReader for a tenant the app resolved server-side.
34
34
  agent: { expose: false },
35
35
  description:
36
- "Returns the tenant's mail brand row and footer resolved for one locale, or null without a mail renderer; dispatched by the signed unsubscribe route to dress its pages like the mail, not meant for UI callers.",
36
+ "Returns the tenant's mail brand row and footer resolved for one locale, or null without a mail renderer; dispatched by the signed unsubscribe route or by createUnsubscribePageChromeReader for a tenant the app resolved server-side, to dress its pages like the mail; not meant for UI callers.",
37
37
  handler: async (query, ctx): Promise<MailChrome | null> => {
38
38
  const { tenantId } = query.user;
39
39
  if (!ctx.systemDb) {
@@ -53,14 +53,15 @@ export const deliveryAttemptsTable = pgTable(
53
53
  (t) => [index(DELIVERY_ATTEMPTS_TENANT_CREATED_INDEX).on(t.tenantId, t.createdAt)],
54
54
  );
55
55
 
56
- // **Unmanaged table** — bewusst KEIN createEntity. Begründung:
57
- // - id kommt aus dem Aggregate-Stream (kein gen_random_uuid()-DEFAULT)
58
- // - kein version/inserted_by/modified_by/modified_at — keine in-place-
59
- // Edits, keine Audit-Spalten nötig (idempotent-on-replay via PK-Konflikt)
60
- // - created_at statt inserted_at — historischer Naming-Drift, kein Bug
61
- // App trägt Verantwortung für tenant-scoping in Queries + replay-idempotency.
62
- // pgTable bleibt source-of-truth für Query-API; Phase 4 leitet das pgTable
63
- // aus dieser Meta ab.
56
+ // **Unmanaged table** — deliberately has no createEntity because:
57
+ // - id comes from the aggregate stream (no gen_random_uuid()-DEFAULT)
58
+ // - no version/inserted_by/modified_by/modified_at: no in-place edits or
59
+ // audit columns are needed (idempotent-on-replay via PK conflict)
60
+ // - created_at rather than inserted_at reflects historical naming drift, not
61
+ // a bug
62
+ // The app is responsible for tenant scoping in queries and replay idempotency.
63
+ // pgTable remains the source of truth for the query API; the pgTable is derived
64
+ // from this metadata.
64
65
  export const deliveryAttemptsTableMeta: EntityTableMeta = defineUnmanagedTable({
65
66
  tableName: "store_delivery_attempts",
66
67
  indexes: [{ name: DELIVERY_ATTEMPTS_TENANT_CREATED_INDEX, columns: ["tenant_id", "created_at"] }],
@@ -10,7 +10,9 @@ export type UnsubscribeLinkConfig = {
10
10
  readonly secret: string;
11
11
  readonly baseUrl: string;
12
12
  /** The sending tenant's own public origin (subdomain or custom domain), null when it has
13
- * none. The host must serve this app's `/api` routes. Null, a throw or an unusable value
13
+ * none. The host must serve this app's `/api` routes, and the callback must only return a
14
+ * verified, active domain of the tenant (the check that lets the app serve under it), else null:
15
+ * the link carries a bearer token that unsubscribes and yields a resubscribe token. Null, a throw or an unusable value
14
16
  * fall back to `baseUrl`, so a missing tenant origin never fails a send. */
15
17
  readonly tenantOrigin?: (ctx: ChannelContext) => Promise<string | null | undefined>;
16
18
  };
@@ -14,6 +14,7 @@ export const UNSUBSCRIBE_PAGE_EN = {
14
14
  "mail.unsubscribe.resubscribedMessage": "You have been subscribed again.",
15
15
  "mail.unsubscribe.failed": "That did not work. Please try again later.",
16
16
  "mail.unsubscribe.failedTitle": "Something went wrong",
17
+ "mail.unsubscribe.resubscribeLimitReached": "This address cannot be subscribed again here.",
17
18
  "mail.unsubscribe.invalidTitle": "Link no longer valid",
18
19
  "mail.unsubscribe.invalidMessage":
19
20
  "This link is invalid or has expired. Please use the unsubscribe link in a more recent email.",
@@ -11,6 +11,7 @@ export type UnsubscribePageState =
11
11
  | { readonly kind: "unsubscribed"; readonly resubscribeToken?: string }
12
12
  | { readonly kind: "resubscribed" }
13
13
  | { readonly kind: "failed" }
14
+ | { readonly kind: "resubscribeLimitReached" }
14
15
  | { readonly kind: "invalid" };
15
16
 
16
17
  export type UnsubscribePageInput = {
@@ -162,6 +163,11 @@ ${tokenForm(DELIVERY_RESUBSCRIBE_PATH, state.resubscribeToken, mailT(lang, "mail
162
163
  title: mailT(lang, "mail.unsubscribe.failedTitle"),
163
164
  bodyHtml: paragraph("mail.unsubscribe.failed"),
164
165
  };
166
+ case "resubscribeLimitReached":
167
+ return {
168
+ title: mailT(lang, "mail.unsubscribe.failedTitle"),
169
+ bodyHtml: paragraph("mail.unsubscribe.resubscribeLimitReached"),
170
+ };
165
171
  case "invalid":
166
172
  return {
167
173
  title: mailT(lang, "mail.unsubscribe.invalidTitle"),
@@ -31,13 +31,13 @@ const localeClaimSchema = z
31
31
  .regex(/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{1,8})*$/)
32
32
  .optional();
33
33
 
34
- // Shape des verified-JWT-payloads. tenantId kommt als string aus jose und
35
- // wird NACH erfolgreichem parse() zur Branded TenantId — kein blind-cast.
34
+ // Shape of verified JWT payloads. `tenantId` arrives from jose as a string and
35
+ // becomes a branded `TenantId` only after successful `parse()`—never via a blind cast.
36
36
  //
37
37
  // `kind` is explicitly typed as "absent or undefined, nothing else" here
38
38
  // (not bare `.optional()`, which would also accept any other value on an
39
- // unrelated key) so an address-token payload — which always carries
40
- // `kind: "address"` — fails this schema instead of silently parsing with
39
+ // unrelated key) so an address-token payload—which always carries
40
+ // `kind: "address"`—fails this schema instead of silently parsing with
41
41
  // `addressHash` mistaken for a userId.
42
42
  const unsubscribeJwtPayloadSchema = z.object({
43
43
  kind: z.undefined().optional(),
@@ -569,11 +569,20 @@ async function verifyPost(
569
569
  encodedSecret: Uint8Array,
570
570
  purpose: TokenPurpose,
571
571
  ): Promise<VerifiedUnsubscribe | RejectedForPage> {
572
- return isFormRequest(request.headers["content-type"])
572
+ return isFormRequest(request.headers["content-type"]) && !isOneClickPost(request)
573
573
  ? verifyForPage(token, encodedSecret, purpose, request.headers)
574
574
  : verifyUnsubscribeToken(token, encodedSecret, purpose);
575
575
  }
576
576
 
577
+ // RFC 8058 mail-provider POSTs are form-encoded too, but nobody looks at the answer: they keep
578
+ // the JSON rejection and get no branded page.
579
+ function isOneClickPost(request: SignatureExtraRouteVerifyRequest): boolean {
580
+ return (
581
+ isFormRequest(request.headers["content-type"]) &&
582
+ request.rawBody.trim() === DELIVERY_UNSUBSCRIBE_ONE_CLICK_HEADER_VALUE
583
+ );
584
+ }
585
+
577
586
  function isFormRequest(contentType: string | undefined): boolean {
578
587
  return contentType?.includes("application/x-www-form-urlencoded") === true;
579
588
  }
@@ -635,22 +644,37 @@ export function createUnsubscribeRoutes(
635
644
  : pageResponse(c, deps, { kind: "confirm", token: verified.token }, verified, 200),
636
645
  });
637
646
 
638
- const writeRoute = signatureRoute<VerifiedUnsubscribe | RejectedForPage>({
647
+ const writeRoute = signatureRoute<
648
+ (VerifiedUnsubscribe & { readonly oneClick: boolean }) | RejectedForPage
649
+ >({
639
650
  method: "POST",
640
651
  path: DELIVERY_UNSUBSCRIBE_PATH,
641
652
  entry: "signature",
642
- verify: async (request) =>
643
- verifyPost(request, tokenFromPostRequest(request), encodedSecret, "unsubscribe"),
653
+ verify: async (request) => {
654
+ const verified = await verifyPost(
655
+ request,
656
+ tokenFromPostRequest(request),
657
+ encodedSecret,
658
+ "unsubscribe",
659
+ );
660
+ return verified.kind === "rejected"
661
+ ? verified
662
+ : { ...verified, oneClick: isOneClickPost(request) };
663
+ },
644
664
  handler: async (c, verified, deps) => {
645
665
  if (verified.kind === "rejected") {
646
666
  return pageResponse(c, deps, { kind: "invalid" }, verified, 400);
647
667
  }
668
+ // No chrome lookup for a one-click client: it never renders the page.
669
+ const pageScope: PageScope = verified.oneClick
670
+ ? { tenantId: undefined, locale: verified.locale }
671
+ : verified;
648
672
  // Token-verify passed — everything below is a legitimate write. Don't
649
673
  // swallow write-errors as "invalid token", that would mask real bugs
650
674
  // (e.g. events-table missing, DB down) behind a misleading 400.
651
675
  const succeeded = await dispatchUnsubscribeWrite(verified, deps);
652
676
  if (!succeeded) {
653
- return pageResponse(c, deps, { kind: "failed" }, verified, 500);
677
+ return pageResponse(c, deps, { kind: "failed" }, pageScope, 500);
654
678
  }
655
679
  return pageResponse(
656
680
  c,
@@ -659,7 +683,7 @@ export function createUnsubscribeRoutes(
659
683
  kind: "unsubscribed",
660
684
  resubscribeToken: await signResubscribeToken(verified, encodedSecret),
661
685
  },
662
- verified,
686
+ pageScope,
663
687
  200,
664
688
  );
665
689
  },
@@ -681,15 +705,12 @@ export function createUnsubscribeRoutes(
681
705
  const outcome = await dispatchResubscribeWrite(verified, deps);
682
706
  // The undo button on the unsubscribed page posts a form; a browser should land on a page.
683
707
  if (isFormRequest(c.req.header("content-type"))) {
684
- return outcome === "success"
685
- ? pageResponse(c, deps, { kind: "resubscribed" }, verified, 200)
686
- : pageResponse(
687
- c,
688
- deps,
689
- { kind: "failed" },
690
- verified,
691
- outcome === "limit_reached" ? 409 : 500,
692
- );
708
+ if (outcome === "success") {
709
+ return pageResponse(c, deps, { kind: "resubscribed" }, verified, 200);
710
+ }
711
+ return outcome === "limit_reached"
712
+ ? pageResponse(c, deps, { kind: "resubscribeLimitReached" }, verified, 409)
713
+ : pageResponse(c, deps, { kind: "failed" }, verified, 500);
693
714
  }
694
715
  if (outcome === "limit_reached") {
695
716
  return c.json(
@@ -28,10 +28,9 @@ const executor = createEventStoreExecutor(
28
28
  { entityName: "notification-preference" },
29
29
  );
30
30
 
31
- // Konkretes Lookup-Result-Shape — nur die Felder die der upsert
32
- // tatsächlich für den Update-Path braucht. Vermeidet `row["x"] as T` index-
33
- // access casts; der Generic-Param am fetchOne macht den Cast zentralisiert
34
- // im Helper (db-row-boundary), nicht 4× pro Callsite.
31
+ // Concrete lookup result shape containing only the fields needed by the upsert update path. Avoids
32
+ // `row["x"] as T` index-access casts; the generic parameter on fetchOne centralizes the cast in the
33
+ // helper (`db-row-boundary`) instead of repeating it at each call site.
35
34
  type PreferenceLookupRow = {
36
35
  readonly id: string;
37
36
  readonly version: number;
@@ -6,7 +6,7 @@ import {
6
6
  createTextField,
7
7
  } from "@cosmicdrift/kumiko-framework/engine";
8
8
 
9
- // Phase-1 (MVP) page shape — LiteParse fills this in (kumiko-enterprise#273).
9
+ // (MVP) page shape — LiteParse fills this in.
10
10
  // Kept minimal on purpose: downstream themes (provider, recipe) extend it.
11
11
  // Stored as JSON.stringify(IngestPage[]) in the encrypted `pages` column —
12
12
  // jsonb has no encryption support in the engine, and this column holds the
@@ -29,7 +29,7 @@ export type DocumentExtractMeta = {
29
29
 
30
30
  // documentExtract — implicit entity-projection (r.entity, NOT r.projection):
31
31
  // an explicit r.projection would make `forget` non-rebuild-safe and require
32
- // archiveStream instead of the regular forget path (kumiko-framework#1495).
32
+ // archiveStream instead of the regular forget path.
33
33
  // fileRefId points at the source file_refs row; storageKey duplicates it for
34
34
  // direct provider access without a join.
35
35
  export const documentExtractEntity = createEntity({
@@ -42,11 +42,11 @@ export const documentExtractEntity = createEntity({
42
42
  reason: "technical_reference",
43
43
  }),
44
44
  // Holds the full extracted document text (PII). `personal: "tenant"`,
45
- // NOT `encrypted: true` (#1621): the master-key path has no erasure subject,
45
+ // NOT `encrypted: true`: the master-key path has no erasure subject,
46
46
  // so nothing here would ever be shreddable. Tenant-subject ciphertext
47
- // dies with eraseSubjectKeys on tenant-destroy (#800 pattern). Whose
47
+ // dies with eraseSubjectKeys on tenant-destroy. Whose
48
48
  // subject a third party named inside a document is stays open, same as
49
- // inbound-mail-foundation (#957). meta is provider telemetry only and
49
+ // inbound-mail-foundation. meta is provider telemetry only and
50
50
  // stays plaintext jsonb.
51
51
  pages: createLongTextField({
52
52
  personal: "tenant",
@@ -4,8 +4,8 @@ import * as z from "zod";
4
4
  // stream per fileRef with aggregateId derived from the fileRefId
5
5
  // (documentIngestAggregateId), never the fileRefId itself: foreign events on
6
6
  // the fileRef stream would break the fileRef's optimistic lock. Not backed by an r.entity;
7
- // this is a pure saga-anchor event (kumiko-framework#1497) that the Phase-2
8
- // worker job (kumiko-enterprise LiteParse provider) subscribes to.
7
+ // this is a pure saga-anchor event that the worker job (kumiko-enterprise LiteParse provider)
8
+ // subscribes to.
9
9
  export const DOCUMENT_INGEST_AGGREGATE_TYPE = "document-ingest";
10
10
 
11
11
  // Stream name of stored extract events; differs from the camelCase r.entity name
@@ -166,7 +166,7 @@ export function createDocumentIngestFoundationFeature() {
166
166
  default: "deu+eng",
167
167
  // Tesseract -l argument syntax: one or more 3-letter language codes
168
168
  // joined by "+" (e.g. "deu+eng"). Unconstrained free text here would
169
- // reach the OCR provider call unvalidated (#1501).
169
+ // reach the OCR provider call unvalidated.
170
170
  pattern: { regex: "^[a-z]{3}(\\+[a-z]{3})*$" },
171
171
  write: access.roles("TenantAdmin", "SystemAdmin"),
172
172
  read: access.roles("TenantAdmin", "SystemAdmin", "User"),
@@ -178,7 +178,7 @@ export function createDocumentIngestFoundationFeature() {
178
178
  default: 50,
179
179
  // Without a bound a tenant could set 0 (silently kills ingest) or an
180
180
  // unbounded value (OCR worker runs per-file for as long as the PDF
181
- // has pages — job-queue starvation) (#1501).
181
+ // has pages — job-queue starvation).
182
182
  bounds: { min: 1, max: 500 },
183
183
  write: access.roles("TenantAdmin", "SystemAdmin"),
184
184
  read: access.roles("TenantAdmin", "SystemAdmin", "User"),
@@ -2,7 +2,7 @@
2
2
  // longText (jsonb has no encryption support), so writers must persist
3
3
  // JSON.stringify(IngestPage[]) and readers must parse back. Centralising
4
4
  // the codec here keeps liteparse + recipe consumers lockstep with the
5
- // entity shape (kumiko-framework#1549/1).
5
+ // entity shape.
6
6
 
7
7
  import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
8
8
  import type { IngestPage } from "./entity.ts";
@@ -1,4 +1,4 @@
1
- // Tenant-destroy hook for the documentExtract entity-projection (#1621).
1
+ // Tenant-destroy hook for the documentExtract entity-projection.
2
2
  //
3
3
  // Per-row forget() through the executor, not a bulk deleteMany: documentExtract
4
4
  // is an ES-managed implicit projection, so a store-table write here would be
@@ -6,9 +6,9 @@
6
6
  // resurrect every row this hook removed. forget() (Art. 17 hard-purge) is
7
7
  // replayed by the implicit projection itself, which keeps the erasure
8
8
  // rebuild-safe — the same reasoning as tenant-lifecycle's membership stage,
9
- // and the reason the feature owns an r.entity instead of an r.projection
10
- // (kumiko-framework#1495). The `pages` ciphertext dies separately when the
11
- // pipeline's later `subject-keys` stage erases the tenant subject key.
9
+ // and the reason the feature owns an r.entity instead of an r.projection.
10
+ // The `pages` ciphertext dies separately when the pipeline's later
11
+ // `subject-keys` stage erases the tenant subject key.
12
12
 
13
13
  import { createSystemUser, type TenantDataDestroyHook } from "@cosmicdrift/kumiko-framework/engine";
14
14
  import { documentExtractsTable } from "./entity.ts";
@@ -66,7 +66,7 @@ export function composeTierResolverWithGlobalToggles(
66
66
  // Non-toggleable (always-on) names must keep reaching `result` through the
67
67
  // globalCascade loop below even if this resolver's SYSTEM_TENANT_ID answer
68
68
  // satisfies the emptiness guard above without also merging always-on into
69
- // every per-tenant tierSet (framework#1528).
69
+ // every per-tenant tierSet.
70
70
  tierManaged = new Set(
71
71
  [...managed].filter((name) => {
72
72
  const feature = registry.getFeature(name);
@@ -104,7 +104,7 @@ export function createFeatureTogglesFeature(
104
104
  r.translations({ keys: FEATURE_TOGGLES_I18N });
105
105
 
106
106
  // toggle-cache-sync — multi-instance snapshot propagation. One shared
107
- // cursor reads every toggle-set event once (fw#2625); the winning
107
+ // cursor reads every toggle-set event once; the winning
108
108
  // process's handler calls runtime.broadcastToggle, which publishes on
109
109
  // GlobalFeatureToggleRuntime's syncSignal so every process (including
110
110
  // the one that won the cursor) applies the flip to its own snapshot —
@@ -38,7 +38,7 @@ export const globalFeatureStateTable: WritableSchemaTable & TenancyBrand<"global
38
38
  // sees the table, so `kumiko schema generate` reports no changes and no
39
39
  // app ever gets a migration for it (framework gap, not app-local). Derived
40
40
  // from the pgTable above instead of hand-written a second time — the two
41
- // used to drift independently (framework#1529): a column added only to
41
+ // used to drift independently: a column added only to
42
42
  // the pgTable made queries type-check while the migration generator stayed
43
43
  // blind to it, failing in prod with "column ... does not exist" while every
44
44
  // mocked-stack test stayed green.
@@ -38,11 +38,11 @@ export const registeredQuery = defineQueryHandler({
38
38
  const overrideRows = await db.global(globalFeatureStateTable).selectMany<OverrideRow>();
39
39
  const overrides = new Map(overrideRows.map((r) => [r.featureName, r.enabled]));
40
40
 
41
- // SystemAdmin operator-tooling: das listing soll die PLATTFORM-truth
42
- // zeigen (alle features im Registry), nicht den eigenen tier-cut.
43
- // Sprint-8a per-tenant signature → wir rufen mit SYSTEM_TENANT_ID,
44
- // App-resolver returnt union-of-all-tier-features. Sentinel-Convention
45
- // dokumentiert in DispatcherOptions.effectiveFeatures.
41
+ // SystemAdmin operator tooling: the listing must show platform truth
42
+ // (all features in the registry), not its own tier cut.
43
+ // The per-tenant signature requires SYSTEM_TENANT_ID; the app resolver
44
+ // returns the union of all tier features. The sentinel convention is
45
+ // documented in DispatcherOptions.effectiveFeatures.
46
46
  const effective = ctx.effectiveFeatures?.(SYSTEM_TENANT_ID);
47
47
 
48
48
  const rows: Array<{
@@ -16,7 +16,7 @@ import { createCacheSyncToggleSignal } from "./toggle-sync-signal.ts";
16
16
 
17
17
  const log = createFallbackLogger("kumiko:feature-toggles");
18
18
 
19
- // Cross-replica transport for a toggle flip (fw#2625). Deliberately narrow
19
+ // Cross-replica transport for a toggle flip. Deliberately narrow
20
20
  // (featureName + enabled, not a generic channel/payload pair) so a caller
21
21
  // can't wire the wrong signal instance in by accident — see
22
22
  // createRedisToggleSyncSignal (toggle-sync-signal.ts) for the Redis-backed
@@ -27,7 +27,7 @@ function isTogglePayload(value: unknown): value is { featureName: string; enable
27
27
  );
28
28
  }
29
29
 
30
- // fw#2625: gives toggle-cache-sync the cross-replica transport its shared
30
+ // Gives toggle-cache-sync the cross-replica transport its shared
31
31
  // dispatcher cursor needs — without this, only the one process that won
32
32
  // the shared cursor's toggle-set event would ever learn about a flip.
33
33
  // Standalone Redis transport for callers that want their own connections;
@@ -11,7 +11,7 @@ export const FEATURE_TOGGLE_AGGREGATE_TYPE = "feature-toggles";
11
11
 
12
12
  // Shared acknowledgeCrossTenant() reason across all three handlers that read
13
13
  // or write globalFeatureStateTable — one string so the three call sites
14
- // can't drift (framework#2076).
14
+ // can't drift.
15
15
  export const FEATURE_TOGGLE_CROSS_TENANT_REASON =
16
16
  "global feature-toggle state, no tenant scope by design";
17
17
 
@@ -35,13 +35,13 @@ const FEATURE_NAME = "file-derivatives";
35
35
  // charset constraint (`Readonly<Record<string, VariantSpec>>`), so this
36
36
  // stays permissive rather than guessing a convention — narrower than this
37
37
  // would silently 404 a legitimately declared name again. Do not reintroduce
38
- // a name list here "for safety" — see #1985.
38
+ // a name list here "for safety".
39
39
  const VARIANT_NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
40
40
 
41
41
  /** Host → tenantId for the anonymous media route.
42
42
  * MUST be cheap/synchronous (in-memory map or cached lookup): it runs
43
43
  * *before* the query-handler rate limit, so a DB round-trip here is an
44
- * unthrottled DoS surface for anonymous callers rotating Host headers (#1977). */
44
+ * unthrottled DoS surface for anonymous callers rotating Host headers. */
45
45
  export type PublicVariantResolveApexTenant = (
46
46
  host: string,
47
47
  ) => Promise<TenantId | null> | TenantId | null;