@cosmicdrift/kumiko-bundled-features 0.377.0 → 0.379.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 (669) hide show
  1. package/dist/account-security/feature.js +2 -2
  2. package/dist/account-security/index.d.ts +2 -2
  3. package/dist/account-security/index.js +2 -2
  4. package/dist/account-security/{constants.js → web/constants.js} +0 -1
  5. package/dist/account-security/{i18n.js → web/i18n.js} +0 -1
  6. package/dist/admin-shell/feature.js +4 -3
  7. package/dist/admin-shell/index.d.ts +2 -2
  8. package/dist/admin-shell/index.js +2 -2
  9. package/dist/admin-shell/web/client-plugin.js +2 -3
  10. package/dist/admin-shell/{constants.js → web/constants.js} +0 -1
  11. package/dist/admin-shell/web/default-translations.d.ts +2 -0
  12. package/dist/admin-shell/web/default-translations.js +4 -0
  13. package/dist/admin-shell/web/i18n.d.ts +5 -2
  14. package/dist/admin-shell/web/i18n.js +50 -5
  15. package/dist/admin-shell/web/index.js +0 -1
  16. package/dist/audit/feature.js +58 -59
  17. package/dist/audit/handlers/audit-events.d.ts +102 -0
  18. package/dist/audit/handlers/audit-events.js +112 -0
  19. package/dist/audit/handlers/audit-system-db.d.ts +1 -0
  20. package/dist/audit/handlers/audit-system-db.js +9 -0
  21. package/dist/audit/handlers/details-all-tenants.query.d.ts +15 -0
  22. package/dist/audit/handlers/details-all-tenants.query.js +20 -0
  23. package/dist/audit/handlers/details.query.d.ts +2 -1
  24. package/dist/audit/handlers/details.query.js +8 -24
  25. package/dist/audit/handlers/list-all-tenants.query.d.ts +41 -0
  26. package/dist/audit/handlers/list-all-tenants.query.js +32 -0
  27. package/dist/audit/handlers/list.query.d.ts +2 -1
  28. package/dist/audit/handlers/list.query.js +9 -99
  29. package/dist/audit/handlers/resolve-audit-tenant.d.ts +3 -1
  30. package/dist/audit/handlers/resolve-audit-tenant.js +21 -7
  31. package/dist/audit/index.d.ts +1 -1
  32. package/dist/audit/index.js +1 -1
  33. package/dist/audit/run-escape-hatch-retention.js +1 -1
  34. package/dist/audit/screens.d.ts +65 -0
  35. package/dist/audit/screens.js +73 -0
  36. package/dist/audit/web/client-plugin.js +2 -3
  37. package/dist/audit/{constants.d.ts → web/constants.d.ts} +8 -0
  38. package/dist/audit/{constants.js → web/constants.js} +8 -1
  39. package/dist/audit/web/default-translations.d.ts +2 -0
  40. package/dist/audit/web/default-translations.js +3 -0
  41. package/dist/audit/web/i18n.d.ts +5 -2
  42. package/dist/audit/web/i18n.js +31 -4
  43. package/dist/audit/web/index.js +0 -1
  44. package/dist/auth-email-password/bootstrap.d.ts +1 -1
  45. package/dist/auth-email-password/bootstrap.js +4 -4
  46. package/dist/auth-email-password/errors.js +1 -1
  47. package/dist/auth-email-password/feature.js +2 -2
  48. package/dist/auth-email-password/handlers/confirm-account-unlock.write.js +1 -1
  49. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  50. package/dist/auth-email-password/handlers/invite-create.write.d.ts +1 -1
  51. package/dist/auth-email-password/handlers/invite-create.write.js +3 -3
  52. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  53. package/dist/auth-email-password/handlers/login.write.d.ts +1 -0
  54. package/dist/auth-email-password/handlers/login.write.js +26 -1
  55. package/dist/auth-email-password/handlers/request-account-unlock.write.js +1 -1
  56. package/dist/auth-email-password/handlers/request-email-verification.write.js +1 -1
  57. package/dist/auth-email-password/handlers/request-password-reset.write.js +1 -1
  58. package/dist/auth-email-password/handlers/reset-password.write.js +1 -1
  59. package/dist/auth-email-password/handlers/verify-email.write.js +1 -1
  60. package/dist/auth-email-password/index.d.ts +1 -1
  61. package/dist/auth-email-password/index.js +1 -1
  62. package/dist/auth-email-password/mail-notifications.js +1 -1
  63. package/dist/auth-email-password/signup-activation.js +1 -1
  64. package/dist/auth-email-password/web/auth-client.js +0 -1
  65. package/dist/auth-email-password/web/auth-form-logic.js +0 -1
  66. package/dist/auth-email-password/web/auth-form-primitives.js +0 -1
  67. package/dist/auth-email-password/web/auth-gate.js +0 -1
  68. package/dist/auth-email-password/web/auth-redirect.js +0 -1
  69. package/dist/auth-email-password/web/client-actions.js +0 -1
  70. package/dist/auth-email-password/web/client-plugin.js +1 -2
  71. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +0 -1
  72. package/dist/auth-email-password/{constants.js → web/constants.js} +3 -6
  73. package/dist/auth-email-password/web/default-topbar-actions.js +0 -1
  74. package/dist/auth-email-password/web/forgot-password-screen.js +0 -1
  75. package/dist/auth-email-password/{i18n.js → web/i18n.js} +3 -4
  76. package/dist/auth-email-password/web/index.d.ts +1 -1
  77. package/dist/auth-email-password/web/index.js +1 -2
  78. package/dist/auth-email-password/web/invite-accept-screen.d.ts +2 -2
  79. package/dist/auth-email-password/web/invite-accept-screen.js +0 -1
  80. package/dist/auth-email-password/web/login-screen.js +0 -1
  81. package/dist/auth-email-password/{mail-i18n.js → web/mail-i18n.js} +0 -1
  82. package/dist/auth-email-password/web/request-account-unlock-screen.js +0 -1
  83. package/dist/auth-email-password/web/reset-password-screen.js +0 -1
  84. package/dist/auth-email-password/web/session-bootstrap-error.js +0 -1
  85. package/dist/auth-email-password/web/session.js +0 -1
  86. package/dist/auth-email-password/web/signup-complete-screen.d.ts +2 -2
  87. package/dist/auth-email-password/web/signup-complete-screen.js +0 -1
  88. package/dist/auth-email-password/web/signup-screen.js +0 -1
  89. package/dist/auth-email-password/web/tenant-menu-items.js +0 -1
  90. package/dist/auth-email-password/web/tenant-switcher.js +0 -1
  91. package/dist/auth-email-password/web/use-shell-user.js +0 -1
  92. package/dist/auth-email-password/web/user-menu.js +0 -1
  93. package/dist/auth-email-password/web/verify-email-screen.js +0 -1
  94. package/dist/auth-mfa/errors.d.ts +1 -1
  95. package/dist/auth-mfa/errors.js +2 -2
  96. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
  97. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  98. package/dist/auth-mfa/handlers/enable-start.write.js +1 -1
  99. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  100. package/dist/auth-mfa/index.d.ts +1 -1
  101. package/dist/auth-mfa/index.js +1 -1
  102. package/dist/auth-mfa/mfa-status-checker.js +1 -1
  103. package/dist/auth-mfa/screens.js +1 -1
  104. package/dist/auth-mfa/web/client-plugin.js +0 -1
  105. package/dist/auth-mfa/{constants.js → web/constants.js} +0 -1
  106. package/dist/auth-mfa/web/i18n.js +0 -1
  107. package/dist/auth-mfa/web/index.js +0 -1
  108. package/dist/auth-mfa/web/mfa-client.js +0 -1
  109. package/dist/auth-mfa/web/mfa-disable-dialog.js +1 -2
  110. package/dist/auth-mfa/web/mfa-recovery-codes-reveal.js +0 -1
  111. package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +1 -2
  112. package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +11 -18
  113. package/dist/auth-mfa/web/mfa-verify-screen.js +0 -1
  114. package/dist/billing-foundation/checkout-core.js +1 -1
  115. package/dist/billing-foundation/consumer-protection/consent-text.d.ts +2 -2
  116. package/dist/billing-foundation/consumer-protection/consent-text.js +1 -1
  117. package/dist/billing-foundation/consumer-protection/issue-confirmation.js +7 -3
  118. package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
  119. package/dist/billing-foundation/consumer-protection/register-consent.js +1 -1
  120. package/dist/billing-foundation/consumer-protection/register-termination.js +8 -2
  121. package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +1 -0
  122. package/dist/billing-foundation/consumer-protection/stored-user-email.js +8 -0
  123. package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +5 -1
  124. package/dist/billing-foundation/consumer-protection/termination-mail.js +3 -1
  125. package/dist/billing-foundation/consumer-protection/termination-notify.js +1 -1
  126. package/dist/billing-foundation/consumer-protection/termination-pages.js +109 -15
  127. package/dist/billing-foundation/consumer-protection/termination-record.d.ts +8 -1
  128. package/dist/billing-foundation/consumer-protection/termination-record.js +76 -3
  129. package/dist/billing-foundation/consumer-protection/termination-request.js +33 -6
  130. package/dist/billing-foundation/consumer-protection/termination-revoke.d.ts +28 -0
  131. package/dist/billing-foundation/consumer-protection/termination-revoke.js +149 -0
  132. package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +17 -1
  133. package/dist/billing-foundation/consumer-protection/termination-texts.js +39 -0
  134. package/dist/billing-foundation/events.d.ts +9 -0
  135. package/dist/billing-foundation/events.js +14 -2
  136. package/dist/billing-foundation/feature.js +1 -1
  137. package/dist/billing-foundation/handlers/process-event.write.d.ts +5 -1
  138. package/dist/billing-foundation/handlers/process-event.write.js +57 -3
  139. package/dist/billing-foundation/handlers/switch-plan.write.js +1 -1
  140. package/dist/billing-foundation/handlers/sync-subscription.write.js +1 -1
  141. package/dist/billing-foundation/index.d.ts +2 -2
  142. package/dist/billing-foundation/index.js +2 -2
  143. package/dist/billing-foundation/plan-catalog.js +1 -1
  144. package/dist/billing-foundation/screens.js +1 -1
  145. package/dist/billing-foundation/subscription-tier-sync.js +1 -1
  146. package/dist/billing-foundation/types.d.ts +14 -2
  147. package/dist/billing-foundation/types.js +1 -1
  148. package/dist/billing-foundation/validate-options.js +3 -3
  149. package/dist/billing-foundation/web/billing-contact-plan.js +1 -2
  150. package/dist/billing-foundation/web/billing-plans-panel.js +1 -2
  151. package/dist/billing-foundation/web/cancel-contract-dialog.js +1 -2
  152. package/dist/billing-foundation/web/checkout-consent-dialog.js +1 -2
  153. package/dist/billing-foundation/web/client-plugin.js +1 -1
  154. package/dist/billing-foundation/{constants.d.ts → web/constants.d.ts} +21 -14
  155. package/dist/billing-foundation/{constants.js → web/constants.js} +35 -31
  156. package/dist/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.js +0 -1
  157. package/dist/billing-foundation/{contact-card.js → web/contact-card.js} +0 -1
  158. package/dist/billing-foundation/web/index.d.ts +2 -2
  159. package/dist/billing-foundation/web/index.js +2 -3
  160. package/dist/billing-foundation/web/localized-params.js +0 -1
  161. package/dist/billing-foundation/webhook-handler.js +4 -1
  162. package/dist/cap-counter/stock-cap-guard.js +8 -0
  163. package/dist/cap-overview/feature.js +1 -1
  164. package/dist/cap-overview/handlers/caps-usage.query.js +1 -1
  165. package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
  166. package/dist/cap-overview/index.d.ts +2 -2
  167. package/dist/cap-overview/index.js +2 -2
  168. package/dist/cap-overview/screens.js +1 -1
  169. package/dist/cap-overview/web/cap-cards-panel.js +1 -1
  170. package/dist/cap-overview/web/cap-usage-bar.js +1 -2
  171. package/dist/cap-overview/web/client-plugin.js +1 -1
  172. package/dist/cap-overview/{constants.js → web/constants.js} +0 -1
  173. package/dist/cap-overview/web/index.js +0 -1
  174. package/dist/cap-overview/{usage-math.d.ts → web/usage-math.d.ts} +1 -1
  175. package/dist/compliance-profiles/feature.js +1 -1
  176. package/dist/compliance-profiles/index.d.ts +1 -1
  177. package/dist/compliance-profiles/index.js +1 -1
  178. package/dist/compliance-profiles/web/client-plugin.js +1 -2
  179. package/dist/compliance-profiles/web/compliance-profile-catalog.js +1 -2
  180. package/dist/compliance-profiles/{constants.js → web/constants.js} +0 -1
  181. package/dist/compliance-profiles/web/index.js +0 -1
  182. package/dist/config/index.d.ts +1 -1
  183. package/dist/config/index.js +1 -1
  184. package/dist/config/web/client-plugin.d.ts +1 -1
  185. package/dist/config/web/client-plugin.js +1 -2
  186. package/dist/config/{constants.js → web/constants.js} +0 -1
  187. package/dist/config/web/i18n.js +1 -1
  188. package/dist/config/web/index.d.ts +1 -1
  189. package/dist/config/web/index.js +1 -2
  190. package/dist/config/write-helpers.js +1 -1
  191. package/dist/custom-fields/feature.js +1 -1
  192. package/dist/custom-fields/handlers/clear-custom-field.write.js +1 -1
  193. package/dist/custom-fields/handlers/define-tenant-field.write.js +1 -1
  194. package/dist/custom-fields/handlers/delete-system-field.write.js +1 -1
  195. package/dist/custom-fields/handlers/delete-tenant-field.write.js +1 -1
  196. package/dist/custom-fields/handlers/set-custom-field.write.js +1 -1
  197. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  198. package/dist/custom-fields/index.d.ts +1 -1
  199. package/dist/custom-fields/index.js +1 -1
  200. package/dist/custom-fields/lib/value-schema.js +1 -1
  201. package/dist/custom-fields/schemas.js +1 -1
  202. package/dist/custom-fields/web/client-plugin.js +1 -2
  203. package/dist/custom-fields/{constants.js → web/constants.js} +18 -19
  204. package/dist/custom-fields/web/custom-fields-form-section.js +1 -2
  205. package/dist/custom-fields/web/i18n.js +0 -1
  206. package/dist/custom-fields/web/index.d.ts +1 -1
  207. package/dist/custom-fields/web/index.js +1 -2
  208. package/dist/custom-fields/wire-for-entity.js +1 -1
  209. package/dist/delivery/address-opt-out.js +1 -1
  210. package/dist/delivery/attempt-log-retention.js +21 -3
  211. package/dist/delivery/constants.d.ts +1 -1
  212. package/dist/delivery/constants.js +2 -2
  213. package/dist/delivery/i18n.js +1 -1
  214. package/dist/delivery/unsubscribe-page.js +1 -1
  215. package/dist/delivery/web/client-plugin.js +1 -1
  216. package/dist/delivery/web/delivery-channel-cell.js +0 -1
  217. package/dist/delivery/web/delivery-error-cell.js +0 -1
  218. package/dist/delivery/web/delivery-status-cell.js +1 -2
  219. package/dist/delivery/web/delivery-time-cell.js +0 -1
  220. package/dist/delivery/web/delivery-type-cell.js +0 -1
  221. package/dist/delivery/web/index.js +0 -1
  222. package/dist/delivery/{public-names.js → web/public-names.js} +0 -1
  223. package/dist/document-ingest-foundation/events.d.ts +1 -0
  224. package/dist/document-ingest-foundation/events.js +3 -0
  225. package/dist/document-ingest-foundation/executor.js +2 -1
  226. package/dist/document-ingest-foundation/feature.js +16 -5
  227. package/dist/document-ingest-foundation/index.d.ts +1 -1
  228. package/dist/document-ingest-foundation/index.js +1 -1
  229. package/dist/feature-toggles/feature.d.ts +1 -1
  230. package/dist/feature-toggles/feature.js +2 -2
  231. package/dist/feature-toggles/handlers/list.query.js +1 -1
  232. package/dist/feature-toggles/handlers/registered.query.js +1 -1
  233. package/dist/feature-toggles/handlers/set.write.js +1 -1
  234. package/dist/feature-toggles/index.d.ts +1 -1
  235. package/dist/feature-toggles/index.js +1 -1
  236. package/dist/feature-toggles/web/client-plugin.js +1 -2
  237. package/dist/feature-toggles/{constants.js → web/constants.js} +0 -1
  238. package/dist/feature-toggles/web/index.js +0 -1
  239. package/dist/folders/feature.js +1 -1
  240. package/dist/folders/handlers/clear-folder.write.js +1 -1
  241. package/dist/folders/handlers/delete-folder.write.js +1 -1
  242. package/dist/folders/handlers/set-folder.write.js +1 -1
  243. package/dist/folders/index.d.ts +1 -1
  244. package/dist/folders/index.js +1 -1
  245. package/dist/folders/web/client-plugin.js +1 -2
  246. package/dist/folders/{constants.js → web/constants.js} +0 -1
  247. package/dist/folders/web/folder-manager.js +1 -2
  248. package/dist/folders/web/folder-section.js +1 -2
  249. package/dist/folders/web/i18n.js +0 -1
  250. package/dist/folders/web/index.d.ts +1 -1
  251. package/dist/folders/web/index.js +1 -2
  252. package/dist/folders/web/tree.js +0 -1
  253. package/dist/form-draft/db/queries/cleanup.d.ts +3 -2
  254. package/dist/form-draft/db/queries/cleanup.js +18 -9
  255. package/dist/form-draft/decrypt-draft.d.ts +2 -0
  256. package/dist/form-draft/decrypt-draft.js +19 -0
  257. package/dist/form-draft/entity.js +6 -9
  258. package/dist/form-draft/feature.js +1 -1
  259. package/dist/form-draft/handlers/cleanup.job.d.ts +1 -0
  260. package/dist/form-draft/handlers/cleanup.job.js +17 -4
  261. package/dist/form-draft/handlers/discard.write.js +1 -1
  262. package/dist/form-draft/handlers/get.query.js +6 -7
  263. package/dist/form-draft/handlers/list.query.js +11 -7
  264. package/dist/form-draft/handlers/save.write.js +1 -1
  265. package/dist/form-draft/index.d.ts +1 -1
  266. package/dist/form-draft/index.js +1 -1
  267. package/dist/form-draft/lookup.d.ts +2 -2
  268. package/dist/form-draft/lookup.js +7 -2
  269. package/dist/form-draft/schemas.js +1 -1
  270. package/dist/form-draft/{constants.js → web/constants.js} +0 -1
  271. package/dist/form-draft-user-data/hooks.js +2 -2
  272. package/dist/inbound-mail-foundation/handlers/list-accounts.query.d.ts +1 -1
  273. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +11 -3
  274. package/dist/inbound-mail-foundation/retention-sweep.js +7 -5
  275. package/dist/jobs/feature.js +2 -2
  276. package/dist/jobs/handlers/retry.write.js +1 -1
  277. package/dist/jobs/handlers/trigger.write.js +1 -1
  278. package/dist/jobs/index.d.ts +1 -1
  279. package/dist/jobs/index.js +1 -1
  280. package/dist/jobs/web/client-plugin.js +2 -3
  281. package/dist/jobs/{constants.js → web/constants.js} +0 -1
  282. package/dist/jobs/web/default-translations.d.ts +2 -0
  283. package/dist/jobs/web/default-translations.js +3 -0
  284. package/dist/jobs/web/i18n.d.ts +5 -2
  285. package/dist/jobs/web/i18n.js +51 -4
  286. package/dist/jobs/web/index.js +0 -1
  287. package/dist/ledger/entity.d.ts +1 -1
  288. package/dist/ledger/entity.js +1 -1
  289. package/dist/ledger/feature.js +1 -1
  290. package/dist/ledger/handlers/confirm-schedule-period.write.js +2 -5
  291. package/dist/ledger/handlers/create-transaction.write.js +1 -1
  292. package/dist/ledger/handlers/reports.query.js +1 -1
  293. package/dist/ledger/handlers/reverse-transaction.write.js +1 -1
  294. package/dist/ledger/index.d.ts +1 -1
  295. package/dist/ledger/index.js +1 -1
  296. package/dist/ledger/recurring.d.ts +1 -1
  297. package/dist/ledger/reports.d.ts +1 -1
  298. package/dist/ledger/schemas.js +1 -1
  299. package/dist/ledger/{constants.js → web/constants.js} +0 -1
  300. package/dist/ledger/web/index.d.ts +1 -1
  301. package/dist/ledger/web/index.js +1 -2
  302. package/dist/legal-pages/feature.d.ts +1 -1
  303. package/dist/legal-pages/feature.js +1 -1
  304. package/dist/legal-pages/index.d.ts +1 -1
  305. package/dist/legal-pages/index.js +1 -1
  306. package/dist/legal-pages/lib/boot-check.d.ts +1 -1
  307. package/dist/legal-pages/lib/boot-check.js +1 -1
  308. package/dist/legal-pages/lib/validate-routes.d.ts +1 -1
  309. package/dist/legal-pages/web/client-plugin.js +1 -2
  310. package/dist/legal-pages/{constants.js → web/constants.js} +6 -8
  311. package/dist/legal-pages/web/index.js +0 -1
  312. package/dist/mail-foundation/i18n.d.ts +5 -2
  313. package/dist/mail-foundation/i18n.js +3 -2
  314. package/dist/mail-transport-smtp/i18n.d.ts +1 -1
  315. package/dist/mail-transport-smtp/i18n.js +1 -1
  316. package/dist/managed-pages/feature.js +1 -1
  317. package/dist/managed-pages/web/client-plugin.js +1 -2
  318. package/dist/managed-pages/web/default-translations.d.ts +2 -0
  319. package/dist/managed-pages/web/default-translations.js +11 -0
  320. package/dist/managed-pages/web/i18n.d.ts +5 -2
  321. package/dist/managed-pages/web/i18n.js +53 -12
  322. package/dist/managed-pages/web/index.d.ts +1 -1
  323. package/dist/managed-pages/web/index.js +1 -2
  324. package/dist/metrics/compute.d.ts +1 -1
  325. package/dist/metrics/compute.js +1 -1
  326. package/dist/metrics/feature.js +1 -1
  327. package/dist/metrics/index.d.ts +1 -1
  328. package/dist/metrics/index.js +1 -1
  329. package/dist/metrics/types.d.ts +1 -1
  330. package/dist/metrics/validate.js +1 -1
  331. package/dist/metrics/{constants.js → web/constants.js} +0 -1
  332. package/dist/metrics/window.d.ts +1 -1
  333. package/dist/notes-history/feature.js +1 -1
  334. package/dist/notes-history/handlers/add-note.write.js +1 -1
  335. package/dist/notes-history/index.d.ts +1 -1
  336. package/dist/notes-history/index.js +1 -1
  337. package/dist/notes-history/web/client-plugin.js +1 -2
  338. package/dist/notes-history/{constants.js → web/constants.js} +0 -1
  339. package/dist/notes-history/web/i18n.js +0 -1
  340. package/dist/notes-history/web/index.d.ts +1 -1
  341. package/dist/notes-history/web/index.js +1 -2
  342. package/dist/notes-history/web/notes-section.js +2 -3
  343. package/dist/personal-access-tokens/feature.d.ts +2 -2
  344. package/dist/personal-access-tokens/feature.js +6 -4
  345. package/dist/personal-access-tokens/handlers/available-scopes.query.d.ts +1 -1
  346. package/dist/personal-access-tokens/handlers/create.write.js +1 -1
  347. package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
  348. package/dist/personal-access-tokens/hash.js +1 -1
  349. package/dist/personal-access-tokens/i18n.d.ts +1 -1
  350. package/dist/personal-access-tokens/i18n.js +1 -1
  351. package/dist/personal-access-tokens/index.d.ts +5 -5
  352. package/dist/personal-access-tokens/index.js +3 -3
  353. package/dist/personal-access-tokens/resolver.d.ts +1 -1
  354. package/dist/personal-access-tokens/resolver.js +1 -1
  355. package/dist/personal-access-tokens/schema/api-token.js +1 -1
  356. package/dist/personal-access-tokens/screens.d.ts +1 -1
  357. package/dist/personal-access-tokens/screens.js +1 -1
  358. package/dist/personal-access-tokens/{constants.js → web/constants.js} +0 -1
  359. package/dist/presets/index.d.ts +0 -1
  360. package/dist/presets/index.js +0 -1
  361. package/dist/presets/security-baseline.d.ts +1 -1
  362. package/dist/presets/security-baseline.js +1 -1
  363. package/dist/secrets/feature.js +1 -1
  364. package/dist/secrets/handlers/delete.write.js +1 -1
  365. package/dist/secrets/handlers/list.query.js +1 -1
  366. package/dist/secrets/handlers/set.write.js +1 -1
  367. package/dist/secrets/i18n.js +1 -1
  368. package/dist/secrets/index.d.ts +1 -1
  369. package/dist/secrets/index.js +1 -1
  370. package/dist/secrets/{constants.js → web/constants.js} +0 -1
  371. package/dist/secrets/write-gate.js +1 -1
  372. package/dist/sessions/feature.js +7 -4
  373. package/dist/sessions/{i18n.js → web/i18n.js} +0 -1
  374. package/dist/shared/index.d.ts +1 -1
  375. package/dist/shared/index.js +1 -1
  376. package/dist/shared/purge-files-reaching-subject.js +7 -3
  377. package/dist/subscription-stripe/feature.js +2 -1
  378. package/dist/subscription-stripe/plugin-methods.d.ts +3 -0
  379. package/dist/subscription-stripe/plugin-methods.js +14 -0
  380. package/dist/subscription-stripe/verify-webhook.js +1 -0
  381. package/dist/tags/feature.js +1 -1
  382. package/dist/tags/handlers/assign-tag.write.js +11 -7
  383. package/dist/tags/handlers/create-tag.write.js +1 -1
  384. package/dist/tags/handlers/delete-tag.write.js +4 -1
  385. package/dist/tags/handlers/remove-tag.write.js +1 -1
  386. package/dist/tags/handlers/update-tag.write.js +1 -1
  387. package/dist/tags/index.d.ts +1 -1
  388. package/dist/tags/index.js +1 -1
  389. package/dist/tags/screens.js +1 -1
  390. package/dist/tags/web/client-plugin.js +1 -2
  391. package/dist/tags/{constants.d.ts → web/constants.d.ts} +1 -0
  392. package/dist/tags/{constants.js → web/constants.js} +3 -1
  393. package/dist/tags/web/entity-tags.js +1 -2
  394. package/dist/tags/web/i18n.js +2 -2
  395. package/dist/tags/web/index.d.ts +1 -1
  396. package/dist/tags/web/index.js +1 -2
  397. package/dist/tags/web/tag-filter.js +1 -2
  398. package/dist/tags/web/tag-manager.js +5 -4
  399. package/dist/tags/web/tag-picker.js +0 -1
  400. package/dist/tags/web/tag-section.js +1 -2
  401. package/dist/tags/web/tags-cell.js +1 -2
  402. package/dist/template-resolver/api.d.ts +21 -23
  403. package/dist/template-resolver/api.js +34 -6
  404. package/dist/template-resolver/compile-document-body.d.ts +3 -0
  405. package/dist/template-resolver/compile-document-body.js +51 -4
  406. package/dist/template-resolver/compile-steps-block.js +2 -2
  407. package/dist/template-resolver/document-ops.d.ts +1 -1
  408. package/dist/template-resolver/document-ops.js +3 -3
  409. package/dist/template-resolver/document-sanitizer.d.ts +2 -2
  410. package/dist/template-resolver/document-sanitizer.js +23 -3
  411. package/dist/template-resolver/feature.d.ts +11 -0
  412. package/dist/template-resolver/feature.js +68 -35
  413. package/dist/template-resolver/handlers/by-slug.query.js +6 -1
  414. package/dist/template-resolver/handlers/by-tenant.query.js +6 -2
  415. package/dist/template-resolver/handlers/collection-item.query.js +2 -1
  416. package/dist/template-resolver/handlers/collection-list.query.js +2 -1
  417. package/dist/template-resolver/handlers/collection-set.write.d.ts +2 -1
  418. package/dist/template-resolver/handlers/collection-set.write.js +15 -3
  419. package/dist/template-resolver/handlers/collection-shared.d.ts +1 -2
  420. package/dist/template-resolver/handlers/collection-shared.js +0 -4
  421. package/dist/template-resolver/handlers/copy-locale.write.d.ts +2 -1
  422. package/dist/template-resolver/handlers/copy-locale.write.js +69 -65
  423. package/dist/template-resolver/handlers/diff-to-system.query.js +5 -1
  424. package/dist/template-resolver/handlers/discard-draft.write.d.ts +3 -2
  425. package/dist/template-resolver/handlers/discard-draft.write.js +19 -7
  426. package/dist/template-resolver/handlers/document-base.d.ts +1 -1
  427. package/dist/template-resolver/handlers/document-base.js +6 -1
  428. package/dist/template-resolver/handlers/document-blocks.query.d.ts +1 -1
  429. package/dist/template-resolver/handlers/document-blocks.query.js +2 -2
  430. package/dist/template-resolver/handlers/export-bundle.query.js +5 -2
  431. package/dist/template-resolver/handlers/find-by-id.query.js +4 -2
  432. package/dist/template-resolver/handlers/import-bundle.write.d.ts +2 -1
  433. package/dist/template-resolver/handlers/import-bundle.write.js +30 -25
  434. package/dist/template-resolver/handlers/layout-source.query.js +5 -5
  435. package/dist/template-resolver/handlers/list.query.js +5 -2
  436. package/dist/template-resolver/handlers/overview.query.d.ts +12 -3
  437. package/dist/template-resolver/handlers/overview.query.js +87 -51
  438. package/dist/template-resolver/handlers/patch-draft.write.d.ts +2 -1
  439. package/dist/template-resolver/handlers/patch-draft.write.js +93 -87
  440. package/dist/template-resolver/handlers/reset-to-system.write.d.ts +2 -1
  441. package/dist/template-resolver/handlers/reset-to-system.write.js +51 -44
  442. package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +2 -1
  443. package/dist/template-resolver/handlers/resource-link-pdf.write.js +34 -28
  444. package/dist/template-resolver/handlers/resource-remove.write.d.ts +2 -1
  445. package/dist/template-resolver/handlers/resource-remove.write.js +39 -33
  446. package/dist/template-resolver/handlers/resource-shared.js +1 -1
  447. package/dist/template-resolver/handlers/resource-upload.write.d.ts +2 -1
  448. package/dist/template-resolver/handlers/resource-upload.write.js +105 -97
  449. package/dist/template-resolver/handlers/send-test-shared.d.ts +5 -0
  450. package/dist/template-resolver/handlers/send-test-shared.js +19 -0
  451. package/dist/template-resolver/handlers/send-test-status.query.d.ts +9 -0
  452. package/dist/template-resolver/handlers/send-test-status.query.js +18 -0
  453. package/dist/template-resolver/handlers/send-test.write.d.ts +2 -1
  454. package/dist/template-resolver/handlers/send-test.write.js +89 -91
  455. package/dist/template-resolver/handlers/set.write.d.ts +2 -1
  456. package/dist/template-resolver/handlers/set.write.js +95 -91
  457. package/dist/template-resolver/handlers/shared.js +1 -1
  458. package/dist/template-resolver/handlers/template-gates.d.ts +1 -1
  459. package/dist/template-resolver/handlers/template-gates.js +1 -1
  460. package/dist/template-resolver/handlers/template-write.d.ts +1 -1
  461. package/dist/template-resolver/handlers/template-write.js +1 -1
  462. package/dist/template-resolver/handlers/toggle-status.write.d.ts +6 -7
  463. package/dist/template-resolver/handlers/toggle-status.write.js +28 -10
  464. package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +2 -1
  465. package/dist/template-resolver/handlers/upsert-tenant.write.js +30 -24
  466. package/dist/template-resolver/handlers/usage.query.js +3 -2
  467. package/dist/template-resolver/handlers/validate.query.d.ts +1 -1
  468. package/dist/template-resolver/handlers/validate.query.js +3 -1
  469. package/dist/template-resolver/i18n.d.ts +3 -0
  470. package/dist/template-resolver/i18n.js +24 -0
  471. package/dist/template-resolver/index.d.ts +8 -5
  472. package/dist/template-resolver/index.js +6 -4
  473. package/dist/template-resolver/layout-appearance.js +1 -1
  474. package/dist/template-resolver/layout-regions.d.ts +1 -1
  475. package/dist/template-resolver/seeding.d.ts +4 -1
  476. package/dist/template-resolver/seeding.js +13 -7
  477. package/dist/template-resolver/store-template-resource.js +2 -2
  478. package/dist/template-resolver/table.js +1 -1
  479. package/dist/template-resolver/template-bundle.js +2 -2
  480. package/dist/template-resolver/template-delivery-policy.d.ts +22 -0
  481. package/dist/template-resolver/template-delivery-policy.js +40 -0
  482. package/dist/template-resolver/template-draft.d.ts +1 -1
  483. package/dist/template-resolver/template-draft.js +1 -1
  484. package/dist/template-resolver/template-edit-policy.d.ts +22 -0
  485. package/dist/template-resolver/template-edit-policy.js +45 -0
  486. package/dist/template-resolver/template-meta.d.ts +2 -2
  487. package/dist/template-resolver/template-meta.js +2 -2
  488. package/dist/template-resolver/template-preview.d.ts +1 -1
  489. package/dist/template-resolver/template-preview.js +15 -6
  490. package/dist/template-resolver/template-usage.d.ts +1 -1
  491. package/dist/template-resolver/template-usage.js +1 -1
  492. package/dist/template-resolver/template-validation.js +34 -14
  493. package/dist/template-resolver/testing.js +1 -1
  494. package/dist/template-resolver/user-content-table.js +1 -1
  495. package/dist/template-resolver/web/client-plugin.js +1 -2
  496. package/dist/template-resolver/{constants.d.ts → web/constants.d.ts} +4 -1
  497. package/dist/template-resolver/{constants.js → web/constants.js} +9 -10
  498. package/dist/template-resolver/{document-blocks.d.ts → web/document-blocks.d.ts} +2 -2
  499. package/dist/template-resolver/{document-blocks.js → web/document-blocks.js} +1 -0
  500. package/dist/template-resolver/web/document-editor-extensions.d.ts +1 -0
  501. package/dist/template-resolver/web/document-editor-extensions.js +22 -2
  502. package/dist/template-resolver/web/document-editor.js +0 -1
  503. package/dist/template-resolver/web/document-images.d.ts +2 -0
  504. package/dist/template-resolver/web/document-images.js +27 -0
  505. package/dist/template-resolver/{document-schema.d.ts → web/document-schema.d.ts} +2 -1
  506. package/dist/template-resolver/{document-schema.js → web/document-schema.js} +4 -1
  507. package/dist/template-resolver/{document-steps.js → web/document-steps.js} +0 -1
  508. package/dist/template-resolver/web/document-tiptap-editor.d.ts +1 -1
  509. package/dist/template-resolver/web/document-tiptap-editor.js +24 -9
  510. package/dist/template-resolver/web/document-toolbar-blocks.d.ts +4 -2
  511. package/dist/template-resolver/web/document-toolbar-blocks.js +1 -1
  512. package/dist/template-resolver/web/editor-handle.js +1 -1
  513. package/dist/template-resolver/web/i18n.js +5 -1
  514. package/dist/template-resolver/web/index.d.ts +3 -3
  515. package/dist/template-resolver/web/index.js +3 -4
  516. package/dist/template-resolver/{mail-constants.js → web/mail-constants.js} +0 -1
  517. package/dist/template-resolver/{pdf-constants.js → web/pdf-constants.js} +0 -1
  518. package/dist/template-resolver/web/placeholder-line-editor-lazy.js +0 -1
  519. package/dist/template-resolver/web/placeholder-line-editor.js +6 -4
  520. package/dist/template-resolver/{qualified-names.d.ts → web/qualified-names.d.ts} +2 -0
  521. package/dist/template-resolver/{qualified-names.js → web/qualified-names.js} +2 -1
  522. package/dist/template-resolver/web/use-stable-by-key.js +0 -1
  523. package/dist/tenant/handlers/add-member.write.js +1 -1
  524. package/dist/tenant/index.d.ts +1 -1
  525. package/dist/tenant/index.js +1 -1
  526. package/dist/tenant/invitation-table.js +1 -1
  527. package/dist/tenant/invited-membership.js +1 -1
  528. package/dist/tenant/last-tenant-admin.js +1 -1
  529. package/dist/tenant/member-role-options.js +1 -1
  530. package/dist/tenant/screens.js +1 -1
  531. package/dist/tenant/web/client-plugin.js +1 -2
  532. package/dist/tenant/{constants.js → web/constants.js} +3 -6
  533. package/dist/tenant/web/index.js +0 -1
  534. package/dist/tenant/web/member-roles-cell.js +0 -1
  535. package/dist/tenant/web/member-status-cell.js +0 -1
  536. package/dist/tenant-lifecycle/stages.js +2 -3
  537. package/dist/tier-engine/entity.d.ts +1 -1
  538. package/dist/tier-engine/entity.js +1 -1
  539. package/dist/tier-engine/feature.js +2 -2
  540. package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -1
  541. package/dist/tier-engine/index.d.ts +1 -1
  542. package/dist/tier-engine/index.js +1 -1
  543. package/dist/tier-engine/web/client-plugin.js +2 -3
  544. package/dist/tier-engine/{constants.js → web/constants.js} +2 -3
  545. package/dist/tier-engine/{i18n.js → web/i18n.js} +0 -1
  546. package/dist/tier-engine/web/index.js +0 -1
  547. package/dist/user/handlers/create.write.js +1 -1
  548. package/dist/user/handlers/update-roles.js +1 -1
  549. package/dist/user/handlers/update.write.js +1 -1
  550. package/dist/user/index.d.ts +1 -1
  551. package/dist/user/index.js +1 -1
  552. package/dist/user/invited-global-roles.d.ts +1 -1
  553. package/dist/user/invited-global-roles.js +1 -1
  554. package/dist/user/schema/user.js +1 -1
  555. package/dist/user/{constants.js → web/constants.js} +0 -1
  556. package/dist/user-data-rights/env.js +1 -1
  557. package/dist/user-data-rights/feature.js +3 -3
  558. package/dist/user-data-rights/index.d.ts +1 -1
  559. package/dist/user-data-rights/index.js +1 -1
  560. package/dist/user-data-rights/lib/resolve-tenant-model.js +1 -1
  561. package/dist/user-data-rights/mail-notifications.js +1 -1
  562. package/dist/user-data-rights/web/client-plugin.js +2 -3
  563. package/dist/user-data-rights/web/confirm-deletion-screen.js +0 -1
  564. package/dist/user-data-rights/{constants.js → web/constants.js} +11 -12
  565. package/dist/user-data-rights/web/default-translations.d.ts +2 -0
  566. package/dist/user-data-rights/web/default-translations.js +59 -0
  567. package/dist/user-data-rights/web/i18n.d.ts +5 -2
  568. package/dist/user-data-rights/web/i18n.js +37 -59
  569. package/dist/user-data-rights/web/index.d.ts +1 -1
  570. package/dist/user-data-rights/web/index.js +1 -2
  571. package/dist/user-data-rights/web/privacy-center-screen.js +1 -2
  572. package/dist/user-data-rights/web/request-deletion-screen.js +0 -1
  573. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +6 -1
  574. package/dist/user-profile/feature.js +1 -1
  575. package/dist/user-profile/handlers/change-email.write.js +1 -1
  576. package/dist/user-profile/index.d.ts +1 -1
  577. package/dist/user-profile/index.js +1 -1
  578. package/dist/user-profile/web/client-plugin.js +2 -3
  579. package/dist/user-profile/{constants.js → web/constants.js} +0 -1
  580. package/dist/user-profile/{i18n.js → web/i18n.js} +0 -1
  581. package/dist/user-profile/web/profile-screen.js +2 -3
  582. package/dist/waitlist/entity.js +1 -1
  583. package/dist/waitlist/feature.js +1 -1
  584. package/dist/waitlist/handlers/export-purge.write.js +1 -1
  585. package/dist/waitlist/handlers/invite.write.js +1 -1
  586. package/dist/waitlist/handlers/reject.write.js +1 -1
  587. package/dist/waitlist/handlers/submit.write.js +4 -3
  588. package/dist/waitlist/import.d.ts +1 -1
  589. package/dist/waitlist/index.d.ts +1 -1
  590. package/dist/waitlist/index.js +1 -1
  591. package/dist/waitlist/legacy-migrate.js +1 -1
  592. package/dist/waitlist/link-on-signup.js +1 -1
  593. package/dist/waitlist/mail.d.ts +0 -1
  594. package/dist/waitlist/mail.js +6 -4
  595. package/dist/waitlist/payloads.js +1 -1
  596. package/dist/waitlist/screens.js +1 -1
  597. package/dist/waitlist/{constants.js → web/constants.js} +0 -1
  598. package/kumiko-es-tables.json +102 -0
  599. package/package.json +30 -29
  600. package/src/audit/changes.json +7 -0
  601. package/src/auth-email-password/changes.json +6 -0
  602. package/src/auth-mfa/changes.json +6 -0
  603. package/src/billing-foundation/changes.json +18 -0
  604. package/src/cap-counter/changes.json +12 -0
  605. package/src/delivery/changes.json +6 -0
  606. package/src/document-ingest-foundation/changes.json +6 -0
  607. package/src/files/changes.json +7 -0
  608. package/src/form-draft/changes.json +7 -0
  609. package/src/inbound-mail-foundation/changes.json +6 -0
  610. package/src/ledger/changes.json +7 -0
  611. package/src/mail-foundation/changes.json +6 -0
  612. package/src/presets/changes.json +7 -0
  613. package/src/tags/changes.json +6 -0
  614. package/src/template-resolver/changes.json +63 -0
  615. package/src/user-data-rights/changes.json +14 -0
  616. package/src/waitlist/changes.json +6 -0
  617. package/dist/admin-shell/i18n.d.ts +0 -5
  618. package/dist/admin-shell/i18n.js +0 -51
  619. package/dist/audit/i18n.d.ts +0 -5
  620. package/dist/audit/i18n.js +0 -22
  621. package/dist/jobs/i18n.d.ts +0 -5
  622. package/dist/jobs/i18n.js +0 -52
  623. package/dist/managed-pages/i18n.d.ts +0 -5
  624. package/dist/managed-pages/i18n.js +0 -55
  625. package/dist/presets/dsgvo-self-service.d.ts +0 -10
  626. package/dist/presets/dsgvo-self-service.js +0 -24
  627. package/dist/user-data-rights/i18n.d.ts +0 -5
  628. package/dist/user-data-rights/i18n.js +0 -39
  629. /package/dist/account-security/{constants.d.ts → web/constants.d.ts} +0 -0
  630. /package/dist/account-security/{i18n.d.ts → web/i18n.d.ts} +0 -0
  631. /package/dist/admin-shell/{constants.d.ts → web/constants.d.ts} +0 -0
  632. /package/dist/auth-email-password/{constants.d.ts → web/constants.d.ts} +0 -0
  633. /package/dist/auth-email-password/{i18n.d.ts → web/i18n.d.ts} +0 -0
  634. /package/dist/auth-email-password/{mail-i18n.d.ts → web/mail-i18n.d.ts} +0 -0
  635. /package/dist/auth-mfa/{constants.d.ts → web/constants.d.ts} +0 -0
  636. /package/dist/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.d.ts +0 -0
  637. /package/dist/billing-foundation/{contact-card.d.ts → web/contact-card.d.ts} +0 -0
  638. /package/dist/cap-overview/{constants.d.ts → web/constants.d.ts} +0 -0
  639. /package/dist/cap-overview/{usage-math.js → web/usage-math.js} +0 -0
  640. /package/dist/compliance-profiles/{constants.d.ts → web/constants.d.ts} +0 -0
  641. /package/dist/config/{constants.d.ts → web/constants.d.ts} +0 -0
  642. /package/dist/custom-fields/{constants.d.ts → web/constants.d.ts} +0 -0
  643. /package/dist/delivery/{public-names.d.ts → web/public-names.d.ts} +0 -0
  644. /package/dist/feature-toggles/{constants.d.ts → web/constants.d.ts} +0 -0
  645. /package/dist/folders/{constants.d.ts → web/constants.d.ts} +0 -0
  646. /package/dist/form-draft/{constants.d.ts → web/constants.d.ts} +0 -0
  647. /package/dist/jobs/{constants.d.ts → web/constants.d.ts} +0 -0
  648. /package/dist/ledger/{constants.d.ts → web/constants.d.ts} +0 -0
  649. /package/dist/legal-pages/{constants.d.ts → web/constants.d.ts} +0 -0
  650. /package/dist/metrics/{constants.d.ts → web/constants.d.ts} +0 -0
  651. /package/dist/notes-history/{constants.d.ts → web/constants.d.ts} +0 -0
  652. /package/dist/personal-access-tokens/{constants.d.ts → web/constants.d.ts} +0 -0
  653. /package/dist/personal-access-tokens/{scopes.d.ts → web/scopes.d.ts} +0 -0
  654. /package/dist/personal-access-tokens/{scopes.js → web/scopes.js} +0 -0
  655. /package/dist/secrets/{constants.d.ts → web/constants.d.ts} +0 -0
  656. /package/dist/sessions/{i18n.d.ts → web/i18n.d.ts} +0 -0
  657. /package/dist/template-resolver/{document-steps.d.ts → web/document-steps.d.ts} +0 -0
  658. /package/dist/template-resolver/{mail-constants.d.ts → web/mail-constants.d.ts} +0 -0
  659. /package/dist/template-resolver/{pdf-constants.d.ts → web/pdf-constants.d.ts} +0 -0
  660. /package/dist/template-resolver/{placeholder-text.d.ts → web/placeholder-text.d.ts} +0 -0
  661. /package/dist/template-resolver/{placeholder-text.js → web/placeholder-text.js} +0 -0
  662. /package/dist/tenant/{constants.d.ts → web/constants.d.ts} +0 -0
  663. /package/dist/tier-engine/{constants.d.ts → web/constants.d.ts} +0 -0
  664. /package/dist/tier-engine/{i18n.d.ts → web/i18n.d.ts} +0 -0
  665. /package/dist/user/{constants.d.ts → web/constants.d.ts} +0 -0
  666. /package/dist/user-data-rights/{constants.d.ts → web/constants.d.ts} +0 -0
  667. /package/dist/user-profile/{constants.d.ts → web/constants.d.ts} +0 -0
  668. /package/dist/user-profile/{i18n.d.ts → web/i18n.d.ts} +0 -0
  669. /package/dist/waitlist/{constants.d.ts → web/constants.d.ts} +0 -0
