@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
@@ -6,12 +6,14 @@
6
6
  import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { isPluginBillingEnabled } from "./checkout-core.ts";
8
8
  import { getSubscriptionForTenant } from "./get-subscription-for-tenant.ts";
9
- import type {
10
- BillingPlanCatalog,
11
- BillingPlansResult,
12
- BillingPlanView,
13
- ProviderPrice,
14
- SubscriptionProviderPlugin,
9
+ import {
10
+ type BillingPlanCatalog,
11
+ type BillingPlansResult,
12
+ type BillingPlanView,
13
+ canSwitchPlans,
14
+ canSwitchPlansInApp,
15
+ type ProviderPrice,
16
+ type SubscriptionProviderPlugin,
15
17
  } from "./types.ts";
16
18
  import {
17
19
  BillingPlanActions,
@@ -51,7 +53,7 @@ function invertPriceToTier(
51
53
  return byTier;
52
54
  }
53
55
 
54
- type ResolvedPlanPrice = { readonly priceId: string; readonly price: ProviderPrice } | null;
56
+ export type ResolvedPlanPrice = { readonly priceId: string; readonly price: ProviderPrice } | null;
55
57
 
56
58
  /** Resolves one active, flat-amount price per plan tier. 0 or >1 active
57
59
  * flat-amount prices for a tier is ambiguous — the caller can't tell which
@@ -120,7 +122,7 @@ function canSwitchToTier(
120
122
  isSwitchableSubscriptionStatus(subscription.status) &&
121
123
  tier !== subscription.tier &&
122
124
  subscription.cancelAt === null &&
123
- plugin?.createPlanSwitchSession !== undefined
125
+ canSwitchPlans(plugin)
124
126
  );
125
127
  }
126
128
 
@@ -157,37 +159,60 @@ function resolvePlanAction(
157
159
  : BillingPlanActions.unavailable;
158
160
  }
159
161
 
160
- /** `plugin === null` — no provider is registered/resolvable for this
161
- * catalog (see checkout-core's `findCatalogProvider`) — collapses onto the
162
- * same "enabled: false" result a disabled provider produces, rather than
163
- * a separate error shape the panel would need to special-case. */
164
- export async function buildBillingPlans(
162
+ /** Tenant-level state every provider's plan list is measured against; loaded
163
+ * once so a multi-provider result does not repeat the reads per provider. */
164
+ export type BillingPlansBase = {
165
+ readonly currentTierValue: string;
166
+ readonly subscriptionView: Awaited<ReturnType<typeof getSubscriptionForTenant>>;
167
+ readonly subscription: BillingPlansResult["subscription"];
168
+ readonly blockingSubscription: boolean;
169
+ readonly canPurchase: boolean;
170
+ };
171
+
172
+ export async function loadBillingPlansBase(
165
173
  ctx: HandlerContext,
166
- plugin: SubscriptionProviderPlugin | null,
167
174
  catalog: BillingPlanCatalog,
168
175
  now: () => Temporal.Instant,
169
- ): Promise<BillingPlansResult> {
176
+ ): Promise<BillingPlansBase> {
170
177
  const currentTierValue = await catalog.resolveCurrentTier(ctx.db, ctx.user.tenantId);
171
- const enabled = plugin !== null && (await isPluginBillingEnabled(ctx, plugin));
172
- const resolvedPrices =
173
- enabled && plugin
174
- ? await resolvePlanPrices(ctx, plugin, catalog)
175
- : new Map<string, ResolvedPlanPrice>(catalog.plans.map((tier) => [tier, null]));
176
-
177
178
  const subscriptionView = await getSubscriptionForTenant(ctx, ctx.user.tenantId);
178
- const nowInstant = now();
179
+ const blockingSubscription =
180
+ subscriptionView !== null && isSubscriptionBlockingCheckout(subscriptionView, now());
179
181
  const subscription = subscriptionView
180
182
  ? {
181
183
  status: subscriptionView.status,
182
184
  tier: subscriptionView.tier,
183
- terminal: !isSubscriptionBlockingCheckout(subscriptionView, nowInstant),
185
+ terminal: !blockingSubscription,
184
186
  currentPeriodEnd: subscriptionView.currentPeriodEnd.toString(),
185
187
  cancelAt: subscriptionView.cancelAt?.toString() ?? null,
186
188
  }
187
189
  : null;
190
+ const canPurchase = userHasAnyRole(ctx.user.roles, purchaseRolesOf(catalog));
191
+ return { currentTierValue, subscriptionView, subscription, blockingSubscription, canPurchase };
192
+ }
193
+
194
+ export type ProviderPlanViews = {
195
+ readonly enabled: boolean;
196
+ readonly inAppSwitch: boolean;
197
+ readonly plans: readonly BillingPlanView[];
198
+ };
188
199
 
189
- const purchaseRoles = purchaseRolesOf(catalog);
190
- const canPurchase = userHasAnyRole(ctx.user.roles, purchaseRoles);
200
+ /** `plugin === null` — no provider is registered/resolvable for this
201
+ * catalog (see checkout-core's `listCatalogProviders`) — collapses onto the
202
+ * same "enabled: false" result a disabled provider produces, rather than
203
+ * a separate error shape the panel would need to special-case. */
204
+ export async function buildProviderPlanViews(
205
+ ctx: HandlerContext,
206
+ plugin: SubscriptionProviderPlugin | null,
207
+ catalog: BillingPlanCatalog,
208
+ base: BillingPlansBase,
209
+ ): Promise<ProviderPlanViews> {
210
+ const { currentTierValue, subscription, canPurchase } = base;
211
+ const enabled = plugin !== null && (await isPluginBillingEnabled(ctx, plugin));
212
+ const resolvedPrices =
213
+ enabled && plugin
214
+ ? await resolvePlanPrices(ctx, plugin, catalog)
215
+ : new Map<string, ResolvedPlanPrice>(catalog.plans.map((tier) => [tier, null]));
191
216
 
192
217
  const plans: BillingPlanView[] = catalog.plans.map((tier) => {
193
218
  const isCurrent = tier === currentTierValue;
@@ -221,8 +246,17 @@ export async function buildBillingPlans(
221
246
  };
222
247
  });
223
248
 
249
+ return { enabled, inAppSwitch: plugin !== null && canSwitchPlansInApp(plugin), plans };
250
+ }
251
+
252
+ export function toBillingPlansResult(
253
+ catalog: BillingPlanCatalog,
254
+ base: BillingPlansBase,
255
+ views: ProviderPlanViews,
256
+ ): BillingPlansResult {
257
+ const { currentTierValue, subscription, canPurchase } = base;
224
258
  return {
225
- enabled,
259
+ enabled: views.enabled,
226
260
  currentTier: {
227
261
  tier: currentTierValue,
228
262
  labelKey: catalog.tierLabelKey(currentTierValue),
@@ -230,7 +264,8 @@ export async function buildBillingPlans(
230
264
  },
231
265
  subscription,
232
266
  canPurchase,
233
- plans,
267
+ plans: views.plans,
268
+ ...(views.inAppSwitch && { inAppPlanSwitch: true as const }),
234
269
  ...(catalog.contact !== undefined && { contact: catalog.contact }),
235
270
  };
236
271
  }
@@ -0,0 +1,84 @@
1
+ // Pre-checks shared by switch-plan and plan-switch-preview: both must agree on
2
+ // which subscription, provider and target price a plan switch means.
3
+ // Internal — not re-exported from index.ts.
4
+
5
+ import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
6
+ import { ConflictError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
7
+ import {
8
+ assertBillingEnabled,
9
+ findProviderPlugin,
10
+ listCatalogProviders,
11
+ type ResolvedProvider,
12
+ } from "./checkout-core.ts";
13
+ import { getSubscriptionForTenant, type SubscriptionView } from "./get-subscription-for-tenant.ts";
14
+ import { type ResolvedPlanPrice, resolvePlanPrices } from "./plan-catalog.ts";
15
+ import { type BillingPlanCatalog, canSwitchPlans } from "./types.ts";
16
+ import { isSwitchableSubscriptionStatus } from "./web/constants.ts";
17
+
18
+ export type PreparedPlanSwitch = {
19
+ readonly provider: ResolvedProvider;
20
+ readonly subscription: SubscriptionView;
21
+ readonly target: NonNullable<ResolvedPlanPrice>;
22
+ readonly allowedPriceIds: readonly string[];
23
+ };
24
+
25
+ export async function preparePlanSwitch(
26
+ ctx: HandlerContext,
27
+ catalog: BillingPlanCatalog,
28
+ tier: string,
29
+ handlerName: string,
30
+ ): Promise<PreparedPlanSwitch> {
31
+ const subscription = await getSubscriptionForTenant(ctx, ctx.user.tenantId);
32
+ if (!subscription || !isSwitchableSubscriptionStatus(subscription.status)) {
33
+ throw new ConflictError({
34
+ i18nKey: "billing-foundation.errors.noActiveSubscription",
35
+ message:
36
+ "tenant has no switchable subscription; use billing-foundation:write:start-plan-checkout to start one",
37
+ });
38
+ }
39
+ // providerSubscriptionId only exists at the subscription's own provider; a catalog that
40
+ // no longer sells through that provider cannot switch it.
41
+ const provider = findProviderPlugin(ctx, subscription.providerName);
42
+ const isCatalogProvider =
43
+ provider !== null &&
44
+ listCatalogProviders(ctx, catalog).some((candidate) => candidate.name === provider.name);
45
+ if (!provider || !isCatalogProvider) {
46
+ throw new ConflictError({
47
+ i18nKey: "billing-foundation.errors.providerMismatch",
48
+ message: `tenant's active subscription is on provider "${subscription.providerName}", which the plan catalog does not sell through — switch-plan cannot switch across providers`,
49
+ });
50
+ }
51
+ await assertBillingEnabled(ctx, provider.plugin, handlerName);
52
+ if (subscription.cancelAt !== null) {
53
+ throw new ConflictError({
54
+ i18nKey: "billing-foundation.errors.cancellationScheduled",
55
+ message:
56
+ "subscription has a scheduled cancellation; reactivate it via billing-foundation:write:create-portal-session before switching plans",
57
+ });
58
+ }
59
+ if (tier === subscription.tier) {
60
+ throw new ConflictError({
61
+ i18nKey: "billing-foundation.errors.alreadyOnPlan",
62
+ message: `tenant is already on plan "${tier}"`,
63
+ });
64
+ }
65
+ if (!canSwitchPlans(provider.plugin)) {
66
+ throw new UnprocessableError("plan_switch_not_supported", {
67
+ i18nKey: "billing-foundation.errors.planSwitchNotSupported",
68
+ message: `subscription-foundation: provider "${subscription.providerName}" supports neither createPlanSwitchSession nor previewPlanSwitch + applyPlanSwitch`,
69
+ });
70
+ }
71
+
72
+ const prices = await resolvePlanPrices(ctx, provider.plugin, catalog);
73
+ const target = prices.get(tier);
74
+ if (!target) {
75
+ throw new UnprocessableError("price_unavailable", {
76
+ i18nKey: "billing-foundation.errors.priceUnavailable",
77
+ message: `subscription-foundation: no live price resolved for tier "${tier}"`,
78
+ });
79
+ }
80
+ const allowedPriceIds = [...prices.values()]
81
+ .filter((p): p is NonNullable<typeof p> => p !== null)
82
+ .map((p) => p.priceId);
83
+ return { provider, subscription, target, allowedPriceIds };
84
+ }
@@ -1,18 +1,18 @@
1
- // Inline-projection für `read_subscriptions`. Materialisiert die 5
2
- // subscription-events in eine row pro Tenant.
1
+ // Inline projection for `read_subscriptions`. Materializes the 5
2
+ // subscription events into one row per tenant.
3
3
  //
4
- // Apply läuft in derselben TX wie ctx.unsafeAppendEvent — Caller sieht
5
- // seinen Schreib-State sofort (kein dispatcher-tick nötig). PK = event.
6
- // aggregateId (= deterministic uuidv5 pro Tenant) → replays kollidieren
7
- // auf der PK statt doppelte rows zu erzeugen.
4
+ // Apply runs in the same transaction as ctx.unsafeAppendEvent, so the caller
5
+ // sees its write state immediately (no dispatcher tick required). The PK is
6
+ // event.aggregateId (= deterministic uuidv5 per tenant), so replays collide
7
+ // on the PK instead of creating duplicate rows.
8
8
  //
9
- // **Production-deployment caveat:** der Generator in
10
- // `samples/apps/platform/drizzle/generate.ts` scant `feature.entities` —
11
- // `subscriptionsProjectionTable` ist als raw drizzle-pgTable in der
12
- // projection registriert, NICHT als r.entity. Apps die subscription-
13
- // foundation production mounten müssen die Tabelle in ihre eigene
14
- // `drizzle/generate.ts` ergänzen (= via subscriptionsProjectionTable-
15
- // import). setupTestStack pusht sie automatisch via r.projection.table.
9
+ // **Production-deployment caveat:** the generator in
10
+ // `samples/apps/platform/drizzle/generate.ts` scans `feature.entities` —
11
+ // `subscriptionsProjectionTable` is registered in the projection as a raw
12
+ // drizzle-pgTable, NOT as r.entity. Apps mounting subscription-foundation in
13
+ // production must add the table to their own `drizzle/generate.ts` (via an
14
+ // import of subscriptionsProjectionTable). setupTestStack pushes it
15
+ // automatically via r.projection.table.
16
16
 
17
17
  import {
18
18
  buildEntityTable,
@@ -26,9 +26,9 @@ import { paymentRowId } from "./aggregate-id.ts";
26
26
  import { paymentEntity, subscriptionEntity } from "./entities.ts";
27
27
  import type { PaymentEventPayload, SubscriptionEventPayload } from "./events.ts";
28
28
 
29
- // Drizzle-table-instance aus dem entity-shape. Wird sowohl von der
30
- // projection-apply als auch von list-query / get-helper genutzt damit
31
- // alle drei Stellen denselben column-namespace teilen.
29
+ // This Drizzle table instance is derived from the entity shape and is shared
30
+ // by the projection apply, list query, and get helper so all three use the
31
+ // same column namespace.
32
32
  export const subscriptionsProjectionTable = buildEntityTable("subscription", subscriptionEntity);
33
33
 
34
34
  // Same production-deployment caveat as subscriptionsProjectionTable above:
@@ -38,11 +38,11 @@ export const paymentsProjectionTable = buildEntityTable("payment", paymentEntity
38
38
 
39
39
  // Unbranded metas: the apply functions below ARE the executor of these
40
40
  // projections, so they may write through the typed helpers.
41
- const subscriptionsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
41
+ export const subscriptionsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
42
42
  subscriptionsProjectionTable,
43
43
  "subscription",
44
44
  );
45
- const paymentsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
45
+ export const paymentsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
46
46
  paymentsProjectionTable,
47
47
  "payment",
48
48
  );
@@ -99,10 +99,10 @@ async function upsert(
99
99
  }>,
100
100
  fullPayload: SubscriptionEventPayload,
101
101
  ): Promise<void> {
102
- // INSERT-fallback braucht ALL fields (NOT NULL constraints). Wenn
103
- // jemand nur teil-felder updated (z.B. invoice-payment-failed nur
104
- // status+tier), nutzen wir trotzdem den vollen payload für den
105
- // INSERT-Pfad und nur den teil-`set` für ON CONFLICT.
102
+ // The INSERT fallback requires ALL fields because of NOT NULL constraints.
103
+ // If an update changes only some fields (for example, invoice-payment-failed
104
+ // changes only status+tier), the full payload is still used for the INSERT
105
+ // path, while only the partial `set` is used for ON CONFLICT.
106
106
  const insertCols = {
107
107
  id: event.aggregateId,
108
108
  tenantId: event.tenantId,
@@ -123,23 +123,23 @@ async function upsert(
123
123
  }
124
124
 
125
125
  // =============================================================================
126
- // Apply-functions — eine pro event-typ
126
+ // Apply functions — one per event type
127
127
  //
128
- // Alle UPSERT für defensive consistency: ein out-of-order event
129
- // (z.B. rebuild-from-events) kann in jeder Reihenfolge ankommen
130
- // und die row korrekt materialisieren.
128
+ // All use UPSERT for defensive consistency: an out-of-order event (for
129
+ // example, during a rebuild-from-events) can arrive in any order and still
130
+ // materialize the row correctly.
131
131
  // =============================================================================
132
132
 
133
- /** subscription-created → UPSERT mit allen Feldern. PK = aggregateId =
134
- * subscriptionAggregateId(tenantId), one row pro Tenant. UPSERT damit
135
- * Disney+-Wechsel-Pattern (= zweiter Provider sendet create für selben
136
- * Tenant) den existing row überschreibt statt PK-conflict. */
133
+ /** subscription-created → UPSERT with all fields. PK = aggregateId =
134
+ * subscriptionAggregateId(tenantId), with one row per tenant. UPSERT allows
135
+ * the Disney+-change pattern (a second provider sends create for the same
136
+ * tenant) to overwrite the existing row instead of causing a PK conflict. */
137
137
  export const applySubscriptionCreated = defineApply<SubscriptionEventPayload>(async (event, tx) => {
138
138
  const full = fullSetFromPayload(event.payload);
139
139
  await upsert(tx, event, { ...full, ...cancelAtSetFromPayload(event.payload) }, event.payload);
140
140
  });
141
141
 
142
- /** subscription-updated → UPSERT mit allen Feldern. */
142
+ /** subscription-updated → UPSERT with all fields. */
143
143
  export const applySubscriptionUpdated = defineApply<SubscriptionEventPayload>(async (event, tx) => {
144
144
  const full = fullSetFromPayload(event.payload);
145
145
  await upsert(tx, event, { ...full, ...cancelAtSetFromPayload(event.payload) }, event.payload);
@@ -163,8 +163,9 @@ export const applySubscriptionCanceled = defineApply<SubscriptionEventPayload>(
163
163
  },
164
164
  );
165
165
 
166
- /** invoice-paid → state-update (status, tier, currentPeriodEnd).
167
- * Invoice-history selbst lebt im event-store (= Replay-fähig). */
166
+ /** invoice-paid → state update (status, tier, currentPeriodEnd).
167
+ * The invoice history itself lives in the event store, so it remains
168
+ * replayable. */
168
169
  export const applyInvoicePaid = defineApply<SubscriptionEventPayload>(async (event, tx) => {
169
170
  const p = event.payload;
170
171
  await upsert(
@@ -180,10 +181,10 @@ export const applyInvoicePaid = defineApply<SubscriptionEventPayload>(async (eve
180
181
  );
181
182
  });
182
183
 
183
- /** invoice-payment-failed → status (typisch past_due) + tier. tier-
184
- * engine liest die row + entscheidet ob downgrade. currentPeriodEnd
185
- * bewusst nicht — die Period ist noch nicht "vorbei", payment hat
186
- * nur nicht geklappt. */
184
+ /** invoice-payment-failed → status (typically past_due) + tier. The tier
185
+ * engine reads the row and decides whether to downgrade. currentPeriodEnd is
186
+ * intentionally unchanged: the period has not "ended"; payment simply
187
+ * failed. */
187
188
  export const applyInvoicePaymentFailed = defineApply<SubscriptionEventPayload>(
188
189
  async (event, tx) => {
189
190
  const p = event.payload;
@@ -1,7 +1,7 @@
1
1
  // Generic Stripe/PayPal-webhook → tier-engine sync route. Extracted from the
2
- // near-identical webhook-route.ts app copies in show-pony and publicstatus
3
- // (infra#446) — the only per-app variables were the TierName union/default,
4
- // so it is now a factory parameter.
2
+ // near-identical webhook-route.ts app copies in show-pony and publicstatus — the
3
+ // only per-app variables were the TierName union/default, so it is now a factory
4
+ // parameter.
5
5
 
6
6
  import {
7
7
  isTierAssignmentSource,
@@ -1,10 +1,9 @@
1
- import type { EntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
2
1
  import { declareEscapeHatch, type TenantDataHookCtx } from "@cosmicdrift/kumiko-framework/engine";
3
2
  import { archiveStream } from "@cosmicdrift/kumiko-framework/event-store";
4
3
  import { resolveProfileForTenant } from "../compliance-profiles/index.ts";
5
4
  import { paymentAggregateId, subscriptionAggregateId } from "./aggregate-id.ts";
6
5
  import { PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE } from "./events.ts";
7
- import { paymentsProjectionTable, subscriptionsProjectionTable } from "./projection.ts";
6
+ import { paymentsProjectionMeta, subscriptionsProjectionMeta } from "./projection.ts";
8
7
 
9
8
  // providerCustomerId/providerSubscriptionId are `personal: "tenant"` on the
10
9
  // entity (envelope-encrypted with the tenant subject key, see entities.ts) —
@@ -19,7 +18,7 @@ export const SUBSCRIPTION_TENANT_DESTROY_ARCHIVE_REASON =
19
18
  export const PAYMENT_TENANT_DESTROY_ARCHIVE_REASON =
20
19
  "tenant-destroy looks up the compliance profile and archives the payment event-stream before the projection rows are redacted/deleted";
21
20
 
22
- /** Tenant-destroy hook for billing PII (#800). HGB retains the accounting
21
+ /** Tenant-destroy hook for billing PII. HGB retains the accounting
23
22
  * row but redacts the two provider-subject PII fields; other profiles
24
23
  * hard-delete the row. Either way the subscription stream is archived so a
25
24
  * future projection rebuild can't resurrect what was erased. */
@@ -32,12 +31,12 @@ export async function subscriptionTenantDestroyHook(ctx: TenantDataHookCtx): Pro
32
31
  const aggregateId = subscriptionAggregateId(ctx.tenantId);
33
32
  if (profile.key === "de-hr-dsgvo-hgb") {
34
33
  await ctx.db.updateMany(
35
- subscriptionsProjectionTable as EntityTableMeta,
34
+ subscriptionsProjectionMeta,
36
35
  { providerCustomerId: REDACTED_PII_VALUE, providerSubscriptionId: REDACTED_PII_VALUE },
37
36
  { id: aggregateId },
38
37
  );
39
38
  } else {
40
- await ctx.db.deleteMany(subscriptionsProjectionTable as EntityTableMeta, { id: aggregateId });
39
+ await ctx.db.deleteMany(subscriptionsProjectionMeta, { id: aggregateId });
41
40
  }
42
41
  await archiveStream(ctx.db.unsafeRaw(), {
43
42
  tenantId: ctx.tenantId,
@@ -48,7 +47,7 @@ export async function subscriptionTenantDestroyHook(ctx: TenantDataHookCtx): Pro
48
47
  });
49
48
  }
50
49
 
51
- /** Tenant-destroy hook for payment PII (#800). Unlike subscriptionTenantDestroyHook
50
+ /** Tenant-destroy hook for payment PII. Unlike subscriptionTenantDestroyHook
52
51
  * (one row per tenant, targeted by `id`), a tenant can have many payment
53
52
  * rows — the predicate here is `tenantId`, not `id`. The payment-stream
54
53
  * itself is still one stream per tenant (paymentAggregateId), so
@@ -62,12 +61,12 @@ export async function paymentTenantDestroyHook(ctx: TenantDataHookCtx): Promise<
62
61
  const aggregateId = paymentAggregateId(ctx.tenantId);
63
62
  if (profile.key === "de-hr-dsgvo-hgb") {
64
63
  await ctx.db.updateMany(
65
- paymentsProjectionTable as EntityTableMeta,
64
+ paymentsProjectionMeta,
66
65
  { providerCustomerId: REDACTED_PII_VALUE },
67
66
  { tenantId: ctx.tenantId },
68
67
  );
69
68
  } else {
70
- await ctx.db.deleteMany(paymentsProjectionTable as EntityTableMeta, {
69
+ await ctx.db.deleteMany(paymentsProjectionMeta, {
71
70
  tenantId: ctx.tenantId,
72
71
  });
73
72
  }