@cosmicdrift/kumiko-bundled-features 0.367.0 → 0.369.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/dist/audit/handlers/details.query.js +1 -1
- package/dist/audit/handlers/list.query.js +1 -1
- package/dist/audit/run-escape-hatch-retention.js +1 -1
- package/dist/auth-email-password/bootstrap.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +6 -3
- package/dist/auth-email-password/handlers/invite-accept.write.js +6 -3
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +6 -3
- package/dist/auth-email-password/handlers/signup-confirm.write.js +1 -1
- package/dist/auth-email-password/seeding.js +2 -2
- package/dist/auth-foundation/feature.d.ts +4 -0
- package/dist/auth-foundation/feature.js +37 -33
- package/dist/auth-foundation/index.d.ts +1 -1
- package/dist/auth-foundation/index.js +1 -1
- package/dist/auth-mfa/db/queries.js +1 -2
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +2 -3
- package/dist/auth-mfa/handlers/status.query.js +1 -1
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/mfa-code-verifier.js +1 -1
- package/dist/auth-mfa/mfa-status-checker.js +1 -1
- package/dist/auth-mfa-user-data/index.d.ts +4 -0
- package/dist/auth-mfa-user-data/index.js +13 -9
- package/dist/billing-foundation/billing-info-query.js +1 -1
- package/dist/billing-foundation/feature.d.ts +1 -0
- package/dist/billing-foundation/feature.js +5 -6
- package/dist/billing-foundation/handlers/create-portal-session.write.js +1 -1
- package/dist/billing-foundation/projection.js +1 -2
- package/dist/cap-counter/calendar-cap-usage-reservation.d.ts +7 -0
- package/dist/cap-counter/calendar-cap-usage-reservation.js +28 -2
- package/dist/cap-counter/cap-reservation.d.ts +16 -0
- package/dist/cap-counter/cap-reservation.js +144 -14
- package/dist/cap-counter/feature.d.ts +4 -0
- package/dist/cap-counter/feature.js +74 -68
- package/dist/cap-counter/handlers/increment-rolling.write.js +3 -4
- package/dist/cap-counter/index.d.ts +3 -2
- package/dist/cap-counter/index.js +3 -2
- package/dist/cap-counter/tables.js +10 -3
- package/dist/cap-overview/handlers/caps-usage.query.js +1 -2
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +1 -2
- package/dist/cap-overview/handlers/tenant-options.query.js +1 -1
- package/dist/channel-email/email-channel.d.ts +13 -5
- package/dist/channel-email/email-channel.js +17 -3
- package/dist/channel-email/feature.js +1 -1
- package/dist/channel-email/index.d.ts +1 -1
- package/dist/channel-email/index.js +1 -1
- package/dist/channel-in-app/handlers/inbox.query.js +1 -1
- package/dist/channel-in-app/handlers/mark-all-read.write.js +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.js +1 -1
- package/dist/channel-in-app/handlers/unread-count.query.js +1 -1
- package/dist/channel-in-app/tables.js +1 -2
- package/dist/compliance-profiles/handlers/for-tenant.query.js +1 -1
- package/dist/compliance-profiles/handlers/needs-profile.query.js +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.js +1 -2
- package/dist/compliance-profiles/resolve-for-tenant.js +1 -1
- package/dist/compliance-profiles/seeding.js +3 -5
- package/dist/compliance-profiles-ops/index.d.ts +8 -0
- package/dist/compliance-profiles-ops/index.js +19 -15
- package/dist/config/db/queries/resolver.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +2 -2
- package/dist/config/resolver.js +1 -1
- package/dist/config/web/i18n.js +1 -2
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.js +6 -3
- package/dist/custom-fields/db/queries/field-access.js +1 -1
- package/dist/custom-fields/db/queries/projection.js +1 -1
- package/dist/custom-fields/db/queries/quota.js +1 -1
- package/dist/custom-fields/db/queries/retention.js +1 -2
- package/dist/custom-fields/db/queries/user-data-rights.js +1 -1
- package/dist/custom-fields/feature.d.ts +20 -2
- package/dist/custom-fields/feature.js +9 -13
- package/dist/custom-fields/handlers/clear-custom-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/set-custom-field.write.js +2 -2
- package/dist/custom-fields/wire-for-entity.js +4 -4
- package/dist/data-retention/resolve-for-tenant.js +1 -1
- package/dist/data-retention/run-retention-cleanup.js +17 -13
- package/dist/delivery/address-opt-out.js +1 -2
- package/dist/delivery/attempt-log-retention.js +1 -1
- package/dist/delivery/channel-context.js +1 -1
- package/dist/delivery/db/queries/address-opt-outs.js +1 -1
- package/dist/delivery/db/queries/preferences.js +1 -1
- package/dist/delivery/delivery-service.js +16 -7
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +2 -3
- package/dist/delivery/handlers/preferences.query.js +1 -1
- package/dist/delivery/index.d.ts +3 -2
- package/dist/delivery/index.js +3 -2
- package/dist/delivery/unsubscribe.d.ts +13 -0
- package/dist/delivery/unsubscribe.js +32 -27
- package/dist/delivery/upsert-preference.js +1 -2
- package/dist/derivatives-sharp/feature.d.ts +4 -0
- package/dist/derivatives-sharp/feature.js +15 -11
- package/dist/derivatives-sharp/index.d.ts +1 -1
- package/dist/derivatives-sharp/index.js +1 -1
- package/dist/document-ingest-foundation/feature.d.ts +7 -0
- package/dist/document-ingest-foundation/feature.js +94 -90
- package/dist/document-ingest-foundation/forget-extract-with-file-ref.js +3 -3
- package/dist/document-ingest-foundation/index.d.ts +1 -1
- package/dist/document-ingest-foundation/index.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -2
- package/dist/feature-toggles/handlers/set.write.js +3 -5
- package/dist/feature-toggles/toggle-runtime.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -0
- package/dist/file-derivatives/feature.js +2 -1
- package/dist/file-derivatives/handlers/public-variant-by-file-ref.query.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-foundation/feature.d.ts +6 -0
- package/dist/file-foundation/feature.js +29 -25
- package/dist/file-foundation/index.d.ts +1 -1
- package/dist/file-foundation/index.js +1 -1
- package/dist/file-foundation/read-file-ref-content.js +1 -1
- package/dist/file-provider-inmemory/feature.d.ts +4 -0
- package/dist/file-provider-inmemory/feature.js +24 -20
- package/dist/file-provider-inmemory/index.d.ts +1 -1
- package/dist/file-provider-inmemory/index.js +1 -1
- package/dist/file-provider-s3/env-feature.d.ts +3 -0
- package/dist/file-provider-s3/env-feature.js +46 -0
- package/dist/file-provider-s3/feature.d.ts +26 -0
- package/dist/file-provider-s3/feature.js +84 -72
- package/dist/file-provider-s3/index.d.ts +1 -1
- package/dist/file-provider-s3/index.js +1 -1
- package/dist/file-provider-s3/lib/index.d.ts +3 -0
- package/dist/file-provider-s3/lib/index.js +2 -0
- package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.js +19 -19
- package/dist/file-provider-s3-env/index.d.ts +8 -1
- package/dist/file-provider-s3-env/index.js +7 -2
- package/dist/files-provider-s3/index.d.ts +5 -3
- package/dist/files-provider-s3/index.js +5 -2
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +1 -1
- package/dist/files-tenant-data/hooks.js +1 -2
- package/dist/folders/feature.d.ts +6 -2
- package/dist/folders/feature.js +4 -2
- package/dist/folders-user-data/index.d.ts +4 -0
- package/dist/folders-user-data/index.js +21 -17
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/draft-count.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -2
- package/dist/form-draft/feature.d.ts +4 -0
- package/dist/form-draft/feature.js +5 -1
- package/dist/form-draft/handlers/cleanup.job.js +2 -2
- package/dist/form-draft/index.d.ts +1 -1
- package/dist/form-draft/index.js +1 -1
- package/dist/form-draft/lookup.js +1 -1
- package/dist/form-draft-user-data/index.d.ts +4 -0
- package/dist/form-draft-user-data/index.js +13 -9
- package/dist/inbound-mail-foundation/feature.d.ts +4 -0
- package/dist/inbound-mail-foundation/feature.js +151 -147
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -2
- package/dist/inbound-mail-foundation/index.d.ts +1 -1
- package/dist/inbound-mail-foundation/index.js +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +1 -2
- package/dist/inbound-mail-foundation/projection.js +1 -2
- package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
- package/dist/inbound-provider-imap/feature.d.ts +4 -0
- package/dist/inbound-provider-imap/feature.js +16 -12
- package/dist/inbound-provider-imap/index.d.ts +1 -1
- package/dist/inbound-provider-imap/index.js +1 -1
- package/dist/inbound-provider-inmemory/feature.d.ts +4 -0
- package/dist/inbound-provider-inmemory/feature.js +14 -10
- package/dist/inbound-provider-inmemory/index.d.ts +1 -1
- package/dist/inbound-provider-inmemory/index.js +1 -1
- package/dist/jobs/db/queries/retention.js +1 -1
- package/dist/jobs/db/queries/stale-run-sweep.js +1 -1
- package/dist/jobs/handlers/detail.query.js +1 -1
- package/dist/jobs/handlers/list.query.js +1 -2
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/handlers/tenant-failures.query.js +1 -1
- package/dist/jobs/handlers/tenant-runs.query.js +1 -1
- package/dist/jobs/job-run-logger.js +1 -2
- package/dist/jobs/tenant-job-failure-table.js +1 -2
- package/dist/jobs/tenant-job-run-table.js +1 -2
- package/dist/ledger/feature.d.ts +6 -2
- package/dist/ledger/feature.js +4 -2
- package/dist/mail-foundation/feature.d.ts +11 -0
- package/dist/mail-foundation/feature.js +52 -42
- package/dist/mail-foundation/i18n.d.ts +14 -0
- package/dist/mail-foundation/i18n.js +8 -0
- package/dist/mail-foundation/index.d.ts +1 -1
- package/dist/mail-foundation/index.js +1 -1
- package/dist/mail-transport-inmemory/feature.d.ts +4 -0
- package/dist/mail-transport-inmemory/feature.js +26 -16
- package/dist/mail-transport-inmemory/index.d.ts +1 -1
- package/dist/mail-transport-inmemory/index.js +1 -1
- package/dist/mail-transport-smtp/config-keys.d.ts +7 -0
- package/dist/mail-transport-smtp/config-keys.js +65 -0
- package/dist/mail-transport-smtp/feature.d.ts +17 -1
- package/dist/mail-transport-smtp/feature.js +58 -80
- package/dist/mail-transport-smtp/i18n.d.ts +41 -0
- package/dist/mail-transport-smtp/i18n.js +28 -0
- package/dist/mail-transport-smtp/index.d.ts +1 -1
- package/dist/mail-transport-smtp/index.js +1 -1
- package/dist/managed-pages/handlers/by-slug.query.js +1 -1
- package/dist/managed-pages/handlers/by-tenant-published.query.js +1 -2
- package/dist/managed-pages/handlers/set.write.js +1 -2
- package/dist/managed-pages/seeding.js +3 -5
- package/dist/metrics/compute.d.ts +1 -1
- package/dist/metrics/filters.d.ts +1 -1
- package/dist/metrics/filters.js +1 -1
- package/dist/metrics/validate.js +1 -1
- package/dist/notes-history/feature.d.ts +7 -2
- package/dist/notes-history/feature.js +4 -2
- package/dist/notes-history/handlers/add-note.write.js +1 -1
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/notes-history-user-data/index.d.ts +4 -0
- package/dist/notes-history-user-data/index.js +21 -17
- package/dist/personal-access-tokens/feature.d.ts +4 -1
- package/dist/personal-access-tokens/feature.js +10 -2
- package/dist/personal-access-tokens/handlers/create.write.js +1 -1
- package/dist/personal-access-tokens/handlers/list.query.js +2 -2
- package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
- package/dist/personal-access-tokens/resolver.js +1 -1
- package/dist/personal-access-tokens/revoke-for-user.js +1 -1
- package/dist/personal-access-tokens/roles.js +3 -5
- package/dist/personal-access-tokens/screens.js +2 -0
- package/dist/readiness/feature.d.ts +8 -0
- package/dist/readiness/feature.js +18 -14
- package/dist/readiness/index.d.ts +1 -1
- package/dist/readiness/index.js +1 -1
- package/dist/secrets/db/queries/read.js +1 -1
- package/dist/secrets/feature.d.ts +4 -0
- package/dist/secrets/feature.js +19 -6
- package/dist/secrets/handlers/delete.write.js +3 -2
- package/dist/secrets/handlers/rotate.job.js +2 -3
- package/dist/secrets/handlers/set.write.js +3 -2
- package/dist/secrets/secrets-context.js +3 -4
- package/dist/sessions/db/queries/cleanup.js +1 -1
- package/dist/sessions/handlers/detail.query.js +1 -1
- package/dist/sessions/handlers/list.query.js +2 -2
- package/dist/sessions/handlers/mine.query.js +1 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/session-callbacks.js +4 -6
- package/dist/sessions/testing.d.ts +1 -1
- package/dist/tags/feature.d.ts +6 -2
- package/dist/tags/feature.js +4 -2
- package/dist/template-resolver/api.js +1 -1
- package/dist/template-resolver/constants.d.ts +0 -1
- package/dist/template-resolver/constants.js +0 -1
- package/dist/template-resolver/handlers/bundle-import.js +1 -1
- package/dist/template-resolver/handlers/by-slug.query.js +1 -1
- package/dist/template-resolver/handlers/by-tenant.query.js +1 -2
- package/dist/template-resolver/handlers/collection-item.query.js +1 -1
- package/dist/template-resolver/handlers/collection-list.query.js +1 -2
- package/dist/template-resolver/handlers/collection-set.write.js +1 -1
- package/dist/template-resolver/handlers/copy-locale.write.js +1 -1
- package/dist/template-resolver/handlers/diff-to-system.query.js +1 -1
- package/dist/template-resolver/handlers/export-bundle.query.js +1 -1
- package/dist/template-resolver/handlers/find-by-id.query.js +1 -1
- package/dist/template-resolver/handlers/layout-source.query.js +1 -1
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/overview.query.js +1 -1
- package/dist/template-resolver/handlers/reset-to-system.write.js +1 -1
- package/dist/template-resolver/handlers/resource-remove.write.js +1 -1
- package/dist/template-resolver/handlers/send-test.write.js +4 -2
- package/dist/template-resolver/handlers/set.write.js +1 -1
- package/dist/template-resolver/handlers/template-write.js +1 -1
- package/dist/template-resolver/handlers/tenant-overrides.query.js +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.js +1 -1
- package/dist/template-resolver/handlers/usage.query.js +1 -1
- package/dist/template-resolver/handlers/validate.query.js +1 -1
- package/dist/template-resolver/seeding.js +3 -4
- package/dist/template-resolver/store-template-resource.js +1 -1
- package/dist/template-resolver/template-preview.js +1 -1
- package/dist/template-resolver/template-resources.js +1 -1
- package/dist/template-resolver/testing.js +1 -1
- package/dist/template-resolver-user-data/index.d.ts +4 -0
- package/dist/template-resolver-user-data/index.js +17 -13
- package/dist/tenant/handlers/active-tenant-ids.query.js +1 -1
- package/dist/tenant/handlers/add-member.write.js +1 -2
- package/dist/tenant/handlers/cancel-invitation.write.js +1 -1
- package/dist/tenant/handlers/invitations.query.js +1 -1
- package/dist/tenant/handlers/me.query.js +1 -1
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/memberships.query.js +1 -1
- package/dist/tenant/handlers/remove-member.write.js +1 -2
- package/dist/tenant/handlers/resolve-user-ids.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/handlers/update-member-roles.write.js +1 -2
- package/dist/tenant/invited-membership.js +2 -3
- package/dist/tenant/last-tenant-admin.js +1 -2
- package/dist/tenant/seeding.js +12 -6
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +1 -2
- package/dist/tenant-lifecycle/handlers/request-destruction.write.js +1 -2
- package/dist/tenant-lifecycle/lib/revoke-tenant-sessions.js +1 -1
- package/dist/tenant-lifecycle/lifecycle-gate.js +1 -1
- package/dist/tenant-lifecycle/run-tenant-destroy.js +3 -5
- package/dist/tenant-lifecycle/stages.js +10 -6
- package/dist/tenant-lifecycle/testing.d.ts +1 -1
- package/dist/tenant-lifecycle/testing.js +2 -2
- package/dist/tenant-settings/feature.d.ts +1 -0
- package/dist/tenant-settings/feature.js +2 -1
- package/dist/tier-engine/feature.d.ts +1 -8
- package/dist/tier-engine/feature.js +71 -78
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +2 -3
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -2
- package/dist/user/db/queries/stream-tenant-backfill.js +1 -1
- package/dist/user/handlers/create.write.js +1 -2
- package/dist/user/handlers/find-for-auth.query.js +1 -1
- package/dist/user/handlers/list.query.js +1 -1
- package/dist/user/handlers/update-roles.js +1 -2
- package/dist/user/index.d.ts +1 -1
- package/dist/user/index.js +1 -1
- package/dist/user/invited-global-roles.js +2 -3
- package/dist/user/principal-status.d.ts +4 -0
- package/dist/user/principal-status.js +9 -3
- package/dist/user/resolve-display-names.js +1 -1
- package/dist/user/seeding.js +5 -6
- package/dist/user-data-rights/audit-download.js +2 -2
- package/dist/user-data-rights/db/queries/export-jobs.js +1 -1
- package/dist/user-data-rights/db/queries/forget-cleanup.js +1 -1
- package/dist/user-data-rights/feature.js +7 -4
- package/dist/user-data-rights/handlers/download-by-job.query.js +1 -1
- package/dist/user-data-rights/handlers/download-by-token.query.js +1 -1
- package/dist/user-data-rights/handlers/export-status.query.js +1 -1
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
- package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
- package/dist/user-data-rights/handlers/request-export.write.js +1 -2
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +3 -3
- package/dist/user-data-rights/lib/default-mailers.d.ts +3 -0
- package/dist/user-data-rights/lib/default-mailers.js +25 -3
- package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.d.ts +1 -1
- package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.js +1 -1
- package/dist/user-data-rights/lib/update-user-lifecycle.d.ts +1 -0
- package/dist/user-data-rights/lib/update-user-lifecycle.js +3 -3
- package/dist/user-data-rights/run-export-jobs.js +2 -3
- package/dist/user-data-rights/run-forget-cleanup.js +9 -5
- package/dist/user-data-rights/run-user-export.js +9 -5
- package/dist/waitlist/handlers/invite.write.js +1 -2
- package/dist/waitlist/handlers/reject.write.js +1 -1
- package/dist/waitlist/lib.js +1 -2
- package/dist/workflow-runner/event-subscriber.js +1 -1
- package/dist/workflow-runner/feature.d.ts +4 -0
- package/dist/workflow-runner/feature.js +44 -40
- package/dist/workflow-runner/handlers/resume-run.write.js +1 -1
- package/dist/workflow-runner/index.d.ts +1 -1
- package/dist/workflow-runner/index.js +1 -1
- package/dist/workflow-runner/pending-projection.js +1 -1
- package/package.json +28 -11
- package/src/cap-counter/changes.json +13 -0
- package/src/channel-email/changes.json +7 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/delivery/changes.json +6 -0
- package/src/file-provider-s3/changes.json +10 -1
- package/src/mail-transport-smtp/changes.json +7 -0
- package/src/personal-access-tokens/changes.json +6 -0
- package/src/secrets/changes.json +6 -0
- package/src/user/changes.json +6 -0
- package/src/user-data-rights/changes.json +6 -0
- package/dist/file-provider-s3-env/feature.d.ts +0 -3
- package/dist/file-provider-s3-env/feature.js +0 -46
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.d.ts +0 -0
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.js +0 -0
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.d.ts +0 -0
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
//
|
|
41
41
|
// **Boot-Dependencies:** config + tenant.
|
|
42
42
|
// kumiko-lint-ignore app-feature-structure Phase-3 conversion tracked in #2312 (feature.ts > 300 lines)
|
|
43
|
-
import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/
|
|
44
|
-
import { buildEntityTable, createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
|
|
43
|
+
import { buildEntityTable, createEventStoreExecutor, createTenantDb, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
|
|
45
44
|
import { defineEntityCreateHandler, defineEntityListHandler, defineEntityUpdateHandler, defineFeature, defineQueryHandler, HookPhases, SYSTEM_TENANT_ID, TENANT_TIER_RESOLVER_EXT, } from "@cosmicdrift/kumiko-framework/engine";
|
|
46
45
|
import { getUnscopedAggregateStreamMaxVersion } from "@cosmicdrift/kumiko-framework/event-store";
|
|
47
46
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
@@ -217,14 +216,14 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
217
216
|
if (!opts.tierMap)
|
|
218
217
|
return;
|
|
219
218
|
const tierMap = opts.tierMap;
|
|
220
|
-
// Closure
|
|
221
|
-
// cache
|
|
222
|
-
// pre-
|
|
219
|
+
// Closure state: per-tenant cache of effective sets. Hooks keep the
|
|
220
|
+
// cache current during the process lifetime; build() in the extension
|
|
221
|
+
// pickup pre-loads existing assignments at boot.
|
|
223
222
|
const cache = new Map();
|
|
224
|
-
// alwaysOn
|
|
225
|
-
// non-toggleable features). Hooks
|
|
226
|
-
//
|
|
227
|
-
//
|
|
223
|
+
// The alwaysOn set is computed in build(deps) from registry.features (all
|
|
224
|
+
// non-toggleable features). Hooks need it for mergeAlwaysOn calls — late
|
|
225
|
+
// bound via a mutable holder, filled before any request (build runs
|
|
226
|
+
// pre-listen via the runDevApp/runProdApp pickup).
|
|
228
227
|
const alwaysOnHolder = { set: new Set() };
|
|
229
228
|
// Bus handed to build(); hooks fire outside build and publish through it.
|
|
230
229
|
const busHolder = { bus: undefined };
|
|
@@ -242,13 +241,14 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
242
241
|
// The writer already updated its own cache; only other pods need to re-read.
|
|
243
242
|
busHolder.bus?.publish(CACHE_SYNC_TOPICS.tierAssignment, message, { remoteOnly: true });
|
|
244
243
|
};
|
|
245
|
-
// Trial:
|
|
246
|
-
//
|
|
247
|
-
// boot-cached
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
244
|
+
// Trial: derived from time (tenant.inserted_at ≈ signup) and checked live
|
|
245
|
+
// at the feature gate — NOT in the resolver cache. The resolver is
|
|
246
|
+
// boot-cached and synchronous, so it sees neither fresh signups nor the
|
|
247
|
+
// passage of time; the trial status changes over time and applies from
|
|
248
|
+
// second 1 after signup. That is why it lives as an async trialGate
|
|
249
|
+
// (below, attached at the end of build) which the dispatcher consults
|
|
250
|
+
// only on the disabled path. trialFeatures = fixed feature set of the
|
|
251
|
+
// trial tier.
|
|
252
252
|
if (opts.trial && !tierMap[opts.trial.tier]) {
|
|
253
253
|
throw new Error(`tier-engine: trial.tier "${opts.trial.tier}" is not a key in tierMap — trial would unlock no features`);
|
|
254
254
|
}
|
|
@@ -286,7 +286,7 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
286
286
|
target: { allOf: "tier-assignment" },
|
|
287
287
|
handler: async (payload) => {
|
|
288
288
|
const data = payload.data; // @cast-boundary engine-payload
|
|
289
|
-
// skip:
|
|
289
|
+
// skip: same type-guard semantics as the postSave hook above.
|
|
290
290
|
if (typeof data.tenantId !== "string")
|
|
291
291
|
return;
|
|
292
292
|
const tenantId = data.tenantId;
|
|
@@ -295,18 +295,19 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
295
295
|
publishAssignmentChange(tenantId);
|
|
296
296
|
},
|
|
297
297
|
});
|
|
298
|
-
// Auto-default-tier-on-tenant-signup: hook fires inTransaction (atomic
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
// tenant/seeding.ts
|
|
298
|
+
// Auto-default-tier-on-tenant-signup: the hook fires inTransaction (atomic
|
|
299
|
+
// with the tenant-create rollback) and writes the tier-assignment via the
|
|
300
|
+
// direct executor (not ctx.write — the hook has an AppContext). Same
|
|
301
|
+
// pattern as seedTenant in tenant/seeding.ts.
|
|
302
302
|
//
|
|
303
|
-
// **Idempotency:** deterministic aggregate
|
|
304
|
-
// (
|
|
305
|
-
//
|
|
306
|
-
// tenant-create
|
|
303
|
+
// **Idempotency:** deterministic aggregate id derived from tenantId. A
|
|
304
|
+
// re-replay (after a projection rebuild or hook retry) finds
|
|
305
|
+
// stream-version > 0 and skips instead of throwing version_conflict. The
|
|
306
|
+
// caller sees a successful tenant-create plus the existing
|
|
307
|
+
// tier-assignment.
|
|
307
308
|
//
|
|
308
|
-
// **Cross-tenant write:** executor
|
|
309
|
-
//
|
|
309
|
+
// **Cross-tenant write:** the executor needs a systemUser WITH tenantId =
|
|
310
|
+
// the new tenant (memory `feedback_event_store_tenant_consistency`).
|
|
310
311
|
if (opts.defaultTier !== undefined) {
|
|
311
312
|
const defaultTier = opts.defaultTier;
|
|
312
313
|
const autoDefaultTierHookReason = "seeds the default tier-assignment stream of the tenant just created";
|
|
@@ -314,16 +315,16 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
314
315
|
type: "postSave",
|
|
315
316
|
target: { allOf: "tenant" },
|
|
316
317
|
handler: async (result, ctx) => {
|
|
317
|
-
// result
|
|
318
|
+
// result shape: kumiko-framework's SaveContext with isNew + data
|
|
318
319
|
const saveResult = result; // @cast-boundary engine-payload
|
|
319
|
-
// skip:
|
|
320
|
-
//
|
|
321
|
-
//
|
|
320
|
+
// skip: only on tenant-create (initial) — tenant updates fire
|
|
321
|
+
// postSave too, but a re-keying or name update must not create a
|
|
322
|
+
// new tier-assignment.
|
|
322
323
|
if (saveResult.isNew !== true)
|
|
323
324
|
return;
|
|
324
325
|
const data = saveResult.data; // @cast-boundary engine-payload
|
|
325
|
-
// skip: defensive type
|
|
326
|
-
// CrudExecutor's payload
|
|
326
|
+
// skip: defensive type guard. The tenant entity always has an id, but
|
|
327
|
+
// CrudExecutor's payload shape is unknown at runtime.
|
|
327
328
|
if (typeof data.id !== "string")
|
|
328
329
|
return;
|
|
329
330
|
const newTenantId = data.id; // @cast-boundary engine-payload
|
|
@@ -342,48 +343,47 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
342
343
|
// blocking), silent-skip is defensive-soft.
|
|
343
344
|
if (!rawDb)
|
|
344
345
|
return;
|
|
345
|
-
// Idempotency: stream-existence
|
|
346
|
-
// seedTenant.ts.
|
|
346
|
+
// Idempotency: stream-existence check before create. Same pattern as
|
|
347
|
+
// seedTenant.ts. On a re-replay (rebuild) do not bump the version.
|
|
347
348
|
const streamVersion = await getUnscopedAggregateStreamMaxVersion(rawDb, aggregateId);
|
|
348
349
|
// skip: idempotent — tier-assignment stream already seeded (rebuild/replay).
|
|
349
350
|
if (streamVersion > 0)
|
|
350
351
|
return;
|
|
351
|
-
// SystemUser
|
|
352
|
-
// user (
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
// `feedback_event_store_tenant_consistency`: by.tenantId
|
|
356
|
-
//
|
|
352
|
+
// SystemUser for the NEW tenant — the hook is triggered by the signup
|
|
353
|
+
// user (another tenant, or SystemAdmin), but the tier-assignment has
|
|
354
|
+
// to land in the stream of the newly created tenant (= aggregate id
|
|
355
|
+
// deterministic on newTenantId). Memory
|
|
356
|
+
// `feedback_event_store_tenant_consistency`: by.tenantId must equal
|
|
357
|
+
// the target tenant.
|
|
357
358
|
const systemUser = {
|
|
358
359
|
id: "00000000-0000-4000-8000-000000000001",
|
|
359
360
|
tenantId: newTenantId,
|
|
360
361
|
roles: ["SystemAdmin"],
|
|
361
362
|
};
|
|
362
|
-
const tdb = createTenantDb(rawDb, newTenantId, "system");
|
|
363
|
+
const tdb = createTenantDb({ db: rawDb, tenantId: newTenantId, mode: "system" });
|
|
363
364
|
await tierAssignmentExecutor.create({ id: aggregateId, tier: defaultTier, source: TierAssignmentSources.default }, systemUser, tdb);
|
|
364
365
|
},
|
|
365
366
|
phase: HookPhases.inTransaction,
|
|
366
367
|
escapeHatch: { reason: autoDefaultTierHookReason },
|
|
367
368
|
});
|
|
368
369
|
}
|
|
369
|
-
// Extension-point declaration + self-registration.
|
|
370
|
-
// mail-foundation/file-foundation:
|
|
371
|
-
//
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
// findTierResolverUsage's "single-plugin"-comment.
|
|
370
|
+
// Extension-point declaration + self-registration. Same pattern as
|
|
371
|
+
// mail-foundation/file-foundation: the feature declares the extension
|
|
372
|
+
// point AND registers itself as the default plugin. Other features could
|
|
373
|
+
// register there later (e.g. a future toggle-only resolver), but only one
|
|
374
|
+
// plugin wins — see the "single-plugin" comment on findTierResolverUsage.
|
|
375
375
|
r.extendsRegistrar(TENANT_TIER_RESOLVER_EXT, { onRegister: () => { } });
|
|
376
376
|
// Plugin-registration: framework's runDevApp/runProdApp picks this up
|
|
377
377
|
// post-stack-setup, calls build(deps), wires effectiveFeatures.
|
|
378
378
|
const plugin = {
|
|
379
379
|
build: async (deps) => {
|
|
380
|
-
// Always-on
|
|
381
|
-
// Kumiko
|
|
382
|
-
//
|
|
383
|
-
// Framework
|
|
384
|
-
// sessions, etc.)
|
|
385
|
-
//
|
|
386
|
-
//
|
|
380
|
+
// Always-on set: all non-toggleable features in the registry. Canonical
|
|
381
|
+
// Kumiko pattern (matches the feature-toggles resolver): only features
|
|
382
|
+
// that explicitly register `r.toggleable()` are tier-cuttable.
|
|
383
|
+
// Framework base features (auth-email-password, config, user, tenant,
|
|
384
|
+
// sessions, etc.) are non-toggleable → ALWAYS active for every tenant
|
|
385
|
+
// regardless of tier. Otherwise the dispatcher would answer 403 on the
|
|
386
|
+
// login handler because "feature auth-email-password disabled".
|
|
387
387
|
const computedAlwaysOn = new Set();
|
|
388
388
|
for (const feature of deps.registry.features.values()) {
|
|
389
389
|
if (feature.toggleableDefault === undefined)
|
|
@@ -452,16 +452,16 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
452
452
|
// Synchronous resolver-callback for dispatcher hot-path.
|
|
453
453
|
const resolver = (tenantId) => {
|
|
454
454
|
// Operator-tooling + async-event-dispatch convention: SYSTEM_TENANT_ID
|
|
455
|
-
// gets the union of all tier
|
|
455
|
+
// gets the union of all tier features (see DispatcherOptions doc).
|
|
456
456
|
if (tenantId === SYSTEM_TENANT_ID) {
|
|
457
457
|
return mergeAlwaysOn(computedAlwaysOn, unionAllTierFeatures(tierMap));
|
|
458
458
|
}
|
|
459
|
-
// Cache
|
|
460
|
-
// boot,
|
|
461
|
-
//
|
|
462
|
-
// `feedback_security_default_on`: secure
|
|
463
|
-
//
|
|
464
|
-
//
|
|
459
|
+
// Cache miss: the tenant is not in the cache yet (e.g. brand new after
|
|
460
|
+
// boot, or the defaultTier hook has not fired yet). The default set
|
|
461
|
+
// is least-privileged — typically free-tier features. Memory
|
|
462
|
+
// `feedback_security_default_on`: secure by default. The trial is NOT
|
|
463
|
+
// added here (sync/boot-cached, cannot see the passage of time) — the
|
|
464
|
+
// trialGate below does that on the disabled-gate path.
|
|
465
465
|
const fallbackTier = opts.defaultTier;
|
|
466
466
|
return (cache.get(tenantId) ??
|
|
467
467
|
(fallbackTier === undefined
|
|
@@ -471,11 +471,11 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
471
471
|
const trial = opts.trial;
|
|
472
472
|
if (trial === undefined)
|
|
473
473
|
return resolver;
|
|
474
|
-
// Live
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
//
|
|
474
|
+
// Live trial gate: reads tenant.inserted_at (≈ signup; exists for EVERY
|
|
475
|
+
// tenant incl. auth-signup via seedTenant — unlike the tier-assignment
|
|
476
|
+
// row, which the seed path does not create) and checks the window
|
|
477
|
+
// against the current time. Consulted only on the disabled-gate path.
|
|
478
|
+
// inserted_at is immutable → read once per tenant.
|
|
479
479
|
// Promise-memo (not a plain value cache): N concurrent requests for the
|
|
480
480
|
// same fresh tenant must await the SAME in-flight fetchOne, not each
|
|
481
481
|
// fire their own — a plain `Map<TenantId, number>` set AFTER the await
|
|
@@ -496,8 +496,8 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
496
496
|
startedMemo.set(tenantId, startedMsPromise);
|
|
497
497
|
}
|
|
498
498
|
const startedMs = await startedMsPromise;
|
|
499
|
-
// Tenant
|
|
500
|
-
//
|
|
499
|
+
// Tenant row not projected yet (replay race) → do not memoize the
|
|
500
|
+
// miss, re-read on the next request.
|
|
501
501
|
if (startedMs === undefined) {
|
|
502
502
|
startedMemo.delete(tenantId);
|
|
503
503
|
return false;
|
|
@@ -509,14 +509,7 @@ export function createTierEngineFeature(opts = {}) {
|
|
|
509
509
|
};
|
|
510
510
|
// biome-ignore lint/correctness/useHookAtTopLevel: r.useExtension is a framework registrar method, not a React hook.
|
|
511
511
|
r.useExtension(TENANT_TIER_RESOLVER_EXT, TIER_ENGINE_FEATURE, plugin);
|
|
512
|
-
});
|
|
512
|
+
}, Object.keys(opts).length === 0 ? { dedupeOptions: {} } : undefined);
|
|
513
513
|
}
|
|
514
|
-
/**
|
|
515
|
-
* Legacy named export — equivalent to `createTierEngineFeature()` ohne opts.
|
|
516
|
-
* Storage-only mode (no resolver, no auto-default). Existing apps die
|
|
517
|
-
* `tierEngineFeature` referenzieren bekommen identical behavior.
|
|
518
|
-
*
|
|
519
|
-
* Migration zu `createTierEngineFeature({ defaultTier, tierMap })` gibt
|
|
520
|
-
* volle Tier-Composition (Sprint-8a Pattern).
|
|
521
|
-
*/
|
|
514
|
+
/** @deprecated Use createTierEngineFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
522
515
|
export const tierEngineFeature = createTierEngineFeature();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { buildEntityTable, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { buildEntityTable, createTenantDb, fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import * as z from "zod";
|
|
5
4
|
import { tierAssignmentEntity } from "../entity.js";
|
|
@@ -20,7 +19,7 @@ export const getTenantTierQuery = defineQueryHandler({
|
|
|
20
19
|
},
|
|
21
20
|
handler: async (query, ctx) => {
|
|
22
21
|
const tenantId = query.payload.tenantId; // @cast-boundary engine-bridge
|
|
23
|
-
const tdb = createTenantDb(ctx.db.unsafeRaw(), tenantId, "system");
|
|
22
|
+
const tdb = createTenantDb({ db: ctx.db.unsafeRaw(), tenantId, mode: "system" });
|
|
24
23
|
const row = await fetchOne(tdb, tierAssignmentTable, { tenantId });
|
|
25
24
|
return row ?? null;
|
|
26
25
|
},
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { buildEntityTable, createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { buildEntityTable, createEventStoreExecutor, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import * as z from "zod";
|
|
5
4
|
import { requireForTenant } from "../../shared/index.js";
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// After a run, rebuild the user projection so read_users.tenant_id reflects
|
|
24
24
|
// the stream move: rebuildProjection("user:projection:user-entity", ...) or
|
|
25
25
|
// the jobs:job:projection-rebuild job.
|
|
26
|
-
import { asRawClient, transaction, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/
|
|
26
|
+
import { asRawClient, transaction, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
|
|
27
27
|
import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
28
28
|
export async function backfillUserStreamTenants(db) {
|
|
29
29
|
const candidates = await unsafeReadRetrying(db, `SELECT DISTINCT "aggregate_id" FROM "kumiko_events"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { defineWriteHandler, findForbiddenRoleAssignment, } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import { AccessDeniedError, ConflictError, InternalError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
4
|
import { canonicalizeLocaleTag, isValidLocaleTag } from "@cosmicdrift/kumiko-framework/i18n";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import * as z from "zod";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { access, defineEntityListHandler, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
4
4
|
// kumiko-lint-ignore cross-feature-import SystemAdmin user-list joins memberships for tenants column
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { acquireNamespacedAdvisoryLock, createEventStoreExecutor, } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { acquireNamespacedAdvisoryLock, createEventStoreExecutor, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { createSystemUser, findForbiddenRoleAssignment, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import { AccessDeniedError, ConflictError, InternalError, NotFoundError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
4
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
package/dist/user/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { UserCommandSchemas } from "./command-schemas.js";
|
|
|
2
2
|
export { USER_FEATURE, UserErrors, UserHandlers, UserQueries } from "./constants.js";
|
|
3
3
|
export { backfillUserStreamTenants, type UserStreamBackfillResult, } from "./db/queries/stream-tenant-backfill.js";
|
|
4
4
|
export { createUserFeature } from "./feature.js";
|
|
5
|
-
export { isPrincipalBlocked, principalStatusPlugin } from "./principal-status.js";
|
|
5
|
+
export { isPrincipalBlocked, isPrincipalRowBlocked, principalStatusPlugin, } from "./principal-status.js";
|
|
6
6
|
export { resolveUserDisplayNames } from "./resolve-display-names.js";
|
|
7
7
|
export type { UserStatus } from "./schema/user.js";
|
|
8
8
|
export { USER_ANONYMIZED_DISPLAY_NAME, USER_ANONYMIZED_EMAIL_DOMAIN, USER_ANONYMIZED_EMAIL_PREFIX, USER_DELETED_DISPLAY_NAME, USER_DELETED_EMAIL_PREFIX, USER_STATUS, userEntity, userTable, } from "./schema/user.js";
|
package/dist/user/index.js
CHANGED
|
@@ -2,6 +2,6 @@ export { UserCommandSchemas } from "./command-schemas.js";
|
|
|
2
2
|
export { USER_FEATURE, UserErrors, UserHandlers, UserQueries } from "./constants.js";
|
|
3
3
|
export { backfillUserStreamTenants, } from "./db/queries/stream-tenant-backfill.js";
|
|
4
4
|
export { createUserFeature } from "./feature.js";
|
|
5
|
-
export { isPrincipalBlocked, principalStatusPlugin } from "./principal-status.js";
|
|
5
|
+
export { isPrincipalBlocked, isPrincipalRowBlocked, principalStatusPlugin, } from "./principal-status.js";
|
|
6
6
|
export { resolveUserDisplayNames } from "./resolve-display-names.js";
|
|
7
7
|
export { USER_ANONYMIZED_DISPLAY_NAME, USER_ANONYMIZED_EMAIL_DOMAIN, USER_ANONYMIZED_EMAIL_PREFIX, USER_DELETED_DISPLAY_NAME, USER_DELETED_EMAIL_PREFIX, USER_STATUS, userEntity, userTable, } from "./schema/user.js";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { createSystemUser, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
4
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
@@ -25,7 +24,7 @@ export async function grantInvitedGlobalRoles(db, options) {
|
|
|
25
24
|
if (missingRoles.length === 0)
|
|
26
25
|
return grantedGlobalRoles(currentRoles);
|
|
27
26
|
const roles = [...currentRoles, ...missingRoles];
|
|
28
|
-
const updateResult = await userExecutor.update({ id: existing.id, version: existing.version, changes: { roles } }, createSystemUser(SYSTEM_TENANT_ID), createTenantDb(db, SYSTEM_TENANT_ID, "system"));
|
|
27
|
+
const updateResult = await userExecutor.update({ id: existing.id, version: existing.version, changes: { roles } }, createSystemUser(SYSTEM_TENANT_ID), createTenantDb({ db, tenantId: SYSTEM_TENANT_ID, mode: "system" }));
|
|
29
28
|
if (!updateResult.isSuccess)
|
|
30
29
|
return updateResult;
|
|
31
30
|
return grantedGlobalRoles(roles);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { PrincipalStatusPlugin } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { type UserStatus } from "./schema/user.js";
|
|
3
3
|
export declare function isPrincipalBlocked(status: UserStatus): boolean;
|
|
4
|
+
export declare function isPrincipalRowBlocked(row: {
|
|
5
|
+
readonly status: UserStatus;
|
|
6
|
+
readonly isDeleted: boolean;
|
|
7
|
+
}): boolean;
|
|
4
8
|
export declare const principalStatusPlugin: PrincipalStatusPlugin;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
3
3
|
import { USER_STATUS, userTable } from "./schema/user.js";
|
|
4
4
|
// Locked accounts whose live sessions must be refused. deletionRequested is
|
|
@@ -12,14 +12,20 @@ const BLOCKED_STATUSES = new Set([
|
|
|
12
12
|
export function isPrincipalBlocked(status) {
|
|
13
13
|
return BLOCKED_STATUSES.has(status);
|
|
14
14
|
}
|
|
15
|
+
// A soft-deleted row (executor.delete) keeps its last status, so isDeleted must block on its own.
|
|
16
|
+
export function isPrincipalRowBlocked(row) {
|
|
17
|
+
return row.isDeleted || isPrincipalBlocked(row.status);
|
|
18
|
+
}
|
|
15
19
|
// Registered via r.useExtension(EXT_PRINCIPAL_STATUS, "user", principalStatusPlugin)
|
|
16
20
|
// so resolveActiveMembershipFn can reject a blocked principal without knowing about `user`'s table.
|
|
17
21
|
export const principalStatusPlugin = {
|
|
18
22
|
async resolveStatus(userId, { db }) {
|
|
19
|
-
const row = await fetchOne(db, userTable, {
|
|
23
|
+
const row = await fetchOne(db, userTable, {
|
|
24
|
+
id: userId,
|
|
25
|
+
});
|
|
20
26
|
if (!row)
|
|
21
27
|
return "unknown";
|
|
22
|
-
return
|
|
28
|
+
return isPrincipalRowBlocked(row) ? "blocked" : "active";
|
|
23
29
|
},
|
|
24
30
|
// ctx.queryAsMember's global-roles/timezone/locale source — same fields
|
|
25
31
|
// login mints a session from (see login.write.ts gateBuildSession).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { decryptStoredPii, mapWithConcurrency } from "../shared/index.js";
|
|
3
3
|
import { userTable } from "./schema/user.js";
|
|
4
4
|
// Shares the KMS adapter's small dedicated pool, same as member-directory.
|
package/dist/user/seeding.js
CHANGED
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
// umgehen, also kein `user.created`-Event und keine MSP-Konsumenten
|
|
10
10
|
// (audit, search-index) sehen den Seed. Der Executor-Pfad emittiert
|
|
11
11
|
// das Event UND schreibt die Projection-Zeile in einer TX.
|
|
12
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
13
12
|
import { computeBlindIndex, configuredBlindIndexKey } from "@cosmicdrift/kumiko-framework/crypto";
|
|
14
|
-
import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
|
|
15
|
-
import { TestUsers } from "@cosmicdrift/kumiko-framework/
|
|
13
|
+
import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
14
|
+
import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
|
|
16
15
|
// kumiko-lint-ignore cross-feature-import shares the postSave-hooks fixture contract with tenant/seeding (#1478)
|
|
17
16
|
import { fireEntityPostSave } from "../tenant/seeding.js";
|
|
18
17
|
import { userEntity, userTable } from "./schema/user.js";
|
|
@@ -32,7 +31,7 @@ hooks) {
|
|
|
32
31
|
// executor.create erwartet eine TenantDb (mit .insert()-API). User
|
|
33
32
|
// ist zwar tenant-agnostic (kein tenant_id-Spalte), aber das runtime-
|
|
34
33
|
// Interface braucht den Wrap.
|
|
35
|
-
const tdb = createTenantDb(db, by.tenantId, "system");
|
|
34
|
+
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
36
35
|
const existing = await fetchOne(db, userTable, { email: options.email, isDeleted: false });
|
|
37
36
|
// @cast-boundary db-row: users.id ist uuid-Spalte (string), fetchOne
|
|
38
37
|
// liefert die Projection-Row als Record<string, unknown>.
|
|
@@ -66,7 +65,7 @@ export async function reconcileSeededUserEmailVerified(db, existingRow, by) {
|
|
|
66
65
|
// @cast-boundary db-row: users.id ist uuid-Spalte (string), fetchOne
|
|
67
66
|
// liefert die Projection-Row als Record<string, unknown>.
|
|
68
67
|
const id = existingRow["id"];
|
|
69
|
-
const tdb = createTenantDb(db, by.tenantId, "system");
|
|
68
|
+
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
70
69
|
const result = await userExecutor.update({ id, version: existingRow["version"], changes: { emailVerified: true } }, by, tdb);
|
|
71
70
|
// version_conflict = a concurrent write already changed the row —
|
|
72
71
|
// fine for a seed helper, don't fail the whole seed run over it.
|
|
@@ -101,7 +100,7 @@ export async function rewriteSeededUserEmail(db, existingRow, email, by) {
|
|
|
101
100
|
if (indexed)
|
|
102
101
|
return;
|
|
103
102
|
}
|
|
104
|
-
const tdb = createTenantDb(db, by.tenantId, "system");
|
|
103
|
+
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
105
104
|
const result = await userExecutor.update({ id, version, changes: { email } }, by, tdb);
|
|
106
105
|
// version_conflict: a concurrent write already changed the row — fine for a seed helper.
|
|
107
106
|
// unique_violation: a duplicate row already holds the blind index; the repair
|
|
@@ -29,7 +29,7 @@ const attemptCrud = createEventStoreExecutor(downloadAttemptsTable, downloadAtte
|
|
|
29
29
|
export async function recordDownloadUse(args) {
|
|
30
30
|
const { db, tokenId, tokenVersion, tokenUseCount, tenantId, now, ip, userAgent } = args;
|
|
31
31
|
const executor = createSystemUser(tenantId);
|
|
32
|
-
const tdb = createTenantDb(db, tenantId, "system");
|
|
32
|
+
const tdb = createTenantDb({ db, tenantId, mode: "system" });
|
|
33
33
|
await tokenCrud
|
|
34
34
|
.update({
|
|
35
35
|
id: tokenId,
|
|
@@ -53,7 +53,7 @@ export async function recordDownloadUse(args) {
|
|
|
53
53
|
export async function recordInvalidAttempt(args) {
|
|
54
54
|
const { db, tenantId, now } = args;
|
|
55
55
|
const executor = createSystemUser(tenantId);
|
|
56
|
-
const tdb = createTenantDb(db, tenantId, "system");
|
|
56
|
+
const tdb = createTenantDb({ db, tenantId, mode: "system" });
|
|
57
57
|
await attemptCrud
|
|
58
58
|
.create({
|
|
59
59
|
result: args.result,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { exportJobsTable } from "../../schema/export-job.js";
|
|
3
3
|
// @wrapper-known semantic-alias
|
|
4
4
|
export async function selectExportJobsForStorageCleanup(db, doneStatus, failedStatus) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
3
|
import { userTable } from "../../../user/index.js";
|
|
4
4
|
export async function selectUsersDueForForgetCleanup(db, status, gracePeriodEndCutoff) {
|
|
@@ -521,15 +521,18 @@ export function createUserDataRightsFeature(opts = {}) {
|
|
|
521
521
|
db: forgetDb,
|
|
522
522
|
userId: forgetUserId,
|
|
523
523
|
});
|
|
524
|
-
// Without an app callback the default mail goes out when
|
|
525
|
-
// mail renderer are mounted. The user is already erased
|
|
526
|
-
// delivery log: an attempt row would be new personal data.
|
|
524
|
+
// Without an app callback the default mail goes out when an email channel or a
|
|
525
|
+
// mail transport, plus a mail renderer, are mounted. The user is already erased
|
|
526
|
+
// here, so it bypasses the delivery log: an attempt row would be new personal data.
|
|
527
527
|
const forgetConfigResolver = ctx.configResolver;
|
|
528
528
|
const sendDeletionExecutedEmail = opts.sendDeletionExecutedEmail ??
|
|
529
|
-
(
|
|
529
|
+
((isGdprMailDeliveryAvailable(forgetRegistry) ||
|
|
530
|
+
isMailTransportAvailable(forgetRegistry)) &&
|
|
531
|
+
isMailRendererAvailable(forgetRegistry)
|
|
530
532
|
? makeDefaultDeletionExecutedEmail({
|
|
531
533
|
registry: forgetRegistry,
|
|
532
534
|
db: forgetDb,
|
|
535
|
+
...(ctx.secrets !== undefined && { secrets: ctx.secrets }),
|
|
533
536
|
resolveTransport: makeTenantMailTransportResolver({
|
|
534
537
|
registry: forgetRegistry,
|
|
535
538
|
configResolver: forgetConfigResolver,
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// 6. Audit-Update: useCount + 1, IP, UA, lastUsedAt (best-effort)
|
|
24
24
|
// 7. Return {url, expiresAt}
|
|
25
25
|
import { requestContext } from "@cosmicdrift/kumiko-framework/api";
|
|
26
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
26
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
27
27
|
import { defineQueryHandler, SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
28
28
|
import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
|
|
29
29
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// **r.httpRoute-Wrapper** (siehe feature.ts) macht 302-Redirect zu
|
|
26
26
|
// signedUrl — User klickt 1× Email-Link, Browser folgt redirect, Download
|
|
27
27
|
// startet. Dieser query-handler liefert nur das JSON.
|
|
28
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
28
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
29
29
|
import { defineQueryHandler, SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
30
30
|
import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
|
|
31
31
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// **Read-Only-Endpoint:** Pollt nur, kein State-Flip. Idempotent + cache-
|
|
12
12
|
// fest. UI poll-Intervall typisch 2-5s waehrend running.
|
|
13
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
13
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
14
14
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
15
15
|
import * as z from "zod";
|
|
16
16
|
import { exportJobsTable } from "../schema/export-job.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
import * as z from "zod";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
4
4
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
// `requestedFromTenantId` persistiert den Initial-Tenant aus dem
|
|
20
20
|
// 1. Klick — Worker liest sein Compliance-Profile aus DIESEM Tenant
|
|
21
21
|
// fuer Job-TTL/Stale/Cleanup.
|
|
22
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
23
|
-
import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
22
|
+
import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
24
23
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
25
24
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
26
25
|
import * as z from "zod";
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// Setup laeuft der Job mit `createSystemUser(...)` als executor.
|
|
10
10
|
//
|
|
11
11
|
// Rueckgabe: Stats fuer Operator-Monitoring (processed-count, error-list).
|
|
12
|
-
import { access, defineWriteHandler
|
|
12
|
+
import { access, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
13
13
|
import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
14
14
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
15
15
|
import * as z from "zod";
|
|
@@ -46,7 +46,7 @@ export function createRunForgetCleanupHandler(opts = {}) {
|
|
|
46
46
|
registry: ctx.registry,
|
|
47
47
|
configResolver: ctx.configResolver,
|
|
48
48
|
db: forgetDb,
|
|
49
|
-
userId: ctx.
|
|
49
|
+
userId: ctx.user.id,
|
|
50
50
|
});
|
|
51
51
|
const result = await runForgetCleanup({
|
|
52
52
|
db: runner,
|
|
@@ -59,7 +59,7 @@ export function createRunForgetCleanupHandler(opts = {}) {
|
|
|
59
59
|
configResolver: ctx.configResolver,
|
|
60
60
|
secrets: ctx.secrets,
|
|
61
61
|
db: forgetDb,
|
|
62
|
-
userId: ctx.
|
|
62
|
+
userId: ctx.user.id,
|
|
63
63
|
handlerName: "user-data-rights:run-forget-cleanup",
|
|
64
64
|
}),
|
|
65
65
|
...(opts.sendDeletionExecutedEmail && {
|