@@ -5,13 +5,13 @@ import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
5
5
  import * as z from "zod";
6
6
  import { burnToken, sessionLocaleField, sessionTimezoneField } from "../../shared/index.js";
7
7
  import { USER_STATUS, UserQueries } from "../../user/index.js";
8
- import { MFA_VERIFY_LOCKOUT_MINUTES, MFA_VERIFY_MAX_ATTEMPTS } from "../constants.js";
9
8
  import { findUserMfaRow } from "../db/queries.js";
10
9
  import { invalidChallengeToken, invalidTotpCode, tooManyAttempts } from "../errors.js";
11
10
  import { verifyMfaChallengeToken } from "../mfa-challenge-token.js";
12
11
  import { clearMfaVerifyAttempts, getMfaVerifyLockoutState, recordFailedMfaVerifyAttempt, } from "../mfa-verify-attempts.js";
13
12
  import { encodeRecoveryCodes, userMfaEntity, userMfaTable } from "../schema/user-mfa.js";
14
13
  import { verifyMfaFactor } from "../verify-factor.js";
14
+ import { MFA_VERIFY_LOCKOUT_MINUTES, MFA_VERIFY_MAX_ATTEMPTS } from "../web/constants.js";
15
15
  const executor = createEventStoreExecutor(userMfaTable, userMfaEntity, {
16
16
  entityName: "user-mfa",
17
17
  });
