@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
|
@@ -150,8 +150,8 @@ export function createEnableConfirmPreauthHandler(opts: EnableConfirmPreauthOpti
|
|
|
150
150
|
// re-enrollment until an operator manually disables MFA. NOT fixed by
|
|
151
151
|
// this ordering: burnToken() above still runs before this check, so a
|
|
152
152
|
// mid-flight restricted/deleted user still burns their setup token
|
|
153
|
-
//
|
|
154
|
-
//
|
|
153
|
+
// — moving the burn later would need care around the
|
|
154
|
+
// existing userId-unique-constraint backstop between the
|
|
155
155
|
// `existing` check above and executor.create() below.
|
|
156
156
|
const systemUser = createSystemUser(tenantId, ["SystemAdmin"]);
|
|
157
157
|
const userRow = (await ctx.queryAs(systemUser, UserQueries.findForAuth, {
|
|
@@ -207,10 +207,10 @@ export function createEnableConfirmPreauthHandler(opts: EnableConfirmPreauthOpti
|
|
|
207
207
|
id: userId,
|
|
208
208
|
tenantId,
|
|
209
209
|
roles: mergedRoles,
|
|
210
|
-
// This endpoint logs the user in directly
|
|
210
|
+
// This endpoint logs the user in directly, so a stored
|
|
211
211
|
// timezone must survive the preauth-MFA-enrollment login just like
|
|
212
212
|
// a plain password login does — same helper as verify.write.ts /
|
|
213
|
-
// invite-accept-with-login.write.ts
|
|
213
|
+
// invite-accept-with-login.write.ts.
|
|
214
214
|
...sessionTimezoneField(userRow?.timezone),
|
|
215
215
|
...sessionLocaleField(userRow?.locale),
|
|
216
216
|
};
|
|
@@ -56,8 +56,8 @@ export function createEnableConfirmHandler(opts: EnableConfirmOptions) {
|
|
|
56
56
|
// already rules that out).
|
|
57
57
|
if (verify.payload.userId !== event.user.id) return invalidSetupToken();
|
|
58
58
|
|
|
59
|
-
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts
|
|
60
|
-
//
|
|
59
|
+
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts:
|
|
60
|
+
// session-authed (lower risk — the caller already has a
|
|
61
61
|
// valid JWT), but silently skipping the single-use burn here would
|
|
62
62
|
// still let a double-confirm race complete twice instead of the
|
|
63
63
|
// second seeing invalidSetupToken(). Checked before the TOTP verify
|
|
@@ -55,7 +55,7 @@ export function createEnableStartPreauthHandler(opts: EnableStartPreauthOptions)
|
|
|
55
55
|
);
|
|
56
56
|
// Same generic "sign in again" error as an expired/invalid MFA
|
|
57
57
|
// challenge token — both mean the login-flow token expired, no
|
|
58
|
-
// distinct i18n needed
|
|
58
|
+
// distinct i18n needed.
|
|
59
59
|
if (!verified.ok) return invalidChallengeToken();
|
|
60
60
|
const { userId, tenantId } = verified.payload;
|
|
61
61
|
|
|
@@ -154,7 +154,7 @@ export async function mfaReencryptJob(
|
|
|
154
154
|
|
|
155
155
|
// After PII peel (when configured), values must be current-cipher
|
|
156
156
|
// envelopes — non-JSON/non-envelope is not a supported legacy decrypt
|
|
157
|
-
// path
|
|
157
|
+
// path, matching config behavior.
|
|
158
158
|
const totpClass = classifyStoredEnvelope(envelopeValues.totpSecret, targetVersion);
|
|
159
159
|
const recoveryClass = classifyStoredEnvelope(envelopeValues.recoveryCodes, targetVersion);
|
|
160
160
|
if (totpClass === "unrecognized" || recoveryClass === "unrecognized") {
|
|
@@ -47,11 +47,11 @@ export function createRegenerateRecoveryHandler(opts: RegenerateRecoveryOptions)
|
|
|
47
47
|
// count, since either way the presented code is consumed/irrelevant
|
|
48
48
|
// afterward.
|
|
49
49
|
//
|
|
50
|
-
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
50
|
+
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts:
|
|
51
|
+
// without ctx.redis, verifyMfaFactor's TOTP-replay burn is skipped,
|
|
52
|
+
// letting an observed code be replayed within the ±1-step window to
|
|
53
|
+
// regenerate (and thus invalidate) recovery codes — a session-authed
|
|
54
|
+
// route, so pre-unwiring JWTs stay a valid attack path.
|
|
55
55
|
if (!ctx.redis) {
|
|
56
56
|
return writeFailure(
|
|
57
57
|
new InternalError({
|
|
@@ -67,7 +67,7 @@ export function createMfaVerifyHandler(opts: MfaVerifyOptions) {
|
|
|
67
67
|
if (!verified.ok) return invalidChallengeToken();
|
|
68
68
|
const { userId, tenantId } = verified.payload;
|
|
69
69
|
|
|
70
|
-
// Fail closed, matching enable-confirm-preauth.write.ts
|
|
70
|
+
// Fail closed, matching enable-confirm-preauth.write.ts:
|
|
71
71
|
// this route sits behind a challenge token from a successful login,
|
|
72
72
|
// but its own secret is still just a short TOTP/recovery code —
|
|
73
73
|
// silently skipping the brute-force cap and single-use burn when
|
|
@@ -18,7 +18,7 @@ const CHALLENGE_TOKEN_PURPOSE = "mfa-challenge-token-v1";
|
|
|
18
18
|
|
|
19
19
|
// A blank or whitespace-only override is treated as absent — an empty env
|
|
20
20
|
// var (MFA_SETUP_TOKEN_SECRET="") must fall back to derivation, not sign
|
|
21
|
-
// tokens with an empty/near-empty HMAC key
|
|
21
|
+
// tokens with an empty/near-empty HMAC key.
|
|
22
22
|
function resolveSecret(override: string | undefined, fallback: () => string): string {
|
|
23
23
|
return override !== undefined && override.trim() !== "" ? override : fallback();
|
|
24
24
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Client
|
|
1
|
+
// Client feature factory for auth-mfa — mirrors emailPasswordClient()'s
|
|
2
2
|
// shape so apps register both the same way:
|
|
3
3
|
// createKumikoApp({ clientFeatures: [emailPasswordClient(), authMfaClient()] }).
|
|
4
4
|
// No gates: MfaVerifyScreen isn't a route gate, it's a state swap wired
|
|
@@ -12,7 +12,7 @@ import type { ComponentType, ReactNode } from "react";
|
|
|
12
12
|
import { defaultTranslations, mergeTranslations } from "./i18n.ts";
|
|
13
13
|
|
|
14
14
|
export type AuthMfaClientOptions = {
|
|
15
|
-
/** Key
|
|
15
|
+
/** Key overrides per locale, merged with the default bundles (de/en). */
|
|
16
16
|
readonly translations?: TranslationsByLocale;
|
|
17
17
|
};
|
|
18
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Default
|
|
2
|
-
// authMfaClient()
|
|
3
|
-
// Keys
|
|
1
|
+
// Default bundles for the auth-mfa feature UI, merged by
|
|
2
|
+
// authMfaClient() analogously to emailPasswordClient() from auth-email-password.
|
|
3
|
+
// Keys follow `auth.mfa.<area>.<slug>`.
|
|
4
4
|
|
|
5
5
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// Public exports
|
|
2
|
-
//
|
|
3
|
-
// (defineFeature)
|
|
4
|
-
// password/web/index.ts
|
|
1
|
+
// Public exports for the browser side of the auth-mfa feature. The subpath
|
|
2
|
+
// export `@cosmicdrift/kumiko-bundled-features/auth-mfa/web` keeps the server
|
|
3
|
+
// side (`defineFeature`) free of React/DOM dependencies, matching the same
|
|
4
|
+
// separation in auth-email-password/web/index.ts.
|
|
5
5
|
|
|
6
6
|
export type { AuthMfaClientFeature, AuthMfaClientOptions } from "./client-plugin.ts";
|
|
7
7
|
export { authMfaClient } from "./client-plugin.ts";
|
|
@@ -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
|
|
|
9
9
|
// kumiko-lint-ignore cross-feature-import client-only types, the feature's server barrel has no web/ re-export
|
|
10
10
|
import {
|
|
@@ -76,11 +76,12 @@ export type MfaSetupPreauthStartResult =
|
|
|
76
76
|
| { readonly kind: "success"; readonly data: MfaSetupPreauthStart }
|
|
77
77
|
| { readonly kind: "failure"; readonly error: LoginFailure };
|
|
78
78
|
|
|
79
|
-
// Browser
|
|
79
|
+
// Browser side of POST /api/auth/mfa/preauth-enable-start — lets a user
|
|
80
80
|
// blocked at login by MFA enforcement generate a TOTP secret/QR without a
|
|
81
|
-
// session, using the preauthSetupToken login()'s
|
|
82
|
-
//
|
|
83
|
-
//
|
|
81
|
+
// session, using the preauthSetupToken carried by login()'s
|
|
82
|
+
// mfa-setup-required result. No JWT/cookie is issued here (see the route
|
|
83
|
+
// comment in auth-routes.ts); the response's
|
|
84
|
+
// setupToken is consumed by confirmMfaSetupPreauth below.
|
|
84
85
|
export async function startMfaSetupPreauth(
|
|
85
86
|
preauthSetupToken: string,
|
|
86
87
|
accountLabel: string,
|
|
@@ -139,12 +140,12 @@ export async function startMfaSetupPreauth(
|
|
|
139
140
|
};
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
// Browser
|
|
143
|
-
//
|
|
144
|
-
// required block.
|
|
145
|
-
// the same mintSessionAndRespond()
|
|
146
|
-
//
|
|
147
|
-
//
|
|
143
|
+
// Browser side of POST /api/auth/mfa/preauth-confirm — completes both the
|
|
144
|
+
// enrollment started by startMfaSetupPreauth and the login
|
|
145
|
+
// mfa-setup-required block. Its response mirrors /auth/mfa/verify's and is
|
|
146
|
+
// minted via the same mintSessionAndRespond(). It remains a separate function
|
|
147
|
+
// so this file's two already-tested request shapes stay independently
|
|
148
|
+
// editable.
|
|
148
149
|
export async function confirmMfaSetupPreauth(
|
|
149
150
|
setupToken: string,
|
|
150
151
|
code: string,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// Login
|
|
2
|
-
// (/auth/login
|
|
3
|
-
// useState
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// Login challenge step, rendered when LoginScreen's onMfaChallenge fires
|
|
2
|
+
// (/auth/login returned mfaRequired). It follows login-screen.tsx:
|
|
3
|
+
// useState plus a direct fetch call, without a dispatcher because no JWT
|
|
4
|
+
// exists yet. After success, it calls session.refresh() instead of a hard
|
|
5
|
+
// reload so the caller (typically wizard state in the app root) can render
|
|
6
|
+
// immediately when status:"authenticated" arrives.
|
|
7
7
|
|
|
8
8
|
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
9
9
|
import { type FormEvent, type ReactNode, useState } from "react";
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
2
|
|
|
3
|
-
// Fixed UUID
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// __tests__/feature.test.ts pinnt die UUID.
|
|
3
|
+
// Fixed UUID namespace for deterministic aggregate-id derivation.
|
|
4
|
+
// Generated once and immutable: changing it would re-key every existing
|
|
5
|
+
// aggregate stream, breaking subscription state and audit history. The drift
|
|
6
|
+
// pin in __tests__/feature.test.ts locks the UUID.
|
|
8
7
|
|
|
9
|
-
/**
|
|
8
|
+
/** Exactly one subscription aggregate exists per platform tenant. */
|
|
10
9
|
const SUBSCRIPTION_NAMESPACE = "5c3b2d1e-9a4f-4e8c-b7a3-1f8d6c2e9a4b";
|
|
11
10
|
|
|
12
11
|
/** Exactly ONE payment-aggregate-stream exists per platform tenant (it
|
|
@@ -26,11 +25,11 @@ const PAYMENT_ROW_NAMESPACE = "3a1c9f4e-6b2d-4c8a-9e5f-7d4b1a2c8e6f";
|
|
|
26
25
|
const TERMINATION_UNMATCHED_NAMESPACE = "7e2f4b9a-3c1d-4a68-8d05-b6c9e1f27a34";
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
|
-
* Deterministic aggregate
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* Stripe→Mollie
|
|
33
|
-
*
|
|
28
|
+
* Deterministic aggregate ID for a platform tenant's subscription. Exactly
|
|
29
|
+
* one subscription exists per tenant; add-ons are line items in that
|
|
30
|
+
* subscription, not separate aggregates. A provider change, such as a
|
|
31
|
+
* Stripe→Mollie migration, appends a new event to the same stream because
|
|
32
|
+
* the tenant and aggregate stream remain the same.
|
|
34
33
|
*/
|
|
35
34
|
// @wrapper-known uuid-domain
|
|
36
35
|
export function subscriptionAggregateId(tenantId: string): string {
|
|
@@ -4,39 +4,39 @@ import {
|
|
|
4
4
|
createTextField,
|
|
5
5
|
createTimestampField,
|
|
6
6
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
7
|
-
// `subscription` — current state
|
|
7
|
+
// `subscription` — current state per platform tenant (= read model)
|
|
8
8
|
// =============================================================================
|
|
9
9
|
//
|
|
10
|
-
// Inline
|
|
11
|
-
// apply (
|
|
12
|
-
//
|
|
10
|
+
// Inline projection target. Written by the `subscription` projection-
|
|
11
|
+
// apply (see feature.ts), NEVER directly by the handler. Source of truth is
|
|
12
|
+
// the event-store stream `subscription` with aggregate-id =
|
|
13
13
|
// uuidv5(SUBSCRIPTION_NAMESPACE, tenantId).
|
|
14
14
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
15
|
+
// ONE row per platform tenant. The aggregate ID is deterministic so that
|
|
16
|
+
// webhook replays (Stripe sends up to 5 times in 4 hours when delivery is
|
|
17
|
+
// stalled) write to the same stream instead of creating two rows.
|
|
18
18
|
//
|
|
19
|
-
// **
|
|
20
|
-
// - providerName: "stripe" / "mollie" —
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// - providerCustomerId / providerSubscriptionId: provider-
|
|
24
|
-
// IDs.
|
|
19
|
+
// **Fields:**
|
|
20
|
+
// - providerName: "stripe" / "mollie" — the provider holding the
|
|
21
|
+
// subscription. A provider change is a new event on the same stream;
|
|
22
|
+
// the projection overwrites the value.
|
|
23
|
+
// - providerCustomerId / providerSubscriptionId: provider-specific IDs.
|
|
25
24
|
// - status: active / past_due / canceled / trialing / incomplete —
|
|
26
|
-
//
|
|
27
|
-
// - tier: "free" / "pro" / ... —
|
|
28
|
-
// price-to-tier
|
|
29
|
-
// - currentPeriodEnd:
|
|
25
|
+
// normalized across providers.
|
|
26
|
+
// - tier: "free" / "pro" / ... — consumed by the tier engine. Resolved
|
|
27
|
+
// from the price-to-tier map in the plugin.
|
|
28
|
+
// - currentPeriodEnd: when the current billing period ends.
|
|
30
29
|
// - cancelAt: when a scheduled cancellation ends the subscription;
|
|
31
30
|
// nullable because a renewing subscription has none.
|
|
32
31
|
//
|
|
33
|
-
// **
|
|
34
|
-
// - invoice-history, payment-method, line-items, tax-info
|
|
35
|
-
//
|
|
32
|
+
// **Not included here:**
|
|
33
|
+
// - invoice-history, payment-method, line-items, tax-info — the tenant
|
|
34
|
+
// fetches all of these directly from the provider via a
|
|
35
|
+
// customer-portal-session.
|
|
36
36
|
//
|
|
37
|
-
// **Audit/event
|
|
38
|
-
// stream —
|
|
39
|
-
// audit
|
|
37
|
+
// **Audit/event history:** lives in the event store under the `subscription`
|
|
38
|
+
// stream — there is NO separate `subscription-event` table (= ES is the
|
|
39
|
+
// audit source of truth and can be replayed through upcasters).
|
|
40
40
|
export const subscriptionEntity = createEntity({
|
|
41
41
|
table: "read_subscriptions",
|
|
42
42
|
fields: {
|
|
@@ -47,10 +47,10 @@ export const subscriptionEntity = createEntity({
|
|
|
47
47
|
reason: "technical_reference",
|
|
48
48
|
}),
|
|
49
49
|
// `personal: "tenant"` (not `encrypted`): the field must crypto-shred when
|
|
50
|
-
// eraseSubjectKeys erases the tenant's subject key on tenant-destroy
|
|
51
|
-
//
|
|
50
|
+
// eraseSubjectKeys erases the tenant's subject key on tenant-destroy.
|
|
51
|
+
// `encrypted: true` uses the app-wide master key instead — that
|
|
52
52
|
// key is never erased per-tenant, so it would only add encryption-at-
|
|
53
|
-
// rest, not the erasure guarantee
|
|
53
|
+
// rest, not the erasure guarantee.
|
|
54
54
|
// maxLength 1000, not 200: the stored value is PII-ciphertext
|
|
55
55
|
// (`kumiko-pii:v1:<subject>:<blob>`), not the raw provider id — a
|
|
56
56
|
// 200-char plaintext id becomes ~300+ chars of ciphertext. Matches
|
|
@@ -112,7 +112,7 @@ export const paymentEntity = createEntity({
|
|
|
112
112
|
reason: "technical_reference",
|
|
113
113
|
}),
|
|
114
114
|
// Same `personal: "tenant"` rationale as subscriptionEntity above —
|
|
115
|
-
// crypto-shreds on tenant-destroy
|
|
115
|
+
// crypto-shreds on tenant-destroy via eraseSubjectKeys.
|
|
116
116
|
providerCustomerId: createTextField({
|
|
117
117
|
required: true,
|
|
118
118
|
maxLength: 1000,
|
|
@@ -1,25 +1,25 @@
|
|
|
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
|
|
|
13
13
|
import * as z from "zod";
|
|
14
14
|
import { BILLING_FOUNDATION_FEATURE, SubscriptionStatuses } from "./web/constants.ts";
|
|
15
15
|
import { CONSENT_LOCALES } from "./web/consumer-protection/consent-locale.ts";
|
|
16
16
|
|
|
17
|
-
// Aggregate
|
|
18
|
-
//
|
|
17
|
+
// Aggregate type for the event store. One subscription per tenant is
|
|
18
|
+
// one stream; the subscriptionAggregateId helper provides the stream ID.
|
|
19
19
|
export const SUBSCRIPTION_AGGREGATE_TYPE = "subscription" as const;
|
|
20
20
|
|
|
21
|
-
// Event-name
|
|
22
|
-
// FQN (
|
|
21
|
+
// Event-name constants — short form (for r.defineEvent) and qualified
|
|
22
|
+
// FQN (for ctx.unsafeAppendEvent and projection-apply keys).
|
|
23
23
|
export const SUBSCRIPTION_CREATED_EVENT_SHORT = "subscription-created" as const;
|
|
24
24
|
export const SUBSCRIPTION_UPDATED_EVENT_SHORT = "subscription-updated" as const;
|
|
25
25
|
export const SUBSCRIPTION_CANCELED_EVENT_SHORT = "subscription-canceled" as const;
|
|
@@ -37,7 +37,7 @@ export const INVOICE_PAID_EVENT_QN =
|
|
|
37
37
|
export const INVOICE_PAYMENT_FAILED_EVENT_QN =
|
|
38
38
|
`${BILLING_FOUNDATION_FEATURE}:event:${INVOICE_PAYMENT_FAILED_EVENT_SHORT}` as const;
|
|
39
39
|
|
|
40
|
-
// Status
|
|
40
|
+
// Status enum for event payloads (= the provider's subscription-state snapshot).
|
|
41
41
|
const statusEnum = z.enum([
|
|
42
42
|
SubscriptionStatuses.active,
|
|
43
43
|
SubscriptionStatuses.trialing,
|
|
@@ -46,10 +46,11 @@ const statusEnum = z.enum([
|
|
|
46
46
|
SubscriptionStatuses.incomplete,
|
|
47
47
|
]);
|
|
48
48
|
|
|
49
|
-
// Common payload —
|
|
50
|
-
// snapshot.
|
|
49
|
+
// Common payload — all five events carry the same subscription-state
|
|
50
|
+
// snapshot. The event type identifies what happened; the payload contains
|
|
51
|
+
// the resulting state.
|
|
51
52
|
// The raw provider event is deliberately not stored: it carries plaintext
|
|
52
|
-
// PII and event headers
|
|
53
|
+
// PII, and event headers cannot be crypto-shredded.
|
|
53
54
|
export const subscriptionEventPayloadSchema = z.object({
|
|
54
55
|
providerName: z.string().min(1).max(50),
|
|
55
56
|
// 1000, not 200: these two are `tenantOwned: true` on the entity (see
|
|
@@ -72,10 +73,10 @@ export const subscriptionEventPayloadSchema = z.object({
|
|
|
72
73
|
});
|
|
73
74
|
export type SubscriptionEventPayload = z.infer<typeof subscriptionEventPayloadSchema>;
|
|
74
75
|
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
// Idempotency
|
|
78
|
-
//
|
|
76
|
+
// Header shape — persisted in the event store as event.metadata.headers
|
|
77
|
+
// (an open-shape JSONB column containing primitives only).
|
|
78
|
+
// Idempotency anchor: providerEventId is checked per provider before append
|
|
79
|
+
// to determine whether it has already been seen.
|
|
79
80
|
export type SubscriptionEventHeaders = {
|
|
80
81
|
readonly providerEventId: string;
|
|
81
82
|
readonly providerName: string;
|
|
@@ -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
|
|
|
53
52
|
import {
|
|
54
53
|
defineFeature,
|
|
@@ -199,19 +198,19 @@ export function createBillingFoundationFeature<TTier extends string = string>(
|
|
|
199
198
|
},
|
|
200
199
|
});
|
|
201
200
|
|
|
202
|
-
// Plugin extension
|
|
201
|
+
// Plugin extension point. Provider plugins register here.
|
|
203
202
|
r.extendsRegistrar(SUBSCRIPTION_PROVIDER_EXTENSION, {
|
|
204
203
|
onRegister: () => {
|
|
205
204
|
// No side-effects at register-time.
|
|
206
205
|
},
|
|
207
206
|
});
|
|
208
207
|
|
|
209
|
-
// Custom write
|
|
210
|
-
// - process-event: programmatic entry
|
|
211
|
-
//
|
|
208
|
+
// Custom write handlers:
|
|
209
|
+
// - process-event: programmatic entry point called by the webhook
|
|
210
|
+
// handler; dispatches to the type-matched appendEvent
|
|
212
211
|
// - create-checkout-session: bare priceId-driven checkout (hardened,
|
|
213
212
|
// see checkout-core)
|
|
214
|
-
// - create-portal-session: Tenant
|
|
213
|
+
// - create-portal-session: Tenant Admin "Manage Subscription" flow
|
|
215
214
|
r.writeHandler(createProcessEventHandler(widened.now));
|
|
216
215
|
r.writeHandler(createCheckoutSessionHandler(widened));
|
|
217
216
|
r.writeHandler(createPortalSessionHandler(widened));
|
|
@@ -1,6 +1,4 @@
|
|
|
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
|
|
|
5
3
|
import {
|
|
6
4
|
configuredPiiSubjectKms,
|
|
@@ -27,9 +25,9 @@ export type SubscriptionView = {
|
|
|
27
25
|
readonly lastChangedAt: Temporal.Instant;
|
|
28
26
|
};
|
|
29
27
|
|
|
30
|
-
/**
|
|
31
|
-
* aggregate
|
|
32
|
-
*
|
|
28
|
+
/** Returns the tenant's only subscription row (deterministic
|
|
29
|
+
* aggregate ID), or null if the tenant has never subscribed. The status
|
|
30
|
+
* may be active/canceled/past_due/etc.; the caller decides what to do. */
|
|
33
31
|
export async function getSubscriptionForTenant(
|
|
34
32
|
ctx: HandlerContext,
|
|
35
33
|
tenantId: string,
|