@cosmicdrift/kumiko-bundled-features 0.385.0 → 0.387.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 (470) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/agent-tools/tool-dispatch.js +0 -2
  4. package/dist/audit/screens.js +1 -1
  5. package/dist/auth-email-password/feature.js +1 -1
  6. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  7. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  8. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  9. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  10. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  11. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  12. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  13. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  14. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  15. package/dist/auth-email-password/handlers/login.write.js +1 -1
  16. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  17. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  18. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  19. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  20. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  21. package/dist/auth-email-password/index.js +5 -5
  22. package/dist/auth-email-password/lockout-store.js +1 -1
  23. package/dist/auth-email-password/seeding.d.ts +42 -45
  24. package/dist/auth-email-password/seeding.js +51 -53
  25. package/dist/auth-email-password/signup-token-store.js +8 -8
  26. package/dist/auth-email-password/testing.js +3 -3
  27. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  28. package/dist/auth-email-password/web/auth-client.js +36 -37
  29. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  30. package/dist/auth-email-password/web/auth-gate.js +15 -16
  31. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  32. package/dist/auth-email-password/web/client-plugin.js +4 -5
  33. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  34. package/dist/auth-email-password/web/constants.js +3 -3
  35. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  36. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  37. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  38. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  39. package/dist/auth-email-password/web/index.js +5 -5
  40. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  41. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  42. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  43. package/dist/auth-email-password/web/login-screen.js +2 -3
  44. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  45. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  46. package/dist/auth-email-password/web/session.d.ts +10 -9
  47. package/dist/auth-email-password/web/session.js +28 -29
  48. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  49. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  50. package/dist/auth-email-password/web/signup-screen.js +13 -13
  51. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  52. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  53. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  54. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  55. package/dist/auth-email-password/web/user-menu.js +12 -13
  56. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  57. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  58. package/dist/auth-foundation/boot-checks.js +4 -4
  59. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  60. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  61. package/dist/auth-foundation/types.js +2 -2
  62. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  63. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  64. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  65. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  66. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  67. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  68. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  69. package/dist/auth-mfa/token-secrets.js +1 -1
  70. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  71. package/dist/auth-mfa/web/client-plugin.js +1 -1
  72. package/dist/auth-mfa/web/i18n.js +3 -3
  73. package/dist/auth-mfa/web/index.js +4 -4
  74. package/dist/auth-mfa/web/mfa-client.js +17 -16
  75. package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
  76. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  77. package/dist/billing-foundation/aggregate-id.js +10 -11
  78. package/dist/billing-foundation/entities.js +27 -27
  79. package/dist/billing-foundation/events.js +18 -17
  80. package/dist/billing-foundation/feature.js +42 -43
  81. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  82. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  83. package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
  84. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  85. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  86. package/dist/billing-foundation/handlers/process-event.write.js +20 -20
  87. package/dist/billing-foundation/projection.d.ts +15 -11
  88. package/dist/billing-foundation/projection.js +38 -37
  89. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  90. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  91. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  92. package/dist/billing-foundation/types.d.ts +40 -41
  93. package/dist/billing-foundation/types.js +20 -20
  94. package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
  95. package/dist/cap-counter/aggregate-id.js +8 -9
  96. package/dist/cap-counter/constants.js +11 -12
  97. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  98. package/dist/cap-counter/enforce-cap.js +47 -48
  99. package/dist/cap-counter/entity.js +29 -29
  100. package/dist/cap-counter/feature.js +34 -35
  101. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  102. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  103. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  104. package/dist/cap-counter/stock-cap-guard.js +1 -1
  105. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  106. package/dist/channel-email/smtp-transport.d.ts +18 -17
  107. package/dist/channel-email/smtp-transport.js +24 -21
  108. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  109. package/dist/compliance-profiles/feature.js +4 -4
  110. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  111. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  112. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  113. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  114. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  115. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  116. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  117. package/dist/compliance-profiles/seeding.js +14 -15
  118. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  119. package/dist/compliance-profiles-ops/index.js +2 -2
  120. package/dist/config/handlers/readiness.query.d.ts +4 -4
  121. package/dist/config/handlers/readiness.query.js +1 -1
  122. package/dist/config/handlers/reencrypt.job.js +4 -5
  123. package/dist/config/handlers/set.write.js +4 -4
  124. package/dist/config/resolver.js +4 -4
  125. package/dist/config/table.js +10 -10
  126. package/dist/config/write-helpers.js +1 -1
  127. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  128. package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
  129. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  130. package/dist/custom-fields/aggregate-id.js +16 -17
  131. package/dist/custom-fields/entity.js +49 -47
  132. package/dist/custom-fields/events.js +7 -8
  133. package/dist/custom-fields/feature.d.ts +14 -14
  134. package/dist/custom-fields/feature.js +53 -54
  135. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  136. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  137. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  138. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  139. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  140. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  141. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  142. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  143. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  144. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  145. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  146. package/dist/custom-fields/lib/field-access.js +2 -2
  147. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  148. package/dist/custom-fields/lib/quota.js +1 -1
  149. package/dist/custom-fields/lib/value-schema.js +10 -12
  150. package/dist/custom-fields/run-retention.js +3 -3
  151. package/dist/custom-fields/schemas.js +14 -14
  152. package/dist/custom-fields/web/client-plugin.js +2 -5
  153. package/dist/custom-fields/web/constants.js +2 -2
  154. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  155. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  156. package/dist/custom-fields/wire-for-entity.js +65 -67
  157. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  158. package/dist/data-retention/_internal/parse-override.js +2 -3
  159. package/dist/data-retention/feature.js +11 -18
  160. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  161. package/dist/data-retention/keep-for.d.ts +7 -7
  162. package/dist/data-retention/keep-for.js +15 -15
  163. package/dist/data-retention/override-schema.d.ts +3 -4
  164. package/dist/data-retention/override-schema.js +13 -15
  165. package/dist/data-retention/presets.d.ts +4 -5
  166. package/dist/data-retention/presets.js +18 -23
  167. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  168. package/dist/data-retention/resolver.d.ts +12 -12
  169. package/dist/data-retention/resolver.js +24 -23
  170. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  171. package/dist/data-retention/run-retention-cleanup.js +61 -51
  172. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  173. package/dist/delivery/feature.js +2 -2
  174. package/dist/delivery/handlers/log.query.js +1 -1
  175. package/dist/delivery/tables.js +9 -8
  176. package/dist/delivery/unsubscribe.js +4 -4
  177. package/dist/document-ingest-foundation/entity.js +4 -4
  178. package/dist/document-ingest-foundation/events.js +2 -2
  179. package/dist/document-ingest-foundation/feature.js +2 -2
  180. package/dist/document-ingest-foundation/pages.js +1 -1
  181. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  182. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  183. package/dist/feature-toggles/feature.js +1 -1
  184. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  185. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  186. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  187. package/dist/feature-toggles/web/constants.js +1 -1
  188. package/dist/file-derivatives/feature.d.ts +1 -1
  189. package/dist/file-derivatives/feature.js +1 -1
  190. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  191. package/dist/file-derivatives/presets.js +1 -1
  192. package/dist/file-foundation/feature.js +6 -6
  193. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  194. package/dist/file-provider-inmemory/feature.js +16 -16
  195. package/dist/file-provider-s3/feature.js +16 -16
  196. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  197. package/dist/files/feature.js +6 -6
  198. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  199. package/dist/files-tenant-data/hooks.js +24 -26
  200. package/dist/files-tenant-data/index.js +1 -1
  201. package/dist/folders/feature.d.ts +1 -1
  202. package/dist/folders/web/folder-manager.js +2 -2
  203. package/dist/folders/web/tree.js +5 -5
  204. package/dist/form-draft/db/queries/cleanup.js +1 -1
  205. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  206. package/dist/form-draft/entity.js +3 -3
  207. package/dist/form-draft/feature.js +4 -5
  208. package/dist/form-draft/handlers/discard.write.js +1 -1
  209. package/dist/form-draft/release-file-refs.js +6 -6
  210. package/dist/form-draft/schemas.js +3 -3
  211. package/dist/form-draft/web/constants.js +0 -2
  212. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  213. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  214. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  215. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  216. package/dist/inbound-mail-foundation/constants.js +30 -33
  217. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  218. package/dist/inbound-mail-foundation/entities.js +47 -48
  219. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  220. package/dist/inbound-mail-foundation/events.js +50 -47
  221. package/dist/inbound-mail-foundation/feature.js +39 -39
  222. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  223. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  224. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  225. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  226. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  227. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  228. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  229. package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
  230. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  231. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  232. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  233. package/dist/inbound-mail-foundation/projection.js +31 -29
  234. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  235. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  236. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  237. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  238. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  239. package/dist/inbound-mail-foundation/types.d.ts +45 -46
  240. package/dist/inbound-mail-foundation/types.js +21 -21
  241. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  242. package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
  243. package/dist/inbound-provider-imap/credential-document.js +13 -13
  244. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  245. package/dist/inbound-provider-imap/feature.js +42 -40
  246. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  247. package/dist/inbound-provider-imap/imap-client.js +20 -19
  248. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  249. package/dist/inbound-provider-inmemory/feature.js +19 -19
  250. package/dist/jobs/db/queries/retention.js +2 -2
  251. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  252. package/dist/jobs/events.js +1 -1
  253. package/dist/jobs/feature.js +5 -6
  254. package/dist/jobs/handlers/detail.query.js +4 -4
  255. package/dist/jobs/handlers/list.query.js +1 -1
  256. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  257. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  258. package/dist/jobs/handlers/retry.write.js +1 -1
  259. package/dist/jobs/job-instant.js +1 -1
  260. package/dist/jobs/job-run-logger.js +10 -11
  261. package/dist/jobs/job-run-table.js +3 -3
  262. package/dist/jobs/screens.js +1 -1
  263. package/dist/jobs/tenant-job-failure-table.js +1 -1
  264. package/dist/jobs/tenant-job-run-table.js +1 -1
  265. package/dist/ledger/entity.js +5 -5
  266. package/dist/ledger/feature.js +3 -3
  267. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  268. package/dist/ledger/recurring.js +12 -12
  269. package/dist/ledger/schemas.js +1 -1
  270. package/dist/ledger/web/constants.js +2 -2
  271. package/dist/ledger/web/index.js +7 -7
  272. package/dist/legal-pages/feature.d.ts +4 -4
  273. package/dist/legal-pages/feature.js +25 -26
  274. package/dist/legal-pages/markdown.js +3 -3
  275. package/dist/legal-pages/web/client-plugin.js +23 -24
  276. package/dist/legal-pages/web/index.js +0 -1
  277. package/dist/mail-foundation/feature.d.ts +2 -2
  278. package/dist/mail-foundation/feature.js +24 -25
  279. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  280. package/dist/mail-transport-inmemory/feature.js +27 -28
  281. package/dist/mail-transport-smtp/feature.js +20 -20
  282. package/dist/managed-pages/branding.js +6 -6
  283. package/dist/managed-pages/feature.d.ts +26 -26
  284. package/dist/managed-pages/feature.js +34 -34
  285. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  286. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  287. package/dist/managed-pages/handlers/set.write.js +5 -7
  288. package/dist/managed-pages/screens/page-screens.js +11 -11
  289. package/dist/managed-pages/seeding.js +8 -8
  290. package/dist/managed-pages/table.js +13 -12
  291. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  292. package/dist/managed-pages/web/client-plugin.js +5 -5
  293. package/dist/managed-pages/web/i18n.js +1 -1
  294. package/dist/notes-history/entity.js +4 -4
  295. package/dist/notes-history/feature.d.ts +2 -2
  296. package/dist/notes-history-user-data/hooks.js +1 -1
  297. package/dist/page-render/layout.js +9 -9
  298. package/dist/page-render/markdown.js +11 -11
  299. package/dist/page-render/security-headers.js +7 -6
  300. package/dist/personal-access-tokens/feature.js +5 -5
  301. package/dist/personal-access-tokens/roles.js +2 -2
  302. package/dist/readiness/handlers/status.query.js +3 -3
  303. package/dist/renderer-foundation/api.js +12 -13
  304. package/dist/renderer-foundation/constants.js +2 -2
  305. package/dist/renderer-foundation/feature.js +7 -7
  306. package/dist/secrets/feature.js +9 -9
  307. package/dist/secrets/web/constants.js +2 -2
  308. package/dist/seo/feature.js +3 -3
  309. package/dist/sessions/constants.d.ts +1 -1
  310. package/dist/sessions/constants.js +1 -1
  311. package/dist/sessions/feature.js +8 -8
  312. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  313. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  314. package/dist/sessions/handlers/revoke.write.js +1 -1
  315. package/dist/sessions/schema/user-session.js +4 -4
  316. package/dist/sessions/screens.js +2 -2
  317. package/dist/sessions/session-callbacks.js +2 -2
  318. package/dist/sessions/session-revoked-event.js +2 -2
  319. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  320. package/dist/shared/decrypt-stored-pii.js +1 -1
  321. package/dist/shared/encrypt-for-direct-write.js +1 -1
  322. package/dist/shared/map-with-concurrency.js +5 -4
  323. package/dist/shared/parent-visibility.js +2 -2
  324. package/dist/shared/password-hashing.js +1 -1
  325. package/dist/shared/signup-handover.js +1 -2
  326. package/dist/shared/single-use-token-store.js +1 -1
  327. package/dist/subscription-mollie/constants.js +15 -17
  328. package/dist/subscription-mollie/feature.d.ts +17 -18
  329. package/dist/subscription-mollie/feature.js +24 -24
  330. package/dist/subscription-mollie/index.js +3 -3
  331. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  332. package/dist/subscription-mollie/plugin-methods.js +15 -14
  333. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  334. package/dist/subscription-mollie/verify-webhook.js +27 -27
  335. package/dist/subscription-stripe/constants.js +4 -6
  336. package/dist/subscription-stripe/feature.d.ts +14 -14
  337. package/dist/subscription-stripe/feature.js +35 -34
  338. package/dist/subscription-stripe/index.js +6 -6
  339. package/dist/subscription-stripe/plugin-methods.js +18 -18
  340. package/dist/subscription-stripe/runtime.d.ts +1 -1
  341. package/dist/subscription-stripe/runtime.js +1 -1
  342. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  343. package/dist/subscription-stripe/verify-webhook.js +59 -61
  344. package/dist/tags/feature.d.ts +3 -3
  345. package/dist/tags/screens.js +1 -1
  346. package/dist/template-resolver/api.js +10 -10
  347. package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
  348. package/dist/template-resolver/handlers/list.query.js +1 -1
  349. package/dist/template-resolver/handlers/shared.js +2 -2
  350. package/dist/template-resolver/handlers/template-write.js +3 -3
  351. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  352. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  353. package/dist/template-resolver/seeding.js +4 -4
  354. package/dist/template-resolver/table.js +10 -11
  355. package/dist/template-resolver/web/client-plugin.js +2 -2
  356. package/dist/tenant/feature.js +7 -7
  357. package/dist/tenant/handlers/member-directory.query.js +1 -1
  358. package/dist/tenant/handlers/members.query.js +1 -1
  359. package/dist/tenant/handlers/team-list.query.js +1 -1
  360. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  361. package/dist/tenant/invitation-table.js +37 -40
  362. package/dist/tenant/membership-table.js +3 -3
  363. package/dist/tenant/schema/tenant.js +7 -9
  364. package/dist/tenant/screens.js +1 -1
  365. package/dist/tenant/seeding.d.ts +6 -5
  366. package/dist/tenant/seeding.js +12 -12
  367. package/dist/tenant/testing.js +5 -6
  368. package/dist/tenant/web/constants.js +2 -2
  369. package/dist/tenant-handover/events.js +5 -7
  370. package/dist/tenant-handover/feature.js +1 -1
  371. package/dist/tenant-handover/grant.js +1 -1
  372. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  373. package/dist/tenant-handover/move-entity-graph.js +8 -9
  374. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  375. package/dist/tenant-handover/transfer-graph.js +4 -5
  376. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  377. package/dist/tenant-lifecycle/feature.js +1 -1
  378. package/dist/tenant-settings/constants.js +1 -1
  379. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  380. package/dist/tenant-settings/tenant-defaults.js +9 -2
  381. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  382. package/dist/tier-engine/aggregate-id.js +15 -16
  383. package/dist/tier-engine/compose-app.d.ts +14 -14
  384. package/dist/tier-engine/compose-app.js +1 -1
  385. package/dist/tier-engine/entity.js +18 -19
  386. package/dist/tier-engine/feature.d.ts +19 -17
  387. package/dist/tier-engine/feature.js +68 -69
  388. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  389. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  390. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
  391. package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
  392. package/dist/tier-engine/tier-resolver.js +2 -2
  393. package/dist/tier-engine/trial.js +8 -8
  394. package/dist/tier-engine/web/index.js +4 -4
  395. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  396. package/dist/user/handlers/create.write.js +4 -4
  397. package/dist/user/schema/user.d.ts +11 -11
  398. package/dist/user/schema/user.js +45 -44
  399. package/dist/user/seeding.d.ts +15 -15
  400. package/dist/user/seeding.js +28 -28
  401. package/dist/user/testing.js +3 -3
  402. package/dist/user-data-rights/audit-download.d.ts +8 -8
  403. package/dist/user-data-rights/audit-download.js +19 -20
  404. package/dist/user-data-rights/boot-checks.js +1 -1
  405. package/dist/user-data-rights/deletion-token.js +1 -1
  406. package/dist/user-data-rights/feature.d.ts +49 -50
  407. package/dist/user-data-rights/feature.js +54 -53
  408. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  409. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  410. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  411. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  412. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  413. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  414. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  415. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  416. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  417. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  418. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  419. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  420. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  421. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  422. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  423. package/dist/user-data-rights/index.js +8 -10
  424. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  425. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  426. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  427. package/dist/user-data-rights/run-export-jobs.js +127 -233
  428. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  429. package/dist/user-data-rights/run-forget-cleanup.js +63 -82
  430. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  431. package/dist/user-data-rights/run-user-export.js +55 -57
  432. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  433. package/dist/user-data-rights/schema/download-token.js +37 -41
  434. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  435. package/dist/user-data-rights/schema/export-job.js +65 -67
  436. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  437. package/dist/user-data-rights/token-helpers.js +21 -25
  438. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  439. package/dist/user-data-rights/web/client-plugin.js +1 -1
  440. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  441. package/dist/user-data-rights/web/constants.js +1 -1
  442. package/dist/user-data-rights/web/index.js +5 -5
  443. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  444. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  445. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  446. package/dist/user-data-rights/zip-path.d.ts +15 -15
  447. package/dist/user-data-rights/zip-path.js +41 -40
  448. package/dist/user-data-rights-defaults/feature.js +15 -15
  449. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  450. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  451. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  452. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  453. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  454. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  455. package/dist/user-profile/handlers/change-email.write.js +13 -13
  456. package/dist/user-profile/index.js +3 -3
  457. package/dist/user-profile/web/client-plugin.js +1 -1
  458. package/dist/user-profile/web/constants.js +1 -1
  459. package/dist/user-profile/web/profile-screen.js +1 -1
  460. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  461. package/dist/workflow-runner/aggregate-id.js +1 -1
  462. package/dist/workflow-runner/event-subscriber.js +4 -5
  463. package/dist/workflow-runner/event-trigger.js +4 -17
  464. package/dist/workflow-runner/feature.js +2 -2
  465. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  466. package/dist/workflow-runner/pending-projection.js +6 -7
  467. package/dist/workflow-runner/runner.js +6 -6
  468. package/dist/workflow-runner/tables.js +6 -6
  469. package/dist/workflow-runner/workflow-registry.js +1 -1
  470. package/package.json +10 -10