@@ -1,6 +1,5 @@
1
1
  export { base32Decode } from "./base32.ts";
2
2
  export { type MfaRequiredPolicy, mfaRequiredConfigHandle } from "./config.ts";
3
- export { AUTH_MFA_FEATURE, AuthMfaHandlers, AuthMfaQueries, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./constants.ts";
4
3
  export { authMfaEnvSchema, mfaTokenSecretsEnvSchema } from "./env.ts";
5
4
  export type { AuthMfaFeatureOptions } from "./feature.ts";
6
5
  export { createAuthMfaFeature } from "./feature.ts";
@@ -10,3 +9,4 @@ export type { MfaCodeVerifier, MfaCodeVerifyResult } from "./mfa-code-verifier.t
10
9
  export type { MfaStatusChecker, MfaStatusCheckResult } from "./mfa-status-checker.ts";
11
10
  export { userMfaEntity, userMfaTable } from "./schema/user-mfa.ts";
12
11
  export { type MfaTokenSecretOverrides, type MfaTokenSecretsEnv, type ResolvedMfaTokenSecrets, resolveMfaTokenSecrets, resolveMfaTokenSecretsFromEnv, } from "./token-secrets.ts";
12
+ export { AUTH_MFA_FEATURE, AuthMfaHandlers, AuthMfaQueries, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./web/constants.ts";
@@ -1,8 +1,8 @@
1
1
  export { base32Decode } from "./base32.js";
2
2
  export { mfaRequiredConfigHandle } from "./config.js";
3
- export { AUTH_MFA_FEATURE, AuthMfaHandlers, AuthMfaQueries, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./constants.js";
4
3
  export { authMfaEnvSchema, mfaTokenSecretsEnvSchema } from "./env.js";
5
4
  export { createAuthMfaFeature } from "./feature.js";
6
5
  export { bindMfaRevokeAllOtherSessionsFromFeature, bindMfaTokenSecretsFromFeature, bindRevokeAllPatTokensFromFeature, mfaStatusCheckerFromFeature, mfaVerifierFromFeature, } from "./feature-exports.js";
7
6
  export { userMfaEntity, userMfaTable } from "./schema/user-mfa.js";
8
7
  export { resolveMfaTokenSecrets, resolveMfaTokenSecretsFromEnv, } from "./token-secrets.js";
8
+ export { AUTH_MFA_FEATURE, AuthMfaHandlers, AuthMfaQueries, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./web/constants.js";
@@ -1,10 +1,10 @@
1
1
  import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { access, declareEscapeHatch, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { mfaRequiredConfigHandle, mfaRequiredConfigKey } from "./config.js";
4
- import { MFA_CHALLENGE_TOKEN_TTL_MINUTES, MFA_PREAUTH_SETUP_TOKEN_TTL_MINUTES, } from "./constants.js";
5
4
  import { findUserMfaRow } from "./db/queries.js";
6
5
  import { signMfaChallengeToken } from "./mfa-challenge-token.js";
7
6
  import { signMfaPreauthSetupToken } from "./mfa-preauth-setup-token.js";
7
+ import { MFA_CHALLENGE_TOKEN_TTL_MINUTES, MFA_PREAUTH_SETUP_TOKEN_TTL_MINUTES, } from "./web/constants.js";
8
8
  export function createMfaStatusChecker(opts) {
9
9
  return async (ctx, userId, tenantId, roles) => {
10
10
  declareEscapeHatch({
@@ -1,5 +1,5 @@
1
1
  import { i18nKey, } from "@cosmicdrift/kumiko-framework/engine";
2
- import { AuthMfaHandlers, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./constants.js";
2
+ import { AuthMfaHandlers, MFA_DISABLE_SCREEN_ID, MFA_ENABLE_SCREEN_ID, MFA_REGENERATE_RECOVERY_SCREEN_ID, } from "./web/constants.js";
3
3
  // Declarative TOTP-enrollment screen: mint (no input) -> reveal QR/secret/
4
4
  // recovery-codes -> confirm with a 6-digit code. `setupToken` is carried
5
5
  // from the mint payload into the confirm payload but never listed in
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Client-Feature-Factory für auth-mfa — mirrors emailPasswordClient()'s
3
2
  // shape so apps register both the same way:
4
3
  // createKumikoApp({ clientFeatures: [emailPasswordClient(), authMfaClient()] }).
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Pure constants — client-marked so auth-mfa/web/ may import handler QNs
3
2
  // and the screen id without pulling the feature's server runtime barrel.
4
3
  // Qualified write-handler names — feature is registered as "auth-mfa", each
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Default-Bundles für die auth-mfa Feature-UI. Merged in mit
3
2
  // authMfaClient() analog zu emailPasswordClient() aus auth-email-password.
4
3
  // Keys folgen `auth.mfa.<area>.<slug>`.
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Public exports für die Browser-Seite des auth-mfa Features. Sub-Path-
3
2
  // Export `@cosmicdrift/kumiko-bundled-features/auth-mfa/web` — Server-Seite
4
3
  // (defineFeature) bleibt frei von React-/DOM-Deps, siehe auth-email-
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Browser-Seite von POST /api/auth/mfa/verify — completes the two-step
3
2
  // login LoginScreen started when the server responded mfaRequired. Same
4
3
  // fetch/CSRF pattern as auth-email-password's login() (pre-session, no
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // @runtime client
3
2
  // MfaDisableDialog — confirm-with-code before turning MFA off. Uses the
4
3
  // generic Dialog primitive (unlike MfaRegenerateRecoveryDialog): disable is
5
4
  // single-step, no state to preserve after confirm, so
@@ -12,7 +11,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
12
11
  // by the caller, not the dialog).
13
12
  import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
14
13
  import { useState } from "react";
15
- import { AuthMfaHandlers } from "../constants.js";
14
+ import { AuthMfaHandlers } from "./constants.js";
16
15
  // kumiko-lint-ignore no-custom-primitives Uses usePrimitives().Dialog internally, name is an MFA domain action, not a primitive reimplementation
17
16
  export function MfaDisableDialog({ open, onOpenChange, onDisabled, onError, }) {
18
17
  const t = useTranslation();
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @runtime client
3
2
  // MfaRecoveryCodesReveal — one-time display of a fresh recovery-code set,
4
3
  // with an acknowledge-then-dismiss gate. Standalone so MfaRegenerateRecovery-
5
4
  // Dialog's caller can render it after the dialog closes — the codes only
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // @runtime client
3
2
  // MfaRegenerateRecoveryDialog — confirm-with-code, then the caller reveals
4
3
  // the new codes. The reveal itself can't live inside this Dialog: Dialog
5
4
  // closes in a `finally` right after onConfirm resolves (see profile-screen.
@@ -9,7 +8,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
9
8
  // (or equivalent) once the dialog has closed.
10
9
  import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
11
10
  import { useState } from "react";
12
- import { AuthMfaHandlers } from "../constants.js";
11
+ import { AuthMfaHandlers } from "./constants.js";
13
12
  // kumiko-lint-ignore no-custom-primitives Uses usePrimitives().Dialog internally, name is an MFA domain action, not a primitive reimplementation
14
13
  export function MfaRegenerateRecoveryDialog({ open, onOpenChange, onRegenerated, onError, }) {
15
14
  const t = useTranslation();
@@ -1,7 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @runtime client
3
- // Consumers that type-check this source never include the ambient declaration on their own.
4
- /// <reference path="./qrcode-browser.d.ts" />
5
2
  // Pre-auth twin of the declarative auth-mfa-enable secretMint screen: a user
6
3
  // blocked at login by MFA enforcement and not yet enrolled lands here
7
4
  // straight out of the login flow — there is no session yet. Identity comes
@@ -17,9 +14,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
14
  // has useSession() in scope) must call refresh() there, otherwise the app
18
15
  // stays "unauthenticated" until the next reload.
19
16
  import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
20
- // qrcode's package.json#browser remap avoids Node-only deps (yargs/pngjs)
21
- // for bundlers that honor it — Metro doesn't, hence the explicit subpath.
22
- import QRCode from "qrcode/lib/browser.js";
23
17
  import { useState } from "react";
24
18
  // kumiko-lint-ignore cross-feature-import client-only component, the feature's server barrel has no web/ re-export
25
19
  import { AuthCard } from "../../auth-email-password/web/index.js";
@@ -50,7 +44,7 @@ function reasonToKey(reason) {
50
44
  }
51
45
  export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title, subtitle, onSuccess, onCancel, }) {
52
46
  const t = useTranslation();
53
- const { Button, Banner, Field, Form, Input, Section } = usePrimitives();
47
+ const { Button, Banner, Field, Form, Input, Section, SecretReveal } = usePrimitives();
54
48
  const [setup, setSetup] = useState(null);
55
49
  const [acknowledged, setAcknowledged] = useState(false);
56
50
  const [code, setCode] = useState("");
@@ -68,18 +62,11 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
68
62
  setRetryAfterSeconds(res.error.retryAfterSeconds ?? null);
69
63
  return;
70
64
  }
71
- // errorCorrectionLevel "H" (~30% redundancy) — more resilient to
72
- // camera/lighting issues than the default, no downside for a code
73
- // this short-lived.
74
- const qrSvg = await QRCode.toString(res.data.otpauthUri, {
75
- type: "svg",
76
- errorCorrectionLevel: "H",
77
- });
78
65
  setSetup({
79
66
  setupToken: res.data.setupToken,
80
67
  secretParam: extractSecret(res.data.otpauthUri),
81
68
  recoveryCodes: res.data.recoveryCodes,
82
- qrSvg,
69
+ otpauthUri: res.data.otpauthUri,
83
70
  });
84
71
  setAcknowledged(false);
85
72
  setCode("");
@@ -129,7 +116,13 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
129
116
  };
130
117
  return (_jsxs(AuthCard, { title: title ?? t("auth.mfa.setup.title"), subtitle: subtitle ?? t("auth.mfa.setup.subtitle"), children: [error !== null ? (_jsx(Banner, { variant: "error", children: error === "too_many_attempts" && retryAfterSeconds !== null
131
118
  ? t("auth.mfa.errors.tooManyAttemptsWithSeconds", { seconds: retryAfterSeconds })
132
- : t(reasonToKey(error)) })) : null, !setup && (_jsxs(Section, { testId: "mfa-setup-preauth-intro", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: t("auth.mfa.setup.intro") }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { variant: "primary", onClick: () => void startSetup(), loading: busy, disabled: busy, children: t("auth.mfa.setup.start") }) })] })), setup && (_jsx(Form, { onSubmit: onSubmit, children: _jsxs(Section, { testId: "mfa-setup-preauth-setup", children: [_jsxs("div", { className: "flex flex-col items-center gap-2 text-center", children: [_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.scanTitle") }), _jsx("div", { className: "h-40 w-40",
133
- // biome-ignore lint/security/noDangerouslySetInnerHtml: qrcode-generated SVG, no user input
134
- dangerouslySetInnerHTML: { __html: setup.qrSvg } }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.manualEntry") }), _jsx("code", { className: "inline-block break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.secretParam })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.recoveryTitle") }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.recoveryHint") }), _jsx("code", { className: "block whitespace-pre-wrap break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.recoveryCodes.join("\n") }), _jsx(Field, { id: "mfa-setup-preauth-ack", label: t("auth.mfa.enable.acknowledge"), children: _jsx(Input, { kind: "boolean", id: "mfa-setup-preauth-ack", name: "mfa-setup-preauth-ack", value: acknowledged, onChange: setAcknowledged }) })] }), _jsx(Field, { id: "mfa-setup-preauth-code", label: t("auth.mfa.enable.code"), required: true, children: _jsx(Input, { kind: "text", id: "mfa-setup-preauth-code", name: "mfa-setup-preauth-code", value: code, onChange: setCode, disabled: busy || !acknowledged, autoComplete: "one-time-code" }) }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { type: "submit", variant: "primary", loading: busy, disabled: busy || !acknowledged || code.length !== 6, children: t("auth.mfa.setup.confirm") }) })] }) })), onCancel ? (_jsx("div", { className: "flex justify-center", children: _jsx(Button, { type: "button", variant: "secondary", onClick: onCancel, disabled: busy, children: t("auth.mfa.verify.backToLogin") }) })) : null] }));
119
+ : t(reasonToKey(error)) })) : null, !setup && (_jsxs(Section, { testId: "mfa-setup-preauth-intro", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: t("auth.mfa.setup.intro") }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { variant: "primary", onClick: () => void startSetup(), loading: busy, disabled: busy, children: t("auth.mfa.setup.start") }) })] })), setup && (_jsx(Form, { onSubmit: onSubmit, children: _jsxs(Section, { testId: "mfa-setup-preauth-setup", children: [_jsxs("div", { className: "flex flex-col items-center gap-2 text-center", children: [SecretReveal !== undefined ? (_jsx(SecretReveal, { values: [
120
+ {
121
+ label: t("auth.mfa.enable.scanTitle"),
122
+ value: setup.otpauthUri,
123
+ qr: true,
124
+ copyable: false,
125
+ multiline: false,
126
+ },
127
+ ], copyLabel: t("kumiko.secretMint.copy"), copiedLabel: t("kumiko.secretMint.copied"), testId: "mfa-setup-preauth-qr" })) : (_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.scanTitle") })), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.manualEntry") }), _jsx("code", { className: "inline-block break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.secretParam })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.recoveryTitle") }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.recoveryHint") }), _jsx("code", { className: "block whitespace-pre-wrap break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.recoveryCodes.join("\n") }), _jsx(Field, { id: "mfa-setup-preauth-ack", label: t("auth.mfa.enable.acknowledge"), children: _jsx(Input, { kind: "boolean", id: "mfa-setup-preauth-ack", name: "mfa-setup-preauth-ack", value: acknowledged, onChange: setAcknowledged }) })] }), _jsx(Field, { id: "mfa-setup-preauth-code", label: t("auth.mfa.enable.code"), required: true, children: _jsx(Input, { kind: "text", id: "mfa-setup-preauth-code", name: "mfa-setup-preauth-code", value: code, onChange: setCode, disabled: busy || !acknowledged, autoComplete: "one-time-code" }) }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { type: "submit", variant: "primary", loading: busy, disabled: busy || !acknowledged || code.length !== 6, children: t("auth.mfa.setup.confirm") }) })] }) })), onCancel ? (_jsx("div", { className: "flex justify-center", children: _jsx(Button, { type: "button", variant: "secondary", onClick: onCancel, disabled: busy, children: t("auth.mfa.verify.backToLogin") }) })) : null] }));
135
128
  }
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @runtime client
3
2
  // Login-Challenge-Step, gerendert wenn LoginScreen's onMfaChallenge feuert
