@cosmicdrift/kumiko-samples 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.
- package/LICENSE +21 -57
- package/README.md +1 -1
- package/package.json +2 -2
- package/packages/bundled-features/package.json +2 -2
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +0 -2
- package/packages/bundled-features/src/audit/screens.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
- package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
- package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
- package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
- package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
- package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
- package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
- package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
- package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
- package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
- package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
- package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
- package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
- package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
- package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
- package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
- package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
- package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
- package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
- package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
- package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
- package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
- package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
- package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
- package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/web/i18n.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +6 -6
- package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
- package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
- package/packages/bundled-features/src/billing-foundation/events.ts +22 -21
- package/packages/bundled-features/src/billing-foundation/feature.ts +42 -43
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +18 -17
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
- package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +20 -20
- package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
- package/packages/bundled-features/src/billing-foundation/types.ts +64 -65
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +4 -4
- package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
- package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
- package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +64 -67
- package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
- package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
- package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
- package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +1 -1
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
- package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
- package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
- package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
- package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
- package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
- package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
- package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
- package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
- package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
- package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
- package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
- package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
- package/packages/bundled-features/src/config/resolver.ts +4 -4
- package/packages/bundled-features/src/config/table.ts +10 -10
- package/packages/bundled-features/src/config/write-helpers.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +13 -12
- package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
- package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
- package/packages/bundled-features/src/custom-fields/events.ts +7 -8
- package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
- package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
- package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
- package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
- package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
- package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
- package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
- package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
- package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
- package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
- package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
- package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
- package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
- package/packages/bundled-features/src/data-retention/feature.ts +11 -18
- package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
- package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
- package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
- package/packages/bundled-features/src/data-retention/presets.ts +18 -23
- package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
- package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
- package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
- package/packages/bundled-features/src/delivery/feature.ts +3 -3
- package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
- package/packages/bundled-features/src/delivery/tables.ts +9 -8
- package/packages/bundled-features/src/delivery/unsubscribe.ts +4 -4
- package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
- package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
- package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
- package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
- package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
- package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
- package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
- package/packages/bundled-features/src/files/feature.ts +6 -6
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
- package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
- package/packages/bundled-features/src/folders/feature.ts +1 -1
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
- package/packages/bundled-features/src/folders/web/tree.ts +5 -5
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
- package/packages/bundled-features/src/form-draft/entity.ts +3 -3
- package/packages/bundled-features/src/form-draft/feature.ts +4 -5
- package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
- package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
- package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
- package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
- package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
- package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
- package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
- package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
- package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +11 -11
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
- package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +66 -67
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +69 -68
- package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
- package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
- package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
- package/packages/bundled-features/src/jobs/events.ts +1 -1
- package/packages/bundled-features/src/jobs/feature.ts +6 -7
- package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +14 -15
- package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
- package/packages/bundled-features/src/jobs/screens.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
- package/packages/bundled-features/src/ledger/entity.ts +5 -5
- package/packages/bundled-features/src/ledger/feature.ts +3 -3
- package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
- package/packages/bundled-features/src/ledger/recurring.ts +12 -12
- package/packages/bundled-features/src/ledger/schemas.ts +1 -1
- package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
- package/packages/bundled-features/src/ledger/web/index.ts +7 -7
- package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
- package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
- package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
- package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
- package/packages/bundled-features/src/mail-foundation/feature.ts +26 -27
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
- package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
- package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
- package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
- package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
- package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
- package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
- package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
- package/packages/bundled-features/src/managed-pages/table.ts +16 -15
- package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
- package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
- package/packages/bundled-features/src/notes-history/entity.ts +4 -4
- package/packages/bundled-features/src/notes-history/feature.ts +2 -2
- package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
- package/packages/bundled-features/src/page-render/layout.ts +9 -9
- package/packages/bundled-features/src/page-render/markdown.ts +11 -11
- package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +5 -5
- package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
- package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
- package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
- package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
- package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
- package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
- package/packages/bundled-features/src/secrets/feature.ts +9 -9
- package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
- package/packages/bundled-features/src/seo/feature.ts +3 -3
- package/packages/bundled-features/src/sessions/constants.ts +1 -1
- package/packages/bundled-features/src/sessions/feature.ts +9 -9
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
- package/packages/bundled-features/src/sessions/screens.ts +2 -2
- package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
- package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
- package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
- package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +1 -1
- package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
- package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
- package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
- package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
- package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
- package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
- package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
- package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
- package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
- package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
- package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
- package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
- package/packages/bundled-features/src/subscription-stripe/feature.ts +44 -43
- package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
- package/packages/bundled-features/src/subscription-stripe/runtime.ts +2 -2
- package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
- package/packages/bundled-features/src/tags/feature.ts +3 -3
- package/packages/bundled-features/src/tags/screens.ts +1 -1
- package/packages/bundled-features/src/template-resolver/api.ts +10 -10
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +5 -5
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
- package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
- package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
- package/packages/bundled-features/src/template-resolver/seeding.ts +4 -4
- package/packages/bundled-features/src/template-resolver/table.ts +13 -14
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
- package/packages/bundled-features/src/tenant/feature.ts +7 -7
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
- package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
- package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
- package/packages/bundled-features/src/tenant/screens.ts +1 -1
- package/packages/bundled-features/src/tenant/seeding.ts +19 -18
- package/packages/bundled-features/src/tenant/testing.ts +5 -6
- package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
- package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
- package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
- package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
- package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
- package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +2 -2
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
- package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
- package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
- package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
- package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
- package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
- package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
- package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +8 -8
- package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
- package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
- package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
- package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
- package/packages/bundled-features/src/user/schema/user.ts +45 -44
- package/packages/bundled-features/src/user/seeding.ts +40 -40
- package/packages/bundled-features/src/user/testing.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
- package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
- package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
- package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
- package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
- package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
- package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
- package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
- package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
- package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
- package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +166 -276
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +85 -107
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
- package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
- package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
- package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
- package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
- package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
- package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
- package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
- package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
- package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
- package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
- package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
- package/packages/bundled-features/src/user-profile/index.ts +3 -3
- package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
- package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
- package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
- package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
- package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
- package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
- package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
- package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// subscription-mollie — Mollie
|
|
4
|
-
//
|
|
3
|
+
// subscription-mollie — Mollie plugin for subscription-foundation
|
|
4
|
+
// plugin API (EU compliance for the DACH mid-market).
|
|
5
5
|
//
|
|
6
|
-
// **Factory
|
|
7
|
-
// mount
|
|
8
|
-
//
|
|
9
|
-
// 4.5.0
|
|
10
|
-
//
|
|
11
|
-
//
|
|
6
|
+
// **Factory pattern (analogous to subscription-stripe):** reads the API key
|
|
7
|
+
// at mount time from the factory options (typically process.env from the app
|
|
8
|
+
// builder's bin/server.ts). Mollie has NO webhook secret — Mollie SDK
|
|
9
|
+
// 4.5.0 provides no native HMAC signature verification API. Security comes
|
|
10
|
+
// from non-guessable IDs + API validation; the app builder can optionally
|
|
11
|
+
// add a URL-token wrapper in front.
|
|
12
12
|
//
|
|
13
|
-
// **
|
|
13
|
+
// **Scope:**
|
|
14
14
|
// - verifyAndParseWebhook ✓ (lazy-fetch payment + subscription via
|
|
15
|
-
// Mollie
|
|
16
|
-
// - createCheckoutSession ✓ (Mollie's
|
|
17
|
-
//
|
|
18
|
-
// - createPortalSession ✗ (Mollie
|
|
19
|
-
// - cancelSubscription ✗ (Mollie
|
|
20
|
-
// subId;
|
|
21
|
-
// via Mollie
|
|
15
|
+
// Mollie API, heuristic event-type mapping)
|
|
16
|
+
// - createCheckoutSession ✓ (Mollie's multistep flow: create customer
|
|
17
|
+
// + first payment with sequenceType="first" → redirectUrl)
|
|
18
|
+
// - createPortalSession ✗ (Mollie has no customer portal)
|
|
19
|
+
// - cancelSubscription ✗ (Mollie additionally requires customerId besides
|
|
20
|
+
// subId; the plugin contract does not pass it through — the app builder
|
|
21
|
+
// cancels via the Mollie dashboard or a custom route)
|
|
22
22
|
//
|
|
23
|
-
// **
|
|
23
|
+
// **Example usage in run-config.ts:**
|
|
24
24
|
//
|
|
25
25
|
// const features = [
|
|
26
26
|
// billingFoundationFeature,
|
|
@@ -62,29 +62,28 @@ export const subscriptionMollieEnvSchema = z.object({
|
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
export type SubscriptionMollieOptions = {
|
|
65
|
-
/** Mollie
|
|
66
|
-
*
|
|
65
|
+
/** Mollie API key (`test_...` or `live_...`). App-wide, mounted from
|
|
66
|
+
* process.env or system configuration. */
|
|
67
67
|
readonly apiKey: string;
|
|
68
|
-
/** Foundation
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* webhooks an diese URL. Typisch:
|
|
68
|
+
/** Foundation webhook URL registered by the app builder in the Mollie
|
|
69
|
+
* dashboard. The plugin passes it to Mollie when creating a payment;
|
|
70
|
+
* Mollie sends payment-event webhooks to this URL. Typically:
|
|
72
71
|
* `https://app.example.com/api/subscription/webhook/mollie`. */
|
|
73
72
|
readonly webhookUrl: string;
|
|
74
|
-
/** Price-to-tier
|
|
75
|
-
* metadata (= `metadata.priceId`
|
|
76
|
-
* createCheckoutSession
|
|
73
|
+
/** Price-to-tier map. The plugin reads the priceId from the subscription
|
|
74
|
+
* metadata (= `metadata.priceId` set by the app builder when calling
|
|
75
|
+
* createCheckoutSession) and maps it to a tier name. */
|
|
77
76
|
readonly priceToTier: Readonly<Record<string, string>>;
|
|
78
|
-
/** Mollie
|
|
79
|
-
*
|
|
80
|
-
*
|
|
77
|
+
/** Mollie subscription setup per priceId. Mollie has no native price-ID
|
|
78
|
+
* concept, so the app builder must provide an amount/interval/description
|
|
79
|
+
* for each virtual priceId. */
|
|
81
80
|
readonly priceToConfig: Readonly<Record<string, MolliePriceConfig>>;
|
|
82
|
-
/** @internal Test-only injection
|
|
83
|
-
*
|
|
84
|
-
* factory
|
|
85
|
-
*
|
|
86
|
-
* factory
|
|
87
|
-
*
|
|
81
|
+
/** @internal Test-only injection port: replaces the verify-webhook fetch
|
|
82
|
+
* client with a mock instance. Production leaves this undefined; the
|
|
83
|
+
* factory builds the adapter from `createMollieClient(apiKey)`. The
|
|
84
|
+
* integration test (mollie-foundation.integration.ts) uses it so the real
|
|
85
|
+
* factory code (drift validation, plugin registration) runs in the test
|
|
86
|
+
* path without making Mollie API calls. */
|
|
88
87
|
readonly _clientShapeForTests?: MollieClientShape;
|
|
89
88
|
};
|
|
90
89
|
|
|
@@ -102,8 +101,8 @@ export function createSubscriptionMollieFeature(
|
|
|
102
101
|
);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
// Drift
|
|
106
|
-
//
|
|
104
|
+
// Drift guard: priceToTier and priceToConfig must have identical keys;
|
|
105
|
+
// otherwise verifyAndParseWebhook silently returns null.
|
|
107
106
|
const tierKeys = new Set(Object.keys(options.priceToTier));
|
|
108
107
|
const configKeys = new Set(Object.keys(options.priceToConfig));
|
|
109
108
|
const missingInConfig = [...tierKeys].filter((k) => !configKeys.has(k));
|
|
@@ -118,9 +117,9 @@ export function createSubscriptionMollieFeature(
|
|
|
118
117
|
|
|
119
118
|
const client = createMollieClient({ apiKey: options.apiKey });
|
|
120
119
|
|
|
121
|
-
// Adapter
|
|
122
|
-
//
|
|
123
|
-
//
|
|
120
|
+
// Adapter that binds the plugin's minimal fetch client to the full Mollie
|
|
121
|
+
// client. The minimal plugin fetch API lets tests mock it without mocking
|
|
122
|
+
// the full MollieClient.
|
|
124
123
|
const fetchAdapter: MollieClientShape = options._clientShapeForTests ?? {
|
|
125
124
|
payments: { get: (id: string) => client.payments.get(id) },
|
|
126
125
|
customerSubscriptions: {
|
|
@@ -160,8 +159,8 @@ export function createSubscriptionMollieFeature(
|
|
|
160
159
|
const plugin: SubscriptionProviderPlugin = {
|
|
161
160
|
verifyAndParseWebhook: verifyAndParse,
|
|
162
161
|
createCheckoutSession: checkoutSession,
|
|
163
|
-
// createPortalSession
|
|
164
|
-
// plugin-methods.ts
|
|
162
|
+
// createPortalSession and cancelSubscription are intentionally omitted;
|
|
163
|
+
// see plugin-methods.ts for why.
|
|
165
164
|
priceToTier: options.priceToTier,
|
|
166
165
|
};
|
|
167
166
|
r.useExtension("subscriptionProvider", MOLLIE_PROVIDER_NAME, plugin);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Public API of the subscription-mollie bundled-feature.
|
|
2
2
|
//
|
|
3
|
-
// **Internal-only** (
|
|
4
|
-
// - verifyAndParseMollieWebhook (
|
|
3
|
+
// **Internal-only** (not in the public barrel—the App Builder never uses it directly):
|
|
4
|
+
// - verifyAndParseMollieWebhook (called internally by the feature.ts factory)
|
|
5
5
|
// - mapMollieEventType / mapMollieStatus / extractMollieId (pure helpers,
|
|
6
|
-
// test-only
|
|
6
|
+
// test-only—direct-import from the file if ever genuinely needed externally)
|
|
7
7
|
|
|
8
8
|
export { MOLLIE_PROVIDER_NAME, SUBSCRIPTION_MOLLIE_FEATURE } from "./constants.ts";
|
|
9
9
|
export {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
// Mollie
|
|
2
|
-
// createCheckoutSession
|
|
3
|
-
//
|
|
1
|
+
// Mollie plugin methods for the POST-tenant-resolution phase:
|
|
2
|
+
// createCheckoutSession only. createPortalSession and cancelSubscription
|
|
3
|
+
// are not implemented because Mollie's API does not provide these patterns
|
|
4
|
+
// 1:1:
|
|
4
5
|
//
|
|
5
|
-
// - **Portal:** Mollie
|
|
6
|
-
//
|
|
7
|
-
// - **Cancel:** Mollie
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// - **Portal:** Mollie has no customer portal, so the App Builder UI must
|
|
7
|
+
// render it itself.
|
|
8
|
+
// - **Cancel:** Mollie requires (customerId, subId), but the plugin contract
|
|
9
|
+
// passes through only subId. The App Builder cancels through the Mollie
|
|
10
|
+
// dashboard or a custom route until the Foundation contract is extended.
|
|
10
11
|
//
|
|
11
|
-
// **Mollie
|
|
12
|
-
// payment
|
|
13
|
-
// Mollie
|
|
14
|
-
//
|
|
12
|
+
// **The Mollie checkout flow has multiple steps:** create customer → first
|
|
13
|
+
// payment with sequenceType="first" (= mandate setup) → user pays →
|
|
14
|
+
// Mollie webhook → verify-webhook creates the Mollie subscription
|
|
15
|
+
// idempotently (see verify-webhook.ts ensureSubscriptionForMandate).
|
|
15
16
|
|
|
16
17
|
import type { SubscriptionProviderPlugin } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
|
|
17
18
|
import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -22,8 +23,8 @@ export type MollieCheckoutOptions = Parameters<
|
|
|
22
23
|
NonNullable<SubscriptionProviderPlugin["createCheckoutSession"]>
|
|
23
24
|
>[1];
|
|
24
25
|
|
|
25
|
-
/** Mollie
|
|
26
|
-
*
|
|
26
|
+
/** Mollie has no native price ID concept; the App Builder maintains
|
|
27
|
+
* an amount/interval/description for each virtual priceId. */
|
|
27
28
|
export type MolliePriceConfig = {
|
|
28
29
|
/** Mollie-format: 2-decimal string, z.B. `"9.99"`. */
|
|
29
30
|
readonly amountValue: string;
|
|
@@ -67,8 +68,8 @@ export function createMollieCheckoutSession(
|
|
|
67
68
|
// any mandate/subscription handling.
|
|
68
69
|
const sequenceType = options.mode === "payment" ? SequenceType.oneoff : SequenceType.first;
|
|
69
70
|
|
|
70
|
-
// payments.create
|
|
71
|
-
//
|
|
71
|
+
// payments.create is overloaded (Promise or void with a callback);
|
|
72
|
+
// explicitly cast to the Promise<Payment> overload.
|
|
72
73
|
const payment = (await (client.payments.create({
|
|
73
74
|
amount: { currency: priceCfg.amountCurrency, value: priceCfg.amountValue },
|
|
74
75
|
description: priceCfg.description,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// verifyAndParseMollieWebhook
|
|
2
|
-
//
|
|
3
|
-
// `verifyAndParseWebhook
|
|
1
|
+
// verifyAndParseMollieWebhook: Mollie-specific lazy fetch plus event-type
|
|
2
|
+
// heuristic. The plugin build (feature.ts) registers it as
|
|
3
|
+
// `verifyAndParseWebhook`.
|
|
4
4
|
//
|
|
5
|
-
// Mollie's classic
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
5
|
+
// Mollie's classic webhook sends only an `id` (form-urlencoded or JSON), so
|
|
6
|
+
// the payment and subscription are lazily fetched through the Mollie API.
|
|
7
|
+
// sub_xxx events are NOT supported; app builders get them indirectly through
|
|
8
|
+
// tr_xxx payment events (Mollie sends both in parallel for normal lifecycle
|
|
9
|
+
// events).
|
|
10
10
|
//
|
|
11
|
-
// **Mandate
|
|
12
|
-
// `payment.subscriptionId === null` (Mollie's
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// **Mandate setup flow:** the first paid payment arrives with
|
|
12
|
+
// `payment.subscriptionId === null` (Mollie's pattern: the app builder must
|
|
13
|
+
// call `customerSubscriptions.create` itself). The plugin does that
|
|
14
|
+
// (idempotent via a list check) so the foundation receives a created event
|
|
15
|
+
// with a subscription id.
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
parseProviderConsentId,
|
|
@@ -33,9 +33,9 @@ import type { MolliePriceConfig } from "./plugin-methods.ts";
|
|
|
33
33
|
|
|
34
34
|
const log = createFallbackLogger("subscription-mollie");
|
|
35
35
|
|
|
36
|
-
/** Minimal
|
|
37
|
-
*
|
|
38
|
-
* feature.ts
|
|
36
|
+
/** Minimal subset of the Mollie client used by the plugin — kept separate
|
|
37
|
+
* so tests can mock it without the full MollieClient. The adapter in
|
|
38
|
+
* feature.ts bridges it to the real SDK. */
|
|
39
39
|
export type MollieClientShape = {
|
|
40
40
|
readonly payments: { readonly get: (id: string) => Promise<MolliePayment> };
|
|
41
41
|
readonly customerSubscriptions: {
|
|
@@ -54,11 +54,11 @@ export type MollieClientShape = {
|
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
export type MollieWebhookOptions = {
|
|
57
|
-
/** priceId (=
|
|
57
|
+
/** priceId (= virtual key from subscription.metadata) → tier name. */
|
|
58
58
|
readonly priceToTier: Readonly<Record<string, string>>;
|
|
59
|
-
/** priceId → amount/interval/description.
|
|
60
|
-
* flow
|
|
61
|
-
*
|
|
59
|
+
/** priceId → amount/interval/description. Needed for the mandate-setup
|
|
60
|
+
* flow's `customerSubscriptions.create` call. The app builder maintains
|
|
61
|
+
* this map once in the factory options. */
|
|
62
62
|
readonly priceToConfig: Readonly<Record<string, MolliePriceConfig>>;
|
|
63
63
|
};
|
|
64
64
|
|
|
@@ -97,7 +97,7 @@ export function verifyAndParseMollieWebhook(
|
|
|
97
97
|
subscription = await ensureSubscriptionForMandate(client, options, payment);
|
|
98
98
|
if (!subscription) return null;
|
|
99
99
|
} else {
|
|
100
|
-
// One-shot
|
|
100
|
+
// One-shot or first-payment-failed events are outside our domain.
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
103
|
} else if (id.startsWith("sub_")) {
|
|
@@ -121,8 +121,8 @@ export function verifyAndParseMollieWebhook(
|
|
|
121
121
|
const status = mapMollieStatus(subscription.status);
|
|
122
122
|
const periodEndSource = subscription.nextPaymentDate ?? subscription.startDate;
|
|
123
123
|
if (!periodEndSource) {
|
|
124
|
-
// Mollie
|
|
125
|
-
//
|
|
124
|
+
// Mollie API drift: valid subscriptions have at least startDate. Fail
|
|
125
|
+
// loudly so the app owner's monitoring can detect the drift.
|
|
126
126
|
throw new Error(
|
|
127
127
|
`subscription-mollie: subscription ${subscription.id} has neither nextPaymentDate nor startDate`,
|
|
128
128
|
);
|
|
@@ -149,9 +149,9 @@ export function verifyAndParseMollieWebhook(
|
|
|
149
149
|
// Mandate-setup: subscription on-the-fly erstellen
|
|
150
150
|
// =============================================================================
|
|
151
151
|
|
|
152
|
-
/** first-payment-paid
|
|
153
|
-
* Idempotent via list
|
|
154
|
-
*
|
|
152
|
+
/** `first-payment-paid` without subscriptionId → create a Mollie subscription.
|
|
153
|
+
* Idempotent via a list check (replay-safe). Returns null for incomplete
|
|
154
|
+
* metadata or an unknown priceId. */
|
|
155
155
|
async function ensureSubscriptionForMandate(
|
|
156
156
|
client: MollieClientShape,
|
|
157
157
|
options: MollieWebhookOptions,
|
|
@@ -188,10 +188,10 @@ async function ensureSubscriptionForMandate(
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
// =============================================================================
|
|
191
|
-
// Helpers (exported
|
|
191
|
+
// Helpers (exported for tests)
|
|
192
192
|
// =============================================================================
|
|
193
193
|
|
|
194
|
-
/**
|
|
194
|
+
/** Extracts `id` from rawBody — supports form-urlencoded and JSON. */
|
|
195
195
|
export function extractMollieId(rawBody: string, headers: Record<string, string>): string | null {
|
|
196
196
|
const contentType = headers["content-type"] ?? "";
|
|
197
197
|
if (contentType.includes("application/json")) {
|
|
@@ -210,8 +210,8 @@ export function extractMollieId(rawBody: string, headers: Record<string, string>
|
|
|
210
210
|
return params.get("id");
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
/** Mollie
|
|
214
|
-
*
|
|
213
|
+
/** Mollie subscription + optional payment → SubscriptionEventType.
|
|
214
|
+
* Heuristic because Mollie has no explicitly typed events. */
|
|
215
215
|
export function mapMollieEventType(
|
|
216
216
|
subscription: MollieSubscription,
|
|
217
217
|
triggerPayment: MolliePayment | null,
|
|
@@ -240,10 +240,10 @@ export function mapMollieStatus(mollieStatus: MollieSubscription["status"]): Sub
|
|
|
240
240
|
return SubscriptionStatuses.active;
|
|
241
241
|
case "canceled":
|
|
242
242
|
case "completed":
|
|
243
|
-
// completed =
|
|
243
|
+
// completed = all `times` charges have run → treat it like canceled.
|
|
244
244
|
return SubscriptionStatuses.canceled;
|
|
245
245
|
case "suspended":
|
|
246
|
-
//
|
|
246
|
+
// Invalid mandate / payment method failed → grace period.
|
|
247
247
|
return SubscriptionStatuses.pastDue;
|
|
248
248
|
case "pending":
|
|
249
249
|
return SubscriptionStatuses.incomplete;
|
|
@@ -252,8 +252,8 @@ export function mapMollieStatus(mollieStatus: MollieSubscription["status"]): Sub
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
/** Mollie
|
|
256
|
-
* Throws
|
|
255
|
+
/** Mollie provides dates as YYYY-MM-DD; Foundation requires an ISO Instant.
|
|
256
|
+
* Throws on malformed input (= Mollie API drift, which should fail loudly). */
|
|
257
257
|
function mollieDateStringToInstantIso(dateString: string): string {
|
|
258
258
|
return Temporal.Instant.from(`${dateString.slice(0, 10)}T00:00:00Z`).toString();
|
|
259
259
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Feature name
|
|
2
2
|
export const SUBSCRIPTION_STRIPE_FEATURE = "subscription-stripe" as const;
|
|
3
3
|
|
|
4
|
-
// entityName under
|
|
5
|
-
//
|
|
4
|
+
// entityName under which the plugin registers itself as
|
|
5
|
+
// "subscriptionProvider". It must match the path segment in the webhook URL
|
|
6
6
|
// `/api/subscription/webhook/stripe`.
|
|
7
7
|
export const STRIPE_PROVIDER_NAME = "stripe" as const;
|
|
8
8
|
|
|
@@ -14,10 +14,8 @@ export const STRIPE_API_KEY_CONFIG = "api-key" as const;
|
|
|
14
14
|
export const STRIPE_WEBHOOK_SECRET_CONFIG = "webhook-secret" as const;
|
|
15
15
|
export const STRIPE_BILLING_LIVE_CONFIG = "billingLive" as const;
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
// Stripe
|
|
19
|
-
// mappen. Stripe hat ~80 event-types insgesamt; wir filtern auf 5.
|
|
20
|
-
// =============================================================================
|
|
17
|
+
// Stripe event types that map to normalized SubscriptionEventTypes.
|
|
18
|
+
// Stripe has approximately 80 event types; we filter to five.
|
|
21
19
|
|
|
22
20
|
export const StripeEventTypes = {
|
|
23
21
|
customerSubscriptionCreated: "customer.subscription.created",
|
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
// kumiko-feature-version: 3
|
|
2
2
|
//
|
|
3
|
-
// subscription-stripe — Stripe
|
|
4
|
-
//
|
|
3
|
+
// subscription-stripe — Stripe plugin for the billing-foundation
|
|
4
|
+
// plugin API.
|
|
5
5
|
//
|
|
6
|
-
// **Runtime
|
|
7
|
-
//
|
|
8
|
-
// mount-time
|
|
9
|
-
//
|
|
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
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
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-
|
|
18
|
-
// (boolean, default false).
|
|
19
|
-
//
|
|
20
|
-
//
|
|
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
|
|
23
|
-
// apiKey, webhookSecret, priceToTier })`
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// (Stripe
|
|
27
|
-
//
|
|
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
|
|
30
|
-
// (
|
|
31
|
-
//
|
|
32
|
-
// webhook
|
|
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
|
|
|
34
35
|
import type { SubscriptionProviderPlugin } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
|
|
35
36
|
import {
|
|
@@ -115,17 +116,17 @@ export function stripeEnvSchema<const TPrice extends string>(options: {
|
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export type SubscriptionStripeOptions = {
|
|
118
|
-
/** Bridge-fallback webhook
|
|
119
|
-
* `subscription-stripe:config:webhook-secret
|
|
120
|
-
*
|
|
119
|
+
/** Bridge-fallback webhook secret. Optional: v2 reads from the
|
|
120
|
+
* `subscription-stripe:config:webhook-secret` key (backing:"secrets").
|
|
121
|
+
* Set only during the env→secrets transition phase / in tests. */
|
|
121
122
|
readonly webhookSecret?: string;
|
|
122
|
-
/** Bridge-fallback
|
|
123
|
-
* `subscription-stripe:config:api-key
|
|
123
|
+
/** Bridge-fallback API key. Optional: v2 reads from the
|
|
124
|
+
* `subscription-stripe:config:api-key` key (backing:"secrets"). */
|
|
124
125
|
readonly apiKey?: string;
|
|
125
|
-
/** Price-to-tier
|
|
126
|
-
* (subscription.items.data[0].price.id)
|
|
127
|
-
* App-
|
|
128
|
-
* → null (event ignored). */
|
|
126
|
+
/** Price-to-tier mapping. The plugin reads the price ID from the Stripe
|
|
127
|
+
* event (subscription.items.data[0].price.id) and maps it to a tier name.
|
|
128
|
+
* App-specific, so it remains a factory option. If the price ID is absent
|
|
129
|
+
* from the mapping → null (event ignored). */
|
|
129
130
|
readonly priceToTier?: Readonly<Record<string, string>>;
|
|
130
131
|
/** Whether a mode:"payment" checkout (one-off top-ups etc.) gets a Stripe
|
|
131
132
|
* invoice — a receipt/invoice document Stripe generates and sends to the
|
|
@@ -161,11 +162,11 @@ function validateOneOffPriceIds(priceIds: readonly string[]): void {
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/**
|
|
164
|
-
* Factory
|
|
165
|
-
* key-presence
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* extension
|
|
165
|
+
* Factory for the subscription-stripe feature. Always mounts (no
|
|
166
|
+
* key-presence guard) — activity is gated at runtime through config/secrets
|
|
167
|
+
* (following the feature-toggles pattern). The returned FeatureDefinition
|
|
168
|
+
* registers the plugin under billing-foundation's "subscriptionProvider"
|
|
169
|
+
* extension with entityName "stripe".
|
|
169
170
|
*/
|
|
170
171
|
export function createSubscriptionStripeFeature(
|
|
171
172
|
options: SubscriptionStripeOptions = {},
|
|
@@ -192,15 +193,15 @@ export function createSubscriptionStripeFeature(
|
|
|
192
193
|
// the value lives envelope-encrypted in the secrets store under
|
|
193
194
|
// SYSTEM_TENANT_ID, while `mask` derives the sysadmin settings screen +
|
|
194
195
|
// Settings-Hub nav (no hand-written r.screen/r.nav in the consuming app).
|
|
195
|
-
// billingLive is the
|
|
196
|
+
// billingLive is the master switch. The factory-fallback
|
|
196
197
|
// (options.apiKey/.webhookSecret) covers the env→secrets bridge + tests.
|
|
197
198
|
const configKeys = r.config({
|
|
198
199
|
keys: {
|
|
199
200
|
[STRIPE_API_KEY_CONFIG]: createSystemConfig("text", {
|
|
200
201
|
backing: "secrets",
|
|
201
|
-
// Prefix
|
|
202
|
-
//
|
|
203
|
-
// base62
|
|
202
|
+
// Prefix guard, matching subscriptionStripeEnvSchema:
|
|
203
|
+
// catches the wrong-field paste error (pk_/price_) without
|
|
204
|
+
// constraining the base62 body. Anchored, with no backtracking → no ReDoS.
|
|
204
205
|
pattern: { regex: "^(sk|rk)_(test|live)_" },
|
|
205
206
|
write: access.systemAdmin,
|
|
206
207
|
read: access.admin,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Public API of the subscription-stripe bundled
|
|
1
|
+
// Public API of the subscription-stripe bundled feature.
|
|
2
2
|
//
|
|
3
|
-
// **Internal-only** (
|
|
4
|
-
// - StripeWebhookOptions / verifyAndParseStripeWebhook (
|
|
5
|
-
// feature.ts factory
|
|
6
|
-
// - mapStripeEventType / mapStripeStatus (pure helpers,
|
|
7
|
-
//
|
|
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
|
|
|
9
9
|
export {
|
|
10
10
|
STRIPE_PROVIDER_NAME,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
// Stripe
|
|
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
|
-
//
|
|
6
|
-
// SubscriptionProviderPlugin
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
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
|
|
13
|
-
//
|
|
14
|
-
// <SubscriptionProviderPlugin["...method"]>>[1]`).
|
|
15
|
-
//
|
|
16
|
-
//
|
|
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
|
|
|
18
18
|
import { createHash } from "node:crypto";
|
|
19
19
|
import {
|
|
@@ -30,15 +30,10 @@ import Stripe from "stripe";
|
|
|
30
30
|
import type { StripeCtxRuntime } from "./runtime.ts";
|
|
31
31
|
import { isResourceMissingStripeError, mapStripeSubscriptionState } from "./verify-webhook.ts";
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// Stripe-Checkout-Session erstellen. Der hosted-page-URL wird returnt;
|
|
38
|
-
// der App-Builder redirected den Tenant-Admin dorthin. Nach erfolgreichem
|
|
39
|
-
// checkout sendet Stripe `customer.subscription.created` mit
|
|
40
|
-
// `metadata.tenantId` zurück — das ist wie der subsequent webhook den
|
|
41
|
-
// Tenant resolved.
|
|
33
|
+
// Create a Stripe Checkout Session and return its hosted-page URL for the
|
|
34
|
+
// app builder to redirect the tenant admin. After checkout, Stripe sends
|
|
35
|
+
// `customer.subscription.created` with `metadata.tenantId`; the subsequent
|
|
36
|
+
// webhook uses it to resolve the tenant.
|
|
42
37
|
|
|
43
38
|
export type StripeCheckoutOptions = Parameters<
|
|
44
39
|
NonNullable<SubscriptionProviderPlugin["createCheckoutSession"]>
|
|
@@ -120,11 +115,11 @@ export function createStripeCheckoutSession(
|
|
|
120
115
|
{ paymentInvoiceCreation = true }: StripeCheckoutSessionRuntimeOptions = {},
|
|
121
116
|
) {
|
|
122
117
|
return async (ctx: HandlerContext, options: StripeCheckoutOptions): Promise<{ url: string }> => {
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
// billing-live-config-key write
|
|
118
|
+
// Invariant: without billing-live, no Stripe session may be created
|
|
119
|
+
// (sk_test_-keys in production would otherwise create a test-mode checkout).
|
|
120
|
+
// Throw before every Stripe call. The guard used to be provided by the
|
|
121
|
+
// unmounted plugin; Stripe is now always mounted, so the
|
|
122
|
+
// billing-live-config-key gates the write side.
|
|
128
123
|
await runtime.assertBillingLive(ctx);
|
|
129
124
|
const stripe = await runtime.clientForCtx(ctx);
|
|
130
125
|
const mode = options.mode ?? "subscription";
|
|
@@ -49,7 +49,7 @@ export function createStripeClientCache(): (apiKey: string) => Stripe {
|
|
|
49
49
|
const cached = cache.get(apiKey);
|
|
50
50
|
if (cached) return cached;
|
|
51
51
|
// No apiVersion pin — a string literal breaks consumers' typecheck on newer
|
|
52
|
-
// stripe SDKs
|
|
52
|
+
// stripe SDKs; the SDK's own default keeps wire-version and types aligned.
|
|
53
53
|
const client = new Stripe(apiKey);
|
|
54
54
|
cache.set(apiKey, client);
|
|
55
55
|
return client;
|
|
@@ -83,7 +83,7 @@ function parseStoredSecret(raw: string | undefined): string | undefined {
|
|
|
83
83
|
export type StripeCtxRuntime = {
|
|
84
84
|
readonly clientForCtx: (ctx: HandlerContext) => Promise<Stripe>;
|
|
85
85
|
/** Throws FeatureDisabledError unless `billing-live` config is true. The
|
|
86
|
-
*
|
|
86
|
+
* invariant: no Stripe session may be created while billing is not
|
|
87
87
|
* live (sk_test_ keys in prod must not produce a live checkout).
|
|
88
88
|
* `handlerName` names the write-handler in the thrown error — defaults to
|
|
89
89
|
* "create-checkout-session" for existing callers, but plan-switch/portal
|