@@ -1,35 +1,36 @@
1
1
  // kumiko-feature-version: 3
2
2
  //
3
- // subscription-stripe — Stripe-Plugin für die billing-foundation
4
- // Plugin-API.
3
+ // subscription-stripe — Stripe plugin for the billing-foundation
4
+ // plugin API.
5
5
  //
6
- // **Runtime-config (v3):** Stripe-credentials + der billing-live-Master-
7
- // Switch kommen ZUR LAUFZEIT aus dem config-Feature, nicht mehr aus einem
8
- // mount-time-Closure. Damit lassen sich Keys rotieren und prod live-
9
- // schalten ohne Redeploy — und die Eingabe-Maske entsteht von selbst.
6
+ // **Runtime config (v3):** Stripe credentials and the billing-live master
7
+ // switch come from the config feature AT RUNTIME, no longer from a
8
+ // mount-time closure. This allows keys to rotate and production to go live
9
+ // without a redeploy — and the input form is generated automatically.
10
10
  // - `subscription-stripe:config:api-key` + `:webhook-secret` → system
11
- // config keys mit **backing:"secrets"**: der Wert lebt envelope-
12
- // verschlüsselt im secrets-Store unter SYSTEM_TENANT_ID, adressiert
13
- // wird er als config-Key. `mask` leitet den Sysadmin-configEdit-Screen
14
- // + Settings-Hub-Nav ab — kein handgeschriebenes r.screen/r.nav in der
15
- // App mehr (v2 hatte die Keys als `r.secret` + App-eigene Maske).
11
+ // config keys with **backing:"secrets"**: the value is envelope-encrypted
12
+ // in the secrets store under SYSTEM_TENANT_ID and addressed as a
13
+ // config key. `mask` derives the sysadmin configEdit screen +
14
+ // Settings-Hub navigation — the app no longer needs handwritten
15
+ // r.screen/r.nav entries (v2 used `r.secret` keys + an app-owned form).
16
16
  // - `subscription-stripe:config:billing-live` (shortKey `billingLive`,