4
3
  // (/auth/login antwortete mfaRequired). Stilistisch wie login-screen.tsx:
5
4
  // useState + direkter fetch-Call, kein Dispatcher — es existiert noch kein
@@ -4,8 +4,8 @@
4
4
  // and the price/subscription-state gate that turns a bare priceId-driven
5
5
  // checkout into a plan-aware one. Internal — not re-exported from index.ts.
6
6
  import { ConflictError, FeatureDisabledError, UnconfiguredError, UnprocessableError, } from "@cosmicdrift/kumiko-framework/errors";
7
- import { BILLING_FOUNDATION_FEATURE, isSubscriptionBlockingCheckout, SUBSCRIPTION_PROVIDER_EXTENSION, } from "./constants.js";
8
7
  import { getSubscriptionForTenant } from "./get-subscription-for-tenant.js";
8
+ import { BILLING_FOUNDATION_FEATURE, isSubscriptionBlockingCheckout, SUBSCRIPTION_PROVIDER_EXTENSION, } from "./web/constants.js";
9
9
  /** Narrows a `readonly string[]` to the non-empty tuple shape `z.enum`
10
10
  * needs. Callers only reach this with a catalog's `plans` — the feature
11
11
  * factory already rejected an empty `plans` array at mount time, so the
@@ -1,5 +1,5 @@
1
- import type { ConsentLocale } from "./consent-locale.ts";
2
- export { CONSENT_LOCALES, type ConsentLocale, FALLBACK_CONSENT_LOCALE, resolveConsentLocale, } from "./consent-locale.ts";
1
+ import type { ConsentLocale } from "../web/consumer-protection/consent-locale.ts";
2
+ export { CONSENT_LOCALES, type ConsentLocale, FALLBACK_CONSENT_LOCALE, resolveConsentLocale, } from "../web/consumer-protection/consent-locale.ts";
3
3
  export type ConsentTexts = {
4
4
  readonly earlyPerformance: string;
5
5
  readonly withdrawalLoss: string;
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- export { CONSENT_LOCALES, FALLBACK_CONSENT_LOCALE, resolveConsentLocale, } from "./consent-locale.js";
2
+ export { CONSENT_LOCALES, FALLBACK_CONSENT_LOCALE, resolveConsentLocale, } from "../web/consumer-protection/consent-locale.js";
3
3
  export const CONSENT_TEXTS = {
4
4
  de: {
5
5
  earlyPerformance: "Ich verlange ausdrücklich, dass der Anbieter vor Ablauf der Widerrufsfrist mit der Ausführung des Vertrags beginnt.",
@@ -9,10 +9,11 @@ import * as z from "zod";
9
9
  import { requireTemplateResolver, TEXT_BLOCK_KIND } from "../../template-resolver/index.js";
10
10
  import { UserQueries } from "../../user/index.js";
11
11
  import { paymentAggregateId, subscriptionAggregateId } from "../aggregate-id.js";
12
- import { CONTRACT_CONFIRMATION_NOTIFICATION_TYPE } from "../constants.js";
13
12
  import { CHECKOUT_CONSENT_RECORDED_EVENT_QN, CONTRACT_CONFIRMATION_ISSUED_EVENT_QN, checkoutConsentRecordedPayloadSchema, contractConfirmationIssuedPayloadSchema, PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
13
+ import { CONTRACT_CONFIRMATION_NOTIFICATION_TYPE } from "../web/constants.js";
14
14
  import { contractConfirmationVariables } from "./confirmation-mail.js";
15
15
  import { resolveConsentLocale } from "./consent-text.js";
16
+ import { openStoredUserEmail } from "./stored-user-email.js";
16
17
  export const issueContractConfirmationSchema = z
17
18
  .object({
18
19
  consentId: z.string().min(1).max(100),
@@ -100,7 +101,10 @@ export function createIssueContractConfirmationHandler(options, consumerProtecti
100
101
  const recipient = recipientRowSchema.safeParse(await ctx.queryAs(createSystemUser(tenantId), UserQueries.findForAuth, {
101
102
  id: consent.actorUserId,
102
103
  }));
103
- if (!recipient.success || recipient.data.isDeleted === true) {
104
+ const recipientEmail = recipient.success && recipient.data.isDeleted !== true
105
+ ? await openStoredUserEmail(recipient.data.email, "billing-foundation:issue-contract-confirmation")
106
+ : null;
107
+ if (!recipient.success || recipientEmail === null) {
104
108
  ctx.log?.warn(`[billing-foundation:issue-contract-confirmation] recipient of consent ${payload.consentId} not found; no mail sent`);
105
109
  return {
106
110
  isSuccess: true,
@@ -158,7 +162,7 @@ export function createIssueContractConfirmationHandler(options, consumerProtecti
158
162
  };
159
163
  await stream.appendOne({ type: CONTRACT_CONFIRMATION_ISSUED_EVENT_QN, payload: issued });
160
164
  await ctx.notify(CONTRACT_CONFIRMATION_NOTIFICATION_TYPE, {
161
- route: { email: recipient.data.email },
165
+ route: { email: recipientEmail },
162
166
  data: variables,
163
167
  locale,
164
168
  priority: "critical",
@@ -1,5 +1,5 @@
1
1
  import { templateVariable, } from "@cosmicdrift/kumiko-framework/engine";
2
- import { mailHeading, mailParagraph, mailRepeatedRows } from "../../shared/index.js";
2
+ import { mailHeading, mailParagraph, mailParagraphWithLink, mailRepeatedRows, } from "../../shared/index.js";
3
3
  import { CONFIRMATION_LABELS } from "./confirmation-mail.js";
4
4
  import { CONSENT_LOCALES, CONSENT_TEXTS } from "./consent-text.js";
5
5
  import { TERMINATION_TEXTS } from "./termination-texts.js";
@@ -12,6 +12,7 @@ export const TERMINATION_RECEIPT_VARIABLES = {
12
12
  requestId: templateVariable.text({ required: true }),
13
13
  details: textRows(),
14
14
  operatorEmail: templateVariable.text({ required: true }),
15
+ revokeUrl: templateVariable.link(),
15
16
  };
16
17
  export const OPERATOR_NOTICE_VARIABLES = {
17
18
  subject: templateVariable.text({ required: true }),
@@ -43,6 +44,7 @@ export function terminationReceiptTemplate() {
43
44
  mailRepeatedRows("details", "text"),
44
45
  mailParagraph(texts.receiptNextSteps),
45
46
  mailParagraph(texts.receiptRevoke(OPERATOR_EMAIL_SLOT)),
47
+ mailParagraphWithLink(texts.receiptNotMe, texts.receiptNotMeLink, "revokeUrl").replace("<p>", '<p data-if="revokeUrl">'),
46
48
  mailParagraph(`${texts.contact} {operatorEmail}`),
47
49
  ].join(""),
48
50
  };
@@ -1,6 +1,6 @@
1
1
  import { paymentAggregateId, subscriptionAggregateId } from "../aggregate-id.js";
2
- import { SubscriptionFoundationHandlers, SubscriptionStatuses } from "../constants.js";
3
2
  import { CHECKOUT_CONSENT_RECORDED_EVENT_SHORT, CONTRACT_CONFIRMATION_ISSUED_EVENT_SHORT, checkoutConsentRecordedPayloadSchema, contractConfirmationIssuedPayloadSchema, INVOICE_PAID_EVENT_QN, PAYMENT_RECEIVED_EVENT_QN, SUBSCRIPTION_CREATED_EVENT_QN, SUBSCRIPTION_UPDATED_EVENT_QN, } from "../events.js";
3
+ import { SubscriptionFoundationHandlers, SubscriptionStatuses } from "../web/constants.js";
4
4
  import { createIssueContractConfirmationHandler } from "./issue-confirmation.js";
5
5
  import { registerConsumerProtectionMails } from "./mail-notifications.js";
6
6
  import { registerContractTermination } from "./register-termination.js";
@@ -1,10 +1,14 @@
1
- import { SubscriptionCancelTimings, SubscriptionFoundationHandlers } from "../constants.js";
2
- import { CONTRACT_TERMINATION_DECLARED_EVENT_QN, CONTRACT_TERMINATION_DECLARED_EVENT_SHORT, CONTRACT_TERMINATION_REQUESTED_EVENT_SHORT, CONTRACT_TERMINATION_UNMATCHED_EVENT_SHORT, contractTerminationDeclaredPayloadSchema, contractTerminationRequestedPayloadSchema, contractTerminationUnmatchedPayloadSchema, } from "../events.js";
1
+ import { CONTRACT_TERMINATION_DECLARED_EVENT_QN, CONTRACT_TERMINATION_DECLARED_EVENT_SHORT, CONTRACT_TERMINATION_REQUESTED_EVENT_SHORT, CONTRACT_TERMINATION_REVOKED_EVENT_SHORT, CONTRACT_TERMINATION_UNMATCHED_EVENT_SHORT, contractTerminationDeclaredPayloadSchema, contractTerminationRequestedPayloadSchema, contractTerminationRevokedPayloadSchema, contractTerminationUnmatchedPayloadSchema, } from "../events.js";
2
+ import { SubscriptionCancelTimings, SubscriptionFoundationHandlers } from "../web/constants.js";
3
3
  import { createDeclareContractTerminationHandler, createRecordContractTerminationHandler, createRecordUnmatchedContractTerminationHandler, createTerminableSubscriptionQuery, } from "./termination-record.js";
4
4
  import { createRequestContractTerminationHandler, createTerminateContractHandler, } from "./termination-request.js";
5
+ import { createRecordContractTerminationRevocationHandler, createRevokeContractTerminationHandler, } from "./termination-revoke.js";
5
6
  export function registerContractTermination(r, options, consumerProtection) {
6
7
  r.defineEvent(CONTRACT_TERMINATION_REQUESTED_EVENT_SHORT, contractTerminationRequestedPayloadSchema, { piiFields: "none" });
7
8
  r.defineEvent(CONTRACT_TERMINATION_DECLARED_EVENT_SHORT, contractTerminationDeclaredPayloadSchema, { piiFields: "none" });
9
+ r.defineEvent(CONTRACT_TERMINATION_REVOKED_EVENT_SHORT, contractTerminationRevokedPayloadSchema, {
10
+ piiFields: "none",
11
+ });
8
12
  r.defineEvent(CONTRACT_TERMINATION_UNMATCHED_EVENT_SHORT, contractTerminationUnmatchedPayloadSchema, { piiFields: "none" });
9
13
  r.queryHandler(createTerminableSubscriptionQuery());
10
14
  r.writeHandler(createDeclareContractTerminationHandler());
@@ -12,6 +16,8 @@ export function registerContractTermination(r, options, consumerProtection) {
12
16
  r.writeHandler(createRecordUnmatchedContractTerminationHandler());
13
17
  r.writeHandler(createRequestContractTerminationHandler(options, consumerProtection));
14
18
  r.writeHandler(createTerminateContractHandler(options, consumerProtection));
19
+ r.writeHandler(createRevokeContractTerminationHandler());
20
+ r.writeHandler(createRecordContractTerminationRevocationHandler(options, consumerProtection));
15
21
  // The provider cancel of a public declaration runs here, not in the
16
22
  // request: matched and unmatched requests then do the same work and the
17
23
  // response time does not tell whether the email belongs to a customer.
@@ -0,0 +1 @@
1
+ export declare function openStoredUserEmail(stored: string, fallbackRequestId: string): Promise<string | null>;
@@ -0,0 +1,8 @@
1
+ import { PII_ERASED_SENTINEL } from "@cosmicdrift/kumiko-framework/crypto";
2
+ import { decryptStoredPii } from "../../shared/index.js";
3
+ // findForAuth returns the stored column, which is ciphertext under an active KMS;
4
+ // channel-email refuses to mail a ciphertext address. Null for an erased subject.
5
+ export async function openStoredUserEmail(stored, fallbackRequestId) {
6
+ const email = await decryptStoredPii(stored, "email", fallbackRequestId);
7
+ return email === PII_ERASED_SENTINEL ? null : email;
8
+ }
@@ -11,6 +11,8 @@ export type TerminationReceiptVariables = {
11
11
  readonly requestId: string;
12
12
  readonly details: readonly TextRow[];
13
13
  readonly operatorEmail: string;
14
+ /** Only a matched declaration carries the "this was not me" link. */
15
+ readonly revokeUrl?: string;
14
16
  };
