@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
|
@@ -3,17 +3,17 @@ import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
|
3
3
|
/**
|
|
4
4
|
* Tier definition — a named bundle of features + caps.
|
|
5
5
|
*
|
|
6
|
-
* **Generic
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `as Record<string, unknown
|
|
10
|
-
* compile-time
|
|
6
|
+
* **Generic over `TCaps`:** the app defines its cap shape as a concrete
|
|
7
|
+
* type (e.g. `{ apps: number, mailsPerMonth: number, aiTokens: number }`)
|
|
8
|
+
* and the composeApp call returns exactly that shape. No
|
|
9
|
+
* `as Record<string, unknown>` casts are needed in app code; all cap reads
|
|
10
|
+
* are compile-time checked.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* free/pro/business/enterprise/self-host, PublicStatus
|
|
15
|
-
* free/starter/team/agency.
|
|
16
|
-
*
|
|
12
|
+
* The tier engine itself is **agnostic** to concrete tier values and cap
|
|
13
|
+
* dimensions. Each app defines its TierMap: kumiko.rocks has
|
|
14
|
+
* free/pro/business/enterprise/self-host, while PublicStatus has
|
|
15
|
+
* free/starter/team/agency. The engine stores only the tier name as a
|
|
16
|
+
* string and trusts the app's TierMap to define what it means at boot.
|
|
17
17
|
*/
|
|
18
18
|
export type TierDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
19
19
|
/** Feature names to mount on top of the base set (no add-ons applied). */
|
|
@@ -26,9 +26,9 @@ export type TierDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
|
26
26
|
* Add-On definition — a tier-orthogonal feature bundle that can be added
|
|
27
27
|
* to any tier (BYOK-Encryption, Dedicated-Stack, Custom-SLA, ...).
|
|
28
28
|
*
|
|
29
|
-
* `capOverrides`
|
|
30
|
-
*
|
|
31
|
-
* 100k
|
|
29
|
+
* `capOverrides` is `Partial<TCaps>` because an add-on overrides only
|
|
30
|
+
* individual cap values (e.g. “Dedicated-Stack increases mailsPerMonth to
|
|
31
|
+
* 100k”), rather than redefining the entire shape.
|
|
32
32
|
*/
|
|
33
33
|
export type AddOnDefinition<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
34
34
|
/** Feature names to mount additionally when this add-on is active. */
|
|
@@ -70,7 +70,7 @@ export type ComposedApp<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
|
70
70
|
* composeApp — compute the feature-set + caps for a platform-tenant.
|
|
71
71
|
*
|
|
72
72
|
* **Contract:**
|
|
73
|
-
* 1. base features always mount (Tier-Engine itself
|
|
73
|
+
* 1. base features always mount (the Tier-Engine itself is part of them)
|
|
74
74
|
* 2. plus tier-specific features (from tierMap[tier].features)
|
|
75
75
|
* 3. plus add-on features (from addOnMap[addOn].features for each active add-on)
|
|
76
76
|
* 4. caps = tier.caps ⊕ add-on.capOverrides (later add-ons override earlier)
|
|
@@ -5,28 +5,27 @@ import {
|
|
|
5
5
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
6
6
|
import { type TierAssignmentSource, TierAssignmentSources } from "./web/constants.ts";
|
|
7
7
|
|
|
8
|
-
// tier-assignment —
|
|
9
|
-
//
|
|
8
|
+
// tier-assignment — exactly one aggregate per platform tenant. The aggregate ID
|
|
9
|
+
// is derived deterministically from tenantId (uuidv5; see aggregate-id.ts).
|
|
10
10
|
//
|
|
11
|
-
// **Tenant
|
|
12
|
-
// `tenantId
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// **Tenant scope:** applied automatically by Kumiko's tenant-scoped projection —
|
|
12
|
+
// the framework adds `tenantId` as a base column, and the CrudExecutor populates
|
|
13
|
+
// it from `event.user.tenantId`. Each platform tenant has exactly one
|
|
14
|
+
// Tier-Assignment row.
|
|
15
15
|
//
|
|
16
|
-
// **
|
|
17
|
-
// - tier: TierName
|
|
18
|
-
// "self-host").
|
|
19
|
-
//
|
|
20
|
-
// enumerierte Tier-Liste.
|
|
16
|
+
// **Fields**
|
|
17
|
+
// - tier: a TierName string (for example, "free", "pro", "business",
|
|
18
|
+
// "enterprise", or "self-host"). The app defines valid tier values in its
|
|
19
|
+
// TierMap (see compose-app.ts); the engine has no enumerated tier list.
|
|
21
20
|
//
|
|
22
|
-
// **
|
|
23
|
-
// - tenantId:
|
|
24
|
-
// - validFrom/validTo:
|
|
25
|
-
// time
|
|
26
|
-
// - addOns:
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// -
|
|
21
|
+
// **Intentionally omitted from the entity**
|
|
22
|
+
// - tenantId: added automatically as a base column.
|
|
23
|
+
// - validFrom/validTo: redundant for event sourcing (events carry timestamps
|
|
24
|
+
// natively; time travel uses `ctx.loadAggregate({ asOf })`).
|
|
25
|
+
// - addOns: represented by a separate `tier-add-on` entity (1:n relation),
|
|
26
|
+
// allowing event-sourced Add/Remove events with clear audit granularity
|
|
27
|
+
// instead of replacing a JSON array.
|
|
28
|
+
// - Cap values: per-tier cap definitions belong in the app's TierMap.
|
|
30
29
|
export const tierAssignmentEntity = createEntity({
|
|
31
30
|
table: "read_tier_assignments",
|
|
32
31
|
description:
|
|
@@ -1,46 +1,45 @@
|
|
|
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
|
|
40
|
+
// **Boot dependencies:** config + tenant.
|
|
42
41
|
|
|
43
|
-
// kumiko-lint-ignore app-feature-structure
|
|
42
|
+
// kumiko-lint-ignore app-feature-structure feature.ts is over 300 lines and not yet split
|
|
44
43
|
import {
|
|
45
44
|
buildEntityTable,
|
|
46
45
|
createEventStoreExecutor,
|
|
@@ -95,61 +94,63 @@ import { TIER_ENGINE_I18N } from "./web/i18n.ts";
|
|
|
95
94
|
const tierAssignmentTable = buildEntityTable("tier-assignment", tierAssignmentEntity);
|
|
96
95
|
const log = createFallbackLogger("tier-engine");
|
|
97
96
|
|
|
98
|
-
// Event-store
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
97
|
+
// Event-store executor for direct writes from the auto-default-tier hook.
|
|
98
|
+
// Like tenant/seeding.ts, the hook receives AppContext (not ctx.write), but it
|
|
99
|
+
// must write atomically with tenant creation in the same transaction. Call the
|
|
100
|
+
// executor directly rather than going through the dispatcher.
|
|
102
101
|
const tierAssignmentExecutor = createEventStoreExecutor(tierAssignmentTable, tierAssignmentEntity, {
|
|
103
102
|
entityName: "tier-assignment",
|
|
104
103
|
});
|
|
105
104
|
|
|
106
105
|
const adminAccess = { access: { roles: ["TenantAdmin", "SystemAdmin"] } } as const;
|
|
107
|
-
// Tier
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
// TenantAdmin
|
|
111
|
-
//
|
|
106
|
+
// Tier changes are controlled by the platform and billing: a TenantAdmin must
|
|
107
|
+
// never set its own tier, which would allow a free self-upgrade. Writes are
|
|
108
|
+
// therefore SystemAdmin-only, while reads (list, get-active-tier) remain visible
|
|
109
|
+
// to TenantAdmin. The auto-default hook and billing write as the system, so they
|
|
110
|
+
// are not subject to this handler access.
|
|
112
111
|
const writeAccess = { access: { roles: ["SystemAdmin"] } } as const;
|
|
113
112
|
|
|
114
113
|
/**
|
|
115
|
-
* Options for createTierEngineFeature. Both fields optional
|
|
116
|
-
*
|
|
114
|
+
* Options for createTierEngineFeature. Both fields are optional; when both are
|
|
115
|
+
* omitted, the feature provides storage only (backward compatibility with the
|
|
116
|
+
* legacy `tierEngineFeature`).
|
|
117
117
|
*
|
|
118
|
-
* @template TCaps - App-
|
|
119
|
-
* future capsFor() resolver
|
|
118
|
+
* @template TCaps - App-specific capability shape. It flows through tierMap,
|
|
119
|
+
* so a future capsFor() resolver returns this exact shape.
|
|
120
120
|
*/
|
|
121
121
|
export type CreateTierEngineOptions<TCaps extends Readonly<Record<string, unknown>>> = {
|
|
122
122
|
/**
|
|
123
|
-
* Tier
|
|
124
|
-
*
|
|
125
|
-
*
|
|
123
|
+
* Tier name written automatically when a tenant signs up. `tierMap` must
|
|
124
|
+
* contain this tier name; this is validated at boot.
|
|
125
|
+
* When omitted, no tier is assigned automatically and the app writes it
|
|
126
|
+
* manually.
|
|
126
127
|
*/
|
|
127
128
|
readonly defaultTier?: string;
|
|
128
129
|
|
|
129
130
|
/**
|
|
130
|
-
* App-
|
|
131
|
-
*
|
|
132
|
-
* effectiveFeatures
|
|
133
|
-
*
|
|
134
|
-
*
|
|
131
|
+
* App-specific tier map. When set, the feature registers as a plugin for the
|
|
132
|
+
* `tenantTierResolver` extension, so the framework automatically wires
|
|
133
|
+
* effectiveFeatures per tenant.
|
|
134
|
+
* When omitted, no resolver extension is registered; the app must use
|
|
135
|
+
* `composeApp` or its own resolution logic.
|
|
135
136
|
*/
|
|
136
137
|
readonly tierMap?: TierMap<TCaps>;
|
|
137
138
|
|
|
138
139
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
140
|
+
* Optional trial phase: each tenant receives the features of `trial.tier` in
|
|
141
|
+
* addition to its stored tier for `durationHours` after creation, then
|
|
142
|
+
* automatically falls back to its stored tier. Requires `tierMap` to contain
|
|
143
|
+
* the trial tier. The result is derived from inserted_at; no stored flag or
|
|
144
|
+
* scheduler is used.
|
|
144
145
|
*/
|
|
145
146
|
readonly trial?: TrialPolicy;
|
|
146
147
|
};
|
|
147
148
|
|
|
148
149
|
/**
|
|
149
|
-
*
|
|
150
|
-
* SYSTEM_TENANT_ID
|
|
151
|
-
*
|
|
152
|
-
*
|
|
150
|
+
* Computes the union of features across all tiers for a
|
|
151
|
+
* SYSTEM_TENANT_ID resolver call used by operator tooling and asynchronous
|
|
152
|
+
* event dispatch. The operator UI sees every feature regardless of tier, and
|
|
153
|
+
* asynchronous events run without tier restrictions.
|
|
153
154
|
*/
|
|
154
155
|
function unionAllTierFeatures<TCaps extends Readonly<Record<string, unknown>>>(
|
|
155
156
|
tierMap: TierMap<TCaps>,
|
|
@@ -162,9 +163,9 @@ function unionAllTierFeatures<TCaps extends Readonly<Record<string, unknown>>>(
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
166
|
+
* Computes the feature set for a tier name. An unknown tier returns an empty
|
|
167
|
+
* Set defensively because tier names are not validated at boot; tier-engine is
|
|
168
|
+
* generic over tier values.
|
|
168
169
|
*/
|
|
169
170
|
function featuresForTier<TCaps extends Readonly<Record<string, unknown>>>(
|
|
170
171
|
tierMap: TierMap<TCaps>,
|
|
@@ -176,10 +177,10 @@ function featuresForTier<TCaps extends Readonly<Record<string, unknown>>>(
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
/**
|
|
179
|
-
*
|
|
180
|
-
* features (toggleable per tier).
|
|
181
|
-
*
|
|
182
|
-
*
|
|
180
|
+
* Merges always-on features (non-toggleable framework base) with tier-specific
|
|
181
|
+
* features (toggleable per tier). The dispatcher gate blocks only features
|
|
182
|
+
* that explicitly register `r.toggleable()`; all others are always active.
|
|
183
|
+
* The tier resolver must provide the same shape.
|
|
183
184
|
*/
|
|
184
185
|
function mergeAlwaysOn(
|
|
185
186
|
alwaysOn: ReadonlySet<string>,
|
|
@@ -239,13 +240,14 @@ export function createTierEngineFeature<
|
|
|
239
240
|
);
|
|
240
241
|
r.queryHandler(getActiveTierQuery);
|
|
241
242
|
|
|
242
|
-
//
|
|
243
|
-
// Cross-tenant set
|
|
244
|
-
//
|
|
243
|
+
// ── Manual tier grant (SystemAdmin, without billing) ───────────────────────
|
|
244
|
+
// Cross-tenant set and read for the tier-admin screen. tier-options gives
|
|
245
|
+
// the client the app's tier names from the tierMap closure rather than
|
|
246
|
+
// hard-coding them.
|
|
245
247
|
//
|
|
246
248
|
// onAssigned runs after commit (the direct executor write fires no postSave
|
|
247
|
-
// hook).
|
|
248
|
-
// below installs the
|
|
249
|
+
// hook). It is late-bound: without tierMap it remains a no-op; the tierMap
|
|
250
|
+
// block below installs the actual cache update and publication.
|
|
249
251
|
const onTierAssigned: { fn: (tenantId: TenantId, tier: string) => void } = { fn: () => {} };
|
|
250
252
|
r.writeHandler(
|
|
251
253
|
createSetTenantTierWrite({
|
|
@@ -310,11 +312,11 @@ export function createTierEngineFeature<
|
|
|
310
312
|
});
|
|
311
313
|
|
|
312
314
|
// ───────────────────────────────────────────────────────────────────
|
|
313
|
-
// Resolver
|
|
315
|
+
// Resolver extension (only when tierMap is configured)
|
|
314
316
|
// ───────────────────────────────────────────────────────────────────
|
|
315
|
-
// skip:
|
|
316
|
-
//
|
|
317
|
-
//
|
|
317
|
+
// skip: without tierMap, the feature provides storage only (backward
|
|
318
|
+
// compatibility with `tierEngineFeature`). The resolver extension and
|
|
319
|
+
// invalidation hooks need tierMap to map tier names to feature sets.
|
|
318
320
|
if (!opts.tierMap) return;
|
|
319
321
|
|
|
320
322
|
const tierMap = opts.tierMap;
|
|
@@ -414,7 +416,7 @@ export function createTierEngineFeature<
|
|
|
414
416
|
// tier-assignment.
|
|
415
417
|
//
|
|
416
418
|
// **Cross-tenant write:** the executor needs a systemUser WITH tenantId =
|
|
417
|
-
// the new tenant
|
|
419
|
+
// the new tenant.
|
|
418
420
|
if (opts.defaultTier !== undefined) {
|
|
419
421
|
const defaultTier = opts.defaultTier;
|
|
420
422
|
const autoDefaultTierHookReason =
|
|
@@ -459,8 +461,7 @@ export function createTierEngineFeature<
|
|
|
459
461
|
// SystemUser for the NEW tenant — the hook is triggered by the signup
|
|
460
462
|
// user (another tenant, or SystemAdmin), but the tier-assignment has
|
|
461
463
|
// to land in the stream of the newly created tenant (= aggregate id
|
|
462
|
-
// deterministic on newTenantId).
|
|
463
|
-
// `feedback_event_store_tenant_consistency`: by.tenantId must equal
|
|
464
|
+
// deterministic on newTenantId), so by.tenantId must equal
|
|
464
465
|
// the target tenant.
|
|
465
466
|
const systemUser: SessionUser = {
|
|
466
467
|
id: "00000000-0000-4000-8000-000000000001",
|
|
@@ -506,7 +507,7 @@ export function createTierEngineFeature<
|
|
|
506
507
|
|
|
507
508
|
// Pre-load all existing assignments into the cache. SaaS apps typically
|
|
508
509
|
// have <100k tenants, so a single-pass scan is acceptable. The scaling
|
|
509
|
-
// path (lazy load + LRU) is
|
|
510
|
+
// path (lazy load + LRU) is planned once a real need arises.
|
|
510
511
|
type AssignmentRow = { tenantId: string; tier: string };
|
|
511
512
|
const rows = await selectMany<AssignmentRow>(deps.db, tierAssignmentTable);
|
|
512
513
|
for (const row of rows) {
|
|
@@ -586,8 +587,8 @@ export function createTierEngineFeature<
|
|
|
586
587
|
}
|
|
587
588
|
// Cache miss: the tenant is not in the cache yet (e.g. brand new after
|
|
588
589
|
// boot, or the defaultTier hook has not fired yet). The default set
|
|
589
|
-
// is least-privileged
|
|
590
|
-
//
|
|
590
|
+
// is least-privileged, secure by default: typically free-tier features.
|
|
591
|
+
// The trial is NOT
|
|
591
592
|
// added here (sync/boot-cached, cannot see the passage of time) — the
|
|
592
593
|
// trialGate below does that on the disabled-gate path.
|
|
593
594
|
const fallbackTier = opts.defaultTier;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { QueryHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
|
|
4
|
-
// get-active-tier —
|
|
4
|
+
// get-active-tier — returns the current tier assignment for the calling tenant.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// Wraps `ctx.queryProjection` for the most common engine query: which tier is
|
|
7
|
+
// currently active. Returns null when no tier is assigned; the caller (composeApp)
|
|
8
|
+
// maps null to the default tier.
|
|
9
9
|
//
|
|
10
|
-
// **Tenant
|
|
11
|
-
//
|
|
12
|
-
// tier-assignment-Row.
|
|
10
|
+
// **Tenant scope:** `ctx.queryProjection` automatically filters by tenantId.
|
|
11
|
+
// By convention, each platform tenant has exactly one tier-assignment row.
|
|
13
12
|
export const getActiveTierQuery: QueryHandlerDef = {
|
|
14
13
|
name: "get-active-tier",
|
|
15
14
|
description:
|
|
@@ -3,10 +3,10 @@ import { defineQueryHandler, type TenantId } from "@cosmicdrift/kumiko-framework
|
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { type TierAssignmentRow, tierAssignmentEntity } from "../entity.ts";
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
// tier-admin
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// Reads the tier assignment of ANY tenant (cross-tenant) for the
|
|
7
|
+
// tier-admin screen. SystemAdmin-only. get-active-tier reads only its own
|
|
8
|
+
// tenant; this uses a "system"-mode TenantDb for the target tenant (no filter),
|
|
9
|
+
// so the admin can view another tenant's tier. Returns null if none exists yet.
|
|
10
10
|
|
|
11
11
|
const tierAssignmentTable = buildEntityTable("tier-assignment", tierAssignmentEntity);
|
|
12
12
|
|
|
@@ -10,9 +10,9 @@ import { tierAssignmentAggregateId } from "../aggregate-id.ts";
|
|
|
10
10
|
import { type TierAssignmentRow, tierAssignmentEntity } from "../entity.ts";
|
|
11
11
|
import { type TierAssignmentSource, TierAssignmentSources } from "../web/constants.ts";
|
|
12
12
|
|
|
13
|
-
// SystemAdmin
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// A SystemAdmin can set the tier of ANY tenant as a manual grant without
|
|
14
|
+
// billing. This is cross-tenant, so it is restricted to SystemAdmin (not
|
|
15
|
+
// TenantAdmin, which would allow free self-upgrades).
|
|
16
16
|
//
|
|
17
17
|
// Cross-tenant mechanics: ctx.forTenant(tenantId) yields a tenant-mode db bound to the target plus
|
|
18
18
|
// the streamTenantId, so the event lands in the target's stream with the operator as actor.
|
|
@@ -39,11 +39,11 @@ export type SetTenantTierOptions = {
|
|
|
39
39
|
* and notify the other processes. Without a tierMap there is no resolver
|
|
40
40
|
* and this is a no-op. */
|
|
41
41
|
readonly onAssigned?: (tenantId: TenantId, tier: string) => void;
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
42
|
+
/** Without the tierMap closure (storage-only mode), `tier` is validated only for
|
|
43
|
+
* length and non-emptiness. With it, the handler rejects unknown tier names
|
|
44
|
+
* instead of silently writing them through. (featuresForTier defensively
|
|
45
|
+
* returns an empty set for unknown names; otherwise the tenant would silently
|
|
46
|
+
* lose all tier gates.) */
|
|
47
47
|
readonly validTiers?: ReadonlySet<string>;
|
|
48
48
|
};
|
|
49
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generic tier-resolver factory. Extracted from the near-identical
|
|
2
|
-
// tier-resolver.ts app copies in show-pony and publicstatus
|
|
3
|
-
//
|
|
2
|
+
// tier-resolver.ts app copies in show-pony and publicstatus — the only
|
|
3
|
+
// per-app variables were the TierName union and its caps/defaults, so
|
|
4
4
|
// both are now factory parameters.
|
|
5
5
|
|
|
6
6
|
import { buildEntityTable, type TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
// Trial
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// Trial phase: a new tenant receives the features of a higher tier for a grace
|
|
2
|
+
// period starting at its creation date (`inserted_at` of the tier-assignment Row —
|
|
3
|
+
// stable across rebuilds because it comes from the Create Event), regardless of
|
|
4
|
+
// the stored tier. It is derived solely from time: no stored flag, no scheduler,
|
|
5
|
+
// and automatic expiration. The app defines the policy (which tier, how long);
|
|
6
|
+
// the tier-engine applies it in the resolver.
|
|
7
7
|
|
|
8
8
|
export interface TrialPolicy {
|
|
9
|
-
// Tier
|
|
10
|
-
//
|
|
9
|
+
// Tier whose features are additionally enabled during the trial phase
|
|
10
|
+
// (must be a key in tierMap; otherwise no feature takes effect).
|
|
11
11
|
readonly tier: string;
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
12
|
+
// Length of the trial phase from inserted_at, in hours (720 = 30 days). Hours
|
|
13
|
+
// are used instead of days because Temporal.Instant has no calendar days; 720h
|
|
14
|
+
// is the accurate, DST-independent duration.
|
|
15
15
|
readonly durationHours: number;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
// Row
|
|
18
|
+
// Pure millisecond arithmetic on epochMilliseconds, which both sides—the
|
|
19
|
+
// projection Row and Now—provide. No Date and no time zone.
|
|
20
20
|
export function isTrialActive(
|
|
21
21
|
startedAtEpochMs: number,
|
|
22
22
|
nowEpochMs: number,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Public exports
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `@cosmicdrift/kumiko-bundled-features/tier-engine`
|
|
1
|
+
// Public exports for the browser side of the tier-engine feature. Import via
|
|
2
|
+
// `@cosmicdrift/kumiko-bundled-features/tier-engine/web` — the server side
|
|
3
|
+
// (createTierEngineFeature) is under
|
|
4
|
+
// `@cosmicdrift/kumiko-bundled-features/tier-engine` and has no React deps.
|
|
5
5
|
|
|
6
6
|
export { type TierEngineClientOptions, tierEngineClient } from "./client-plugin.tsx";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//
|
|
1
|
+
// One-time migration tooling for older user event streams.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// Making `user` a systemStream entity means every executor op addresses the
|
|
4
4
|
// stream on SYSTEM_TENANT_ID. Streams created before that live on whichever
|
|
5
|
-
// tenant created them ("scattered"), so
|
|
6
|
-
// against the empty SYSTEM stream. The raw UPDATE
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// tenant created them ("scattered"), so newer writes version-conflict
|
|
6
|
+
// against the empty SYSTEM stream. The raw UPDATE breaks as soon as an
|
|
7
|
+
// aggregate has BOTH a legacy stream and newer SYSTEM events
|
|
8
|
+
// (split stream — e.g. a skipOptimisticLock
|
|
9
9
|
// lifecycle write appended v1 on SYSTEM while v1..n live on the old
|
|
10
10
|
// tenant): retenanting then trips events_aggregate_version_uq.
|
|
11
11
|
//
|
|
@@ -75,7 +75,7 @@ async function migrateAggregate(db: DbConnection, aggregateId: string): Promise<
|
|
|
75
75
|
[aggregateId],
|
|
76
76
|
);
|
|
77
77
|
|
|
78
|
-
//
|
|
78
|
+
// Negative interim versions — real versions are always >= 1, so
|
|
79
79
|
// nothing can collide with events_aggregate_version_uq mid-migration.
|
|
80
80
|
for (const [i, ev] of events.entries()) {
|
|
81
81
|
await raw.unsafe(
|
|
@@ -83,7 +83,7 @@ async function migrateAggregate(db: DbConnection, aggregateId: string): Promise<
|
|
|
83
83
|
[SYSTEM_TENANT_ID, -(i + 1), ev.id],
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
|
-
//
|
|
86
|
+
// Final contiguous 1..n.
|
|
87
87
|
for (const [i, ev] of events.entries()) {
|
|
88
88
|
await raw.unsafe(`UPDATE "kumiko_events" SET "version" = $1 WHERE "id" = $2`, [i + 1, ev.id]);
|
|
89
89
|
}
|
|
@@ -22,14 +22,14 @@ const crud = createEventStoreExecutor(userTable, userEntity, { entityName: "user
|
|
|
22
22
|
|
|
23
23
|
// Only the Auth features (running as SYSTEM) or a SystemAdmin may create users.
|
|
24
24
|
//
|
|
25
|
-
// Email uniqueness has two layers
|
|
25
|
+
// Email uniqueness has two layers:
|
|
26
26
|
// 1. A pre-flight fetchOne — fast-fails with a friendly error on the
|
|
27
27
|
// common case, but is race-prone on its own: two concurrent requests
|
|
28
28
|
// can both see "no duplicate" and both proceed to crud.create.
|
|
29
29
|
// 2. The real guard is the unique index over email's blind-index column
|
|
30
30
|
// (schema/user.ts). A losing concurrent create hits that constraint
|
|
31
|
-
// and crud.create returns a UniqueViolationError (framework's
|
|
32
|
-
//
|
|
31
|
+
// and crud.create returns a UniqueViolationError (framework's pg-23505
|
|
32
|
+
// mapping) instead of throwing — remapped below to the same
|
|
33
33
|
// emailAlreadyExists shape the pre-flight path returns, so callers see
|
|
34
34
|
// one consistent error regardless of which layer caught the race.
|
|
35
35
|
export const createWrite = defineWriteHandler({
|
|
@@ -114,7 +114,7 @@ export const createWrite = defineWriteHandler({
|
|
|
114
114
|
// schema/user.ts's `read_users_email_unique` (+ its generated `_bidx`
|
|
115
115
|
// pendant) is the actual race-safety net behind the pre-flight check
|
|
116
116
|
// above — a losing concurrent create surfaces here as a generic
|
|
117
|
-
// UniqueViolationError (framework
|
|
117
|
+
// UniqueViolationError (framework pg-23505 mapping). Only the email
|
|
118
118
|
// constraint gets remapped; any other unique_violation on this entity
|
|
119
119
|
// passes through unchanged.
|
|
120
120
|
function isRecord(value: unknown): value is Record<string, unknown> {
|