17
- // kebab-qualifiziert von r.config) → **system config**
18
- // (boolean, default false). Der Master-Switch: ohne ihn darf kein
19
- // checkout eine Stripe-Session erzeugen (#104-Invariante, write-side
20
- // im createCheckoutSession-Gate durchgesetzt).
17
+ // kebab-qualified by r.config) → **system config**
18
+ // (boolean, default false). The master switch: without it, checkout may
19
+ // not create a Stripe session; this is enforced in the
20
+ // createCheckoutSession gate.
21
21
  //
22
- // **Factory-options als Fallback:** `createSubscriptionStripeFeature({
23
- // apiKey, webhookSecret, priceToTier })` bleibt — apiKey/webhookSecret
24
- // sind jetzt OPTIONAL und dienen nur als Fallback während der env→secrets-
25
- // Bridge-Phase und in Tests, die keinen secrets-context wiren. `priceToTier`
26
- // (Stripe-price-id → app-tier-name) bleibt eine factory-option: app-
27
- // spezifisch, kein Secret, ändert sich selten.
22
+ // **Factory options as fallback:** `createSubscriptionStripeFeature({
23
+ // apiKey, webhookSecret, priceToTier })` remains — apiKey/webhookSecret
24
+ // are now OPTIONAL and serve only as fallbacks during the env→secrets
25
+ // bridge phase and in tests that do not wire a secrets context. `priceToTier`
26
+ // (Stripe price ID → app tier name) remains a factory option: it is
27
+ // app-specific, is not a secret, and changes infrequently.
28
28
  //
