@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.
- package/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.js +0 -2
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Browser
|
|
2
|
-
// login LoginScreen started when the server responded mfaRequired.
|
|
3
|
-
// fetch/CSRF pattern as auth-email-password's login()
|
|
4
|
-
//
|
|
1
|
+
// Browser side of POST /api/auth/mfa/verify — completes the two-step
|
|
2
|
+
// login that LoginScreen started when the server responded with mfaRequired.
|
|
3
|
+
// Uses the same fetch/CSRF pattern as auth-email-password's login(), but runs
|
|
4
|
+
// before a session exists, so it does not call csrfHeader(). The response is
|
|
5
5
|
// byte-identical to /auth/login's ({isSuccess, token, user} | {isSuccess:
|
|
6
|
-
// false, error})
|
|
7
|
-
//
|
|
6
|
+
// false, error}) because auth-routes.ts uses mintSessionAndRespond() for both
|
|
7
|
+
// routes.
|
|
8
8
|
// kumiko-lint-ignore cross-feature-import client-only types, the feature's server barrel has no web/ re-export
|
|
9
9
|
import { toLoginResponse, } from "../../auth-email-password/web/index.js";
|
|
10
10
|
export async function verifyMfaChallenge(challengeToken, code) {
|
|
@@ -40,11 +40,12 @@ export async function verifyMfaChallenge(challengeToken, code) {
|
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
// Browser
|
|
43
|
+
// Browser side of POST /api/auth/mfa/preauth-enable-start — lets a user
|
|
44
44
|
// blocked at login by MFA enforcement generate a TOTP secret/QR without a
|
|
45
|
-
// session, using the preauthSetupToken login()'s
|
|
46
|
-
//
|
|
47
|
-
//
|
|
45
|
+
// session, using the preauthSetupToken carried by login()'s
|
|
46
|
+
// mfa-setup-required result. No JWT/cookie is issued here (see the route
|
|
47
|
+
// comment in auth-routes.ts); the response's
|
|
48
|
+
// setupToken is consumed by confirmMfaSetupPreauth below.
|
|
48
49
|
export async function startMfaSetupPreauth(preauthSetupToken, accountLabel) {
|
|
49
50
|
const res = await fetch("/api/auth/mfa/preauth-enable-start", {
|
|
50
51
|
method: "POST",
|
|
@@ -85,12 +86,12 @@ export async function startMfaSetupPreauth(preauthSetupToken, accountLabel) {
|
|
|
85
86
|
},
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
|
-
// Browser
|
|
89
|
-
//
|
|
90
|
-
// required block.
|
|
91
|
-
// the same mintSessionAndRespond()
|
|
92
|
-
//
|
|
93
|
-
//
|
|
89
|
+
// Browser side of POST /api/auth/mfa/preauth-confirm — completes both the
|
|
90
|
+
// enrollment started by startMfaSetupPreauth and the login
|
|
91
|
+
// mfa-setup-required block. Its response mirrors /auth/mfa/verify's and is
|
|
92
|
+
// minted via the same mintSessionAndRespond(). It remains a separate function
|
|
93
|
+
// so this file's two already-tested request shapes stay independently
|
|
94
|
+
// editable.
|
|
94
95
|
export async function confirmMfaSetupPreauth(setupToken, code) {
|
|
95
96
|
const res = await fetch("/api/auth/mfa/preauth-confirm", {
|
|
96
97
|
method: "POST",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// Login
|
|
3
|
-
// (/auth/login
|
|
4
|
-
// useState
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
2
|
+
// Login challenge step, rendered when LoginScreen's onMfaChallenge fires
|
|
3
|
+
// (/auth/login returned mfaRequired). It follows login-screen.tsx:
|
|
4
|
+
// useState plus a direct fetch call, without a dispatcher because no JWT
|
|
5
|
+
// exists yet. After success, it calls session.refresh() instead of a hard
|
|
6
|
+
// reload so the caller (typically wizard state in the app root) can render
|
|
7
|
+
// immediately when status:"authenticated" arrives.
|
|
8
8
|
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
9
9
|
import { useState } from "react";
|
|
10
10
|
// kumiko-lint-ignore cross-feature-import client-only barrel, the feature's server barrel has no web/ re-export
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deterministic aggregate
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Stripe→Mollie
|
|
6
|
-
*
|
|
2
|
+
* Deterministic aggregate ID for a platform tenant's subscription. Exactly
|
|
3
|
+
* one subscription exists per tenant; add-ons are line items in that
|
|
4
|
+
* subscription, not separate aggregates. A provider change, such as a
|
|
5
|
+
* Stripe→Mollie migration, appends a new event to the same stream because
|
|
6
|
+
* the tenant and aggregate stream remain the same.
|
|
7
7
|
*/
|
|
8
8
|
export declare function subscriptionAggregateId(tenantId: string): string;
|
|
9
9
|
/**
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
|
-
// Fixed UUID
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
/** Pro Plattform-Tenant existiert genau EIN subscription-Aggregate. */
|
|
2
|
+
// Fixed UUID namespace for deterministic aggregate-id derivation.
|
|
3
|
+
// Generated once and immutable: changing it would re-key every existing
|
|
4
|
+
// aggregate stream, breaking subscription state and audit history. The drift
|
|
5
|
+
// pin in __tests__/feature.test.ts locks the UUID.
|
|
6
|
+
/** Exactly one subscription aggregate exists per platform tenant. */
|
|
8
7
|
const SUBSCRIPTION_NAMESPACE = "5c3b2d1e-9a4f-4e8c-b7a3-1f8d6c2e9a4b";
|
|
9
8
|
/** Exactly ONE payment-aggregate-stream exists per platform tenant (it
|
|
10
9
|
* collects many payment-received events — one stream per tenant, not one
|
|
@@ -20,11 +19,11 @@ const PAYMENT_ROW_NAMESPACE = "3a1c9f4e-6b2d-4c8a-9e5f-7d4b1a2c8e6f";
|
|
|
20
19
|
* declaration (one stream per request). Generated 2026-10-03, set in stone. */
|
|
21
20
|
const TERMINATION_UNMATCHED_NAMESPACE = "7e2f4b9a-3c1d-4a68-8d05-b6c9e1f27a34";
|
|
22
21
|
/**
|
|
23
|
-
* Deterministic aggregate
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Stripe→Mollie
|
|
27
|
-
*
|
|
22
|
+
* Deterministic aggregate ID for a platform tenant's subscription. Exactly
|
|
23
|
+
* one subscription exists per tenant; add-ons are line items in that
|
|
24
|
+
* subscription, not separate aggregates. A provider change, such as a
|
|
25
|
+
* Stripe→Mollie migration, appends a new event to the same stream because
|
|
26
|
+
* the tenant and aggregate stream remain the same.
|
|
28
27
|
*/
|
|
29
28
|
// @wrapper-known uuid-domain
|
|
30
29
|
export function subscriptionAggregateId(tenantId) {
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
import { collectPiiSubjectFields } from "@cosmicdrift/kumiko-framework/crypto";
|
|
2
2
|
import { createEntity, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
// `subscription` — current state
|
|
3
|
+
// `subscription` — current state per platform tenant (= read model)
|
|
4
4
|
// =============================================================================
|
|
5
5
|
//
|
|
6
|
-
// Inline
|
|
7
|
-
// apply (
|
|
8
|
-
//
|
|
6
|
+
// Inline projection target. Written by the `subscription` projection-
|
|
7
|
+
// apply (see feature.ts), NEVER directly by the handler. Source of truth is
|
|
8
|
+
// the event-store stream `subscription` with aggregate-id =
|
|
9
9
|
// uuidv5(SUBSCRIPTION_NAMESPACE, tenantId).
|
|
10
10
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// ONE row per platform tenant. The aggregate ID is deterministic so that
|
|
12
|
+
// webhook replays (Stripe sends up to 5 times in 4 hours when delivery is
|
|
13
|
+
// stalled) write to the same stream instead of creating two rows.
|
|
14
14
|
//
|
|
15
|
-
// **
|
|
16
|
-
// - providerName: "stripe" / "mollie" —
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// - providerCustomerId / providerSubscriptionId: provider-
|
|
20
|
-
// IDs.
|
|
15
|
+
// **Fields:**
|
|
16
|
+
// - providerName: "stripe" / "mollie" — the provider holding the
|
|
17
|
+
// subscription. A provider change is a new event on the same stream;
|
|
18
|
+
// the projection overwrites the value.
|
|
19
|
+
// - providerCustomerId / providerSubscriptionId: provider-specific IDs.
|
|
21
20
|
// - status: active / past_due / canceled / trialing / incomplete —
|
|
22
|
-
//
|
|
23
|
-
// - tier: "free" / "pro" / ... —
|
|
24
|
-
// price-to-tier
|
|
25
|
-
// - currentPeriodEnd:
|
|
21
|
+
// normalized across providers.
|
|
22
|
+
// - tier: "free" / "pro" / ... — consumed by the tier engine. Resolved
|
|
23
|
+
// from the price-to-tier map in the plugin.
|
|
24
|
+
// - currentPeriodEnd: when the current billing period ends.
|
|
26
25
|
// - cancelAt: when a scheduled cancellation ends the subscription;
|
|
27
26
|
// nullable because a renewing subscription has none.
|
|
28
27
|
//
|
|
29
|
-
// **
|
|
30
|
-
// - invoice-history, payment-method, line-items, tax-info
|
|
31
|
-
//
|
|
28
|
+
// **Not included here:**
|
|
29
|
+
// - invoice-history, payment-method, line-items, tax-info — the tenant
|
|
30
|
+
// fetches all of these directly from the provider via a
|
|
31
|
+
// customer-portal-session.
|
|
32
32
|
//
|
|
33
|
-
// **Audit/event
|
|
34
|
-
// stream —
|
|
35
|
-
// audit
|
|
33
|
+
// **Audit/event history:** lives in the event store under the `subscription`
|
|
34
|
+
// stream — there is NO separate `subscription-event` table (= ES is the
|
|
35
|
+
// audit source of truth and can be replayed through upcasters).
|
|
36
36
|
export const subscriptionEntity = createEntity({
|
|
37
37
|
table: "read_subscriptions",
|
|
38
38
|
fields: {
|
|
@@ -43,10 +43,10 @@ export const subscriptionEntity = createEntity({
|
|
|
43
43
|
reason: "technical_reference",
|
|
44
44
|
}),
|
|
45
45
|
// `personal: "tenant"` (not `encrypted`): the field must crypto-shred when
|
|
46
|
-
// eraseSubjectKeys erases the tenant's subject key on tenant-destroy
|
|
47
|
-
//
|
|
46
|
+
// eraseSubjectKeys erases the tenant's subject key on tenant-destroy.
|
|
47
|
+
// `encrypted: true` uses the app-wide master key instead — that
|
|
48
48
|
// key is never erased per-tenant, so it would only add encryption-at-
|
|
49
|
-
// rest, not the erasure guarantee
|
|
49
|
+
// rest, not the erasure guarantee.
|
|
50
50
|
// maxLength 1000, not 200: the stored value is PII-ciphertext
|
|
51
51
|
// (`kumiko-pii:v1:<subject>:<blob>`), not the raw provider id — a
|
|
52
52
|
// 200-char plaintext id becomes ~300+ chars of ciphertext. Matches
|
|
@@ -106,7 +106,7 @@ export const paymentEntity = createEntity({
|
|
|
106
106
|
reason: "technical_reference",
|
|
107
107
|
}),
|
|
108
108
|
// Same `personal: "tenant"` rationale as subscriptionEntity above —
|
|
109
|
-
// crypto-shreds on tenant-destroy
|
|
109
|
+
// crypto-shreds on tenant-destroy via eraseSubjectKeys.
|
|
110
110
|
providerCustomerId: createTextField({
|
|
111
111
|
required: true,
|
|
112
112
|
maxLength: 1000,
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
// Domain
|
|
1
|
+
// Domain events for subscription-foundation.
|
|
2
2
|
//
|
|
3
|
-
// **Pattern:** event-sourced —
|
|
4
|
-
//
|
|
5
|
-
// (=
|
|
6
|
-
//
|
|
3
|
+
// **Pattern:** event-sourced — each provider webhook (after plugin
|
|
4
|
+
// verification) becomes a domain event on the subscription stream
|
|
5
|
+
// (= one stream per tenant via subscriptionAggregateId(tenantId)).
|
|
6
|
+
// The read model is an inline projection in the `subscriptions` table.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
// bucket — events
|
|
10
|
-
// accounting-export, churn-analytics)
|
|
11
|
-
//
|
|
8
|
+
// Five fine-grained event types instead of a generic "webhook-received"
|
|
9
|
+
// bucket — events are business facts: future consumers (billing-history,
|
|
10
|
+
// accounting-export, churn-analytics) listen directly for the event type
|
|
11
|
+
// without a payload discriminator.
|
|
12
12
|
import * as z from "zod";
|
|
13
13
|
import { BILLING_FOUNDATION_FEATURE, SubscriptionStatuses } from "./web/constants.js";
|
|
14
14
|
import { CONSENT_LOCALES } from "./web/consumer-protection/consent-locale.js";
|
|
15
|
-
// Aggregate
|
|
16
|
-
//
|
|
15
|
+
// Aggregate type for the event store. One subscription per tenant is
|
|
16
|
+
// one stream; the subscriptionAggregateId helper provides the stream ID.
|
|
17
17
|
export const SUBSCRIPTION_AGGREGATE_TYPE = "subscription";
|
|
18
|
-
// Event-name
|
|
19
|
-
// FQN (
|
|
18
|
+
// Event-name constants — short form (for r.defineEvent) and qualified
|
|
19
|
+
// FQN (for ctx.unsafeAppendEvent and projection-apply keys).
|
|
20
20
|
export const SUBSCRIPTION_CREATED_EVENT_SHORT = "subscription-created";
|
|
21
21
|
export const SUBSCRIPTION_UPDATED_EVENT_SHORT = "subscription-updated";
|
|
22
22
|
export const SUBSCRIPTION_CANCELED_EVENT_SHORT = "subscription-canceled";
|
|
@@ -27,7 +27,7 @@ export const SUBSCRIPTION_UPDATED_EVENT_QN = `${BILLING_FOUNDATION_FEATURE}:even
|
|
|
27
27
|
export const SUBSCRIPTION_CANCELED_EVENT_QN = `${BILLING_FOUNDATION_FEATURE}:event:${SUBSCRIPTION_CANCELED_EVENT_SHORT}`;
|
|
28
28
|
export const INVOICE_PAID_EVENT_QN = `${BILLING_FOUNDATION_FEATURE}:event:${INVOICE_PAID_EVENT_SHORT}`;
|
|
29
29
|
export const INVOICE_PAYMENT_FAILED_EVENT_QN = `${BILLING_FOUNDATION_FEATURE}:event:${INVOICE_PAYMENT_FAILED_EVENT_SHORT}`;
|
|
30
|
-
// Status
|
|
30
|
+
// Status enum for event payloads (= the provider's subscription-state snapshot).
|
|
31
31
|
const statusEnum = z.enum([
|
|
32
32
|
SubscriptionStatuses.active,
|
|
33
33
|
SubscriptionStatuses.trialing,
|
|
@@ -35,10 +35,11 @@ const statusEnum = z.enum([
|
|
|
35
35
|
SubscriptionStatuses.canceled,
|
|
36
36
|
SubscriptionStatuses.incomplete,
|
|
37
37
|
]);
|
|
38
|
-
// Common payload —
|
|
39
|
-
// snapshot.
|
|
38
|
+
// Common payload — all five events carry the same subscription-state
|
|
39
|
+
// snapshot. The event type identifies what happened; the payload contains
|
|
40
|
+
// the resulting state.
|
|
40
41
|
// The raw provider event is deliberately not stored: it carries plaintext
|
|
41
|
-
// PII and event headers
|
|
42
|
+
// PII, and event headers cannot be crypto-shredded.
|
|
42
43
|
export const subscriptionEventPayloadSchema = z.object({
|
|
43
44
|
providerName: z.string().min(1).max(50),
|
|
44
45
|
// 1000, not 200: these two are `tenantOwned: true` on the entity (see
|
|
@@ -1,54 +1,53 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// subscription-foundation
|
|
3
|
+
// subscription-foundation as a Kumiko bundled feature (plugin host).
|
|
4
4
|
//
|
|
5
|
-
// **Multi-
|
|
6
|
-
// parallel
|
|
7
|
-
// subscription-apple-iap + ...)
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// aktiv.
|
|
5
|
+
// **Multi-provider from day one** — the app builder can mount multiple plugins
|
|
6
|
+
// in parallel (subscription-stripe + subscription-paypal +
|
|
7
|
+
// subscription-apple-iap + ...), and the end user chooses between
|
|
8
|
+
// card/PayPal/Apple Pay/Klarna/SEPA at checkout (Disney+ pattern).
|
|
9
|
+
// There is no global `provider` config key — all mounted plugins are active.
|
|
11
10
|
//
|
|
12
|
-
// **
|
|
13
|
-
// 1. **Plugin
|
|
11
|
+
// **What this foundation provides:**
|
|
12
|
+
// 1. **Plugin API** for subscription providers via `r.extendsRegistrar(
|
|
14
13
|
// "subscriptionProvider", ...)`.
|
|
15
|
-
// 2. **5
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// 3. **Inline
|
|
19
|
-
//
|
|
14
|
+
// 2. **5 domain events** on the `subscription` stream (one stream ID per
|
|
15
|
+
// tenant): created/updated/canceled/invoice-paid/invoice-payment-failed.
|
|
16
|
+
// Audit history is provided automatically by the event store.
|
|
17
|
+
// 3. **Inline projection** onto `read_subscriptions` (current state per
|
|
18
|
+
// tenant). Apply runs in the same TX as the event append
|
|
20
19
|
// → read-your-own-write semantics.
|
|
21
|
-
// 4. **process-event
|
|
22
|
-
// webhook
|
|
20
|
+
// 4. **process-event handler**: a programmatic write handler called by the
|
|
21
|
+
// webhook handler that dispatches to the type-matched appendEvent.
|
|
23
22
|
// 5. **createSubscriptionWebhookRoute**: factory for the `entry:"signature"`
|
|
24
23
|
// extraRoute `/api/subscription/webhook/:providerName`.
|
|
25
|
-
// 6. **payment-received event + read_payments projection**: one-off
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
24
|
+
// 6. **payment-received event + read_payments projection**: one-off payments
|
|
25
|
+
// (checkout mode "payment") get their own event, per-tenant aggregate,
|
|
26
|
+
// and `process-payment-event` write handler — not a sixth
|
|
27
|
+
// SubscriptionEventTypes value.
|
|
29
28
|
// 7. **Optional billing-plans catalog** (`createBillingFoundationFeature({
|
|
30
29
|
// baseUrl, catalog })`): a `billing-foundation:query:billing-plans`
|
|
31
|
-
// query plus `start-plan-checkout`/`switch-plan` write
|
|
30
|
+
// query plus `start-plan-checkout`/`switch-plan` write handlers and a
|
|
32
31
|
// dormant `billing-plans` dashboard screen/panel, all derived from the
|
|
33
|
-
//
|
|
32
|
+
// single `catalog` option — no separate per-app price wiring.
|
|
34
33
|
//
|
|
35
|
-
// **
|
|
36
|
-
// -
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// -
|
|
40
|
-
//
|
|
41
|
-
// -
|
|
42
|
-
// -
|
|
43
|
-
//
|
|
34
|
+
// **What this foundation does NOT do:**
|
|
35
|
+
// - No r.entity for `subscription`. The table is a read-only projection —
|
|
36
|
+
// there is no CRUD path. It is written exclusively via projection-apply,
|
|
37
|
+
// triggered by one of the 5 events.
|
|
38
|
+
// - No tier sync with tier-engine. App owners can read the subscription row
|
|
39
|
+
// via `getSubscriptionForTenant(ctx, tenantId)` if needed.
|
|
40
|
+
// - No provider-specific configs.
|
|
41
|
+
// - No marketplace use case (the app tenant bills end customers via Stripe
|
|
42
|
+
// Connect). That comes later as a separate `marketplace-foundation`.
|
|
44
43
|
//
|
|
45
|
-
// **Provider
|
|
46
|
-
//
|
|
47
|
-
// event
|
|
48
|
-
// existing row
|
|
49
|
-
// business
|
|
50
|
-
//
|
|
51
|
-
// `subscription-provider-changed
|
|
44
|
+
// **Provider changes:** The Disney+ pattern (the tenant cancels a Stripe
|
|
45
|
+
// subscription and starts a new one with PayPal) is currently modeled as a
|
|
46
|
+
// second `subscription-created` event. UPSERT in projection-apply overwrites
|
|
47
|
+
// the existing row with the new providerName. This is sufficient for the MVP.
|
|
48
|
+
// If the business fact "provider change" needs its own domain event (for
|
|
49
|
+
// example, for analytics such as "how many changes per month?"), a
|
|
50
|
+
// `subscription-provider-changed` event type can be added later.
|
|
52
51
|
import { defineFeature, EXT_TENANT_DATA, } from "@cosmicdrift/kumiko-framework/engine";
|
|
53
52
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
54
53
|
import { registerConsumerProtection } from "./consumer-protection/register-consent.js";
|
|
@@ -147,18 +146,18 @@ export function createBillingFoundationFeature(options = {}) {
|
|
|
147
146
|
[PAYMENT_RECEIVED_EVENT_QN]: applyPaymentReceived,
|
|
148
147
|
},
|
|
149
148
|
});
|
|
150
|
-
// Plugin extension
|
|
149
|
+
// Plugin extension point. Provider plugins register here.
|
|
151
150
|
r.extendsRegistrar(SUBSCRIPTION_PROVIDER_EXTENSION, {
|
|
152
151
|
onRegister: () => {
|
|
153
152
|
// No side-effects at register-time.
|
|
154
153
|
},
|
|
155
154
|
});
|
|
156
|
-
// Custom write
|
|
157
|
-
// - process-event: programmatic entry
|
|
158
|
-
//
|
|
155
|
+
// Custom write handlers:
|
|
156
|
+
// - process-event: programmatic entry point called by the webhook
|
|
157
|
+
// handler; dispatches to the type-matched appendEvent
|
|
159
158
|
// - create-checkout-session: bare priceId-driven checkout (hardened,
|
|
160
159
|
// see checkout-core)
|
|
161
|
-
// - create-portal-session: Tenant
|
|
160
|
+
// - create-portal-session: Tenant Admin "Manage Subscription" flow
|
|
162
161
|
r.writeHandler(createProcessEventHandler(widened.now));
|
|
163
162
|
r.writeHandler(createCheckoutSessionHandler(widened));
|
|
164
163
|
r.writeHandler(createPortalSessionHandler(widened));
|
|
@@ -15,7 +15,7 @@ export type SubscriptionView = {
|
|
|
15
15
|
* apply-function started stamping it from `event.createdAt`. */
|
|
16
16
|
readonly lastChangedAt: Temporal.Instant;
|
|
17
17
|
};
|
|
18
|
-
/**
|
|
19
|
-
* aggregate
|
|
20
|
-
*
|
|
18
|
+
/** Returns the tenant's only subscription row (deterministic
|
|
19
|
+
* aggregate ID), or null if the tenant has never subscribed. The status
|
|
20
|
+
* may be active/canceled/past_due/etc.; the caller decides what to do. */
|
|
21
21
|
export declare function getSubscriptionForTenant(ctx: HandlerContext, tenantId: string): Promise<SubscriptionView | null>;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
|
-
// Resolver-helper: liest die current subscription-row für einen Tenant
|
|
3
|
-
// aus der read_subscriptions-projection.
|
|
4
2
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
5
3
|
import { subscriptionAggregateId } from "./aggregate-id.js";
|
|
6
4
|
import { SUBSCRIPTION_PII_FIELDS } from "./entities.js";
|
|
7
5
|
import { subscriptionsProjectionTable } from "./projection.js";
|
|
8
|
-
/**
|
|
9
|
-
* aggregate
|
|
10
|
-
*
|
|
6
|
+
/** Returns the tenant's only subscription row (deterministic
|
|
7
|
+
* aggregate ID), or null if the tenant has never subscribed. The status
|
|
8
|
+
* may be active/canceled/past_due/etc.; the caller decides what to do. */
|
|
11
9
|
export async function getSubscriptionForTenant(ctx, tenantId) {
|
|
12
10
|
const aggId = subscriptionAggregateId(tenantId);
|
|
13
11
|
const rows = await ctx.db.selectMany(subscriptionsProjectionTable, { id: aggId }, { limit: 1 });
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// create-checkout-session — Tenant
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `plugin.createCheckoutSession(ctx, ...)`,
|
|
5
|
-
//
|
|
1
|
+
// create-checkout-session — Tenant admin clicks "Upgrade to Pro" (or
|
|
2
|
+
// chooses between card/PayPal/Apple Pay). The handler reads providerName
|
|
3
|
+
// from the payload, looks up the plugin, calls
|
|
4
|
+
// `plugin.createCheckoutSession(ctx, ...)`, and returns the hosted-page URL.
|
|
5
|
+
// The tenant admin is redirected there.
|
|
6
6
|
//
|
|
7
|
-
// **Multi-
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
7
|
+
// **Multi-provider path:** payload.providerName is the entityName
|
|
8
|
+
// of a registered plugin ("stripe" / "paypal" / "mollie" / ...).
|
|
9
|
+
// The app builder shows a UI list of mounted providers; the customer
|
|
10
|
+
// selects one, and this handler dispatches to the matching plugin.
|
|
11
11
|
//
|
|
12
|
-
// **Tenant
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
12
|
+
// **Tenant resolution:** ctx.user.tenantId is passed to the provider as
|
|
13
|
+
// metadata. On the subsequent webhook (subscription.created),
|
|
14
|
+
// verifyAndParseWebhook reads it back from the provider payload and
|
|
15
|
+
// resolves the tenant.
|
|
16
16
|
//
|
|
17
17
|
// **Hardening:** successUrl/cancelUrl must share `options.baseUrl`'s
|
|
18
18
|
// origin; mode:"subscription" requires priceId to be a known price of the
|
|
@@ -31,12 +31,13 @@ const createCheckoutSessionSchema = z.object({
|
|
|
31
31
|
providerName: z.string().min(1).max(50),
|
|
32
32
|
/** Provider-eigene price/plan-ID. */
|
|
33
33
|
priceId: z.string().min(1).max(200),
|
|
34
|
-
/**
|
|
34
|
+
/** Where the customer lands after a successful checkout. */
|
|
35
35
|
successUrl: z.string().url(),
|
|
36
|
-
/**
|
|
36
|
+
/** Where the customer lands if they cancel. */
|
|
37
37
|
cancelUrl: z.string().url(),
|
|
38
|
-
/** Optional:
|
|
39
|
-
*
|
|
38
|
+
/** Optional: existing provider customer when the tenant already
|
|
39
|
+
* has an account with the provider (= plan change instead of a new
|
|
40
|
+
* registration). */
|
|
40
41
|
providerCustomerId: z.string().max(200).optional(),
|
|
41
42
|
/** Optional: `"payment"` for a one-off checkout (e.g. credit top-up)
|
|
42
43
|
* instead of a recurring subscription. Defaults to `"subscription"`. */
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
// create-portal-session — Tenant
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `plugin.createPortalSession(ctx, ...)`,
|
|
1
|
+
// create-portal-session — Tenant admin clicks "Manage Subscription".
|
|
2
|
+
// The handler finds the tenant's current subscription, looks up the matching
|
|
3
|
+
// plugin (= the `subscription.providerName` column), calls
|
|
4
|
+
// `plugin.createPortalSession(ctx, ...)`, and returns the hosted portal URL.
|
|
5
5
|
//
|
|
6
|
-
// **Provider
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// kennt.
|
|
6
|
+
// **Provider resolution:** unlike create-checkout-session (where the tenant
|
|
7
|
+
// chooses a NEW provider when subscribing), the provider here is fixed by the
|
|
8
|
+
// existing subscription row. The tenant cannot access another provider's
|
|
9
|
+
// portal because the subscription does not belong to that provider.
|
|
11
10
|
//
|
|
12
|
-
// **returnUrl:** computed server-side via `portalReturnUrl` (catalog's
|
|
13
|
-
// returnPath, or baseUrl itself)
|
|
14
|
-
//
|
|
11
|
+
// **returnUrl:** computed server-side via `portalReturnUrl` (the catalog's
|
|
12
|
+
// returnPath, or baseUrl itself). The client no longer supplies one, so there
|
|
13
|
+
// is no client-controlled redirect to harden against.
|
|
15
14
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
16
15
|
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
17
16
|
import * as z from "zod";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// list-subscriptions — sysadmin
|
|
2
|
-
// `read_subscriptions
|
|
3
|
-
// subscription
|
|
4
|
-
// tenant-scoped
|
|
1
|
+
// list-subscriptions — sysadmin cross-tenant list query on the
|
|
2
|
+
// `read_subscriptions` projection. Tenant admins read their own
|
|
3
|
+
// subscription through the getSubscriptionForTenant helper (= ctx.db is
|
|
4
|
+
// tenant-scoped and automatically returns only the caller's row).
|
|
5
5
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { SUBSCRIPTION_PII_FIELDS } from "../entities.js";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
// process-event — programmatic write
|
|
2
|
-
// (createSubscriptionWebhookRoute)
|
|
3
|
-
//
|
|
1
|
+
// process-event — programmatic write handler called by the webhook handler
|
|
2
|
+
// (createSubscriptionWebhookRoute) AFTER the plugin has verified the raw body
|
|
3
|
+
// and normalized it into a SubscriptionEvent.
|
|
4
4
|
//
|
|
5
|
-
// **ES
|
|
6
|
-
// 1. Idempotency
|
|
7
|
-
//
|
|
8
|
-
// (Stripe
|
|
9
|
-
//
|
|
10
|
-
// 2. Type
|
|
11
|
-
// →
|
|
12
|
-
// 3. ctx.unsafeAppendEvent —
|
|
13
|
-
// `read_subscriptions
|
|
5
|
+
// **ES pattern:**
|
|
6
|
+
// 1. Idempotency check: loads the subscription stream and scans for an
|
|
7
|
+
// already-seen `metadata.providerEventId`. A provider replay
|
|
8
|
+
// (Stripe retry storm) has the same event ID → duplicate=true,
|
|
9
|
+
// with no second append.
|
|
10
|
+
// 2. Type mapping: SubscriptionEvent.type (= normalized by the plugin)
|
|
11
|
+
// → one of the 5 ES event types.
|
|
12
|
+
// 3. ctx.unsafeAppendEvent — the inline projection materializes the
|
|
13
|
+
// `read_subscriptions` row in the same TX.
|
|
14
14
|
import { configuredPiiSubjectKms, encryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
15
15
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
16
16
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
@@ -21,9 +21,9 @@ import { INVOICE_PAID_EVENT_QN, INVOICE_PAYMENT_FAILED_EVENT_QN, SUBSCRIPTION_AG
|
|
|
21
21
|
import { getSubscriptionForTenant } from "../get-subscription-for-tenant.js";
|
|
22
22
|
import { BILLING_SUBSCRIPTION_LOCK_NAMESPACE, isSubscriptionBlockingCheckout, isSwitchableSubscriptionStatus, SubscriptionEventTypes, SubscriptionStatuses, } from "../web/constants.js";
|
|
23
23
|
// =============================================================================
|
|
24
|
-
// Input
|
|
25
|
-
//
|
|
26
|
-
// programmatic
|
|
24
|
+
// Input schema = the normalized SubscriptionEvent (without tenantId, which
|
|
25
|
+
// comes from event.user.tenantId — the webhook handler sets the
|
|
26
|
+
// programmatic user with the tenantId resolved by the plugin).
|
|
27
27
|
// =============================================================================
|
|
28
28
|
const eventTypeSchema = z.enum([
|
|
29
29
|
SubscriptionEventTypes.created,
|
|
@@ -153,9 +153,9 @@ export async function appendSubscriptionEvent(ctx, tenantId, rawPayload, now = T
|
|
|
153
153
|
// read_subscriptions row with a single call. The subject is the
|
|
154
154
|
// TENANT (tenantOwned) — tenant-destroy's subject-keys stage
|
|
155
155
|
// (eraseSubjectKeys) erases exactly this key, so both copies become
|
|
156
|
-
// genuinely unreadable
|
|
156
|
+
// genuinely unreadable once that stage runs, not just
|
|
157
157
|
// "encrypted at rest". No adapter configured = engine off (fields
|
|
158
|
-
// stay plaintext
|
|
158
|
+
// stay plaintext) — mirrors how the
|
|
159
159
|
// event-store-executor treats an absent piiKms().
|
|
160
160
|
// ---------------------------------------------------------------
|
|
161
161
|
const piiKms = configuredPiiSubjectKms();
|
|
@@ -203,9 +203,9 @@ export async function appendSubscriptionEvent(ctx, tenantId, rawPayload, now = T
|
|
|
203
203
|
// Handler
|
|
204
204
|
// =============================================================================
|
|
205
205
|
//
|
|
206
|
-
// SystemAdmin-only:
|
|
207
|
-
// webhook
|
|
208
|
-
//
|
|
206
|
+
// SystemAdmin-only: this handler is called exclusively by the programmatic
|
|
207
|
+
// webhook handler (with an internal SystemUser), never directly by the
|
|
208
|
+
// tenant admin.
|
|
209
209
|
// One subscription aggregate exists per tenant, but a tenant can legitimately hold two provider
|
|
210
210
|
// subscriptions over time (a stale `incomplete` one superseded by a fresh checkout). A late or
|
|
211
211
|
// retried event of the old subscription must not overwrite the row of the live one, so an event of a
|