@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
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
2
|
|
|
3
|
-
// Fixed UUID
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// __tests__/drift.test.ts pinnt den UUID-Wert.
|
|
3
|
+
// Fixed UUID namespace for deriving cap-counter aggregate IDs.
|
|
4
|
+
// Generated once (2026-05-02) and immutable: changing it would re-key every
|
|
5
|
+
// existing aggregate stream, breaking event replay and counter history and
|
|
6
|
+
// losing the audit trail. The drift test in __tests__/drift.test.ts pins the UUID.
|
|
8
7
|
const CAP_COUNTER_NAMESPACE = "9c1bf2a3-6e4d-4f5b-8a9c-2d3e4f5a6b7c";
|
|
9
8
|
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
9
|
+
// Separate namespace for rolling-window counters. This prevents the aggregate ID
|
|
10
|
+
// from colliding with a calendar counter, even if "1970-01-01..." is passed as
|
|
11
|
+
// periodStart through the calendar path. The drift test in __tests__/drift.test.ts
|
|
12
|
+
// pins the UUID.
|
|
14
13
|
const CAP_COUNTER_ROLLING_NAMESPACE = "8b2ad0c6-1f3e-4f7c-9b8a-3c4d5e6f7a8b";
|
|
15
14
|
|
|
16
15
|
/**
|
|
@@ -3,20 +3,19 @@ export const CAP_COUNTER_FEATURE = "cap-counter" as const;
|
|
|
3
3
|
|
|
4
4
|
export const CAP_COUNTER_LIST_SCREEN_ID = "cap-list" as const;
|
|
5
5
|
|
|
6
|
-
// Aggregate types
|
|
7
|
-
// projection
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// muss.
|
|
6
|
+
// Aggregate types: calendar-period counters use CRUD events for the
|
|
7
|
+
// projection row. Rolling-window counters use a separate aggregate type
|
|
8
|
+
// with custom increment events (no projection—the read sums events from
|
|
9
|
+
// the last N days). They are separate so `r.entity-projection` does not
|
|
10
|
+
// also have to track rolling-counter rows.
|
|
12
11
|
export const CAP_COUNTER_ROLLING_AGGREGATE_TYPE = "cap-counter-rolling" as const;
|
|
13
12
|
|
|
14
|
-
// Custom event
|
|
15
|
-
// _SHORT —
|
|
16
|
-
// (
|
|
17
|
-
// _QN —
|
|
18
|
-
//
|
|
19
|
-
//
|
|
13
|
+
// Custom event types for rolling-window counters. The pair is symmetric:
|
|
14
|
+
// _SHORT — matches `r.defineEvent(short, schema)` in the registrar
|
|
15
|
+
// (the framework automatically prefixes it to the QN)
|
|
16
|
+
// _QN — qualified form for `ctx.unsafeAppendEvent({type})`, the
|
|
17
|
+
// `events.type` column, and `registry.getEvent(qn)` lookups
|
|
18
|
+
// Both MUST stay consistent; the feature test pins against drift.
|
|
20
19
|
export const ROLLING_INCREMENTED_EVENT_SHORT = "rolling-incremented" as const;
|
|
21
20
|
export const ROLLING_INCREMENTED_EVENT_QN = "cap-counter:event:rolling-incremented" as const;
|
|
22
21
|
|
|
@@ -16,16 +16,14 @@ const { table } = createEntityExecutor("cap-counter", capCounterEntity);
|
|
|
16
16
|
// =============================================================================
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Cap-
|
|
20
|
-
* `project_pricing_byok_caps` §3 + `docs/plans/marketing/produkt/
|
|
21
|
-
* pricing.md` Cap-Verhalten-Block.
|
|
19
|
+
* Cap-tolerance profiles, asymmetric by cap type.
|
|
22
20
|
*
|
|
23
|
-
* **Soft** =
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* **Soft** = notification threshold (multiplier × limit). Once reached,
|
|
22
|
+
* a warning is issued (`lastSoftWarnedAt` sets the flag); caller code emits
|
|
23
|
+
* the actual notification.
|
|
26
24
|
*
|
|
27
|
-
* **Hard** =
|
|
28
|
-
*
|
|
25
|
+
* **Hard** = write-block threshold (multiplier × limit). `enforceCap` throws
|
|
26
|
+
* a `cap_exceeded` error, which the dispatcher maps to 429 with an upgrade hint.
|
|
29
27
|
*/
|
|
30
28
|
export type CapToleranceProfile = {
|
|
31
29
|
readonly soft: number;
|
|
@@ -33,13 +31,13 @@ export type CapToleranceProfile = {
|
|
|
33
31
|
};
|
|
34
32
|
|
|
35
33
|
export const CAP_TOLERANCES = {
|
|
36
|
-
/** Mails /
|
|
34
|
+
/** Mails / tokens — inexpensive, with BYOK available from Pro. Generous burst buffer. */
|
|
37
35
|
burstable: { soft: 1.1, hard: 1.2 },
|
|
38
36
|
/** DB-Storage / File-Storage — teuer + persistent. Strikter Cut. */
|
|
39
37
|
storage: { soft: 1.0, hard: 1.05 },
|
|
40
|
-
/**
|
|
38
|
+
/** App count and platform slots — purchased capacity, with no buffer. */
|
|
41
39
|
hardSlot: { soft: 1.0, hard: 1.0 },
|
|
42
|
-
/** Egress —
|
|
40
|
+
/** Egress — bursty traffic is legitimate; only extreme spikes are blocked. */
|
|
43
41
|
egress: { soft: 1.1, hard: 1.3 },
|
|
44
42
|
} as const satisfies Readonly<Record<string, CapToleranceProfile>>;
|
|
45
43
|
|
|
@@ -176,28 +174,26 @@ export async function enforceCap(
|
|
|
176
174
|
// =============================================================================
|
|
177
175
|
|
|
178
176
|
/**
|
|
179
|
-
* Synchronous read-and-check of the calling tenant's
|
|
180
|
-
*
|
|
181
|
-
* `windowDays`
|
|
177
|
+
* Synchronous read-and-check of the calling tenant's rolling-window
|
|
178
|
+
* counter for `capName`. Reads increment events from the last
|
|
179
|
+
* `windowDays` in the event store and sums their `amount`. Returns:
|
|
182
180
|
* - "ok" when sum < soft-threshold
|
|
183
181
|
* - "soft-hit" when soft ≤ sum < hard.
|
|
184
182
|
*
|
|
185
183
|
* **Throws** `CapExceededError` when sum ≥ hard-threshold.
|
|
186
184
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* `lastSoftWarnedAt
|
|
190
|
-
*
|
|
191
|
-
* memoization
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* `false` (= "wir tracken's nicht").
|
|
185
|
+
* **The `crossed` flag is intentionally absent:** Unlike the calendar
|
|
186
|
+
* counter, the rolling aggregate has no projection row with a
|
|
187
|
+
* `lastSoftWarnedAt` flag. The caller must deduplicate notification storms
|
|
188
|
+
* using its own mechanism, such as a cache-table key or request-lifetime
|
|
189
|
+
* memoization. The result shape still matches `EnforceCapResult` so the same
|
|
190
|
+
* caller code works with both functions; `crossed` is always `false` here
|
|
191
|
+
* (= "not tracked").
|
|
195
192
|
*
|
|
196
|
-
* **Performance
|
|
197
|
-
* (tenant, capName).
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* vorgezogen.
|
|
193
|
+
* **Performance note:** The read sums ALL events in the window for
|
|
194
|
+
* (tenant, capName). With 10k+ events per tenant in the window, this could
|
|
195
|
+
* become slow; migrate to a multi-stream projection with pre-aggregated
|
|
196
|
+
* daily buckets if needed.
|
|
201
197
|
*/
|
|
202
198
|
export async function enforceRollingCap(
|
|
203
199
|
ctx: CapCounterContext,
|
|
@@ -324,20 +320,20 @@ export function calendarMonthPeriodEndIso(periodStartIso: string): string {
|
|
|
324
320
|
}
|
|
325
321
|
|
|
326
322
|
// =============================================================================
|
|
327
|
-
// Notification-
|
|
328
|
-
// enforceRollingCap
|
|
329
|
-
// soft-hit
|
|
330
|
-
//
|
|
323
|
+
// Notification-wiring helpers — convenience wrappers for `enforceCap` and
|
|
324
|
+
// `enforceRollingCap` that execute a caller-supplied delivery emitter when
|
|
325
|
+
// a soft-hit threshold is crossed. The cap counter does not know about the
|
|
326
|
+
// delivery feature directly; the caller injects the emitter.
|
|
331
327
|
// =============================================================================
|
|
332
328
|
|
|
333
329
|
/**
|
|
334
|
-
* Soft-hit
|
|
335
|
-
* delivery
|
|
336
|
-
*
|
|
337
|
-
* (`crossed === true
|
|
330
|
+
* Soft-hit notifier callback. The caller supplies the function that emits
|
|
331
|
+
* a delivery event (for example, `delivery.send({to, template, payload})`).
|
|
332
|
+
* It is called exactly once per period for the calendar counter
|
|
333
|
+
* (`crossed === true`, deduplicated via `markSoftWarnedHandler`).
|
|
338
334
|
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
335
|
+
* For the rolling counter, `crossed` is always `false`; the caller must
|
|
336
|
+
* deduplicate notifications itself or intentionally send one per request.
|
|
341
337
|
*/
|
|
342
338
|
export type SoftHitNotifier = (info: {
|
|
343
339
|
readonly capName: string;
|
|
@@ -347,14 +343,14 @@ export type SoftHitNotifier = (info: {
|
|
|
347
343
|
}) => Promise<void> | void;
|
|
348
344
|
|
|
349
345
|
/**
|
|
350
|
-
* Calendar-
|
|
351
|
-
*
|
|
352
|
-
* `mark-soft-warned
|
|
353
|
-
*
|
|
346
|
+
* Calendar-period enforcement with automatic soft-hit notification.
|
|
347
|
+
* Calls `enforceCap`; when `crossed: true`, it calls the notifier and the
|
|
348
|
+
* `mark-soft-warned` handler, which flips `lastSoftWarnedAt` so that the
|
|
349
|
+
* same period does not trigger another notification.
|
|
354
350
|
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
351
|
+
* Returns the `EnforceCapResult` unchanged, allowing the caller to branch
|
|
352
|
+
* on the result, such as showing a UI toast in addition to the email
|
|
353
|
+
* notification.
|
|
358
354
|
*/
|
|
359
355
|
export async function enforceCapAndMaybeNotify(
|
|
360
356
|
ctx: CapCounterContext,
|
|
@@ -400,14 +396,14 @@ export async function enforceCapAndMaybeNotify(
|
|
|
400
396
|
}
|
|
401
397
|
|
|
402
398
|
/**
|
|
403
|
-
* Rolling-
|
|
399
|
+
* Rolling-window enforcement that always sends a notification on a soft hit.
|
|
404
400
|
*
|
|
405
|
-
* **
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
401
|
+
* **Storm risk:** The rolling counter does NOT track `lastSoftWarnedAt`
|
|
402
|
+
* (there is no projection row). On every call while the counter is in the
|
|
403
|
+
* soft range, the notifier fires. The caller must deduplicate, for example
|
|
404
|
+
* with a cache entry `lastNotified[capName]` and a TTL, or call
|
|
405
|
+
* `enforceRollingCapAndMaybeNotify` only once per day or hour
|
|
406
|
+
* (an hourly cron instead of per request).
|
|
411
407
|
*/
|
|
412
408
|
export async function enforceRollingCapAndMaybeNotify(
|
|
413
409
|
ctx: CapCounterContext,
|
|
@@ -439,7 +435,7 @@ export async function enforceRollingCapAndMaybeNotify(
|
|
|
439
435
|
}
|
|
440
436
|
|
|
441
437
|
// =============================================================================
|
|
442
|
-
// Stock
|
|
438
|
+
// Stock cap — live-counted cardinality checked against the tier limit
|
|
443
439
|
// =============================================================================
|
|
444
440
|
|
|
445
441
|
export type StockCapResult =
|
|
@@ -447,24 +443,25 @@ export type StockCapResult =
|
|
|
447
443
|
| { readonly state: "exceeded"; readonly current: number; readonly limit: number };
|
|
448
444
|
|
|
449
445
|
/**
|
|
450
|
-
* Stock
|
|
451
|
-
*
|
|
446
|
+
* Stock cap: checks a cardinality counted LIVE by the caller (for example,
|
|
447
|
+
* the number of existing components for a tenant) against a tier limit.
|
|
452
448
|
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
* (`count(*) WHERE tenant_id = …`)
|
|
456
|
-
* (
|
|
457
|
-
*
|
|
449
|
+
* Unlike {@link enforceCap}/{@link enforceRollingCap}, there is NO stored
|
|
450
|
+
* counter: the caller counts the projection itself
|
|
451
|
+
* (`count(*) WHERE tenant_id = …`) and passes `current`. This avoids drift
|
|
452
|
+
* (a delete immediately frees the slot), requires no counter table or
|
|
453
|
+
* increment/decrement bookkeeping, and measures a stock rather than a flow.
|
|
458
454
|
*
|
|
459
|
-
* **TOCTOU
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
455
|
+
* **TOCTOU caveat:** Counting and writing are not atomic—two concurrent
|
|
456
|
+
* creates can both see `ok` and exceed the limit by one (the same race as
|
|
457
|
+
* with {@link enforceCap}). Strictly hard slots need additional
|
|
458
|
+
* serialization in the create path, such as a unique index on
|
|
459
|
+
* tenantId+slot.
|
|
463
460
|
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
461
|
+
* Pure function—it does NOT throw or map an HTTP status. Reaching a stock
|
|
462
|
+
* limit means "upgrade required", not "retry later" (429); the caller
|
|
463
|
+
* chooses the response, typically an app-specific 422/`upgrade_required`
|
|
464
|
+
* with i18n. With `hardSlot` (soft=hard=1.0), the boundary is exactly `limit`.
|
|
468
465
|
*/
|
|
469
466
|
export function enforceStockCap(options: {
|
|
470
467
|
readonly current: number;
|
|
@@ -5,38 +5,38 @@ import {
|
|
|
5
5
|
createTimestampField,
|
|
6
6
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
7
7
|
|
|
8
|
-
// cap-counter —
|
|
9
|
-
//
|
|
8
|
+
// cap-counter — one row per (tenantId, capName, periodStart). tenantId
|
|
9
|
+
// is added automatically as a base column (Kumiko multi-tenant default).
|
|
10
10
|
//
|
|
11
|
-
// **Identity
|
|
12
|
-
// - aggregate-id: UUID (Kumiko
|
|
13
|
-
// - public natural
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// **Identity model:**
|
|
12
|
+
// - aggregate-id: UUID (required by Kumiko ES)
|
|
13
|
+
// - public natural key: (tenantId, capName, periodStart) — the counter
|
|
14
|
+
// engine derives a deterministic uuidv5 from it so increments use the
|
|
15
|
+
// same stream instead of creating two rows per tenant and cap
|
|
16
16
|
//
|
|
17
|
-
// **
|
|
18
|
-
// - capName:
|
|
19
|
-
// "db-storage-bytes").
|
|
20
|
-
//
|
|
21
|
-
// - value:
|
|
22
|
-
//
|
|
23
|
-
// - periodStart:
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
// now() - 7d`
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
17
|
+
// **Fields:**
|
|
18
|
+
// - capName: the domain concept ("platform-mails", "ai-tokens-7day",
|
|
19
|
+
// "db-storage-bytes"). Free-form string — the app defines its cap
|
|
20
|
+
// names; the engine does not enumerate them.
|
|
21
|
+
// - value: the current counter value. Tokens, MB, count, etc. — the unit
|
|
22
|
+
// belongs to the app; the engine only counts numbers.
|
|
23
|
+
// - periodStart: timestamp when the current counter period began.
|
|
24
|
+
// A calendar-month reset sets a new periodStart (= new aggregate
|
|
25
|
+
// identity). A rolling window (e.g. AI tokens over 7 days) does not
|
|
26
|
+
// reset periodStart and filters on read with `WHERE timestamp >
|
|
27
|
+
// now() - 7d` over the event-store stream — this is the caller's
|
|
28
|
+
// responsibility.
|
|
29
|
+
// - lastSoftWarnedAt: prevents notification storms. Once the soft cap at
|
|
30
|
+
// 110% is reached, subsequent increments must not each send an email to
|
|
31
|
+
// the admin. There is at most one soft warning per period, so this
|
|
32
|
+
// nullable column is reset to null when the period resets.
|
|
32
33
|
//
|
|
33
|
-
// **
|
|
34
|
-
// - softLimit / hardLimit / cap-
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// - userId / aggregate
|
|
38
|
-
//
|
|
39
|
-
// auslöst).
|
|
34
|
+
// **What is intentionally not in the entity:**
|
|
35
|
+
// - softLimit / hardLimit / cap-tolerance multipliers — these come from
|
|
36
|
+
// the app's tier map when enforceCap is called. The counter knows
|
|
37
|
+
// nothing about the tier, only how much is being counted.
|
|
38
|
+
// - userId / aggregate reference — counters are scoped to the platform
|
|
39
|
+
// tenant, not to a user (even when a user triggers the increment).
|
|
40
40
|
export const capCounterEntity = createEntity({
|
|
41
41
|
table: "read_cap_counters",
|
|
42
42
|
description:
|
|
@@ -1,49 +1,48 @@
|
|
|
1
|
-
// cap-counter — Counter
|
|
1
|
+
// cap-counter — Counter Storage + Increment API + Soft-Warn State.
|
|
2
2
|
//
|
|
3
|
-
// **
|
|
4
|
-
// 1. r.entity({ name: "cap-counter" }) —
|
|
5
|
-
// period)
|
|
6
|
-
// 2. increment
|
|
7
|
-
// aggregate-id (try-create / executor-update)
|
|
8
|
-
// event-store optimistic
|
|
9
|
-
// 3. increment-rolling
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// 4. mark-soft-warned
|
|
13
|
-
//
|
|
14
|
-
// 5. get-counter
|
|
15
|
-
// (
|
|
16
|
-
// 6. enforceCap + enforceRollingCap
|
|
17
|
-
//
|
|
18
|
-
//
|
|
3
|
+
// **What this feature provides:**
|
|
4
|
+
// 1. r.entity({ name: "cap-counter" }) — counter rows per (tenant, capName,
|
|
5
|
+
// period) for calendar-period caps (mail/month, egress/month).
|
|
6
|
+
// 2. increment handler — atomic counter increment via deterministic
|
|
7
|
+
// aggregate-id (try-create / executor-update), made race-free by the
|
|
8
|
+
// event-store optimistic lock.
|
|
9
|
+
// 3. increment-rolling handler — append-only custom-event stream for
|
|
10
|
+
// rolling-window caps (AI-tokens-7d, egress-24h). No projection; the
|
|
11
|
+
// value is read from the event stream.
|
|
12
|
+
// 4. mark-soft-warned handler — flips the anti-notification-storm flag
|
|
13
|
+
// (calendar-period counters only).
|
|
14
|
+
// 5. get-counter query — synchronous read of the current counter value
|
|
15
|
+
// (calendar period).
|
|
16
|
+
// 6. enforceCap + enforceRollingCap helpers (see enforce-cap.ts) —
|
|
17
|
+
// pre-save wrappers with asymmetric soft and hard tolerances per
|
|
18
|
+
// cap profile.
|
|
19
19
|
//
|
|
20
|
-
// **Calendar vs.
|
|
20
|
+
// **Calendar vs. rolling — when to use which:**
|
|
21
21
|
// - **Calendar period** (bookCapUsage + enforceCap): the cap resets at
|
|
22
|
-
// period start (
|
|
23
|
-
// projection
|
|
22
|
+
// period start (the first of the month, etc.). The counter is one row in
|
|
23
|
+
// the projection, enabling fast reads.
|
|
24
24
|
// - **Rolling window** (CapCounterHandlers.incrementRolling + enforceRollingCap):
|
|
25
|
-
// the cap rolls continuously (e.g. "last 7 days"). Values expire
|
|
26
|
-
//
|
|
27
|
-
//
|
|
25
|
+
// the cap rolls continuously (e.g. "last 7 days"). Values expire event
|
|
26
|
+
// by event without a reset. There is no projection; reads sum the events
|
|
27
|
+
// from the last N days.
|
|
28
28
|
//
|
|
29
29
|
// **What this feature does NOT do:**
|
|
30
30
|
// - **No foundation wiring.** mail-foundation / file-foundation /
|
|
31
|
-
// ai-foundation are BYOK by default
|
|
31
|
+
// ai-foundation are BYOK by default and currently have no platform pool
|
|
32
32
|
// to count. cap-counter is generic: an app owner who wants to use the
|
|
33
33
|
// counter calls `bookCapUsage(...)` /
|
|
34
34
|
// `ctx.write(CapCounterHandlers.incrementRolling, ...)` from their own handler.
|
|
35
|
-
// - **No reset cron for the calendar period.**
|
|
36
|
-
// periodStartIso part of the aggregate id rolls over to a fresh
|
|
37
|
-
//
|
|
38
|
-
// - **
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
// nicht direkt.
|
|
35
|
+
// - **No reset cron for the calendar period.** It works without one: the
|
|
36
|
+
// periodStartIso part of the aggregate id rolls over to a fresh counter
|
|
37
|
+
// at the period boundary. Old rows remain for auditing.
|
|
38
|
+
// - **No notification path is hard-wired.** cap-counter is decoupled —
|
|
39
|
+
// `enforceCapAndMaybeNotify` (see enforce-cap.ts) is a convenience helper
|
|
40
|
+
// that invokes a caller-supplied emit callback; cap-counter does not know
|
|
41
|
+
// the delivery feature directly.
|
|
43
42
|
//
|
|
44
|
-
// **Boot
|
|
45
|
-
// config,
|
|
46
|
-
//
|
|
43
|
+
// **Boot dependencies:** none. cap-counter is plain vanilla — it needs no
|
|
44
|
+
// config, secrets, or tenant feature. Tenant scoping comes from the framework
|
|
45
|
+
// default (Base-Column tenantId).
|
|
47
46
|
|
|
48
47
|
import {
|
|
49
48
|
access,
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
// increment-rolling — Rolling-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// increment-rolling — Rolling-window counter increment via a custom
|
|
2
|
+
// event instead of CRUD/projection. Designed for caps whose values
|
|
3
|
+
// continuously renew (AI tokens over 7 days, egress over 24 hours).
|
|
4
4
|
//
|
|
5
|
-
// **
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// `amount`-Feld; CRUD-Events tragen nur den kumulativen value.
|
|
5
|
+
// **Why not r.entity / CRUD like the calendar counter:** The calendar
|
|
6
|
+
// counter stores the cumulative value in its projection row. At the
|
|
7
|
+
// period rollover, the aggregate ID changes to the new period start;
|
|
8
|
+
// that is the "reset". A rolling window has no rollover point—the
|
|
9
|
+
// counter continuously rolls out. A single cumulative value would be
|
|
10
|
+
// incorrect because it would grow monotonically without expiration.
|
|
11
|
+
// The correct read semantics are SUM of all increment amounts from the
|
|
12
|
+
// last N days. Therefore, each increment must be a separate event with
|
|
13
|
+
// its own `amount` field; CRUD events carry only the cumulative value.
|
|
15
14
|
//
|
|
16
|
-
// **Aggregate
|
|
17
|
-
// `rollingCapAggregateId`.
|
|
18
|
-
//
|
|
19
|
-
// N
|
|
15
|
+
// **Aggregate stream:** one stream per (tenant, capName)—see
|
|
16
|
+
// `rollingCapAggregateId`. All increments use the same stream in
|
|
17
|
+
// monotonically increasing version order. enforceRollingCap reads the
|
|
18
|
+
// last N days from this stream.
|
|
20
19
|
|
|
21
20
|
import type { WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
22
21
|
import * as z from "zod";
|
|
@@ -33,8 +32,8 @@ const incrementRollingSchema = z.object({
|
|
|
33
32
|
});
|
|
34
33
|
type IncrementRollingPayload = z.infer<typeof incrementRollingSchema>;
|
|
35
34
|
|
|
36
|
-
/** Schema
|
|
37
|
-
*
|
|
35
|
+
/** Schema of the emitted custom event. Identical to the input schema:
|
|
36
|
+
* the caller supplies amount, which we append unchanged to the stream. */
|
|
38
37
|
export const rollingIncrementedSchema = incrementRollingSchema;
|
|
39
38
|
|
|
40
39
|
/** Payload of the event that gives a reserved rolling amount back. */
|
|
@@ -44,27 +43,28 @@ export const rollingReleasedSchema = incrementRollingSchema.extend({
|
|
|
44
43
|
incrementedAt: z.string().optional(),
|
|
45
44
|
});
|
|
46
45
|
|
|
47
|
-
// Rolling-
|
|
48
|
-
//
|
|
49
|
-
//
|
|
46
|
+
// Rolling-increment handler — append-only. Race-free: two parallel
|
|
47
|
+
// increments for (tenant, cap) attach to the same aggregate stream at
|
|
48
|
+
// different versions, and the event store orders them.
|
|
50
49
|
//
|
|
51
|
-
// **
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
50
|
+
// **No version_conflict path** as with the calendar counter: nothing
|
|
51
|
+
// reads projection state before writing. The expectedVersion is
|
|
52
|
+
// implicitly "next-after-current", which the event store determines
|
|
53
|
+
// atomically.
|
|
55
54
|
export const incrementRollingCapHandler: WriteHandlerDef = {
|
|
56
55
|
name: "increment-rolling",
|
|
57
56
|
agent: { expose: false },
|
|
58
57
|
schema: incrementRollingSchema,
|
|
59
|
-
// Internal handler —
|
|
60
|
-
//
|
|
61
|
-
//
|
|
58
|
+
// Internal handler — a system caller (platform foundations after a
|
|
59
|
+
// successful side effect) invokes it. Tenant end users must never
|
|
60
|
+
// call it directly. The audit row shows which subsystem call site
|
|
61
|
+
// attached the operation.
|
|
62
62
|
access: { roles: ["SystemAdmin"] },
|
|
63
63
|
handler: async (event, ctx) => {
|
|
64
64
|
// @cast-boundary engine-payload — dispatcher hands handler the
|
|
65
65
|
// already-Zod-validated payload as `unknown`; cast to the typed
|
|
66
|
-
// shape
|
|
67
|
-
// existing increment.write.ts
|
|
66
|
+
// shape declared via incrementRollingSchema. Mirror the cast in
|
|
67
|
+
// existing increment.write.ts—the same dispatcher boundary.
|
|
68
68
|
const payload = event.payload as IncrementRollingPayload;
|
|
69
69
|
const aggregateId = rollingCapAggregateId(event.user.tenantId, payload.capName);
|
|
70
70
|
|
|
@@ -4,12 +4,11 @@ import { markCapSoftWarned } from "../book-cap-usage.ts";
|
|
|
4
4
|
|
|
5
5
|
// mark-soft-warned — sets lastSoftWarnedAt on the counter so subsequent
|
|
6
6
|
// soft-cap-hits in the same period don't re-trigger notifications.
|
|
7
|
-
//
|
|
7
|
+
// This prevents notification storms.
|
|
8
8
|
//
|
|
9
|
-
// **Caller
|
|
10
|
-
// soft threshold
|
|
11
|
-
// emits
|
|
12
|
-
// emit-side is app-specific; this handler only sets the flag.
|
|
9
|
+
// **Caller pattern:** enforceCap-Helper checks whether the value crosses the
|
|
10
|
+
// soft threshold while lastSoftWarnedAt is null, then calls this handler and
|
|
11
|
+
// emits the application-specific notification. This handler only sets the flag.
|
|
13
12
|
const markSoftWarnedSchema = z.object({
|
|
14
13
|
capName: z.string().min(1).max(100),
|
|
15
14
|
periodStartIso: z.string().min(1),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Generic stock-cap write-guard factory. Extracted from the near-identical
|
|
2
|
-
// cap-guard.ts app copies in show-pony and publicstatus
|
|
2
|
+
// cap-guard.ts app copies in show-pony and publicstatus — the
|
|
3
3
|
// only per-app variable was the Caps shape and how to resolve it for a
|
|
4
4
|
// tenant, so both are now factory parameters.
|
|
5
5
|
|
|
@@ -44,11 +44,9 @@ import { chainReservations } from "./reservation-chain.ts";
|
|
|
44
44
|
// =============================================================================
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* events); für byte/token-cap übergibt der Caller die Größe aus
|
|
51
|
-
* `event.payload`.
|
|
47
|
+
* Dynamic cap definition resolved for each handler invocation. A typical caller reads the tenant
|
|
48
|
+
* tier from `ctx` and maps it to a limit. `amount` defaults to 1 (counting events); for byte or
|
|
49
|
+
* token caps, the caller supplies the size from `event.payload`.
|
|
52
50
|
*/
|
|
53
51
|
export type CalendarCapDef = {
|
|
54
52
|
readonly capName: string;
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
defineQueryHandler,
|
|
4
4
|
mayOverrideTenant,
|
|
5
5
|
type QueryHandlerDefinition,
|
|
6
|
-
type TenantId,
|
|
7
6
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
8
7
|
import {
|
|
9
8
|
AccessDeniedError,
|
|
@@ -77,8 +76,7 @@ export function createCapsUsageQuery(
|
|
|
77
76
|
|
|
78
77
|
// Override path: limits must read the TARGET tenant's config, not the
|
|
79
78
|
// SystemAdmin caller's.
|
|
80
|
-
const config =
|
|
81
|
-
override === undefined ? ctx.config : ctx.configFor?.(targetTenantId as TenantId);
|
|
79
|
+
const config = override === undefined ? ctx.config : ctx.configFor?.(targetTenantId);
|
|
82
80
|
|
|
83
81
|
const rows: CapUsageWithMeta[] = await Promise.all(
|
|
84
82
|
caps.map(async (cap) => {
|
|
@@ -86,7 +86,7 @@ async function resolveLimitsByTenantAndCap(
|
|
|
86
86
|
): Promise<ReadonlyMap<string, number | null>> {
|
|
87
87
|
const entries = await Promise.all(
|
|
88
88
|
tenants.flatMap(({ tenantId, tier }) => {
|
|
89
|
-
const context: CapLimitContext = { config: configFor?.(tenantId
|
|
89
|
+
const context: CapLimitContext = { config: configFor?.(tenantId) };
|
|
90
90
|
return caps.map(
|
|
91
91
|
async (cap) => [tenantCapKey(tenantId, cap.id), await cap.limit(tier, context)] as const,
|
|
92
92
|
);
|