29
- // **Webhook + system-secrets:** verifyAndParseWebhook ist pre-tenant
30
- // (kein ctx). Der billing-foundation-webhook-handler reicht einen system-
31
- // scoped SecretsContext als 3. Arg durch, aus dem der Plugin api-key +
32
- // webhook-secret un-audited liest (sanctioned framework-internal read).
29
+ // **Webhook + system secrets:** verifyAndParseWebhook is pre-tenant
30
+ // (no ctx). The billing-foundation webhook handler passes a system-scoped
31
+ // SecretsContext as the third argument, from which the plugin reads the
32
+ // api key + webhook secret without auditing (a sanctioned framework-internal
33
+ // read).
33
34
  import { access, createSystemConfig, defineFeature, } from "@cosmicdrift/kumiko-framework/engine";
34
35
  import { featureWithEnvSchema } from "@cosmicdrift/kumiko-framework/env";
35
36
  import * as z from "zod";
@@ -92,11 +93,11 @@ function validateOneOffPriceIds(priceIds) {
92
93
  }
93
94
  }
94
95
  /**
95
- * Factory für das subscription-stripe-feature. Mountet IMMER (kein
96
- * key-presence-Guard mehr) — die Aktivität wird runtime über config/secrets
97
- * gegatet (Muster wie feature-toggles). Der returnte FeatureDefinition
98
- * registriert den Plugin gegen billing-foundation's "subscriptionProvider"-
99
- * extension unter entityName "stripe".
96
+ * Factory for the subscription-stripe feature. Always mounts (no
97
+ * key-presence guard) — activity is gated at runtime through config/secrets
98
+ * (following the feature-toggles pattern). The returned FeatureDefinition
99
+ * registers the plugin under billing-foundation's "subscriptionProvider"
100
+ * extension with entityName "stripe".
100
101
  */
