@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
@@ -30,33 +30,32 @@ export type HostRoutingDispatchFn = (
30
30
 
31
31
  const tenantKeyExistsResultSchema = z.object({ exists: z.boolean() });
32
32
 
33
- async function isTenantKeyKnown(systemQuery: PageHeadSystemQuery, key: string): Promise<boolean> {
33
+ async function existsViaSystemQuery(
34
+ systemQuery: PageHeadSystemQuery,
35
+ queryType: string,
36
+ payload: Record<string, string>,
37
+ ): Promise<boolean> {
34
38
  let result: unknown;
35
39
  try {
36
- result = await systemQuery(HostRoutingQueries.tenantKeyExists, { key }, SYSTEM_TENANT_ID);
40
+ result = await systemQuery(queryType, payload, SYSTEM_TENANT_ID);
37
41
  } catch (error) {
38
42
  if (error instanceof ValidationError) return false;
39
- // Over the rate limit every key looks the same: serve the tenant shell,
40
- // which leaks nothing; the API behind it still resolves the tenant itself.
43
+ // Over the rate limit every key looks the same: serve the shell, which
44
+ // leaks nothing. The API resolver is authoritative and answers
45
+ // tenant_required for unknown hosts, while a 404 would hit visitors
46
+ // behind a shared NAT under load.
41
47
  if (error instanceof RateLimitError) return true;
42
48
  throw error;
43
49
  }
44
50
  return tenantKeyExistsResultSchema.parse(result).exists;
45
51
  }
46
52
 
47
- async function isHostKnown(systemQuery: PageHeadSystemQuery, host: string): Promise<boolean> {
48
- let result: unknown;
49
- try {
50
- result = await systemQuery(HostRoutingQueries.hostTenantExists, { host }, SYSTEM_TENANT_ID);
51
- } catch (error) {
52
- if (error instanceof ValidationError) return false;
53
- // The shell is harmless: the API resolver is authoritative and answers
54
- // tenant_required for unknown hosts, while a 404 would hit visitors behind
55
- // a shared NAT under load.
56
- if (error instanceof RateLimitError) return true;
57
- throw error;
58
- }
59
- return tenantKeyExistsResultSchema.parse(result).exists;
53
+ function isTenantKeyKnown(systemQuery: PageHeadSystemQuery, key: string): Promise<boolean> {
54
+ return existsViaSystemQuery(systemQuery, HostRoutingQueries.tenantKeyExists, { key });
55
+ }
56
+
57
+ function isHostKnown(systemQuery: PageHeadSystemQuery, host: string): Promise<boolean> {
58
+ return existsViaSystemQuery(systemQuery, HostRoutingQueries.hostTenantExists, { host });
60
59
  }
61
60
 
62
61
  function serve(
@@ -81,6 +81,7 @@ export type HostRoutingOptions = HostRoutingTenantMode & {
81
81
  // Not allowed with tenantBy "path" (boot error): there the client's X-Tenant
82
82
  // wins over the resolver, so the allowlist would be ineffective.
83
83
  readonly apexAnonymousQueryAllowlist?: Readonly<Record<string, readonly string[]>>;
84
- // Checked first, before any host classification.
84
+ // Checked first within hostDispatch, i.e. only for requests that reach the HTML
85
+ // fallback (no static file, no API route): a `from` matching either never fires.
85
86
  readonly redirects?: readonly HostRoutingRedirect[];
86
87
  };
@@ -1,26 +1,26 @@
1
1
  import { v5 as uuidv5 } from "uuid";
2
2
 
3
- // Fixed UUID-namespaces für deterministic aggregate-id-Ableitung.
4
- // Generiert einmalig (2026-07-12), in Stein gemeißelt: ein Wechsel würde
5
- // jeden existing aggregate-Stream re-keyen → kaputte Message-Historie,
6
- // kaputte Idempotency. Drift-Pins in __tests__/feature.test.ts.
3
+ // Fixed UUID namespaces for deterministic aggregate-ID derivation.
4
+ // Generated once (2026-07-12) and immutable: changing one would re-key
5
+ // every existing aggregate stream, breaking message history and idempotency.
6
+ // Drift is pinned in __tests__/feature.test.ts.
7
7
 
8
- /** Namespace für inbound-message-Streams. */
8
+ /** Namespace for inbound-message streams. */
9
9
  const INBOUND_MESSAGE_NAMESPACE = "7f2a9c41-3d6b-4e0f-9c58-2b1e7a4d8f63";
10
10
 
11
- /** Namespace für mail-thread-Streams. */
11
+ /** Namespace for mail-thread streams. */
12
12
  const MAIL_THREAD_NAMESPACE = "b48d1e72-5c9a-4f36-8e0d-6a3f9b2c7e15";
13
13
 
14
14
  /**
15
- * Deterministic aggregate-id für eine inbound-message. Key ist
16
- * (accountId, providerMessageId): derselbe Provider-Fetch der zweimal
17
- * dieselbe Message liefert (IDLE-Doppel-Notify, Cursor-Overlap,
18
- * Watch-Restart-Replay) landet auf demselben Stream — der Idempotency-
19
- * Check im ingest-handler sieht den bereits appendeten Event.
15
+ * Deterministic aggregate ID for an inbound message. The key is
16
+ * (accountId, providerMessageId): if the provider delivers the same message
17
+ * twice (IDLE duplicate notification, cursor overlap, watch-restart replay),
18
+ * both deliveries use the same stream, so the idempotency check in the
19
+ * ingest handler sees the event that was already appended.
20
20
  *
21
- * accountId (nicht tenantId) im Key: zwei Accounts desselben Tenants
22
- * können dieselbe Mail empfangen (CC an beide Postfächer) — das sind
23
- * fachlich ZWEI inbound-messages.
21
+ * accountId, rather than tenantId, is part of the key because two accounts in
22
+ * the same tenant can receive the same email (CC'd to both inboxes); these
23
+ * are two distinct inbound messages.
24
24
  */
25
25
  // @wrapper-known uuid-domain
26
26
  export function inboundMessageAggregateId(accountId: string, providerMessageId: string): string {
@@ -28,11 +28,11 @@ export function inboundMessageAggregateId(accountId: string, providerMessageId:
28
28
  }
29
29
 
30
30
  /**
31
- * Deterministic aggregate-id für einen mail-thread. Key ist
32
- * (tenantId, threadKey) — Threads sind tenant-weit, nicht account-weit:
33
- * eine Konversation die über zwei verbundene Postfächer läuft ist EIN
34
- * Thread. threadKey kommt normalisiert vom Provider (References/
35
- * In-Reply-To-Chain bzw. Provider-Thread-ID).
31
+ * Deterministic aggregate ID for a mail thread. The key is
32
+ * (tenantId, threadKey): threads are tenant-wide, not account-specific, so a
33
+ * conversation spanning two connected inboxes is one thread. threadKey is
34
+ * normalized by the provider (References/In-Reply-To chain or provider
35
+ * thread ID).
36
36
  */
37
37
  // @wrapper-known uuid-domain
38
38
  export function mailThreadAggregateId(tenantId: string, threadKey: string): string {
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "version": "0.388.0",
4
+ "type": "fix",
5
+ "title": "Undecryptable mail account no longer stops polling of other accounts",
6
+ "detail": "Any decryption failure of an account address (corrupt envelope, missing key, AAD mismatch) is logged by error class and the account is skipped; the other accounts keep polling."
7
+ },
8
+ {
9
+ "version": "0.388.0",
10
+ "type": "fix",
11
+ "title": "Rename audit reason comes from the caller role",
12
+ "detail": "update-account records tenant_admin or system_admin from the caller's roles and honors a client-supplied reason only for the system identity, so a form call can no longer write system reasons such as watch_supervisor. The rename form no longer carries a reason field and the reason payload field is optional."
13
+ },
14
+ {
15
+ "version": "0.388.0",
16
+ "type": "fix",
17
+ "title": "Seen-message lookup handles listings of any size",
18
+ "detail": "filterUnknownMessageIds queries the already seen provider message ids in chunks of 1000, so a full-mailbox listing no longer exceeds the Postgres bind parameter limit and aborts the account's poll."
19
+ },
2
20
  {
3
21
  "version": "0.378.0",
4
22
  "type": "fix",
@@ -1,5 +1,5 @@
1
- // createInboundMailConnectRoutes — declarative extraRoutes (kumiko-
2
- // framework#3050) the app owner mounts via `extraRoutes` in buildServer.
1
+ // createInboundMailConnectRoutes — declarative extraRoutes the app owner mounts
2
+ // via `extraRoutes` in buildServer.
3
3
  //
4
4
  // GET /api/inbound-mail/connect (entry:"user" — signed-in caller)
5
5
  // GET /inbound-mail/oauth/callback (entry:"signature" — anonymous,
@@ -17,6 +17,7 @@ import type {
17
17
  UserExtraRouteDeps,
18
18
  } from "@cosmicdrift/kumiko-framework/api";
19
19
  import { ExtraRouteRejection, signatureRoute } from "@cosmicdrift/kumiko-framework/api";
20
+ import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
20
21
  import type { Context } from "hono";
21
22
  import {
22
23
  INBOUND_MAIL_FOUNDATION_FEATURE,
@@ -241,7 +242,7 @@ export function createInboundMailConnectRoutes(
241
242
  if (!dispatched.isSuccess) {
242
243
  return errorJson(c, 502, "account_create_failed", JSON.stringify(dispatched.error ?? {}));
243
244
  }
244
- const accountId = (dispatched.data as { accountId?: unknown } | undefined)?.accountId;
245
+ const accountId = propertyOf(dispatched.data, "accountId");
245
246
  if (typeof accountId !== "string") {
246
247
  return errorJson(c, 502, "account_create_failed", "connect-account returned no accountId");
247
248
  }
@@ -1,71 +1,69 @@
1
1
  // Feature name
2
2
  export const INBOUND_MAIL_FOUNDATION_FEATURE = "inbound-mail-foundation" as const;
3
3
 
4
- // Extension-point name für Provider-Plugins (inbound-provider-imap,
4
+ // Extension-point name for provider plugins (inbound-provider-imap,
5
5
  // inbound-provider-m365-graph, inbound-provider-gmail-rest, ...).
6
6
  export const INBOUND_MAIL_PROVIDER_EXTENSION = "inboundMailProvider" as const;
7
7
 
8
8
  // Qualified write handler names (QN format: scope:type:name).
9
9
  export const InboundMailFoundationHandlers = {
10
- /** Programmatic entry-point für Provider-Plugins (watch-callback +
11
- * fetchSince-Sync): normalisierte Message rein, Idempotency +
12
- * PII-encrypt + event-append + Thread-Update atomic. */
10
+ /** Programmatic entry point for provider plugins (watch callback +
11
+ * fetchSince sync): accepts a normalized message and atomically performs
12
+ * idempotency handling, PII encryption, event append, and thread update. */
13
13
  ingestMessage: "inbound-mail-foundation:write:ingest-message",
14
- /** Tenant-Admin verbindet ein Postfach (IMAP-Credentials via secrets
15
- * oder OAuth-Redirect via oauth-routes). Legt den mail-account-Stream
16
- * an. */
14
+ /** Tenant admin connects a mailbox (IMAP credentials via secrets or an
15
+ * OAuth redirect via oauth-routes). Creates the mail-account stream. */
17
16
  connectAccount: "inbound-mail-foundation:write:connect-account",
18
- /** Account-Status-Übergänge (watch error/backoff, oauth-refresh
19
- * failed, re-enabled). */
17
+ /** Account status transitions (watch error/backoff, OAuth refresh
18
+ * failure, re-enabled). */
20
19
  updateAccount: "inbound-mail-foundation:write:update-account",
21
- /** Tenant-Admin trennt ein Postfach. Stream bleibt (Audit), Status
22
- * wird disconnected, Watch stoppt. */
20
+ /** Tenant admin disconnects a mailbox. The stream remains for auditing;
21
+ * the status becomes disconnected and the watch stops. */
23
22
  disconnectAccount: "inbound-mail-foundation:write:disconnect-account",
24
23
  } as const;
25
24
 
26
25
  // Qualified query handler names.
27
26
  export const InboundMailFoundationQueries = {
28
- /** Tenant-scoped Liste der verbundenen Postfächer. */
27
+ /** Tenant-scoped list of connected mailboxes. */
29
28
  listAccounts: "inbound-mail-foundation:query:account:list",
30
- /** Tenant-scoped Message-Liste (Inbox-Cockpit). PII wird beim Read
31
- * decrypted. */
29
+ /** Tenant-scoped message list (inbox cockpit). PII is decrypted on read.
30
+ */
32
31
  listMessages: "inbound-mail-foundation:query:message:list",
33
32
  } as const;
34
33
 
35
34
  // Normalized account status values — provider-agnostic.
36
35
  export const InboundMailAccountStatuses = {
37
- /** Verbunden, Watch/Sync läuft (oder ist startbereit). */
36
+ /** Connected; watch/sync is running or ready to start. */
38
37
  active: "active",
39
- /** Credentials/Token ungültig — Tenant-Admin muss re-connecten. */
38
+ /** Credentials or token are invalid; the tenant admin must reconnect. */
40
39
  authError: "auth_error",
41
40
  /** Transienter Fehler, Supervisor backoff-retried. */
42
41
  degraded: "degraded",
43
- /** Vom Tenant-Admin getrennt. Keine Syncs mehr. */
42
+ /** Disconnected by the tenant admin; no further syncs run. */
44
43
  disconnected: "disconnected",
45
44
  } as const;
46
45
  export type InboundMailAccountStatus =
47
46
  (typeof InboundMailAccountStatuses)[keyof typeof InboundMailAccountStatuses];
48
47
 
49
48
  /**
50
- * Tenant-Secret-Slot eines Accounts: IMAP-App-Passwort ODER OAuth-
51
- * Refresh-Token — der Provider interpretiert den Inhalt gemäß
52
- * `authMethod` (Plan §4). Dynamisches Keying pro Account ist vom
53
- * secrets-Feature gedeckt: SecretsContext.get/set nehmen beliebige
54
- * String-Keys (resolveKey in secrets-context.ts) — Plan-Risiko 4
55
- * verifiziert, kein Framework-Gap.
49
+ * Tenant secret slot for an account: IMAP app password OR OAuth refresh
50
+ * token. The provider interprets the contents according to `authMethod`.
51
+ * Dynamic per-account keying is supported by the secrets feature:
52
+ * SecretsContext.get/set accept arbitrary string keys (resolveKey in
53
+ * secrets-context.ts), so no framework change is required.
56
54
  */
57
55
  export function inboundCredentialSecretKey(accountId: string): string {
58
56
  return `${INBOUND_MAIL_FOUNDATION_FEATURE}:inbound.credential.${accountId}`;
59
57
  }
60
58
 
61
- // Auth-Methode eines Accounts — vom connect-Flow gesetzt, von Providern
62
- // gelesen (imap unterscheidet hierüber Passwort-Formular vs. XOAUTH2-
63
- // Fallback, Plan §2).
59
+ // Authentication method for an account, set by the connect flow and read
60
+ // by providers (IMAP uses it to distinguish the password form from the
61
+ // XOAUTH2 fallback).
64
62
  export const InboundMailAuthMethods = {
65
63
  /** Formular-Connect: Config (host/port/secure) + Tenant-Secret. */
66
64
  password: "password",
67
- /** SASL XOAUTH2 über IMAP — Fallback für M365/Gmail-Konten ohne
68
- * gemounteten Enterprise-Provider (gleicher Secret-Slot). */
65
+ /** SASL XOAUTH2 over IMAP — fallback for M365/Gmail accounts without a
66
+ * mounted enterprise provider (same secret slot). */
69
67
  xoauth2: "xoauth2",
70
68
  /** Nativer OAuth-Provider (m365-graph, gmail-rest). */
71
69
  oauth: "oauth",
@@ -73,8 +71,7 @@ export const InboundMailAuthMethods = {
73
71
  export type InboundMailAuthMethod =
74
72
  (typeof InboundMailAuthMethods)[keyof typeof InboundMailAuthMethods];
75
73
 
76
- // **Multi-Provider von Tag 1:** KEIN globaler `provider`-config-key
77
- // (anders als mail-foundation, gleich wie billing-foundation). Ein Tenant
78
- // kann parallel ein IMAP-Postfach UND ein M365-Postfach verbinden — der
79
- // Provider steht pro MailAccount-Row (`provider`-Feld), gesetzt beim
80
- // connect-Flow.
74
+ // **Multi-provider:** no global `provider` config key
75
+ // (unlike mail-foundation, as with billing-foundation). A tenant can connect
76
+ // an IMAP mailbox and an M365 mailbox in parallel; the provider is stored per
77
+ // MailAccount row (`provider` field) and set by the connect flow.
@@ -9,28 +9,27 @@ import {
9
9
  } from "@cosmicdrift/kumiko-framework/engine";
10
10
 
11
11
  // ============================================================================
12
- // Read-Models der drei event-sourced Aggregates
12
+ // Read models for the three event-sourced aggregates
13
13
  // ============================================================================
14
14
  //
15
- // Inline-Projection-Targets. Geschrieben AUSSCHLIESSLICH von den
16
- // projection-applies (siehe feature.ts), nie direkt vom handler.
17
- // Source-of-truth sind die event-store-Streams `mail-account` /
18
- // `inbound-message` / `mail-thread` — die Tabellen sind rebuild-fähig.
15
+ // Inline projection targets. Written EXCLUSIVELY by projection applies
16
+ // (see feature.ts), never directly by the handler.
17
+ // The event-store streams `mail-account` / `inbound-message` / `mail-thread`
18
+ // are the source of truth, so these tables can be rebuilt.
19
19
  //
20
20
  // **PII convention:** `personal: "tenant"` (not `encrypted`): fields must
21
- // crypto-shred when eraseSubjectKeys deletes the tenant subject key on
22
- // tenant-destroy (#800 pattern from billing-foundation).
23
- // maxLength jeweils Ciphertext-budgetiert (`kumiko-pii:v1:<subject>:
24
- // <blob>` — Plaintext×~2.3 + Envelope-Overhead).
21
+ // be crypto-shredded when eraseSubjectKeys deletes the tenant subject key on
22
+ // tenant destruction (pattern from billing-foundation).
23
+ // maxLength is budgeted for ciphertext (`kumiko-pii:v1:<subject>:
24
+ // <blob>` — Plaintext×~2.3 + envelope overhead).
25
25
  //
26
- // **Offene Design-Frage aus dem Plan (§3.4):** PII-Subject einer
27
- // Inbound-Mail ist vorerst der TENANT (Postfach-Inhaber), nicht der
28
- // externe Absender — ein Absender-Forget-Flow bräuchte per-Sender-Keys
29
- // und ist bewusst NICHT Teil von Phase 1 (dokumentierte Entscheidung,
30
- // Erasure-Pfad ist tenant-destroy).
26
+ // **Design decision:** The PII subject of an inbound mail is currently the
27
+ // TENANT (mailbox owner), not the external sender. A sender-forget flow would
28
+ // require per-sender keys and is deliberately not included; the erasure path
29
+ // is tenant destruction.
31
30
 
32
- /** Ein verbundenes Postfach. Eine Row pro Account, PK = aggregateId
33
- * (= accountId, random uuid beim connect). */
31
+ /** A connected mailbox. One row per account, with PK = aggregateId
32
+ * (= accountId, random uuid on connect). */
34
33
  export const mailAccountEntity = createEntity({
35
34
  table: "read_mail_accounts",
36
35
  fields: {
@@ -46,10 +45,10 @@ export const mailAccountEntity = createEntity({
46
45
  personal: false,
47
46
  reason: "technical_reference",
48
47
  }),
49
- // null = tenant-geteiltes Postfach (info@), gesetzt = persönliches
50
- // Postfach dieses Users. Sichtbarkeits-Filter in den list-queries:
51
- // Owner + TenantAdmin (Compliance); KEIN Crypto-Subject-Wechsel in
52
- // V1 (Subject bleibt Tenant, siehe Header).
48
+ // null = tenant-shared mailbox (info@), set = this user's personal
49
+ // mailbox. Visibility filters in the list queries:
50
+ // Owner + TenantAdmin (compliance); NO crypto-subject change in
51
+ // V1 (subject remains Tenant, see header).
53
52
  ownerUserId: createTextField({ maxLength: 36, personal: false, reason: "pseudonymous_fk" }),
54
53
  // Tenant-authored mailbox label, not a person's name.
55
54
  displayName: createTextField({
@@ -57,7 +56,7 @@ export const mailAccountEntity = createEntity({
57
56
  personal: false,
58
57
  reason: "tenant_config_not_personal",
59
58
  }),
60
- // Postfach-Adresse — PII des Tenants.
59
+ // Mailbox address — tenant PII.
61
60
  address: createTextField({ required: true, maxLength: 1000, personal: "tenant", find: "none" }),
62
61
  status: createTextField({
63
62
  required: true,
@@ -70,8 +69,8 @@ export const mailAccountEntity = createEntity({
70
69
  },
71
70
  });
72
71
 
73
- /** Eine eingegangene Mail (Envelope + Snippet, KEIN Body — bodyRef
74
- * zeigt auf file-foundation). PK = aggregateId =
72
+ /** An incoming mail (envelope + snippet, NO body — bodyRef
73
+ * points to file-foundation). PK = aggregateId =
75
74
  * inboundMessageAggregateId(accountId, providerMessageId). */
76
75
  export const inboundMessageEntity = createEntity({
77
76
  table: "read_inbound_messages",
@@ -82,9 +81,9 @@ export const inboundMessageEntity = createEntity({
82
81
  personal: false,
83
82
  reason: "technical_reference",
84
83
  }),
85
- // Scope-Vererbung vom Account zum Ingest-Zeitpunkt — Messages eines
86
- // persönlichen Postfachs sind nur für den Owner (+ TenantAdmin)
87
- // sichtbar, ohne Join auf read_mail_accounts.
84
+ // Scope is inherited from the account at ingest time: messages from a
85
+ // personal mailbox are visible only to the owner (+ TenantAdmin),
86
+ // without joining read_mail_accounts.
88
87
  ownerUserId: createTextField({ maxLength: 36, personal: false, reason: "pseudonymous_fk" }),
89
88
  messageIdHeader: createTextField({
90
89
  required: true,
@@ -127,29 +126,29 @@ export const mailThreadEntity = createEntity({
127
126
  },
128
127
  });
129
128
 
130
- // Single source of truth für die PII-Feld-Listen — encrypt (ingest/
131
- // connect-handler) und decrypt (list-queries) teilen dieselbe Liste,
132
- // damit ein künftiges weiteres tenantOwned-Feld nicht an einer der
133
- // Stellen vergessen wird (Muster billing-foundation entities.ts).
129
+ // Single source of truth for the PII field lists — encrypt (ingest/
130
+ // connect-handler) and decrypt (list-queries) share the same list,
131
+ // so a future tenantOwned field cannot be omitted in either location
132
+ // (pattern from billing-foundation entities.ts).
134
133
  export const MAIL_ACCOUNT_PII_FIELDS = collectPiiSubjectFields(mailAccountEntity);
135
134
  export const INBOUND_MESSAGE_PII_FIELDS = collectPiiSubjectFields(inboundMessageEntity);
136
135
  export const MAIL_THREAD_PII_FIELDS = collectPiiSubjectFields(mailThreadEntity);
137
136
 
138
137
  // ============================================================================
139
- // Unmanaged Direct-Write-Stores — Sync-Maschinerie, NICHT event-sourced
138
+ // Unmanaged direct-write stores — sync machinery, NOT event-sourced
140
139
  // ============================================================================
141
140
  //
142
- // SyncCursor + SeenMessage sind technischer Tick-State des Watch/Sync-
143
- // Loops: hochfrequente Writes ohne Business-Fakt-Charakter. Als r.entity
144
- // würden sie (a) das Event-Log fluten und (b) beim Projection-Rebuild
145
- // gewischt (Direct-Write ohne Event → Rebuild findet nichts, #494/#498-
146
- // Klasse). Deshalb r.unmanagedTable — Migration-DDL ja, Rebuild-Target
147
- // nein (Muster sessions/feature.ts).
141
+ // SyncCursor + SeenMessage are technical tick state for the watch/sync
142
+ // loops: high-frequency writes without business-fact semantics. As
143
+ // r.entity, they would (a) flood the event log and (b) be wiped during a
144
+ // projection rebuild (direct write without an event means the rebuild finds
145
+ // nothing). Therefore r.unmanagedTable — migration DDL, but not a rebuild
146
+ // target (pattern from sessions/feature.ts).
148
147
 
149
- /** Provider-Cursor pro Account ("wo war ich?"): IMAP UIDVALIDITY:UIDNEXT,
150
- * Graph deltaLink, Gmail historyId. Eine Row pro (accountId, scope).
151
- * Write-locked auf privileged — nur Foundation-Handler/Supervisor
152
- * schreiben, kein Tenant-Request. */
148
+ /** Provider cursor per account ("where was I?"): IMAP UIDVALIDITY:UIDNEXT,
149
+ * Graph deltaLink, Gmail historyId. One row per (accountId, scope).
150
+ * Write-locked to privileged — only Foundation handlers/supervisors
151
+ * write it; tenant requests cannot. */
153
152
  export const syncCursorEntity = createEntity({
154
153
  table: "store_mail_sync_cursors",
155
154
  softDelete: false,
@@ -182,10 +181,10 @@ export const syncCursorEntity = createEntity({
182
181
  },
183
182
  });
184
183
 
185
- /** Dedup-Anchor für O(1)-Idempotency ohne Stream-Scan bei sehr langen
186
- * Message-Historien: (accountId, providerMessageId) UNIQUE. Der
187
- * ingest-handler prüft zuerst hier (cheap), der Stream-Scan bleibt
188
- * Defense-in-depth. */
184
+ /** Deduplication anchor for O(1) idempotency without scanning the stream
185
+ * for very long message histories: (accountId, providerMessageId) UNIQUE.
186
+ * The ingest handler checks here first (cheap); the stream scan remains
187
+ * defense-in-depth. */
189
188
  export const seenMessageEntity = createEntity({
190
189
  table: "store_mail_seen_messages",
191
190
  softDelete: false,
@@ -211,9 +210,9 @@ export const seenMessageEntity = createEntity({
211
210
  },
212
211
  });
213
212
 
214
- // Plain EntityTableMeta (kein branded EntityTable) — unmanaged Direct-
215
- // Write-Stores, Handler schreiben via ctx.db (siehe user-session.ts-
216
- // Rationale).
213
+ // Plain EntityTableMeta (not a branded EntityTable) — unmanaged direct-
214
+ // write stores; handlers write via ctx.db (see user-session.ts-
215
+ // rationale).
217
216
  export const syncCursorTable = deriveEntityTableMeta("mail-sync-cursor", syncCursorEntity, {
218
217
  source: "unmanaged",
219
218
  });