@cosmicdrift/kumiko-bundled-features 0.385.0 → 0.387.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.js +0 -2
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -11,7 +11,7 @@ export const TENANT_SETTINGS_FEATURE_NAME = "tenant-settings";
|
|
|
11
11
|
// strings (mirror tags' Handlers/Queries constants).
|
|
12
12
|
export const TenantSettingsConfig = {
|
|
13
13
|
// Shared with engine/constants.ts's TENANT_CURRENCY_CONFIG_KEY — a
|
|
14
|
-
// `money` field's `currency: { kind: "tenant" }` declaration
|
|
14
|
+
// `money` field's `currency: { kind: "tenant" }` declaration
|
|
15
15
|
// resolves against this same key.
|
|
16
16
|
currency: TENANT_CURRENCY_CONFIG_KEY,
|
|
17
17
|
locale: "tenant-settings:config:locale",
|
|
@@ -2,7 +2,7 @@ import { type AccessRule, type EntityDefinition, type WriteHandlerDef } from "@c
|
|
|
2
2
|
export declare function defineCreateWithTenantDefaults(entityName: string, entity: EntityDefinition, options: {
|
|
3
3
|
/** Required — this is a write-path helper; making it optional let a
|
|
4
4
|
* forgetful caller register a create handler with no access rule at
|
|
5
|
-
* all
|
|
5
|
+
* all. */
|
|
6
6
|
readonly access: AccessRule;
|
|
7
7
|
/** Money field names whose `currency` is filled from tenant-settings when missing. */
|
|
8
8
|
readonly currencyFields?: readonly string[];
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// a schema extension that makes those sub-keys optional, instead of the
|
|
9
9
|
// generic defineEntityCreateHandler.
|
|
10
10
|
import { buildInsertSchema, createEntityExecutor, } from "@cosmicdrift/kumiko-framework/engine";
|
|
11
|
+
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
12
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
11
13
|
import * as z from "zod";
|
|
12
14
|
import { TenantSettingsConfig } from "./constants.js";
|
|
13
15
|
const OPTIONAL_CURRENCY_MONEY = z.object({ amount: z.number(), currency: z.string().optional() });
|
|
@@ -31,10 +33,15 @@ export function defineCreateWithTenantDefaults(entityName, entity, options) {
|
|
|
31
33
|
schema,
|
|
32
34
|
access: options.access,
|
|
33
35
|
handler: async (event, ctx) => {
|
|
36
|
+
if (!isPlainObject(event.payload)) {
|
|
37
|
+
throw new InternalError({
|
|
38
|
+
message: `${entityName}:create payload must be an object after schema validation`,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
34
41
|
const payload = { ...event.payload };
|
|
35
42
|
for (const field of options.currencyFields ?? []) {
|
|
36
43
|
const value = payload[field];
|
|
37
|
-
if (value &&
|
|
44
|
+
if (isPlainObject(value) && !value["currency"]) {
|
|
38
45
|
const currency = await ctx.config?.(TenantSettingsConfig.currency);
|
|
39
46
|
if (typeof currency === "string")
|
|
40
47
|
payload[field] = { ...value, currency };
|
|
@@ -46,7 +53,7 @@ export function defineCreateWithTenantDefaults(entityName, entity, options) {
|
|
|
46
53
|
payload[options.localeField] = locale;
|
|
47
54
|
}
|
|
48
55
|
// Re-validate against the unrelaxed entity schema so config-filled
|
|
49
|
-
// values still honor select/enum field constraints
|
|
56
|
+
// values still honor select/enum field constraints — and so
|
|
50
57
|
// a missing currency after failed/missing tenant-settings mount fails
|
|
51
58
|
// loud instead of inserting half-filled money rows.
|
|
52
59
|
const filled = baseSchema.parse(payload);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deterministic aggregate
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Deterministic aggregate ID for a tier assignment derived from `tenantId`.
|
|
3
|
+
* Each platform tenant has exactly one aggregate; uuidv5 is namespace-
|
|
4
|
+
* deterministic, so identical input produces the same UUID.
|
|
5
5
|
*
|
|
6
|
-
* **
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* **When to use:** The `stripe-sync` feature wraps an idempotent
|
|
7
|
+
* set-tier handler with this function: a second Stripe webhook retry for
|
|
8
|
+
* the same `tenantId` targets the same aggregate stream, causing
|
|
9
|
+
* `version_conflict` from the event store instead of `pg-23505` from the
|
|
10
|
+
* read-model database. This enforces path uniqueness rather than a database
|
|
11
|
+
* constraint.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* Export bereit für Sprint 5.
|
|
13
|
+
* Standard CRUD handlers instead generate UUIDs via `gen_random_uuid()`.
|
|
14
|
+
* This utility is exported for use by the `stripe-sync` feature.
|
|
15
15
|
*/
|
|
16
16
|
export declare function tierAssignmentAggregateId(tenantId: string): string;
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
|
-
// Fixed UUID
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// drift-pin-Test in feature.test.ts pinnt diese Konstante.
|
|
2
|
+
// Fixed UUID namespace for deriving tier-assignment aggregate IDs.
|
|
3
|
+
// Generated once and immutable: changing it would re-key every existing
|
|
4
|
+
// aggregate stream, breaking event replay and projection rebuilds and losing
|
|
5
|
+
// the tier-change audit. The drift-pin test in feature.test.ts pins this constant.
|
|
7
6
|
const TIER_ASSIGNMENT_NAMESPACE = "8e91d2fc-8b7a-4d3e-9f4a-1c5d6e7f8a9b";
|
|
8
7
|
/**
|
|
9
|
-
* Deterministic aggregate
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Deterministic aggregate ID for a tier assignment derived from `tenantId`.
|
|
9
|
+
* Each platform tenant has exactly one aggregate; uuidv5 is namespace-
|
|
10
|
+
* deterministic, so identical input produces the same UUID.
|
|
12
11
|
*
|
|
13
|
-
* **
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* **When to use:** The `stripe-sync` feature wraps an idempotent
|
|
13
|
+
* set-tier handler with this function: a second Stripe webhook retry for
|
|
14
|
+
* the same `tenantId` targets the same aggregate stream, causing
|
|
15
|
+
* `version_conflict` from the event store instead of `pg-23505` from the
|
|
16
|
+
* read-model database. This enforces path uniqueness rather than a database
|
|
17
|
+
* constraint.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Export bereit für Sprint 5.
|
|
19
|
+
* Standard CRUD handlers instead generate UUIDs via `gen_random_uuid()`.
|
|
20
|
+
* This utility is exported for use by the `stripe-sync` feature.
|
|
22
21
|
*/
|
|
23
22
|
// @wrapper-known uuid-domain
|
|
24
23
|
export function tierAssignmentAggregateId(tenantId) {
|
|
@@ -2,17 +2,17 @@ import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
|
2
2
|
/**
|
|
3
3
|
* Tier definition — a named bundle of features + caps.
|
|
4
4
|
*
|
|
5
|
-
* **Generic
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `as Record<string, unknown
|
|
9
|
-
* compile-time
|
|
5
|
+
* **Generic over `TCaps`:** the app defines its cap shape as a concrete
|
|
6
|
+
* type (e.g. `{ apps: number, mailsPerMonth: number, aiTokens: number }`)
|
|
7
|
+
* and the composeApp call returns exactly that shape. No
|
|
8
|
+
* `as Record<string, unknown>` casts are needed in app code; all cap reads
|
|
9
|
+
* are compile-time checked.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* free/pro/business/enterprise/self-host, PublicStatus
|
|
14
|
-
* free/starter/team/agency.
|
|
15
|
-
*
|
|
11
|
+
* The tier engine itself is **agnostic** to concrete tier values and cap
|
|
12
|
+
* dimensions. Each app defines its TierMap: kumiko.rocks has
|
|
13
|
+
* free/pro/business/enterprise/self-host, while PublicStatus has
|
|
14
|
+
* free/starter/team/agency. The engine stores only the tier name as a
|
|
15
|
+
* string and trusts the app's TierMap to define what it means at boot.
|
|
16
16
|
*/
|
|
17
17
|
export type TierDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
18
18
|
/** Feature names to mount on top of the base set (no add-ons applied). */
|
|
@@ -24,9 +24,9 @@ export type TierDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
|
24
24
|
* Add-On definition — a tier-orthogonal feature bundle that can be added
|
|
25
25
|
* to any tier (BYOK-Encryption, Dedicated-Stack, Custom-SLA, ...).
|
|
26
26
|
*
|
|
27
|
-
* `capOverrides`
|
|
28
|
-
*
|
|
29
|
-
* 100k
|
|
27
|
+
* `capOverrides` is `Partial<TCaps>` because an add-on overrides only
|
|
28
|
+
* individual cap values (e.g. “Dedicated-Stack increases mailsPerMonth to
|
|
29
|
+
* 100k”), rather than redefining the entire shape.
|
|
30
30
|
*/
|
|
31
31
|
export type AddOnDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
32
32
|
/** Feature names to mount additionally when this add-on is active. */
|
|
@@ -60,7 +60,7 @@ export type ComposedApp<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
|
60
60
|
* composeApp — compute the feature-set + caps for a platform-tenant.
|
|
61
61
|
*
|
|
62
62
|
* **Contract:**
|
|
63
|
-
* 1. base features always mount (Tier-Engine itself
|
|
63
|
+
* 1. base features always mount (the Tier-Engine itself is part of them)
|
|
64
64
|
* 2. plus tier-specific features (from tierMap[tier].features)
|
|
65
65
|
* 3. plus add-on features (from addOnMap[addOn].features for each active add-on)
|
|
66
66
|
* 4. caps = tier.caps ⊕ add-on.capOverrides (later add-ons override earlier)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* composeApp — compute the feature-set + caps for a platform-tenant.
|
|
3
3
|
*
|
|
4
4
|
* **Contract:**
|
|
5
|
-
* 1. base features always mount (Tier-Engine itself
|
|
5
|
+
* 1. base features always mount (the Tier-Engine itself is part of them)
|
|
6
6
|
* 2. plus tier-specific features (from tierMap[tier].features)
|
|
7
7
|
* 3. plus add-on features (from addOnMap[addOn].features for each active add-on)
|
|
8
8
|
* 4. caps = tier.caps ⊕ add-on.capOverrides (later add-ons override earlier)
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import { createEntity, createSelectField, createTextField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { TierAssignmentSources } from "./web/constants.js";
|
|
3
|
-
// tier-assignment —
|
|
4
|
-
//
|
|
3
|
+
// tier-assignment — exactly one aggregate per platform tenant. The aggregate ID
|
|
4
|
+
// is derived deterministically from tenantId (uuidv5; see aggregate-id.ts).
|
|
5
5
|
//
|
|
6
|
-
// **Tenant
|
|
7
|
-
// `tenantId
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// **Tenant scope:** applied automatically by Kumiko's tenant-scoped projection —
|
|
7
|
+
// the framework adds `tenantId` as a base column, and the CrudExecutor populates
|
|
8
|
+
// it from `event.user.tenantId`. Each platform tenant has exactly one
|
|
9
|
+
// Tier-Assignment row.
|
|
10
10
|
//
|
|
11
|
-
// **
|
|
12
|
-
// - tier: TierName
|
|
13
|
-
// "self-host").
|
|
14
|
-
//
|
|
15
|
-
// enumerierte Tier-Liste.
|
|
11
|
+
// **Fields**
|
|
12
|
+
// - tier: a TierName string (for example, "free", "pro", "business",
|
|
13
|
+
// "enterprise", or "self-host"). The app defines valid tier values in its
|
|
14
|
+
// TierMap (see compose-app.ts); the engine has no enumerated tier list.
|
|
16
15
|
//
|
|
17
|
-
// **
|
|
18
|
-
// - tenantId:
|
|
19
|
-
// - validFrom/validTo:
|
|
20
|
-
// time
|
|
21
|
-
// - addOns:
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// -
|
|
16
|
+
// **Intentionally omitted from the entity**
|
|
17
|
+
// - tenantId: added automatically as a base column.
|
|
18
|
+
// - validFrom/validTo: redundant for event sourcing (events carry timestamps
|
|
19
|
+
// natively; time travel uses `ctx.loadAggregate({ asOf })`).
|
|
20
|
+
// - addOns: represented by a separate `tier-add-on` entity (1:n relation),
|
|
21
|
+
// allowing event-sourced Add/Remove events with clear audit granularity
|
|
22
|
+
// instead of replacing a JSON array.
|
|
23
|
+
// - Cap values: per-tier cap definitions belong in the app's TierMap.
|
|
25
24
|
export const tierAssignmentEntity = createEntity({
|
|
26
25
|
table: "read_tier_assignments",
|
|
27
26
|
description: "The pricing tier currently assigned to a tenant, plus where the assignment came from (manual grant, billing sync or signup default) — one row per tenant.",
|
|
@@ -2,33 +2,35 @@ import { type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
|
2
2
|
import type { TierMap } from "./compose-app.ts";
|
|
3
3
|
import { type TrialPolicy } from "./trial.ts";
|
|
4
4
|
/**
|
|
5
|
-
* Options for createTierEngineFeature. Both fields optional
|
|
6
|
-
*
|
|
5
|
+
* Options for createTierEngineFeature. Both fields are optional; when both are
|
|
6
|
+
* omitted, the feature provides storage only (backward compatibility with the
|
|
7
|
+
* legacy `tierEngineFeature`).
|
|
7
8
|
*
|
|
8
|
-
* @template TCaps - App-
|
|
9
|
-
* future capsFor() resolver
|
|
9
|
+
* @template TCaps - App-specific capability shape. It flows through tierMap,
|
|
10
|
+
* so a future capsFor() resolver returns this exact shape.
|
|
10
11
|
*/
|
|
11
12
|
export type CreateTierEngineOptions<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
12
13
|
/**
|
|
13
|
-
* Tier
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Tier name written automatically when a tenant signs up. `tierMap` must
|
|
15
|
+
* contain this tier name; this is validated at boot.
|
|
16
|
+
* When omitted, no tier is assigned automatically and the app writes it
|
|
17
|
+
* manually.
|
|
16
18
|
*/
|
|
17
19
|
readonly defaultTier?: string;
|
|
18
20
|
/**
|
|
19
|
-
* App-
|
|
20
|
-
*
|
|
21
|
-
* effectiveFeatures
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* App-specific tier map. When set, the feature registers as a plugin for the
|
|
22
|
+
* `tenantTierResolver` extension, so the framework automatically wires
|
|
23
|
+
* effectiveFeatures per tenant.
|
|
24
|
+
* When omitted, no resolver extension is registered; the app must use
|
|
25
|
+
* `composeApp` or its own resolution logic.
|
|
24
26
|
*/
|
|
25
27
|
readonly tierMap?: TierMap<TCaps>;
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* Optional trial phase: each tenant receives the features of `trial.tier` in
|
|
30
|
+
* addition to its stored tier for `durationHours` after creation, then
|
|
31
|
+
* automatically falls back to its stored tier. Requires `tierMap` to contain
|
|
32
|
+
* the trial tier. The result is derived from inserted_at; no stored flag or
|
|
33
|
+
* scheduler is used.
|
|
32
34
|
*/
|
|
33
35
|
readonly trial?: TrialPolicy;
|
|
34
36
|
};
|
|
@@ -1,45 +1,44 @@
|
|
|
1
|
-
// tier-engine —
|
|
1
|
+
// tier-engine — pricing-tier mechanics as a regular bundled feature.
|
|
2
2
|
//
|
|
3
|
-
// **
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// nach dem effective Set für den aktiven Tenant.
|
|
3
|
+
// **What this feature does:**
|
|
4
|
+
// Stores one tier assignment per platform tenant (the active tier). With
|
|
5
|
+
// `tierMap` in the options, it also resolves the per-tenant feature set via
|
|
6
|
+
// the framework's `tenantTierResolver` extension; the dispatcher feature gate
|
|
7
|
+
// automatically asks the resolver for the active tenant's effective set.
|
|
9
8
|
//
|
|
10
|
-
// **
|
|
11
|
-
// 1. `createTierEngineFeature()`
|
|
12
|
-
//
|
|
13
|
-
// logic
|
|
14
|
-
// 2. `createTierEngineFeature({ defaultTier, tierMap })` —
|
|
15
|
-
//
|
|
16
|
-
//
|
|
9
|
+
// **Two usage modes:**
|
|
10
|
+
// 1. `createTierEngineFeature()` without options — storage only (standard CRUD
|
|
11
|
+
// for the tier-assignment entity). Apps can use `composeApp()` or their
|
|
12
|
+
// own logic.
|
|
13
|
+
// 2. `createTierEngineFeature({ defaultTier, tierMap })` — complete tier
|
|
14
|
+
// composition for multi-tenant SaaS apps. The framework auto-wires
|
|
15
|
+
// effectiveFeatures through extension pickup.
|
|
17
16
|
//
|
|
18
|
-
// **Generic
|
|
19
|
-
//
|
|
17
|
+
// **Generic over tier values:** the feature knows no concrete `free`/`pro`/etc.
|
|
18
|
+
// tier values. The app defines its tier map.
|
|
20
19
|
//
|
|
21
|
-
// **Auto-
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// tenant
|
|
25
|
-
//
|
|
26
|
-
// version
|
|
27
|
-
//
|
|
28
|
-
//
|
|
20
|
+
// **Auto-default tier on tenant signup:** when `opts.defaultTier` is set, an
|
|
21
|
+
// `r.entityHook("postSave", "tenant", phase: inTransaction)` automatically
|
|
22
|
+
// writes a tier assignment for the new tenant. The write is atomic with
|
|
23
|
+
// tenant creation: if it fails, tenant creation is rolled back. It is
|
|
24
|
+
// idempotent through a deterministic aggregate ID; replay re-checks the
|
|
25
|
+
// stream version and skips the write if it already exists. A cache-miss
|
|
26
|
+
// fallback also returns the default tier's features when the assignment row
|
|
27
|
+
// is missing, protecting against races while the hook is still running.
|
|
29
28
|
//
|
|
30
|
-
// **In-
|
|
31
|
-
// Closure
|
|
32
|
-
// r.entityHook
|
|
33
|
-
//
|
|
34
|
-
//
|
|
29
|
+
// **In-memory cache with push invalidation:**
|
|
30
|
+
// Closure state per feature instance stores each tenant's effective sets.
|
|
31
|
+
// `r.entityHook` on tier-assignment postSave/postDelete keeps the cache
|
|
32
|
+
// current. The extension-pickup path pre-loads the cache through build(deps)
|
|
33
|
+
// at boot via runDevApp/runProdApp.
|
|
35
34
|
//
|
|
36
|
-
// **SYSTEM_TENANT_ID
|
|
37
|
-
// resolver
|
|
38
|
-
// tier
|
|
39
|
-
//
|
|
35
|
+
// **SYSTEM_TENANT_ID convention:**
|
|
36
|
+
// A resolver callback invoked with SYSTEM_TENANT_ID returns the union of all
|
|
37
|
+
// tier features for asynchronous event dispatch and operator tooling.
|
|
38
|
+
// See the DispatcherOptions.effectiveFeatures documentation.
|
|
40
39
|
//
|
|
41
|
-
// **Boot
|
|
42
|
-
// kumiko-lint-ignore app-feature-structure
|
|
40
|
+
// **Boot dependencies:** config + tenant.
|
|
41
|
+
// kumiko-lint-ignore app-feature-structure feature.ts is over 300 lines and not yet split
|
|
43
42
|
import { buildEntityTable, createEventStoreExecutor, createTenantDb, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
|
|
44
43
|
import { defineEntityCreateHandler, defineEntityListHandler, defineEntityUpdateHandler, defineFeature, defineQueryHandler, HookPhases, SYSTEM_TENANT_ID, TENANT_TIER_RESOLVER_EXT, } from "@cosmicdrift/kumiko-framework/engine";
|
|
45
44
|
import { getUnscopedAggregateStreamMaxVersion } from "@cosmicdrift/kumiko-framework/event-store";
|
|
@@ -61,25 +60,25 @@ import { TIER_ENGINE_I18N } from "./web/i18n.js";
|
|
|
61
60
|
// in the App's drizzle/schema.generated.ts.
|
|
62
61
|
const tierAssignmentTable = buildEntityTable("tier-assignment", tierAssignmentEntity);
|
|
63
62
|
const log = createFallbackLogger("tier-engine");
|
|
64
|
-
// Event-store
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
63
|
+
// Event-store executor for direct writes from the auto-default-tier hook.
|
|
64
|
+
// Like tenant/seeding.ts, the hook receives AppContext (not ctx.write), but it
|
|
65
|
+
// must write atomically with tenant creation in the same transaction. Call the
|
|
66
|
+
// executor directly rather than going through the dispatcher.
|
|
68
67
|
const tierAssignmentExecutor = createEventStoreExecutor(tierAssignmentTable, tierAssignmentEntity, {
|
|
69
68
|
entityName: "tier-assignment",
|
|
70
69
|
});
|
|
71
70
|
const adminAccess = { access: { roles: ["TenantAdmin", "SystemAdmin"] } };
|
|
72
|
-
// Tier
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
// TenantAdmin
|
|
76
|
-
//
|
|
71
|
+
// Tier changes are controlled by the platform and billing: a TenantAdmin must
|
|
72
|
+
// never set its own tier, which would allow a free self-upgrade. Writes are
|
|
73
|
+
// therefore SystemAdmin-only, while reads (list, get-active-tier) remain visible
|
|
74
|
+
// to TenantAdmin. The auto-default hook and billing write as the system, so they
|
|
75
|
+
// are not subject to this handler access.
|
|
77
76
|
const writeAccess = { access: { roles: ["SystemAdmin"] } };
|
|
78
77
|
/**
|
|
79
|
-
*
|
|
80
|
-
* SYSTEM_TENANT_ID
|
|
81
|
-
*
|
|
82
|
-
*
|
|
78
|
+
* Computes the union of features across all tiers for a
|
|
79
|
+
* SYSTEM_TENANT_ID resolver call used by operator tooling and asynchronous
|
|
80
|
+
* event dispatch. The operator UI sees every feature regardless of tier, and
|
|
81
|
+
* asynchronous events run without tier restrictions.
|
|
83
82
|
*/
|
|
84
83
|
function unionAllTierFeatures(tierMap) {
|
|
85
84
|
const all = new Set();
|
|
@@ -90,9 +89,9 @@ function unionAllTierFeatures(tierMap) {
|
|
|
90
89
|
return all;
|
|
91
90
|
}
|
|
92
91
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
92
|
+
* Computes the feature set for a tier name. An unknown tier returns an empty
|
|
93
|
+
* Set defensively because tier names are not validated at boot; tier-engine is
|
|
94
|
+
* generic over tier values.
|
|
96
95
|
*/
|
|
97
96
|
function featuresForTier(tierMap, tierName) {
|
|
98
97
|
const tier = tierMap[tierName];
|
|
@@ -101,10 +100,10 @@ function featuresForTier(tierMap, tierName) {
|
|
|
101
100
|
return new Set(tier.features);
|
|
102
101
|
}
|
|
103
102
|
/**
|
|
104
|
-
*
|
|
105
|
-
* features (toggleable per tier).
|
|
106
|
-
*
|
|
107
|
-
*
|
|
103
|
+
* Merges always-on features (non-toggleable framework base) with tier-specific
|
|
104
|
+
* features (toggleable per tier). The dispatcher gate blocks only features
|
|
105
|
+
* that explicitly register `r.toggleable()`; all others are always active.
|
|
106
|
+
* The tier resolver must provide the same shape.
|
|
108
107
|
*/
|
|
109
108
|
function mergeAlwaysOn(alwaysOn, tierFeatures) {
|
|
110
109
|
const merged = new Set(alwaysOn);
|
|
@@ -144,13 +143,14 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
144
143
|
description: "Lists the tier-assignment rows visible to the caller with tier name and assignment source; use it to see which plan is stored for a tenant.",
|
|
145
144
|
}));
|
|
146
145
|
r.queryHandler(getActiveTierQuery);
|
|
147
|
-
//
|
|
148
|
-
// Cross-tenant set
|
|
149
|
-
//
|
|
146
|
+
// ── Manual tier grant (SystemAdmin, without billing) ───────────────────────
|
|
147
|
+
// Cross-tenant set and read for the tier-admin screen. tier-options gives
|
|
148
|
+
// the client the app's tier names from the tierMap closure rather than
|
|
149
|
+
// hard-coding them.
|
|
150
150
|
//
|
|
151
151
|
// onAssigned runs after commit (the direct executor write fires no postSave
|
|
152
|
-
// hook).
|
|
153
|
-
// below installs the
|
|
152
|
+
// hook). It is late-bound: without tierMap it remains a no-op; the tierMap
|
|
153
|
+
// block below installs the actual cache update and publication.
|
|
154
154
|
const onTierAssigned = { fn: () => { } };
|
|
155
155
|
r.writeHandler(createSetTenantTierWrite({
|
|
156
156
|
onAssigned: (tenantId, tier) => onTierAssigned.fn(tenantId, tier),
|
|
@@ -208,11 +208,11 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
208
208
|
dormant: true,
|
|
209
209
|
});
|
|
210
210
|
// ───────────────────────────────────────────────────────────────────
|
|
211
|
-
// Resolver
|
|
211
|
+
// Resolver extension (only when tierMap is configured)
|
|
212
212
|
// ───────────────────────────────────────────────────────────────────
|
|
213
|
-
// skip:
|
|
214
|
-
//
|
|
215
|
-
//
|
|
213
|
+
// skip: without tierMap, the feature provides storage only (backward
|
|
214
|
+
// compatibility with `tierEngineFeature`). The resolver extension and
|
|
215
|
+
// invalidation hooks need tierMap to map tier names to feature sets.
|
|
216
216
|
if (!opts.tierMap)
|
|
217
217
|
return;
|
|
218
218
|
const tierMap = opts.tierMap;
|
|
@@ -307,7 +307,7 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
307
307
|
// tier-assignment.
|
|
308
308
|
//
|
|
309
309
|
// **Cross-tenant write:** the executor needs a systemUser WITH tenantId =
|
|
310
|
-
// the new tenant
|
|
310
|
+
// the new tenant.
|
|
311
311
|
if (opts.defaultTier !== undefined) {
|
|
312
312
|
const defaultTier = opts.defaultTier;
|
|
313
313
|
const autoDefaultTierHookReason = "seeds the default tier-assignment stream of the tenant just created";
|
|
@@ -352,8 +352,7 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
352
352
|
// SystemUser for the NEW tenant — the hook is triggered by the signup
|
|
353
353
|
// user (another tenant, or SystemAdmin), but the tier-assignment has
|
|
354
354
|
// to land in the stream of the newly created tenant (= aggregate id
|
|
355
|
-
// deterministic on newTenantId).
|
|
356
|
-
// `feedback_event_store_tenant_consistency`: by.tenantId must equal
|
|
355
|
+
// deterministic on newTenantId), so by.tenantId must equal
|
|
357
356
|
// the target tenant.
|
|
358
357
|
const systemUser = {
|
|
359
358
|
id: "00000000-0000-4000-8000-000000000001",
|
|
@@ -458,8 +457,8 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
458
457
|
}
|
|
459
458
|
// Cache miss: the tenant is not in the cache yet (e.g. brand new after
|
|
460
459
|
// boot, or the defaultTier hook has not fired yet). The default set
|
|
461
|
-
// is least-privileged
|
|
462
|
-
//
|
|
460
|
+
// is least-privileged, secure by default: typically free-tier features.
|
|
461
|
+
// The trial is NOT
|
|
463
462
|
// added here (sync/boot-cached, cannot see the passage of time) — the
|
|
464
463
|
// trialGate below does that on the disabled-gate path.
|
|
465
464
|
const fallbackTier = opts.defaultTier;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
// get-active-tier —
|
|
2
|
+
// get-active-tier — returns the current tier assignment for the calling tenant.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Wraps `ctx.queryProjection` for the most common engine query: which tier is
|
|
5
|
+
// currently active. Returns null when no tier is assigned; the caller (composeApp)
|
|
6
|
+
// maps null to the default tier.
|
|
7
7
|
//
|
|
8
|
-
// **Tenant
|
|
9
|
-
//
|
|
10
|
-
// tier-assignment-Row.
|
|
8
|
+
// **Tenant scope:** `ctx.queryProjection` automatically filters by tenantId.
|
|
9
|
+
// By convention, each platform tenant has exactly one tier-assignment row.
|
|
11
10
|
export const getActiveTierQuery = {
|
|
12
11
|
name: "get-active-tier",
|
|
13
12
|
description: "Returns the tier-assignment row currently active for the caller's own tenant, or null when none is assigned; use it to answer which plan the caller is on.",
|
|
@@ -2,10 +2,10 @@ import { buildEntityTable, createTenantDb, fetchOne } from "@cosmicdrift/kumiko-
|
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { tierAssignmentEntity } from "../entity.js";
|
|
5
|
-
//
|
|
6
|
-
// tier-admin
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// Reads the tier assignment of ANY tenant (cross-tenant) for the
|
|
6
|
+
// tier-admin screen. SystemAdmin-only. get-active-tier reads only its own
|
|
7
|
+
// tenant; this uses a "system"-mode TenantDb for the target tenant (no filter),
|
|
8
|
+
// so the admin can view another tenant's tier. Returns null if none exists yet.
|
|
9
9
|
const tierAssignmentTable = buildEntityTable("tier-assignment", tierAssignmentEntity);
|
|
10
10
|
const GET_TENANT_TIER_REASON = "SystemAdmin reads the tier of the tenant named in the payload";
|
|
11
11
|
export const getTenantTierQuery = defineQueryHandler({
|
|
@@ -5,11 +5,11 @@ export type SetTenantTierOptions = {
|
|
|
5
5
|
* and notify the other processes. Without a tierMap there is no resolver
|
|
6
6
|
* and this is a no-op. */
|
|
7
7
|
readonly onAssigned?: (tenantId: TenantId, tier: string) => void;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
/** Without the tierMap closure (storage-only mode), `tier` is validated only for
|
|
9
|
+
* length and non-emptiness. With it, the handler rejects unknown tier names
|
|
10
|
+
* instead of silently writing them through. (featuresForTier defensively
|
|
11
|
+
* returns an empty set for unknown names; otherwise the tenant would silently
|
|
12
|
+
* lose all tier gates.) */
|
|
13
13
|
readonly validTiers?: ReadonlySet<string>;
|
|
14
14
|
};
|
|
15
15
|
export declare function createSetTenantTierWrite(opts?: SetTenantTierOptions): import("@cosmicdrift/kumiko-types/define-handler").WriteHandlerDefinition<"set-tenant-tier", z.ZodObject<{
|
|
@@ -5,9 +5,9 @@ import { requireForTenant } from "../../shared/index.js";
|
|
|
5
5
|
import { tierAssignmentAggregateId } from "../aggregate-id.js";
|
|
6
6
|
import { tierAssignmentEntity } from "../entity.js";
|
|
7
7
|
import { TierAssignmentSources } from "../web/constants.js";
|
|
8
|
-
// SystemAdmin
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// A SystemAdmin can set the tier of ANY tenant as a manual grant without
|
|
9
|
+
// billing. This is cross-tenant, so it is restricted to SystemAdmin (not
|
|
10
|
+
// TenantAdmin, which would allow free self-upgrades).
|
|
11
11
|
//
|
|
12
12
|
// Cross-tenant mechanics: ctx.forTenant(tenantId) yields a tenant-mode db bound to the target plus
|
|
13
13
|
// the streamTenantId, so the event lands in the target's stream with the operator as actor.
|