@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
package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts
CHANGED
|
@@ -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
|
|
@@ -51,12 +51,13 @@ const createCheckoutSessionSchema = z.object({
|
|
|
51
51
|
providerName: z.string().min(1).max(50),
|
|
52
52
|
/** Provider-eigene price/plan-ID. */
|
|
53
53
|
priceId: z.string().min(1).max(200),
|
|
54
|
-
/**
|
|
54
|
+
/** Where the customer lands after a successful checkout. */
|
|
55
55
|
successUrl: z.string().url(),
|
|
56
|
-
/**
|
|
56
|
+
/** Where the customer lands if they cancel. */
|
|
57
57
|
cancelUrl: z.string().url(),
|
|
58
|
-
/** Optional:
|
|
59
|
-
*
|
|
58
|
+
/** Optional: existing provider customer when the tenant already
|
|
59
|
+
* has an account with the provider (= plan change instead of a new
|
|
60
|
+
* registration). */
|
|
60
61
|
providerCustomerId: z.string().max(200).optional(),
|
|
61
62
|
/** Optional: `"payment"` for a one-off checkout (e.g. credit top-up)
|
|
62
63
|
* instead of a recurring subscription. Defaults to `"subscription"`. */
|
package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts
CHANGED
|
@@ -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
|
|
|
16
15
|
import {
|
|
17
16
|
configuredPiiSubjectKms,
|
package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts
CHANGED
|
@@ -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 {
|
|
6
6
|
configuredPiiSubjectKms,
|
|
7
7
|
decryptPiiFieldValues,
|
|
@@ -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
|
|
|
15
15
|
import {
|
|
16
16
|
configuredPiiSubjectKms,
|
|
@@ -42,9 +42,9 @@ import {
|
|
|
42
42
|
} from "../web/constants.ts";
|
|
43
43
|
|
|
44
44
|
// =============================================================================
|
|
45
|
-
// Input
|
|
46
|
-
//
|
|
47
|
-
// programmatic
|
|
45
|
+
// Input schema = the normalized SubscriptionEvent (without tenantId, which
|
|
46
|
+
// comes from event.user.tenantId — the webhook handler sets the
|
|
47
|
+
// programmatic user with the tenantId resolved by the plugin).
|
|
48
48
|
// =============================================================================
|
|
49
49
|
|
|
50
50
|
const eventTypeSchema = z.enum([
|
|
@@ -208,9 +208,9 @@ export async function appendSubscriptionEvent(
|
|
|
208
208
|
// read_subscriptions row with a single call. The subject is the
|
|
209
209
|
// TENANT (tenantOwned) — tenant-destroy's subject-keys stage
|
|
210
210
|
// (eraseSubjectKeys) erases exactly this key, so both copies become
|
|
211
|
-
// genuinely unreadable
|
|
211
|
+
// genuinely unreadable once that stage runs, not just
|
|
212
212
|
// "encrypted at rest". No adapter configured = engine off (fields
|
|
213
|
-
// stay plaintext
|
|
213
|
+
// stay plaintext) — mirrors how the
|
|
214
214
|
// event-store-executor treats an absent piiKms().
|
|
215
215
|
// ---------------------------------------------------------------
|
|
216
216
|
const piiKms = configuredPiiSubjectKms();
|
|
@@ -268,9 +268,9 @@ export async function appendSubscriptionEvent(
|
|
|
268
268
|
// Handler
|
|
269
269
|
// =============================================================================
|
|
270
270
|
//
|
|
271
|
-
// SystemAdmin-only:
|
|
272
|
-
// webhook
|
|
273
|
-
//
|
|
271
|
+
// SystemAdmin-only: this handler is called exclusively by the programmatic
|
|
272
|
+
// webhook handler (with an internal SystemUser), never directly by the
|
|
273
|
+
// tenant admin.
|
|
274
274
|
// One subscription aggregate exists per tenant, but a tenant can legitimately hold two provider
|
|
275
275
|
// subscriptions over time (a stale `incomplete` one superseded by a fresh checkout). A late or
|
|
276
276
|
// retried event of the old subscription must not overwrite the row of the live one, so an event of a
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// Inline
|
|
2
|
-
// subscription
|
|
1
|
+
// Inline projection for `read_subscriptions`. Materializes the 5
|
|
2
|
+
// subscription events into one row per tenant.
|
|
3
3
|
//
|
|
4
|
-
// Apply
|
|
5
|
-
//
|
|
6
|
-
// aggregateId (= deterministic uuidv5
|
|
7
|
-
//
|
|
4
|
+
// Apply runs in the same transaction as ctx.unsafeAppendEvent, so the caller
|
|
5
|
+
// sees its write state immediately (no dispatcher tick required). The PK is
|
|
6
|
+
// event.aggregateId (= deterministic uuidv5 per tenant), so replays collide
|
|
7
|
+
// on the PK instead of creating duplicate rows.
|
|
8
8
|
//
|
|
9
|
-
// **Production-deployment caveat:**
|
|
10
|
-
// `samples/apps/platform/drizzle/generate.ts`
|
|
11
|
-
// `subscriptionsProjectionTable`
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
9
|
+
// **Production-deployment caveat:** the generator in
|
|
10
|
+
// `samples/apps/platform/drizzle/generate.ts` scans `feature.entities` —
|
|
11
|
+
// `subscriptionsProjectionTable` is registered in the projection as a raw
|
|
12
|
+
// drizzle-pgTable, NOT as r.entity. Apps mounting subscription-foundation in
|
|
13
|
+
// production must add the table to their own `drizzle/generate.ts` (via an
|
|
14
|
+
// import of subscriptionsProjectionTable). setupTestStack pushes it
|
|
15
|
+
// automatically via r.projection.table.
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
buildEntityTable,
|
|
@@ -26,9 +26,9 @@ import { paymentRowId } from "./aggregate-id.ts";
|
|
|
26
26
|
import { paymentEntity, subscriptionEntity } from "./entities.ts";
|
|
27
27
|
import type { PaymentEventPayload, SubscriptionEventPayload } from "./events.ts";
|
|
28
28
|
|
|
29
|
-
// Drizzle
|
|
30
|
-
//
|
|
31
|
-
//
|
|
29
|
+
// This Drizzle table instance is derived from the entity shape and is shared
|
|
30
|
+
// by the projection apply, list query, and get helper so all three use the
|
|
31
|
+
// same column namespace.
|
|
32
32
|
export const subscriptionsProjectionTable = buildEntityTable("subscription", subscriptionEntity);
|
|
33
33
|
|
|
34
34
|
// Same production-deployment caveat as subscriptionsProjectionTable above:
|
|
@@ -38,11 +38,11 @@ export const paymentsProjectionTable = buildEntityTable("payment", paymentEntity
|
|
|
38
38
|
|
|
39
39
|
// Unbranded metas: the apply functions below ARE the executor of these
|
|
40
40
|
// projections, so they may write through the typed helpers.
|
|
41
|
-
const subscriptionsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
|
|
41
|
+
export const subscriptionsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
|
|
42
42
|
subscriptionsProjectionTable,
|
|
43
43
|
"subscription",
|
|
44
44
|
);
|
|
45
|
-
const paymentsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
|
|
45
|
+
export const paymentsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
|
|
46
46
|
paymentsProjectionTable,
|
|
47
47
|
"payment",
|
|
48
48
|
);
|
|
@@ -99,10 +99,10 @@ async function upsert(
|
|
|
99
99
|
}>,
|
|
100
100
|
fullPayload: SubscriptionEventPayload,
|
|
101
101
|
): Promise<void> {
|
|
102
|
-
// INSERT
|
|
103
|
-
//
|
|
104
|
-
// status+tier),
|
|
105
|
-
//
|
|
102
|
+
// The INSERT fallback requires ALL fields because of NOT NULL constraints.
|
|
103
|
+
// If an update changes only some fields (for example, invoice-payment-failed
|
|
104
|
+
// changes only status+tier), the full payload is still used for the INSERT
|
|
105
|
+
// path, while only the partial `set` is used for ON CONFLICT.
|
|
106
106
|
const insertCols = {
|
|
107
107
|
id: event.aggregateId,
|
|
108
108
|
tenantId: event.tenantId,
|
|
@@ -123,23 +123,23 @@ async function upsert(
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// =============================================================================
|
|
126
|
-
// Apply
|
|
126
|
+
// Apply functions — one per event type
|
|
127
127
|
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
128
|
+
// All use UPSERT for defensive consistency: an out-of-order event (for
|
|
129
|
+
// example, during a rebuild-from-events) can arrive in any order and still
|
|
130
|
+
// materialize the row correctly.
|
|
131
131
|
// =============================================================================
|
|
132
132
|
|
|
133
|
-
/** subscription-created → UPSERT
|
|
134
|
-
* subscriptionAggregateId(tenantId), one row
|
|
135
|
-
* Disney+-
|
|
136
|
-
*
|
|
133
|
+
/** subscription-created → UPSERT with all fields. PK = aggregateId =
|
|
134
|
+
* subscriptionAggregateId(tenantId), with one row per tenant. UPSERT allows
|
|
135
|
+
* the Disney+-change pattern (a second provider sends create for the same
|
|
136
|
+
* tenant) to overwrite the existing row instead of causing a PK conflict. */
|
|
137
137
|
export const applySubscriptionCreated = defineApply<SubscriptionEventPayload>(async (event, tx) => {
|
|
138
138
|
const full = fullSetFromPayload(event.payload);
|
|
139
139
|
await upsert(tx, event, { ...full, ...cancelAtSetFromPayload(event.payload) }, event.payload);
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
/** subscription-updated → UPSERT
|
|
142
|
+
/** subscription-updated → UPSERT with all fields. */
|
|
143
143
|
export const applySubscriptionUpdated = defineApply<SubscriptionEventPayload>(async (event, tx) => {
|
|
144
144
|
const full = fullSetFromPayload(event.payload);
|
|
145
145
|
await upsert(tx, event, { ...full, ...cancelAtSetFromPayload(event.payload) }, event.payload);
|
|
@@ -163,8 +163,9 @@ export const applySubscriptionCanceled = defineApply<SubscriptionEventPayload>(
|
|
|
163
163
|
},
|
|
164
164
|
);
|
|
165
165
|
|
|
166
|
-
/** invoice-paid → state
|
|
167
|
-
*
|
|
166
|
+
/** invoice-paid → state update (status, tier, currentPeriodEnd).
|
|
167
|
+
* The invoice history itself lives in the event store, so it remains
|
|
168
|
+
* replayable. */
|
|
168
169
|
export const applyInvoicePaid = defineApply<SubscriptionEventPayload>(async (event, tx) => {
|
|
169
170
|
const p = event.payload;
|
|
170
171
|
await upsert(
|
|
@@ -180,10 +181,10 @@ export const applyInvoicePaid = defineApply<SubscriptionEventPayload>(async (eve
|
|
|
180
181
|
);
|
|
181
182
|
});
|
|
182
183
|
|
|
183
|
-
/** invoice-payment-failed → status (
|
|
184
|
-
* engine
|
|
185
|
-
*
|
|
186
|
-
*
|
|
184
|
+
/** invoice-payment-failed → status (typically past_due) + tier. The tier
|
|
185
|
+
* engine reads the row and decides whether to downgrade. currentPeriodEnd is
|
|
186
|
+
* intentionally unchanged: the period has not "ended"; payment simply
|
|
187
|
+
* failed. */
|
|
187
188
|
export const applyInvoicePaymentFailed = defineApply<SubscriptionEventPayload>(
|
|
188
189
|
async (event, tx) => {
|
|
189
190
|
const p = event.payload;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generic Stripe/PayPal-webhook → tier-engine sync route. Extracted from the
|
|
2
|
-
// near-identical webhook-route.ts app copies in show-pony and publicstatus
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// near-identical webhook-route.ts app copies in show-pony and publicstatus — the
|
|
3
|
+
// only per-app variables were the TierName union/default, so it is now a factory
|
|
4
|
+
// parameter.
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
isTierAssignmentSource,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { EntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
|
|
2
1
|
import { declareEscapeHatch, type TenantDataHookCtx } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
2
|
import { archiveStream } from "@cosmicdrift/kumiko-framework/event-store";
|
|
4
3
|
import { resolveProfileForTenant } from "../compliance-profiles/index.ts";
|
|
5
4
|
import { paymentAggregateId, subscriptionAggregateId } from "./aggregate-id.ts";
|
|
6
5
|
import { PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE } from "./events.ts";
|
|
7
|
-
import {
|
|
6
|
+
import { paymentsProjectionMeta, subscriptionsProjectionMeta } from "./projection.ts";
|
|
8
7
|
|
|
9
8
|
// providerCustomerId/providerSubscriptionId are `personal: "tenant"` on the
|
|
10
9
|
// entity (envelope-encrypted with the tenant subject key, see entities.ts) —
|
|
@@ -19,7 +18,7 @@ export const SUBSCRIPTION_TENANT_DESTROY_ARCHIVE_REASON =
|
|
|
19
18
|
export const PAYMENT_TENANT_DESTROY_ARCHIVE_REASON =
|
|
20
19
|
"tenant-destroy looks up the compliance profile and archives the payment event-stream before the projection rows are redacted/deleted";
|
|
21
20
|
|
|
22
|
-
/** Tenant-destroy hook for billing PII
|
|
21
|
+
/** Tenant-destroy hook for billing PII. HGB retains the accounting
|
|
23
22
|
* row but redacts the two provider-subject PII fields; other profiles
|
|
24
23
|
* hard-delete the row. Either way the subscription stream is archived so a
|
|
25
24
|
* future projection rebuild can't resurrect what was erased. */
|
|
@@ -32,12 +31,12 @@ export async function subscriptionTenantDestroyHook(ctx: TenantDataHookCtx): Pro
|
|
|
32
31
|
const aggregateId = subscriptionAggregateId(ctx.tenantId);
|
|
33
32
|
if (profile.key === "de-hr-dsgvo-hgb") {
|
|
34
33
|
await ctx.db.updateMany(
|
|
35
|
-
|
|
34
|
+
subscriptionsProjectionMeta,
|
|
36
35
|
{ providerCustomerId: REDACTED_PII_VALUE, providerSubscriptionId: REDACTED_PII_VALUE },
|
|
37
36
|
{ id: aggregateId },
|
|
38
37
|
);
|
|
39
38
|
} else {
|
|
40
|
-
await ctx.db.deleteMany(
|
|
39
|
+
await ctx.db.deleteMany(subscriptionsProjectionMeta, { id: aggregateId });
|
|
41
40
|
}
|
|
42
41
|
await archiveStream(ctx.db.unsafeRaw(), {
|
|
43
42
|
tenantId: ctx.tenantId,
|
|
@@ -48,7 +47,7 @@ export async function subscriptionTenantDestroyHook(ctx: TenantDataHookCtx): Pro
|
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
/** Tenant-destroy hook for payment PII
|
|
50
|
+
/** Tenant-destroy hook for payment PII. Unlike subscriptionTenantDestroyHook
|
|
52
51
|
* (one row per tenant, targeted by `id`), a tenant can have many payment
|
|
53
52
|
* rows — the predicate here is `tenantId`, not `id`. The payment-stream
|
|
54
53
|
* itself is still one stream per tenant (paymentAggregateId), so
|
|
@@ -62,12 +61,12 @@ export async function paymentTenantDestroyHook(ctx: TenantDataHookCtx): Promise<
|
|
|
62
61
|
const aggregateId = paymentAggregateId(ctx.tenantId);
|
|
63
62
|
if (profile.key === "de-hr-dsgvo-hgb") {
|
|
64
63
|
await ctx.db.updateMany(
|
|
65
|
-
|
|
64
|
+
paymentsProjectionMeta,
|
|
66
65
|
{ providerCustomerId: REDACTED_PII_VALUE },
|
|
67
66
|
{ tenantId: ctx.tenantId },
|
|
68
67
|
);
|
|
69
68
|
} else {
|
|
70
|
-
await ctx.db.deleteMany(
|
|
69
|
+
await ctx.db.deleteMany(paymentsProjectionMeta, {
|
|
71
70
|
tenantId: ctx.tenantId,
|
|
72
71
|
});
|
|
73
72
|
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
|
-
// Plugin
|
|
3
|
-
//
|
|
4
|
-
// `SubscriptionProviderPlugin`
|
|
2
|
+
// Plugin contract and domain types for subscription-foundation. Provider
|
|
3
|
+
// plugins (subscription-stripe, subscription-mollie, ...) implement
|
|
4
|
+
// `SubscriptionProviderPlugin` and register via
|
|
5
5
|
// `r.useExtension("subscriptionProvider", "<name>", { build })`.
|
|
6
6
|
//
|
|
7
7
|
// **Two-phase plugin contract:**
|
|
8
|
-
// 1. **Pre-tenant-resolution:** `verifyAndParseWebhook`
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// Stripe-/PayPal-
|
|
12
|
-
// secret
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// SYSTEM_TENANT_ID. Plugins
|
|
17
|
-
//
|
|
8
|
+
// 1. **Pre-tenant-resolution:** `verifyAndParseWebhook` runs BEFORE
|
|
9
|
+
// a tenant is resolved from the event, so no HandlerContext is
|
|
10
|
+
// available. The **webhook secret is app-wide** (the App Owner's
|
|
11
|
+
// Stripe-/PayPal-account, not tenant-specific). To let a plugin read
|
|
12
|
+
// the secret from the secrets feature AT RUNTIME (instead of a
|
|
13
|
+
// mount-time closure), the webhook handler passes an optional
|
|
14
|
+
// system-scoped `SecretsContext` as the third argument. The plugin
|
|
15
|
+
// reads its app-wide secrets from it without auditing under
|
|
16
|
+
// SYSTEM_TENANT_ID. Plugins that keep their keys in a closure
|
|
17
|
+
// (e.g. mollie) ignore the parameter → backward-compatible.
|
|
18
18
|
// 2. **Post-tenant-resolution:** `createPortalSession` +
|
|
19
|
-
// `cancelSubscription`
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
19
|
+
// `cancelSubscription` are called from regular write handlers with
|
|
20
|
+
// a fully resolved HandlerContext. The plugin can use ctx.config +
|
|
21
|
+
// ctx.secrets for tenant-specific configuration (e.g. tenant-owned
|
|
22
|
+
// customer-id mappings).
|
|
23
23
|
//
|
|
24
|
-
// Foundation
|
|
25
|
-
// proration, multi-currency, coupons etc.
|
|
26
|
-
//
|
|
24
|
+
// Foundation uses only the common subset of provider functionality;
|
|
25
|
+
// proration, multi-currency, coupons, etc. remain provider-specific and
|
|
26
|
+
// are available through the Customer Portal link.
|
|
27
27
|
|
|
28
28
|
import type { TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
29
29
|
import type { HandlerContext, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -41,12 +41,12 @@ import {
|
|
|
41
41
|
import type { ConsentLocale } from "./web/consumer-protection/consent-locale.ts";
|
|
42
42
|
|
|
43
43
|
// =============================================================================
|
|
44
|
-
//
|
|
44
|
+
// Normalized Webhook Event
|
|
45
45
|
// =============================================================================
|
|
46
46
|
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
47
|
+
// The plugin parses the raw provider payload and returns this shape.
|
|
48
|
+
// Foundation has no direct knowledge of Stripe-/Mollie-types; the plugin
|
|
49
|
+
// provides the abstraction.
|
|
50
50
|
|
|
51
51
|
export type SubscriptionEvent = {
|
|
52
52
|
/** Discriminator against PaymentEvent. Optional (instead of required) so
|
|
@@ -55,32 +55,31 @@ export type SubscriptionEvent = {
|
|
|
55
55
|
* `parsed.kind === BillingEventKinds.payment` correctly, because only
|
|
56
56
|
* PaymentEvent["kind"] can take that value. */
|
|
57
57
|
readonly kind?: typeof BillingEventKinds.subscription;
|
|
58
|
-
/** Provider-
|
|
59
|
-
* Stripe: "evt_..."; Mollie: payment-id
|
|
58
|
+
/** Provider-owned event ID — UNIQUE key for idempotency.
|
|
59
|
+
* Stripe: "evt_..."; Mollie: payment-id or subscription-id. */
|
|
60
60
|
readonly providerEventId: string;
|
|
61
61
|
/** Discriminator — welcher Plugin diesen Event geliefert hat. */
|
|
62
62
|
readonly providerName: string;
|
|
63
63
|
/** Normalisierter Event-Type. Plugin filtert provider-spezifische
|
|
64
64
|
* Sub-Types raus (Stripe hat ~80 Event-types, wir kennen 5). */
|
|
65
65
|
readonly type: SubscriptionEventType;
|
|
66
|
-
/**
|
|
67
|
-
*
|
|
66
|
+
/** Platform tenant ID (provider-customer metadata or lookup via
|
|
67
|
+
* providerCustomerId). The plugin performs the resolution. */
|
|
68
68
|
readonly tenantId: string;
|
|
69
69
|
/** Consent id echoed back from checkout metadata; omitted when absent or
|
|
70
70
|
* malformed. */
|
|
71
71
|
readonly consentId?: string;
|
|
72
|
-
/** Provider-
|
|
73
|
-
*
|
|
72
|
+
/** Provider-owned customer ID for later lookup when events lack
|
|
73
|
+
* metadata. */
|
|
74
74
|
readonly providerCustomerId: string;
|
|
75
75
|
/** Provider-eigene subscription-id. */
|
|
76
76
|
readonly providerSubscriptionId: string;
|
|
77
77
|
/** Normalisierter status. */
|
|
78
78
|
readonly status: SubscriptionStatus;
|
|
79
|
-
/** Resolved tier —
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* ignore"). */
|
|
79
|
+
/** Resolved tier — the plugin reads the price ID from the event and
|
|
80
|
+
* maps it through the plugin's `<plugin>:config:price-to-tier` to a
|
|
81
|
+
* tier name. If the price ID is absent from the mapping, the plugin
|
|
82
|
+
* returns null from verifyAndParseWebhook (= "unknown event, ignore"). */
|
|
84
83
|
readonly tier: string;
|
|
85
84
|
/** ISO-timestamp wann die aktuelle Billing-Period endet. */
|
|
86
85
|
readonly currentPeriodEnd: string;
|
|
@@ -172,32 +171,32 @@ export type SubscriptionProviderPlugin = {
|
|
|
172
171
|
) => Promise<SubscriptionEvent | PaymentEvent | null>;
|
|
173
172
|
|
|
174
173
|
/**
|
|
175
|
-
* **Post-tenant-resolution** —
|
|
176
|
-
* `create-checkout-session
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
174
|
+
* **Post-tenant-resolution** — called from the
|
|
175
|
+
* `create-checkout-session` write handler. The plugin builds a
|
|
176
|
+
* provider-specific checkout session and returns its hosted-page URL;
|
|
177
|
+
* the tenant admin is redirected there to complete payment, and the
|
|
178
|
+
* provider sends a `subscription.created` webhook with
|
|
179
|
+
* `metadata.tenantId`.
|
|
181
180
|
*
|
|
182
|
-
* Optional: Apple-IAP
|
|
183
|
-
* Apps
|
|
181
|
+
* Optional: Apple-IAP has no web checkout (everything happens in the app).
|
|
182
|
+
* Apps that use only Apple-IAP omit this field.
|
|
184
183
|
*/
|
|
185
184
|
readonly createCheckoutSession?: (
|
|
186
185
|
ctx: HandlerContext,
|
|
187
186
|
options: {
|
|
188
|
-
/** Provider-
|
|
187
|
+
/** Provider-owned price/plan ID that the customer subscribes to. */
|
|
189
188
|
readonly priceId: string;
|
|
190
|
-
/**
|
|
191
|
-
*
|
|
192
|
-
* `verifyAndParseWebhook`
|
|
189
|
+
/** Platform tenant ID — stored as metadata in the checkout session
|
|
190
|
+
* so the subsequent webhook can resolve the tenant (see the
|
|
191
|
+
* `verifyAndParseWebhook` metadata.tenantId lookup). */
|
|
193
192
|
readonly tenantId: string;
|
|
194
|
-
/**
|
|
193
|
+
/** Where the customer lands after a successful checkout. */
|
|
195
194
|
readonly successUrl: string;
|
|
196
|
-
/**
|
|
195
|
+
/** Where the customer lands if they cancel. */
|
|
197
196
|
readonly cancelUrl: string;
|
|
198
|
-
/** Optional:
|
|
199
|
-
*
|
|
200
|
-
*
|
|
197
|
+
/** Optional: existing provider customer ID when the tenant already
|
|
198
|
+
* has an account with the provider. Otherwise, the provider
|
|
199
|
+
* creates a new customer during checkout. */
|
|
201
200
|
readonly providerCustomerId?: string;
|
|
202
201
|
/** Checkout mode. `"subscription"` (default) starts a recurring
|
|
203
202
|
* billing flow; `"payment"` a one-off checkout (e.g. pay-per-use
|
|
@@ -215,17 +214,17 @@ export type SubscriptionProviderPlugin = {
|
|
|
215
214
|
) => Promise<{ readonly url: string }>;
|
|
216
215
|
|
|
217
216
|
/**
|
|
218
|
-
* **Post-tenant-resolution** —
|
|
219
|
-
*
|
|
217
|
+
* **Post-tenant-resolution** — called from a write handler with a
|
|
218
|
+
* fully resolved ctx. Creates a self-service Portal link.
|
|
220
219
|
* Stripe: customer-portal-session, Mollie: hosted-management-page.
|
|
221
|
-
*
|
|
222
|
-
* (cancel, payment
|
|
220
|
+
* The tenant admin uses it to manage the subscription themselves
|
|
221
|
+
* (cancel, payment method, ...).
|
|
223
222
|
*
|
|
224
|
-
* Optional
|
|
225
|
-
* (Apple-IAP managed
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
223
|
+
* Optional because not every provider has a Portal pattern
|
|
224
|
+
* (Apple-IAP subscriptions are managed in the Apple app, with no web
|
|
225
|
+
* Portal). A plugin that does not support this can omit the field;
|
|
226
|
+
* the foundation then returns a "portal_not_supported" error when a
|
|
227
|
+
* tenant admin requests the Portal link.
|
|
229
228
|
*/
|
|
230
229
|
readonly createPortalSession?: (
|
|
231
230
|
ctx: HandlerContext,
|
|
@@ -236,10 +235,10 @@ export type SubscriptionProviderPlugin = {
|
|
|
236
235
|
) => Promise<{ readonly url: string }>;
|
|
237
236
|
|
|
238
237
|
/**
|
|
239
|
-
* Optional:
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
238
|
+
* Optional: in-app cancellation API. If not implemented, the tenant
|
|
239
|
+
* can cancel only through the Customer Portal link (or not at all if
|
|
240
|
+
* createPortalSession is also missing — the cancellation flow is then
|
|
241
|
+
* provider-dashboard-only).
|
|
243
242
|
*/
|
|
244
243
|
readonly cancelSubscription?: (
|
|
245
244
|
ctx: HandlerContext,
|
|
@@ -78,10 +78,10 @@ function manageOrReactivateAction(
|
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/** `!canPurchase` hides every CTA outright (
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
81
|
+
/** `!canPurchase` hides every CTA outright (see `purchaseNotAllowed`) — distinct
|
|
82
|
+
* from the `unavailable` action's disabled CTA, which still shows a button
|
|
83
|
+
* (for example, when a plan's price failed to load), so this check runs
|
|
84
|
+
* before the general unavailable fallback. */
|
|
85
85
|
|
|
86
86
|
function planCta(
|
|
87
87
|
plan: BillingPlanView,
|
|
@@ -95,7 +95,7 @@ export function createSubscriptionWebhookRoute(options: SubscriptionWebhookRoute
|
|
|
95
95
|
return c.json({ ignored: true }, 200);
|
|
96
96
|
}
|
|
97
97
|
const parsed = verified.event;
|
|
98
|
-
const tenantId = parsed.tenantId
|
|
98
|
+
const tenantId = parsed.tenantId;
|
|
99
99
|
if (parsed.kind === BillingEventKinds.payment) {
|
|
100
100
|
const dispatched = await deps.dispatchSystemWrite({
|
|
101
101
|
handlerQn: SubscriptionFoundationHandlers.processPaymentEvent,
|