15
17
  /** Variables of the operator notice template. */
16
18
  export type OperatorNoticeVariables = {
@@ -39,8 +41,10 @@ export type TerminationReceiptArgs = {
39
41
  readonly receivedAtIso: string;
40
42
  readonly declaration: ReceiptDeclaration;
41
43
  readonly operatorEmail: string;
44
+ readonly revokeUrl?: string;
42
45
  };
43
- /** The content must not depend on whether (or how) the declaration matched a contract. */
46
+ /** Apart from the revoke link, the content must not depend on whether the declaration
47
+ * matched a contract; the link only goes to the address the declarant entered. */
44
48
  export declare function terminationReceiptVariables(args: TerminationReceiptArgs): TerminationReceiptVariables;
45
49
  export type OperatorNoticeArgs = {
46
50
  readonly locale: ConsentLocale;
@@ -32,7 +32,8 @@ function declarationLines(declaration, locale) {
32
32
  ];
33
33
  return lines.map((text) => ({ text }));
34
34
  }
35
- /** The content must not depend on whether (or how) the declaration matched a contract. */
35
+ /** Apart from the revoke link, the content must not depend on whether the declaration
36
+ * matched a contract; the link only goes to the address the declarant entered. */
36
37
  export function terminationReceiptVariables(args) {
37
38
  const texts = TERMINATION_TEXTS[args.locale];
38
39
  return {
@@ -41,6 +42,7 @@ export function terminationReceiptVariables(args) {
41
42
  requestId: args.requestId,
42
43
  details: declarationLines(args.declaration, args.locale),
43
44
  operatorEmail: args.operatorEmail,
45
+ ...(args.revokeUrl !== undefined && { revokeUrl: args.revokeUrl }),
44
46
  };
45
47
  }
46
48
  export function operatorNoticeVariables(args) {
@@ -1,5 +1,5 @@
1
1
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
2
- import { CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE } from "../constants.js";
2
+ import { CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE } from "../web/constants.js";
3
3
  import { operatorNoticeVariables } from "./termination-mail.js";
4
4
  export function requireNotify(ctx) {
5
5
  if (!ctx.notify) {
@@ -4,11 +4,13 @@ import { getSessionCookies } from "@cosmicdrift/kumiko-framework/api";
4
4
  import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-renderer/headless";
5
5
  import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
6
6
  import { getCookie } from "hono/cookie";
7
+ import * as z from "zod";
7
8
  import { redirectToCanonicalPath, securePageHeaders, slashVariantOf, wrapInLayout, } from "../../page-render/index.js";
8
- import { SubscriptionFoundationHandlers } from "../constants.js";
9
9
  import { CONTRACT_TERMINATION_DECLARATION_TYPES, CONTRACT_TERMINATION_KINDS } from "../events.js";
10
+ import { SubscriptionFoundationHandlers } from "../web/constants.js";
10
11
  import { formatReceivedAt } from "./termination-mail.js";
11
12
  import { requestContractTerminationSchema } from "./termination-request.js";
13
+ import { REVOCATION_PATHS, revokeContractTerminationSchema, } from "./termination-revoke.js";
12
14
  import { TERMINATION_TEXTS } from "./termination-texts.js";
13
15
  const PAGE_SLUG = "contract-termination";
14
16
  const DEFAULT_PATHS = {
@@ -43,6 +45,8 @@ function pageHeaders() {
43
45
  ...headers,
44
46
  "content-security-policy": `${headers["content-security-policy"] ?? ""}; frame-ancestors 'none'; form-action 'self'`,
45
47
  "x-frame-options": "DENY",
48
+ // The revoke link carries its token in the query string.
49
+ "referrer-policy": "no-referrer",
46
50
  };
47
51
  }
48
52
  function htmlResponse(ctx, title, bodyHtml, status) {
@@ -205,7 +209,7 @@ function reentryHeaders(c) {
205
209
  }
206
210
  return headers;
207
211
  }
208
- async function submitDeclaration(c, app, clientIp, values, locale) {
212
+ async function dispatchAnonymousWrite(c, app, clientIp, type, payload) {
209
213
  // deps.write only resolves a session user under /api/*; this page lives
210
214
  // outside it, so it re-enters the dispatcher through the app like the
211
215
  // user-export by-token route. The resolved clientIp as env keeps the
@@ -215,25 +219,112 @@ async function submitDeclaration(c, app, clientIp, values, locale) {
215
219
  const response = await app.fetch(new Request(`${new URL(c.req.url).origin}/api/write`, {
216
220
  method: "POST",
217
221
  headers: reentryHeaders(c),
218
- body: JSON.stringify({
219
- type: SubscriptionFoundationHandlers.requestContractTermination,
220
- payload: payloadOf(values, locale),
221
- }),
222
+ body: JSON.stringify({ type, payload }),
222
223
  }), clientIp);
223
224
  const parsed = await response.json().catch(() => null);
224
- if (response.status === 429 || parsed?.error?.code === RATE_LIMITED_CODE) {
225
+ return {
226
+ rateLimited: response.status === 429 || parsed?.error?.code === RATE_LIMITED_CODE,
227
+ ok: response.ok && parsed?.isSuccess === true,
228
+ data: parsed?.data,
229
+ };
230
+ }
231
+ async function submitDeclaration(c, app, clientIp, values, locale) {
232
+ const response = await dispatchAnonymousWrite(c, app, clientIp, SubscriptionFoundationHandlers.requestContractTermination, payloadOf(values, locale));
233
+ if (response.rateLimited)
225
234
  return { kind: "rate-limited" };
226
- }
227
- const requestId = parsed?.data?.requestId;
228
- const receivedAtIso = parsed?.data?.receivedAtIso;
229
- if (response.ok &&
230
- parsed?.isSuccess === true &&
231
- typeof requestId === "string" &&
232
- typeof receivedAtIso === "string") {
235
+ const requestId = response.data?.requestId;
236
+ const receivedAtIso = response.data?.receivedAtIso;
237
+ if (response.ok && typeof requestId === "string" && typeof receivedAtIso === "string") {
233
238
  return { kind: "received", requestId, receivedAtIso };
234
239
  }
235
240
  return { kind: "failed" };
236
241
  }
242
+ const revocationOutcomeSchema = z.object({
243
+ outcome: z.enum(["revoked", "already-revoked", "too-late", "invalid"]),
244
+ });
245
+ // Missing or malformed link parameters answer like a wrong token.
246
+ function revocationValuesOf(source) {
247
+ const text = (key) => {
248
+ const value = source[key];
249
+ return typeof value === "string" ? value : "";
250
+ };
251
+ const parsed = revokeContractTerminationSchema.safeParse({
252
+ requestId: text("r"),
253
+ token: text("t"),
254
+ tenantId: text("tenant"),
255
+ });
256
+ return parsed.success ? parsed.data : null;
257
+ }
258
+ async function submitRevocation(c, app, clientIp, values) {
259
+ const response = await dispatchAnonymousWrite(c, app, clientIp, SubscriptionFoundationHandlers.revokeContractTermination, values);
260
+ if (response.rateLimited)
261
+ return "rate-limited";
262
+ const outcome = revocationOutcomeSchema.safeParse(response.data);
263
+ return response.ok && outcome.success ? outcome.data.outcome : "invalid";
264
+ }
265
+ function revokeConfirmPage(ctx, revokePath, values) {
266
+ const { revoke } = TERMINATION_TEXTS[ctx.locale].page;
267
+ const hidden = [
268
+ ["r", values.requestId],
269
+ ["t", values.token],
270
+ ["tenant", values.tenantId],
271
+ ]
272
+ .map(([name, value]) => `<input type="hidden" name="${escapeHtmlAttr(name)}" value="${escapeHtmlAttr(value ?? "")}">`)
273
+ .join("\n");
274
+ const body = `<h1>${escapeHtml(revoke.confirmTitle)}</h1>
275
+ <p>${escapeHtml(revoke.confirmLead)}</p>
276
+ <form method="post" action="${escapeHtmlAttr(revokePath)}" data-kumiko-form="contract-termination-revoke">
277
+ ${hidden}
278
+ <button type="submit" data-kumiko-button="revoke">${escapeHtml(revoke.confirmButton)}</button>
279
+ </form>`;
280
+ return htmlResponse(ctx, revoke.confirmTitle, body, 200);
281
+ }
282
+ function revokeResultPage(ctx, outcome) {
283
+ const { page } = TERMINATION_TEXTS[ctx.locale];
284
+ const { revoke } = page;
285
+ const simple = (title, text, status) => htmlResponse(ctx, title, `<h1>${escapeHtml(title)}</h1><p>${escapeHtml(text)}</p>`, status);
286
+ switch (outcome) {
287
+ case "revoked":
288
+ return simple(revoke.revokedTitle, revoke.revokedBody, 200);
289
+ case "already-revoked":
290
+ return simple(revoke.alreadyRevokedTitle, revoke.alreadyRevokedBody, 200);
291
+ case "too-late":
292
+ return simple(revoke.tooLateTitle, revoke.tooLateBody, 200);
293
+ case "rate-limited":
294
+ return simple(page.rateLimitedTitle, page.rateLimitedBody, 429);
295
+ case "invalid":
296
+ return simple(revoke.invalidTitle, revoke.invalidBody, 400);
297
+ }
298
+ }
299
+ // GET only renders the confirmation form: mail scanners prefetch links, so the
300
+ // state change waits for the POST.
301
+ function revokeRoutesFor(ctx) {
302
+ const revokePath = REVOCATION_PATHS[ctx.locale];
303
+ return [
304
+ {
305
+ method: "GET",
306
+ path: revokePath,
307
+ entry: "anonymous",
308
+ handler: (c) => {
309
+ const values = revocationValuesOf(c.req.query());
310
+ return values === null
311
+ ? revokeResultPage(ctx, "invalid")
312
+ : revokeConfirmPage(ctx, revokePath, values);
313
+ },
314
+ },
315
+ {
316
+ method: "POST",
317
+ path: revokePath,
318
+ entry: "anonymous",
319
+ handler: async (c, deps) => {
320
+ const values = revocationValuesOf(await c.req.parseBody());
321
+ if (values === null)
322
+ return revokeResultPage(ctx, "invalid");
323
+ return revokeResultPage(ctx, await submitRevocation(c, deps.app, deps.clientIp, values));
324
+ },
325
+ },
326
+ ];
327
+ }
237
328
  function routesFor(ctx) {
238
329
  const { locale, path } = ctx;
239
330
  const slashVariant = slashVariantOf(path);
@@ -290,5 +381,8 @@ export function createContractTerminationRoutes(options = {}) {
290
381
  en: options.paths?.en ?? DEFAULT_PATHS.en,
291
382
  };
292
383
  const wrapLayout = options.wrapLayout ?? wrapInLayout;
293
- return ["de", "en"].flatMap((locale) => routesFor({ locale, path: alternates[locale], wrapLayout, alternates }));
384
+ return ["de", "en"].flatMap((locale) => {
385
+ const pageContext = { locale, path: alternates[locale], wrapLayout, alternates };
386
+ return [...routesFor(pageContext), ...revokeRoutesFor(pageContext)];
387
+ });
294
388
  }
@@ -1,6 +1,7 @@
1
- import { type QueryHandlerDef, type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
1
+ import { type HandlerContext, type QueryHandlerDef, type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import * as z from "zod";
3
3
  import { type ProviderCancelOutcome } from "../events.ts";
4
+ import { type SubscriptionView } from "../get-subscription-for-tenant.ts";
4
5
  import type { ConsumerProtectionOptions, ResolvedBillingFoundationOptions } from "../types.ts";
5
6
  import type { OperatorNoticeReason } from "./termination-texts.ts";
6
7
  export declare const recordContractTerminationSchema: z.ZodObject<{
@@ -43,6 +44,7 @@ export declare const declareContractTerminationSchema: z.ZodObject<{
43
44
  de: "de";
44
45
  en: "en";
45
46
  }>;
47
+ revocationTokenHash: z.ZodOptional<z.ZodString>;
46
48
  }, z.core.$strict>;
47
49
  export type RecordContractTerminationResult = {
48
50
  readonly receivedAtIso: string;
@@ -72,4 +74,9 @@ export declare const terminableSubscriptionSchema: z.ZodObject<{}, z.core.$stric
72
74
  export declare function createTerminableSubscriptionQuery(): QueryHandlerDef;
73
75
  export declare function createDeclareContractTerminationHandler(): WriteHandlerDef;
74
76
  export declare function createRecordContractTerminationHandler(options: ResolvedBillingFoundationOptions, consumerProtection: ConsumerProtectionOptions): WriteHandlerDef;
77
+ export declare function hasRevocation(events: readonly {
78
+ type: string;
79
+ payload: unknown;
80
+ }[], requestId: string): boolean;
81
+ export declare function resumeAtProvider(ctx: HandlerContext, subscription: SubscriptionView | null): Promise<OperatorNoticeReason[]>;
75
82
  export declare function createRecordUnmatchedContractTerminationHandler(): WriteHandlerDef;