101
102
  export function createSubscriptionStripeFeature(options = {}) {
102
103
  validateOneOffPriceIds(options.oneOffPriceIds ?? []);
@@ -118,15 +119,15 @@ export function createSubscriptionStripeFeature(options = {}) {
118
119
  // the value lives envelope-encrypted in the secrets store under
119
120
  // SYSTEM_TENANT_ID, while `mask` derives the sysadmin settings screen +
120
121
  // Settings-Hub nav (no hand-written r.screen/r.nav in the consuming app).
121
- // billingLive is the #104 master switch. The factory-fallback
122
+ // billingLive is the master switch. The factory-fallback
122
123
  // (options.apiKey/.webhookSecret) covers the env→secrets bridge + tests.
123
124
  const configKeys = r.config({
124
125
  keys: {
125
126
  [STRIPE_API_KEY_CONFIG]: createSystemConfig("text", {
126
127
  backing: "secrets",
127
- // Prefix-Guard, deckungsgleich mit subscriptionStripeEnvSchema:
128
- // fängt den Paste-the-wrong-field-Fehler (pk_/price_), ohne den
129
- // base62-Body zu constrainen. Anchored, kein Backtracking → kein ReDoS.
128
+ // Prefix guard, matching subscriptionStripeEnvSchema:
129
+ // catches the wrong-field paste error (pk_/price_) without
130
+ // constraining the base62 body. Anchored, with no backtracking → no ReDoS.
130
131
  pattern: { regex: "^(sk|rk)_(test|live)_" },
131
132
  write: access.systemAdmin,
132
133
  read: access.admin,
@@ -1,9 +1,9 @@
1
- // Public API of the subscription-stripe bundled-feature.
1
+ // Public API of the subscription-stripe bundled feature.
2
2
  //
3
- // **Internal-only** (NICHT im public-barrel — App-Builder nutzt das nie direkt):
4
- // - StripeWebhookOptions / verifyAndParseStripeWebhook (intern vom
5
- // feature.ts factory aufgerufen)
6
- // - mapStripeEventType / mapStripeStatus (pure helpers, test-only;
7
- // direct-import aus dem File wenn echt mal extern gebraucht)
3
+ // **Internal-only** (not in the public barrel — the App Builder never uses it directly):
4
+ // - StripeWebhookOptions / verifyAndParseStripeWebhook (called internally by the
5
+ // feature.ts factory)
6
+ // - mapStripeEventType / mapStripeStatus (pure helpers, for tests only;
7
+ // import directly from the file only if truly needed externally)
8
8
  export { STRIPE_PROVIDER_NAME, StripeEventTypes, SUBSCRIPTION_STRIPE_FEATURE, } from "./constants.js";
9
9
  export { createSubscriptionStripeFeature, stripeEnvSchema, subscriptionStripeEnvSchema, } from "./feature.js";
@@ -1,19 +1,19 @@
1
- // Stripe-Plugin-Methoden für die POST-tenant-resolution-Phase:
1
+ // Stripe plugin methods for the POST-tenant-resolution phase:
2
2
  // createCheckoutSession, createPortalSession, cancelSubscription,
3
- // retrieveSubscription, retrievePrices, planSwitchSession.
3
+ // retrieveSubscription, retrievePrices, and planSwitchSession.
4
4
  //
5
- // Werden vom Plugin-build (feature.ts) als methods auf dem
6
- // SubscriptionProviderPlugin registriert. Anders als
7
- // verifyAndParseWebhook (= pre-tenant) bekommen diese den vollen
8
- // HandlerContext — sie lösen den Stripe-Client zur CALL-Zeit aus dem
9
- // runtime auf (api-key aus system-secrets, audited), statt aus einem
10
- // mount-time-Closure. Key-Rotation wirkt damit ohne Redeploy.
5
+ // The plugin build (`feature.ts`) registers these as methods on
6
+ // `SubscriptionProviderPlugin`. Unlike verifyAndParseWebhook (= pre-tenant),
7
+ // they receive the full HandlerContext and resolve the Stripe client from
8
+ // the runtime at call time (using the audited api-key from system-secrets),
9
+ // rather than from a mount-time closure. Key rotation therefore works
10
+ // without a redeploy.
11
11
  //
12
- // **Type-Ableitung:** die options-shapes der methods werden
13
- // **direkt vom Plugin-Contract** abgeleitet (`Parameters<NonNullable
14
- // <SubscriptionProviderPlugin["...method"]>>[1]`). Wenn Foundation den
15
- // Contract erweitert (z.B. neuer optionaler Field), bemerkt der
16
- // Stripe-Plugin das beim TS-Compile, nicht erst zur Laufzeit.
12
+ // **Type derivation:** method option shapes are derived **directly from the
13
+ // plugin contract** (`Parameters<NonNullable
14
+ // <SubscriptionProviderPlugin["...method"]>>[1]`). If Foundation extends the
15
+ // contract (for example, with a new optional field), the Stripe plugin detects
16
+ // it at TypeScript compile time rather than at runtime.
17
17
  import { createHash } from "node:crypto";
18
18
  import { KNOWN_RECURRING_INTERVALS, SubscriptionCancelTimings, } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
19
19
  import { ConflictError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
@@ -79,11 +79,11 @@ function isUnknownCustomerStripeError(error) {
79
79
  }
80
80
  export function createStripeCheckoutSession(runtime, { paymentInvoiceCreation = true } = {}) {
81
81
  return async (ctx, options) => {
82
- // #104-Invariante: ohne billing-live darf keine Stripe-Session
83
- // entstehen (sk_test_-Keys in prod erzeugen sonst einen Test-Mode-
84
- // Checkout). Throw VOR jedem Stripe-Call. Früher hielt diese Schranke
85
- // das ungemountete Plugin; jetzt mountet stripe immer, also gatet der
86
- // billing-live-config-key write-side.
82
+ // Invariant: without billing-live, no Stripe session may be created
83
+ // (sk_test_-keys in production would otherwise create a test-mode checkout).
84
+ // Throw before every Stripe call. The guard used to be provided by the
85
+ // unmounted plugin; Stripe is now always mounted, so the
86
+ // billing-live-config-key gates the write side.
87
87
  await runtime.assertBillingLive(ctx);
88
88
  const stripe = await runtime.clientForCtx(ctx);
89
89
  const mode = options.mode ?? "subscription";
@@ -19,7 +19,7 @@ export type StripeRuntimeDeps = {
19
19
  export type StripeCtxRuntime = {
20
20
  readonly clientForCtx: (ctx: HandlerContext) => Promise<Stripe>;
21
21
  /** Throws FeatureDisabledError unless `billing-live` config is true. The
22
- * #104 invariant: no Stripe session may be created while billing is not
22
+ * invariant: no Stripe session may be created while billing is not
23
23
  * live (sk_test_ keys in prod must not produce a live checkout).
24
24
  * `handlerName` names the write-handler in the thrown error — defaults to
25
25
  * "create-checkout-session" for existing callers, but plan-switch/portal
@@ -41,7 +41,7 @@ export function createStripeClientCache() {
41
41
  if (cached)
42
42
  return cached;
43
43
  // No apiVersion pin — a string literal breaks consumers' typecheck on newer
44
- // stripe SDKs (#256); the SDK's own default keeps wire-version and types aligned.
44
+ // stripe SDKs; the SDK's own default keeps wire-version and types aligned.
45
45
  const client = new Stripe(apiKey);
46
46
  cache.set(apiKey, client);
47
47
  return client;
@@ -5,17 +5,17 @@ import Stripe from "stripe";
5
5
  import type { StripeWebhookRuntime } from "./runtime.ts";
6
6
  export declare function isResourceMissingStripeError(error: unknown): error is Stripe.errors.StripeInvalidRequestError;
7
7
  export type StripeWebhookOptions = {
8
- /** Price-to-tier-Map. Plugin liest die price-id aus dem event und
9
- * mapped auf tier-name. Fehlt die price-id im Mapping → null. App-
10
- * spezifisch, bleibt eine factory-option (kein Secret). */
8
+ /** Price-to-tier map. The plugin reads the price ID from the event and
9
+ * maps it to a tier name. Returns null when the price ID is not mapped.
10
+ * App-specific and remains a factory option, not a secret. */
11
11
  readonly priceToTier: Readonly<Record<string, string>>;
12
12
  };
13
13
  /**
14
- * Stripe-webhook-handler. Implementiert den Plugin-Contract
15
- * `verifyAndParseWebhook`. **Pre-tenant-resolution** — kein
16
- * HandlerContext; statt eines mount-time-Clients löst der `runtime` den
17
- * Stripe-Client + das webhook-secret zur Call-Zeit aus dem optionalen
18
- * system-SecretsContext (3. Arg) auf.
14
+ * Stripe webhook handler implementing the plugin contract
15
+ * `verifyAndParseWebhook`. **Pre-tenant resolution** — there is no
16
+ * HandlerContext; instead of using a mount-time client, `runtime` resolves
17
+ * the Stripe client and webhook secret at call time from the optional
18
+ * system SecretsContext (third argument).
19
19
  */
20
20
  export declare function verifyAndParseStripeWebhook(runtime: StripeWebhookRuntime, options: StripeWebhookOptions): (rawBody: string, headers: Record<string, string>, systemSecrets?: SecretsContext) => Promise<SubscriptionEvent | PaymentEvent | null>;
21
21
  export type MappedStripeSubscriptionState = {
@@ -37,7 +37,7 @@ export declare function mapStripeSubscriptionState(sub: Pick<Stripe.Subscription
37
37
  export declare function stripeCancelAtIso(sub: Pick<Stripe.Subscription, "cancel_at" | "cancel_at_period_end">, currentPeriodEndIso: string): string | null;
38
38
  /** Stripe-event-type → normalisiert. null = ignore. */
39
39
  export declare function mapStripeEventType(stripeType: string): SubscriptionEventType | null;
40
- /** Stripe-status → normalisiert. Defensive: unbekannte Status →
41
- * incomplete (Plugin sollte das nicht erreichen, aber wir wollen
42
- * kein ungültiger status-string in der DB). */
40
+ /** Maps Stripe statuses to normalized statuses. Unknown statuses are
41
+ * mapped defensively to incomplete; the plugin should not receive them, but
42
+ * an invalid status string must not be stored in the database. */
43
43
  export declare function mapStripeStatus(stripeStatus: Stripe.Subscription.Status): SubscriptionStatus;
@@ -1,35 +1,34 @@
1
- // verifyAndParseStripeWebhook — Stripe-spezifische sig-verify +
2
- // event-mapping. Wird vom Plugin-Build (feature.ts) als
3
- // `verifyAndParseWebhook` registriert.
1
+ // verifyAndParseStripeWebhook — Stripe-specific signature verification +
2
+ // event mapping. Registered by the plugin build (feature.ts) as
3
+ // `verifyAndParseWebhook`.
4
4
  //
5
5
  // **Steps:**
6
- // 1. Sig-verify via stripe.webhooks.constructEvent (HMAC-SHA-256
7
- // gegen rawBody + Stripe-Signature-Header). Wirft bei mismatch
8
- // oder älter als 5min (Replay-Protection).
6
+ // 1. Verify the signature via stripe.webhooks.constructEvent (HMAC-SHA-256
7
+ // against rawBody + Stripe-Signature header). Throws on mismatch or
8
+ // timestamps older than 5 minutes (replay protection).
9
9
  // 1b. checkout.session.completed / .async_payment_succeeded branch off
10
10
  // here into a PaymentEvent (one-off-payment, own aggregate) — see
11
- // "One-off-payment" section below. Everything else falls through.
12
- // 2. Event-type-Filter: nur die 5 event-types die wir auf
13
- // SubscriptionEventTypes mappen kommen weiter; alles andere
14
- // returnt null (foundation antwortet 200 ignored).
15
- // 3. Stripe-payload → SubscriptionEvent normalisieren
16
- // (status-mapping, tenant-id aus metadata, price-to-tier-Lookup).
11
+ // the "One-off-payment" section below. Everything else falls through.
12
+ // 2. Event-type filter: only the 5 event types mapped to
13
+ // SubscriptionEventTypes continue; everything else returns null
14
+ // (the foundation responds with 200 ignored).
15
+ // 3. Normalize the Stripe payload into a SubscriptionEvent
16
+ // (status mapping, tenant ID from metadata, price-to-tier lookup).
17
17
  //
18
- // **Runtime-keys (pre-tenant):** api-key + webhook-secret kommen NICHT
19
- // mehr aus einem mount-time-Closure, sondern werden zur Webhook-Zeit aus
20
- // dem `StripeWebhookRuntime` aufgelöst. Der foundation-webhook-handler
21
- // reicht einen system-scoped SecretsContext als 3. Arg durch; der runtime
22
- // liest beide Keys daraus (un-audited, system-internal) mit Fallback auf
23
- // die factory-options. Damit rotiert ein Key ohne Redeploy — und der
24
- // invoice-lazy-fetch (unten) nutzt denselben rotierten Client wie der
25
- // sig-verify, kein split-brain.
18
+ // **Runtime keys (pre-tenant):** the API key and webhook secret no longer
19
+ // come from a mount-time closure; they are resolved from `StripeWebhookRuntime`
20
+ // at webhook time. The foundation webhook handler passes a system-scoped
21
+ // SecretsContext as the third argument; the runtime reads both keys from it
22
+ // (unaudited, system-internal), falling back to the factory options. This
23
+ // allows key rotation without a redeploy, and the invoice lazy-fetch below
24
+ // uses the same rotated client as signature verification, avoiding split-brain.
26
25
  //
27
26
  // **Invoice-event lazy-fetch:**
28
- // Invoice payloads carry only the subscription id (Stripe does not expand
29
- // subscription in webhooks), so the plugin lazy-fetches via
27
+ // Invoice payloads carry only the subscription ID (Stripe does not expand
28
+ // subscriptions in webhooks), so the plugin lazy-fetches via
30
29
  // `stripe.subscriptions.retrieve(subId)` to get the full subscription for
31
30
  // status/tier/period-end mapping. resource_missing (deleted between webhook
32
- // and retrieve) returns null; any other Stripe error becomes 503 so Stripe
31
+ // and retrieval) returns null; any other Stripe error becomes 503 so Stripe
33
32
  // redelivers.
34
33
  import { BillingEventKinds, parseProviderConsentId, SubscriptionEventTypes, SubscriptionStatuses, } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
35
34
  import { ExtraRouteRejection } from "@cosmicdrift/kumiko-framework/api";
@@ -47,11 +46,11 @@ function transientProviderRejection(error) {
47
46
  return new ExtraRouteRejection(503, { error: { code: "subscription_provider_transient" } }, `stripe retrieve failed: ${error instanceof Error ? error.message : String(error)}`);
48
47
  }
49
48
  /**
50
- * Stripe-webhook-handler. Implementiert den Plugin-Contract
51
- * `verifyAndParseWebhook`. **Pre-tenant-resolution** — kein
52
- * HandlerContext; statt eines mount-time-Clients löst der `runtime` den
53
- * Stripe-Client + das webhook-secret zur Call-Zeit aus dem optionalen
54
- * system-SecretsContext (3. Arg) auf.
49
+ * Stripe webhook handler implementing the plugin contract
50
+ * `verifyAndParseWebhook`. **Pre-tenant resolution** — there is no
51
+ * HandlerContext; instead of using a mount-time client, `runtime` resolves
52
+ * the Stripe client and webhook secret at call time from the optional
53
+ * system SecretsContext (third argument).
55
54
  */
56
55
  export function verifyAndParseStripeWebhook(runtime, options) {
57
56
  return async (rawBody, headers, systemSecrets) => {
@@ -59,15 +58,15 @@ export function verifyAndParseStripeWebhook(runtime, options) {
59
58
  if (!sigHeader) {
60
59
  throw new Error("subscription-stripe: stripe-signature header missing");
61
60
  }
62
- // 0. Runtime-resolve: api-key (für client + lazy-fetch) + webhook-
63
- // secret (für sig-verify) aus system-secrets, Fallback factory-
64
- // options. Wirft wenn beide unkonfiguriert.
61
+ // 0. Resolve at runtime: obtain the API key (for the client and lazy fetch)
62
+ // and webhook secret (for signature verification) from system secrets,
63
+ // falling back to the factory options. Throws if neither is configured.
65
64
  const { stripe, webhookSecret } = await runtime.resolve(systemSecrets);
66
- // 1. Sig-verify. constructEvent throws bei mismatch (= invalid sig)
67
- // oder timestamp-tolerance-violation (default 5min). Foundation
68
- // mapped throw → HTTP 401. Applies to BOTH branches below — the
69
- // payment-branch only branches off AFTER this check; there's no
70
- // path that bypasses signature verification.
65
+ // 1. Verify the signature. constructEvent throws on a mismatch (invalid
66
+ // signature) or timestamp-tolerance violation (default: 5 minutes).
67
+ // The foundation maps the thrown error to HTTP 401. This applies to
68
+ // BOTH branches below: the payment branch is selected only AFTER this
69
+ // check, so no path bypasses signature verification.
71
70
  let event;
72
71
  try {
73
72
  event = await stripe.webhooks.constructEventAsync(rawBody, sigHeader, webhookSecret);
@@ -84,28 +83,27 @@ export function verifyAndParseStripeWebhook(runtime, options) {
84
83
  if (isCheckoutSessionEventType(event.type)) {
85
84
  return await parsePaymentEvent(event, stripe);
86
85
  }
87
- // 2. Event-type-Filter — wir kennen nur 5.
86
+ // 2. Event-type filter — only 5 event types are supported.
88
87
  const normalizedType = mapStripeEventType(event.type);
89
88
  if (!normalizedType) {
90
89
  return null; // foundation returnt 200 ignored
91
90
  }
92
- // 3. Payload-extraction. Stripe liefert je nach event.type
93
- // verschiedene data.object-shapes. Wir extrahieren die
94
- // Subscription-Daten — entweder direkt (subscription-events)
95
- // oder via lazy-fetch (invoice-events).
91
+ // 3. Extract the payload. Stripe uses different data.object shapes
92
+ // depending on event.type. Extract subscription data either directly
93
+ // (subscription events) or through a lazy fetch (invoice events).
96
94
  const sub = await extractSubscriptionFromEvent(event, stripe);
97
95
  if (!sub) {
98
- // event-type war unter den 5 (oben gefiltert), aber payload-shape
99
- // matched nicht — Stripe-SDK-Schema-Drift, defensive null.
96
+ // The event type passed the 5-item filter, but its payload shape did not
97
+ // match — treat this as Stripe SDK schema drift and return null defensively.
100
98
  return null;
101
99
  }
102
- // 4. Tenant-resolution aus metadata. App-Builder setzt
103
- // `metadata.tenantId` beim createCheckoutSession-call.
100
+ // 4. Resolve the tenant from metadata. The app builder sets
101
+ // `metadata.tenantId` when calling createCheckoutSession.
104
102
  const tenantId = sub.metadata?.["tenantId"];
105
103
  if (!tenantId || tenantId.length === 0) {
106
- // Subscription ohne tenant-metadata → kann kein subscription
107
- // erstellen ohne tenant-resolution. Drop the event silent
108
- // (foundation 200 ignored). App-Owner-Bug, nicht foundation-Bug.
104
+ // A subscription without tenant metadata cannot be created without tenant
105
+ // resolution. Drop the event silently (the foundation responds with 200
106
+ // ignored). This is an app-owner error, not a foundation error.
109
107
  return null;
110
108
  }
111
109
  // 5+6. Price-to-tier-Mapping + status/period-end/cancel_at — shared with
@@ -151,7 +149,7 @@ export function mapStripeSubscriptionState(sub, priceToTier) {
151
149
  const periodEndUnixSec = sub.items.data[0]?.current_period_end ?? 0;
152
150
  // Stripe returns Unix-seconds; Temporal.Instant.fromEpochMilliseconds
153
151
  // expects ms. Multiply, then ISO. (No-Date-API-Guard forbids
154
- // `new Date()` — static import above, not the ambient global, see #1490.)
152
+ // `new Date()` — static import above, not the ambient global.)
155
153
  const currentPeriodEnd = Temporal.Instant.fromEpochMilliseconds(periodEndUnixSec * 1000).toString();
156
154
  const cancelAt = stripeCancelAtIso(sub, currentPeriodEnd);
157
155
  return { status, tier, currentPeriodEnd, cancelAt };
@@ -187,9 +185,9 @@ export function mapStripeEventType(stripeType) {
187
185
  return null;
188
186
  }
189
187
  }
190
- /** Stripe-status → normalisiert. Defensive: unbekannte Status →
191
- * incomplete (Plugin sollte das nicht erreichen, aber wir wollen
192
- * kein ungültiger status-string in der DB). */
188
+ /** Maps Stripe statuses to normalized statuses. Unknown statuses are
189
+ * mapped defensively to incomplete; the plugin should not receive them, but
190
+ * an invalid status string must not be stored in the database. */
193
191
  export function mapStripeStatus(stripeStatus) {
194
192
  switch (stripeStatus) {
195
193
  case "active":
@@ -215,9 +213,9 @@ export function mapStripeStatus(stripeStatus) {
215
213
  return SubscriptionStatuses.incomplete;
216
214
  }
217
215
  }
218
- /** Holt die Subscription aus dem Event. Subscription-events haben sie
219
- * direkt im data.object; invoice-events haben nur die subscription-id
220
- * und brauchen einen lazy-fetch via stripe.subscriptions.retrieve. */
216
+ /** Gets the subscription from the event. Subscription events include it
217
+ * directly in data.object; invoice events include only the subscription ID
218
+ * and require a lazy fetch via stripe.subscriptions.retrieve. */
221
219
  // @wrapper-known semantic-alias
222
220
  async function extractSubscriptionFromEvent(event, stripe) {
223
221
  switch (event.type) {
@@ -227,16 +225,16 @@ async function extractSubscriptionFromEvent(event, stripe) {
227
225
  return event.data.object; // @cast-boundary engine-bridge
228
226
  case StripeEventTypes.invoicePaid:
229
227
  case StripeEventTypes.invoicePaymentFailed: {
230
- // Lazy-fetch der subscription. invoice.subscription ist eine
231
- // string-id (Stripe-Webhooks expanden nicht auto). Wir holen das
232
- // full subscription-Object damit der downstream-mapping
233
- // (status, tier via priceId, period-end) konsistent funktioniert.
228
+ // Lazy-fetch the subscription. invoice.subscription is a string ID because
229
+ // Stripe webhooks do not expand it automatically. Fetch the full
230
+ // subscription so downstream status, tier via priceId, and period-end
231
+ // mapping remain consistent.
234
232
  const invoice = event.data.object; // @cast-boundary engine-bridge
235
233
  const subRef = invoice // @cast-boundary engine-payload
236
234
  .subscription;
237
235
  if (!subRef) {
238
- // Invoice ohne subscription-reference (= one-shot-invoice, nicht
239
- // recurring). Nicht unsere Domain — ignorieren.
236
+ // An invoice without a subscription reference is a one-shot invoice, not a
237
+ // recurring invoice. It is outside this domain and should be ignored.
240
238
  return null;
241
239
  }
242
240
  const subId = typeof subRef === "string" ? subRef : subRef.id;
@@ -21,9 +21,9 @@ export type TagsFeatureOptions = {
21
21
  /** Row-level ownership on the tag-assignment rows themselves — orthogonal to
22
22
  * `access`, which only gates whether a caller may dispatch assign/remove/list
23
23
  * at all. `ownership.read` is no longer what keeps a caller from reading
24
- * assignments on host entities they can't see: that gate is default-on since
25
- * fw#2766 and derives from the entity's `parentRef`. Use `ownership.read` for
26
- * an ADDITIONAL row rule on the assignment row itself; it is AND-ed with the
24
+ * assignments on host entities they can't see: that gate is default-on and
25
+ * derives from the entity's `parentRef`. Use `ownership.read` for an
26
+ * ADDITIONAL row rule on the assignment row itself; it is AND-ed with the
27
27
  * host-visibility gate, never a replacement for it. Applies only to
28
28
  * `tag-assignment`; the `tag` catalog stays tenant-wide by design.
29
29
  *
@@ -1,6 +1,6 @@
1
1
  import { i18nKey, } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { DEFAULT_TAG_ACCESS, TAGS_EDIT_SCREEN_ID, TAGS_SCREEN_ID } from "./web/constants.js";
3
- // Declarative catalog screens (Phase-3 / #2312). Access matches create/update/
3
+ // Declarative catalog screens. Access matches create/update/
4
4
  // delete so createTagsFeature({ access|roles }) stays consistent. TagManager
5
5
  // remains for TagPicker/TagSection — only the standalone admin screen moved.
6
6
  export function createTagListScreen(access = DEFAULT_TAG_ACCESS) {
@@ -89,19 +89,19 @@ function pickActiveLayoutRow(rows, locale) {
89
89
  async function fetchTemplate(db, tenantId, slug, kind, locale) {
90
90
  const rows = await selectMany(db, templateResourcesTable, { tenantId, slug, kind, locale }, { limit: 1 });
91
91
  // @cast-boundary db-row — db.select returnt unbenanntes unknown[],
92
- // Row-Shape ist via templateResourcesTable + buildBaseColumns garantiert.
92
+ // The row shape is guaranteed by templateResourcesTable + buildBaseColumns.
93
93
  return rows[0] ?? null;
94
94
  }
95
95
  function toPublic(row) {
96
96
  // @cast-boundary db-row — Drizzle-Schema typisiert kind/contentFormat/
97
- // scope/status als generic text. CHECK-Constraints in der DB schränken
98
- // sie auf die Union-Types ein; Cast assertet das Schema-Wissen.
97
+ // scope/status as generic text. Database CHECK constraints restrict
98
+ // them to the union types; the cast asserts that schema knowledge.
99
99
  const kind = row.kind;
100
- // @cast-boundary db-row — siehe kind.
100
+ // @cast-boundary db-row — see kind.
101
101
  const contentFormat = row.contentFormat;
102
- // @cast-boundary db-row — siehe kind.
102
+ // @cast-boundary db-row — see kind.
103
103
  const scope = row.scope;
104
- // @cast-boundary db-row — siehe kind.
104
+ // @cast-boundary db-row — see kind.
105
105
  const status = row.status;
106
106
  const linkedEntries = parseLinkedResourceEntries(row.linkedResources);
107
107
  return {
@@ -143,7 +143,7 @@ function parseJson(raw) {
143
143
  try {
144
144
  const parsed = JSON.parse(raw);
145
145
  // @cast-boundary engine-payload — JSON.parse returnt unknown, typeof-Guard
146
- // grenzt auf object ein; Record<string, unknown> ist der minimale common-shape.
146
+ // narrows it to object; Record<string, unknown> is the minimal common shape.
147
147
  return typeof parsed === "object" && parsed !== null ? parsed : {};
148
148
  }
149
149
  catch {
@@ -158,11 +158,11 @@ export class TemplateNotFoundError extends Error {
158
158
  this.name = "TemplateNotFoundError";
159
159
  }
160
160
  }
161
- // Single point of truth für "dieser Handler braucht template-resolver".
162
- // Pattern symmetrisch zu requireTextContent.
161
+ // Single source of truth for "this handler requires template-resolver".
162
+ // Pattern symmetric with requireTextContent.
163
163
  export function requireTemplateResolver(ctx, callerName) {
164
164
  // @cast-boundary engine-bridge — templateResolver kommt per extraContext
165
- // aus App-Bootstrap, Framework-Container kennt das Feld nicht von sich aus.
165
+ // from App-Bootstrap; the framework container does not know this field on its own.
166
166
  const api = ctx.templateResolver;
167
167
  if (!api) {
168
168
  throw new InternalError({
@@ -5,11 +5,11 @@ import { templateResourcesTable } from "../table.js";
5
5
  import { deliveryPolicyOf, isRowServedTo } from "../template-delivery-policy.js";
6
6
  import { draftViewerTenantId, isHiddenSystemDraft, toWorkingRow } from "../template-draft.js";
7
7
  import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
8
- // Admin-Lookup für UI-Edit-Flow. Returnt das raw Template inkl. draft/
9
- // archived Status. Tenant-Isolation: User sieht nur Templates des
10
- // eigenen Tenants oder SYSTEM_TENANT (system-defaults sind public-
11
- // readable); ctx.db is tenant-scoped for every role, so the check below is defense in depth. Anonymous bleibt aus — Public-
12
- // Read geht über resolveTemplate aus der API, nicht hier.
8
+ // Admin lookup for the UI editing flow. Returns the raw template, including draft/
9
+ // archived status. Tenant isolation: users see only templates belonging to their own
10
+ // tenant or SYSTEM_TENANT (system defaults are publicly readable); ctx.db is tenant-
11
+ // scoped for every role, so the check below is defense in depth. Anonymous access is
12
+ // excluded—public reads go through resolveTemplate in the API, not here.
13
13
  export const findByIdQuery = defineQueryHandler({
14
14
  name: "find-by-id",
15
15
  schema: z.object({ id: z.string().min(1) }),
@@ -35,7 +35,7 @@ export const listQuery = defineQueryHandler({
35
35
  if (query.payload.status) {
36
36
  where["status"] = query.payload.status;
37
37
  }
38
- // @cast-boundary db-row — selectMany returnt unknown[]; Row-Shape ist
38
+ // @cast-boundary db-row — selectMany returns unknown[]; Row shape is
39
39
  // durch templateResourcesTable + buildBaseColumns garantiert.
40
40
  const rows = (await selectMany(ctx.db, templateResourcesTable, where, {
41
41
  limit: 500,
@@ -30,8 +30,8 @@ export const folderSchema = z
30
30
  export const titleSchema = z.string().min(1).max(200);
31
31
  export const contentFormatSchema = z.enum(CONTENT_FORMATS);
32
32
  export const statusSchema = z.enum(TEMPLATE_STATUSES);
33
- // Common Upsert-Payload — geteilt zwischen upsertSystem + upsertTenant.
34
- // Unterschied: ACL + tenantId-Bestimmung, sonst identisch.
33
+ // Common upsert payload shared by upsertSystem and upsertTenant.
34
+ // Only ACL and tenantId determination differ.
35
35
  export const upsertPayloadSchema = z.object({
36
36
  slug: templateSlugSchema,
37
37
  kind: kindSchema,
@@ -148,9 +148,9 @@ export async function writeTemplateRow(args) {
148
148
  }, user, db, { streamTenantId });
149
149
  if (!result.isSuccess)
150
150
  return result;
151
- // @cast-boundary db-row — executor.create returnt Record-row aus
152
- // INSERT RETURNING; shape { id } ist garantiert weil PK in der
153
- // Returning-Klausel ist.
151
+ // @cast-boundary db-row — executor.create returns a row from
152
+ // INSERT RETURNING; the { id } shape is guaranteed because the primary key is in the
153
+ // RETURNING clause.
154
154
  const createdRow = result.data;
155
155
  return {
156
156
  isSuccess: true,
@@ -2,10 +2,9 @@ import { defineWriteHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framew
2
2
  import { resolveTemplateVariables } from "../template-validation.js";
3
3
  import { upsertPayloadSchema } from "./shared.js";
4
4
  import { writeTemplateRow } from "./template-write.js";
5
- // System-Template anlegen/updaten. Liegt unter SYSTEM_TENANT_ID,
6
- // scope='system'. Nur SystemAdmin (globale Rolle). TenantAdmin kann
7
- // keine System-Defaults überschreiben — der nutzt upsertTenant für
8
- // Overrides.
5
+ // Creates or updates a system template under SYSTEM_TENANT_ID with
6
+ // scope='system'. Only SystemAdmin can change these global defaults;
7
+ // TenantAdmin uses upsertTenant for overrides instead.
9
8
  export const upsertSystemWrite = defineWriteHandler({
10
9
  name: "upsert-system",
11
10
  schema: upsertPayloadSchema,
@@ -4,11 +4,10 @@ import { refuseTemplateEdit, templateEditAccess, } from "../template-edit-policy
4
4
  import { resolveTemplateVariables } from "../template-validation.js";
5
5
  import { upsertPayloadSchema } from "./shared.js";
6
6
  import { writeTemplateRow } from "./template-write.js";
7
- // Tenant-Override anlegen/updaten. Liegt unter event.user.tenantId,
8
- // scope='tenant'. Default-Status='draft' — User publisht explizit
9
- // via publish-Handler. SystemAdmin kann via tenantIdOverride für
10
- // einen anderen Tenant schreiben (typisch: Plattform-Admin-UI das
11
- // Tenant-Templates kuratiert).
7
+ // Creates or updates a tenant override under event.user.tenantId with scope='tenant'.
8
+ // The default status is 'draft'; users must publish explicitly via the publish handler.
9
+ // SystemAdmin can write for another tenant through tenantIdOverride, typically to
10
+ // curate tenant templates from a platform admin UI.
12
11
  export function makeUpsertTenantWrite(policy) {
13
12
  return defineWriteHandler({
14
13
  name: "upsert-tenant",