@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,44 +1,44 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// inbound-mail-foundation — Plugin
|
|
4
|
-
// (
|
|
5
|
-
//
|
|
6
|
-
// file-foundation (
|
|
3
|
+
// inbound-mail-foundation — Plugin host for inbound e-mail
|
|
4
|
+
// (inbox federation). Counterpart to mail-foundation (outbound): separate
|
|
5
|
+
// extension points, separate state — architectural model is
|
|
6
|
+
// file-foundation (the foundation owns state), not mail-transport.
|
|
7
7
|
//
|
|
8
|
-
// **Multi-
|
|
9
|
-
// `provider
|
|
10
|
-
//
|
|
8
|
+
// **Multi-provider from day one** (as with billing-foundation): NO global
|
|
9
|
+
// `provider` config key. A tenant can connect IMAP and (later) M365/Gmail
|
|
10
|
+
// mailboxes in parallel; the provider is specified per MailAccount.
|
|
11
11
|
//
|
|
12
|
-
// **
|
|
13
|
-
// 1. **Plugin
|
|
12
|
+
// **What this foundation provides:**
|
|
13
|
+
// 1. **Plugin API** for inbound providers via r.extendsRegistrar
|
|
14
14
|
// ("inboundMailProvider"): verify/fetch/oauth?/watch? (types.ts).
|
|
15
|
-
// 2. **3 event-sourced
|
|
16
|
-
// inbound-message (
|
|
17
|
-
// aggregateId ⇒ exactly-once
|
|
18
|
-
// mail-thread (
|
|
19
|
-
//
|
|
20
|
-
// 3. **Inline
|
|
15
|
+
// 2. **3 event-sourced streams** — mail-account (lifecycle),
|
|
16
|
+
// inbound-message (exactly ONE received event per message, deterministic
|
|
17
|
+
// aggregateId ⇒ exactly-once despite at-least-once ingest),
|
|
18
|
+
// mail-thread (rollup). Full replayable history for later
|
|
19
|
+
// consumers (business processes: ticket, receipt, auto-reply).
|
|
20
|
+
// 3. **Inline projections** into read_mail_accounts /
|
|
21
21
|
// read_inbound_messages / read_mail_threads (read-your-own-write).
|
|
22
|
-
// 4. **Write
|
|
22
|
+
// 4. **Write/query handlers**: connect/update/disconnect-account,
|
|
23
23
|
// ingest-message (programmatic, SystemAdmin), account:list +
|
|
24
|
-
// message:list (PII-decrypted, scope-
|
|
25
|
-
// 5. **createInboundMailConnectRoutes**: OAuth
|
|
26
|
-
//
|
|
27
|
-
// 6. **createInboundMailSupervisor**: app-
|
|
28
|
-
//
|
|
24
|
+
// message:list (PII-decrypted, scope-filtered).
|
|
25
|
+
// 5. **createInboundMailConnectRoutes**: OAuth connect + anonymous
|
|
26
|
+
// callback (outside /api/*), with HMAC-signed state.
|
|
27
|
+
// 6. **createInboundMailSupervisor**: app-wired watch (IDLE)
|
|
28
|
+
// supervisor with backoff + reconciliation poll.
|
|
29
29
|
//
|
|
30
|
-
// **
|
|
31
|
-
// -
|
|
32
|
-
//
|
|
33
|
-
// inbound-message-received +
|
|
34
|
-
// -
|
|
35
|
-
// Supervisor-storeBody-Hook
|
|
36
|
-
// -
|
|
30
|
+
// **What this foundation does NOT do:**
|
|
31
|
+
// - No business semantics (intent, ticket, assignment, read/
|
|
32
|
+
// completed) — those belong to the app consumer (for example, via an
|
|
33
|
+
// event job on inbound-message-received + its own projection).
|
|
34
|
+
// - No body blob in the event store: rawMime → file-foundation via
|
|
35
|
+
// the Supervisor-storeBody-Hook; the event carries only bodyRef.
|
|
36
|
+
// - No IMAP flag write-back (V1) — inbox status belongs to the consumer.
|
|
37
37
|
//
|
|
38
38
|
// **PII/GDPR:** address/from/to/cc/subject/snippet are `personal: "tenant"`
|
|
39
39
|
// — encrypted BEFORE every event append (the only write path), event log AND
|
|
40
40
|
// projections carry ciphertext; tenant-destroy shreds the subject key
|
|
41
|
-
// (crypto-shredding, same pattern as billing-foundation
|
|
41
|
+
// (crypto-shredding, the same pattern as billing-foundation). The destroy
|
|
42
42
|
// hook additionally archives all streams + deletes the rows.
|
|
43
43
|
|
|
44
44
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -111,7 +111,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
111
111
|
category: "notifications",
|
|
112
112
|
recommended: false,
|
|
113
113
|
});
|
|
114
|
-
// EXT_TENANT_DATA
|
|
114
|
+
// The EXT_TENANT_DATA hook requires the tenant-lifecycle host.
|
|
115
115
|
r.requires({ features: ["tenant-lifecycle"] });
|
|
116
116
|
|
|
117
117
|
// 5 fine-grained domain-events (Payload-Schemas: events.ts).
|
|
@@ -135,7 +135,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
135
135
|
piiFields: "none",
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
// Inline projections — apply in
|
|
138
|
+
// Inline projections — apply in the same transaction as the append.
|
|
139
139
|
r.projection({
|
|
140
140
|
name: "mail-account",
|
|
141
141
|
source: MAIL_ACCOUNT_AGGREGATE_TYPE,
|
|
@@ -177,7 +177,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
177
177
|
|
|
178
178
|
// Sync machinery: high-frequency tick state, deliberately NOT
|
|
179
179
|
// event-sourced — r.storeTable keeps the migration DDL but excludes the
|
|
180
|
-
// tables from the projection rebuild
|
|
180
|
+
// tables from the projection rebuild.
|
|
181
181
|
r.storeTable(syncCursorTable, {
|
|
182
182
|
reason: "read_side.mail_sync_cursors_direct_write",
|
|
183
183
|
});
|
|
@@ -203,8 +203,8 @@ export function createInboundMailFoundationFeature() {
|
|
|
203
203
|
r.screen(mailAccountEditScreen);
|
|
204
204
|
r.translations({ keys: INBOUND_MAIL_FOUNDATION_I18N });
|
|
205
205
|
|
|
206
|
-
// Entity-
|
|
207
|
-
//
|
|
206
|
+
// Entity-specific GDPR destroy hooks — the gdpr-storage boot validator
|
|
207
|
+
// checks the EXT_TENANT_DATA registration for each tenant-subject entity.
|
|
208
208
|
r.useExtension(EXT_TENANT_DATA, "mail-account", {
|
|
209
209
|
destroy: mailAccountTenantDestroyHook,
|
|
210
210
|
escapeHatch: { reason: INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON },
|
|
@@ -218,7 +218,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
218
218
|
escapeHatch: { reason: INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON },
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
// Data-Retention
|
|
221
|
+
// Data-Retention — perTenant fan-out (one run per tenant, like
|
|
222
222
|
// data-retention:retention-cleanup): runInboundMailRetention's raw query
|
|
223
223
|
// helpers need the unfiltered runner, so the handler declares escapeHatch
|
|
224
224
|
// and reaches for ctx.db.unsafeRaw(). Without this cron, read_inbound_messages
|
|
@@ -245,10 +245,10 @@ export function createInboundMailFoundationFeature() {
|
|
|
245
245
|
const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
|
|
246
246
|
const retentionDb = ctx.db.unsafeRaw() as DbConnection; // @cast-boundary db-operator — jobs never run inside a DbTx
|
|
247
247
|
|
|
248
|
-
// Body
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
248
|
+
// Body objects are stored in file-foundation. The provider is lazy and memoized —
|
|
249
|
+
// ingest currently writes no bodyRef (the storeBody hook is not wired),
|
|
250
|
+
// so the provider is never built. Once storeBody is wired, retention
|
|
251
|
+
// also cleans up the bodies.
|
|
252
252
|
let providerPromise: Promise<FileStorageProvider> | null = null;
|
|
253
253
|
const deleteBodyObject = async (bodyRef: string): Promise<void> => {
|
|
254
254
|
if (!providerPromise) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Shared state loader for update-account / disconnect-account.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// "
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// mail-account events are full snapshots (following the billing-foundation
|
|
4
|
+
// pattern: "All events use the same payload shape; the event-type identifies
|
|
5
|
+
// what happened") — a transitional handler loads the latest snapshot, merges
|
|
6
|
+
// its delta fields into it, and appends the new snapshot.
|
|
7
7
|
//
|
|
8
|
-
// **PII
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// **PII discipline:** `address` is already ciphertext in the loaded payload
|
|
9
|
+
// and is copied byte-for-byte — NEVER re-encrypt it (that would require KMS
|
|
10
|
+
// decryption when unavailable or produce double encryption).
|
|
11
11
|
|
|
12
12
|
import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
|
|
13
13
|
import type { MailAccountEventPayload } from "../events.ts";
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
// connect-account —
|
|
2
|
-
// mail-account
|
|
3
|
-
//
|
|
1
|
+
// connect-account — A tenant admin connects a mailbox. Creates the
|
|
2
|
+
// mail-account stream (aggregateId = random uuid = accountId =
|
|
3
|
+
// secret-slot key for the IMAP password/OAuth refresh token).
|
|
4
4
|
//
|
|
5
|
-
// **
|
|
6
|
-
// -
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// asynchron als Status-Übergang).
|
|
5
|
+
// **What does NOT happen here:**
|
|
6
|
+
// - No secret write: IMAP credentials use the secrets path, and OAuth
|
|
7
|
+
// tokens use the generic /inbound-mail/oauth routes—both before or
|
|
8
|
+
// after this call, never in the handler payload (plain passwords must
|
|
9
|
+
// not enter a write payload that can appear in the dispatcher log).
|
|
10
|
+
// - No connection test: the watch supervisor attempts the first fetch
|
|
11
|
+
// and switches to auth_error via update-account on failure—the connect
|
|
12
|
+
// stays fast and offline-capable (the test result arrives asynchronously
|
|
13
|
+
// as a status transition).
|
|
15
14
|
|
|
16
15
|
import {
|
|
17
16
|
configuredPiiSubjectKms,
|
|
@@ -30,7 +29,7 @@ import {
|
|
|
30
29
|
} from "../events.ts";
|
|
31
30
|
|
|
32
31
|
export const connectAccountSchema = z.object({
|
|
33
|
-
/** Provider
|
|
32
|
+
/** Provider key registered with the extension ("imap",
|
|
34
33
|
* "m365-graph", "gmail-rest"). */
|
|
35
34
|
provider: z.string().min(1).max(50),
|
|
36
35
|
authMethod: z.enum([
|
|
@@ -39,16 +38,16 @@ export const connectAccountSchema = z.object({
|
|
|
39
38
|
InboundMailAuthMethods.oauth,
|
|
40
39
|
]),
|
|
41
40
|
displayName: z.string().max(200),
|
|
42
|
-
/**
|
|
41
|
+
/** Mailbox address in plaintext; it is encrypted here. */
|
|
43
42
|
address: z.string().min(1).max(320),
|
|
44
|
-
/** "shared" = tenant
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
/** "shared" = shared across the tenant (info@) · "user" = the caller's
|
|
44
|
+
* personal mailbox (ownerUserId is taken from the session, never from
|
|
45
|
+
* the payload—preventing claims on another user's mailbox). */
|
|
47
46
|
scope: z.enum(["shared", "user"]),
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
* HMAC-
|
|
51
|
-
*
|
|
47
|
+
/** Only for the programmatic OAuth callback path (SystemAdmin): there,
|
|
48
|
+
* the dispatcher user is a SystemUser and the actual owner is in the
|
|
49
|
+
* HMAC-verified state. Tenant callers must not set this field (the
|
|
50
|
+
* handler prevents claims on another user's mailbox). */
|
|
52
51
|
ownerUserIdOverride: z.string().max(36).nullable().optional(),
|
|
53
52
|
});
|
|
54
53
|
type ConnectAccountPayload = z.infer<typeof connectAccountSchema>;
|
|
@@ -75,8 +74,8 @@ export const connectAccountHandler: WriteHandlerDef = {
|
|
|
75
74
|
? event.user.id
|
|
76
75
|
: null;
|
|
77
76
|
|
|
78
|
-
// PII-
|
|
79
|
-
//
|
|
77
|
+
// PII-encrypt the address before the append. This is the only write path to
|
|
78
|
+
// the stream, so it covers both the event log and the projection.
|
|
80
79
|
const piiKms = configuredPiiSubjectKms();
|
|
81
80
|
const plainPii = { tenantId, address: payload.address };
|
|
82
81
|
const encryptedFields = piiKms
|
|
@@ -96,8 +95,8 @@ export const connectAccountHandler: WriteHandlerDef = {
|
|
|
96
95
|
ownerUserId,
|
|
97
96
|
displayName: payload.displayName,
|
|
98
97
|
address: encryptedFields.address,
|
|
99
|
-
// active
|
|
100
|
-
//
|
|
98
|
+
// The account is active upon connection; the supervisor picks it up on
|
|
99
|
+
// the next tick and downgrades it when credentials fail.
|
|
101
100
|
status: InboundMailAccountStatuses.active,
|
|
102
101
|
watchState: "idle",
|
|
103
102
|
};
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// disconnect-account —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// disconnect-account — A TenantAdmin disconnects a mailbox. The stream is retained
|
|
2
|
+
// for audit history, the status becomes disconnected, and the watch supervisor
|
|
3
|
+
// skips the account starting with the next tick. Secret cleanup (IMAP password/
|
|
4
|
+
// refresh token in the accountId slot) is handled by the caller flow; this handler
|
|
5
|
+
// does not touch the secrets path.
|
|
6
6
|
//
|
|
7
|
-
// Idempotent:
|
|
8
|
-
//
|
|
7
|
+
// Idempotent: disconnecting an already disconnected account is a success no-op
|
|
8
|
+
// with no second event, making double-clicks and retries safe.
|
|
9
9
|
|
|
10
10
|
import type { WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
11
11
|
import { failNotFound } from "@cosmicdrift/kumiko-framework/errors";
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
// ingest-message — programmatic entry
|
|
2
|
-
// (watch
|
|
3
|
-
// RawInboundMessage
|
|
1
|
+
// ingest-message — programmatic entry point for provider plugins
|
|
2
|
+
// (watch callback + fetchSince sync). Accepts a normalized
|
|
3
|
+
// RawInboundMessage and performs atomically in ONE TX:
|
|
4
4
|
//
|
|
5
|
-
// 1. Idempotency
|
|
6
|
-
// depth:
|
|
7
|
-
// 2. threadKey
|
|
8
|
-
// References
|
|
9
|
-
// 3. PII
|
|
10
|
-
//
|
|
11
|
-
// 4. inbound-message-received
|
|
12
|
-
// read_inbound_messages in
|
|
5
|
+
// 1. Idempotency check (cheap: store_mail_seen_messages; defense in
|
|
6
|
+
// depth: stream existence check on the deterministic aggregateId).
|
|
7
|
+
// 2. threadKey normalization (provider thread ID preferred, otherwise
|
|
8
|
+
// References chain root, otherwise Message-ID = single-message thread).
|
|
9
|
+
// 3. PII encryption (from/to/cc/subject/snippet) BEFORE the append —
|
|
10
|
+
// both the event log AND projection contain ciphertext.
|
|
11
|
+
// 4. inbound-message-received append (inline projection writes
|
|
12
|
+
// read_inbound_messages in the same TX). Savepoint-scoped
|
|
13
13
|
// (ctx.tryAppendEvent) — a losing concurrent ingest for the same
|
|
14
14
|
// messageAggId returns { duplicate: true } instead of failing the TX.
|
|
15
|
-
// 5. Thread
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// 6. seen-message
|
|
15
|
+
// 5. Thread rollup: mail-thread-updated append with a recalculated
|
|
16
|
+
// snapshot (count+1, max(lastMessageAt)) — the apply is a
|
|
17
|
+
// dumb UPSERT.
|
|
18
|
+
// 6. Insert the seen-message deduplication anchor.
|
|
19
19
|
//
|
|
20
|
-
// SystemAdmin-only:
|
|
21
|
-
//
|
|
20
|
+
// SystemAdmin-only: the caller is the watch/sync supervisor or
|
|
21
|
+
// the poll cron with a programmatic SystemUser — never a tenant request.
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
24
|
configuredPiiSubjectKms,
|
|
@@ -49,25 +49,25 @@ import {
|
|
|
49
49
|
import { inboundMessagesProjectionTable } from "../projection.ts";
|
|
50
50
|
|
|
51
51
|
// =============================================================================
|
|
52
|
-
// Input
|
|
53
|
-
// types.ts)
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
52
|
+
// Input schema — the normalized provider output (RawInboundMessage,
|
|
53
|
+
// types.ts) plus the envelope (accountId/providerName/providerCursor). rawMime
|
|
54
|
+
// is intentionally excluded: the caller persists the body to
|
|
55
|
+
// file-foundation BEFORE the ingest call and passes only bodyRef — the
|
|
56
|
+
// handler payload remains blob-free (event-store discipline).
|
|
57
57
|
// =============================================================================
|
|
58
58
|
|
|
59
59
|
export const ingestMessageSchema = z.object({
|
|
60
60
|
accountId: z.uuid(),
|
|
61
|
-
/** Scope
|
|
62
|
-
* MailAccountRecord
|
|
61
|
+
/** Scope inherited from the account — the supervisor knows the
|
|
62
|
+
* MailAccountRecord and passes ownerUserId through. */
|
|
63
63
|
ownerUserId: z.string().max(36).nullable(),
|
|
64
64
|
providerName: z.string().min(1).max(50),
|
|
65
|
-
/** Provider-native Message-ID —
|
|
65
|
+
/** Provider-native Message-ID — idempotency anchor with accountId. */
|
|
66
66
|
providerMessageId: z.string().min(1).max(500),
|
|
67
|
-
/** RFC-5322 Message-ID
|
|
67
|
+
/** RFC-5322 Message-ID without <>; null → deterministic fallback. */
|
|
68
68
|
messageIdHeader: z.string().min(1).max(500).nullable(),
|
|
69
69
|
providerThreadId: z.string().min(1).max(500).nullable(),
|
|
70
|
-
/** References/In-Reply-To
|
|
70
|
+
/** References/In-Reply-To chain, oldest first. */
|
|
71
71
|
references: z.array(z.string().min(1).max(500)).max(200),
|
|
72
72
|
from: z.string().min(1).max(2000),
|
|
73
73
|
to: z.array(z.string().max(2000)).max(200),
|
|
@@ -78,20 +78,20 @@ export const ingestMessageSchema = z.object({
|
|
|
78
78
|
/** file-foundation-Ref; leer im snippet-only-Mode. */
|
|
79
79
|
bodyRef: z.string().max(500),
|
|
80
80
|
scope: z.string().min(1).max(200),
|
|
81
|
-
/** Cursor
|
|
82
|
-
* metadata.headers,
|
|
81
|
+
/** Cursor snapshot at ingest time — used for debugging/replay and stored in
|
|
82
|
+
* metadata.headers, never in the payload. */
|
|
83
83
|
providerCursor: z.string().max(2000),
|
|
84
84
|
});
|
|
85
85
|
type IngestMessagePayload = z.infer<typeof ingestMessageSchema>;
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* threadKey
|
|
89
|
-
* 1.
|
|
90
|
-
* IMAP
|
|
91
|
-
* 2.
|
|
92
|
-
*
|
|
93
|
-
* 3.
|
|
94
|
-
*
|
|
88
|
+
* Normalizes threadKey:
|
|
89
|
+
* 1. Use the provider thread ID when present — prefix it with the provider
|
|
90
|
+
* so IMAP References keys and Graph conversationIds never collide.
|
|
91
|
+
* 2. Otherwise use the root of the References chain (the oldest Message-ID,
|
|
92
|
+
* which is the thread anchor shared by all replies).
|
|
93
|
+
* 3. Otherwise use the own Message-ID → single-message thread; a later
|
|
94
|
+
* reply carries it as the References root and joins the same thread.
|
|
95
95
|
*/
|
|
96
96
|
function buildThreadKey(p: IngestMessagePayload, effectiveMessageIdHeader: string): string {
|
|
97
97
|
if (p.providerThreadId) return `${p.providerName}:${p.providerThreadId}`.slice(0, 500);
|
|
@@ -123,12 +123,12 @@ export const ingestMessageHandler: WriteHandlerDef = {
|
|
|
123
123
|
const messageAggId = inboundMessageAggregateId(payload.accountId, payload.providerMessageId);
|
|
124
124
|
|
|
125
125
|
// ---------------------------------------------------------------
|
|
126
|
-
// 1. Idempotency.
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
126
|
+
// 1. Idempotency. Use the deduplication anchor row first because it is
|
|
127
|
+
// cheap. The stream check afterward provides defense in depth if
|
|
128
|
+
// an earlier ingest died AFTER the append but BEFORE the seen insert
|
|
129
|
+
// (this cannot happen within one TX, but the check is cheap and makes
|
|
130
|
+
// the handler robust to rebuilding if store_mail_seen_messages is
|
|
131
|
+
// ever truncated).
|
|
132
132
|
// ---------------------------------------------------------------
|
|
133
133
|
const seenRows = await ctx.db.selectMany(seenMessageTable, {
|
|
134
134
|
accountId: payload.accountId,
|
|
@@ -163,11 +163,10 @@ export const ingestMessageHandler: WriteHandlerDef = {
|
|
|
163
163
|
const threadAggId = mailThreadAggregateId(tenantId, threadKey);
|
|
164
164
|
|
|
165
165
|
// ---------------------------------------------------------------
|
|
166
|
-
// 3. PII
|
|
167
|
-
//
|
|
168
|
-
// (primitives only, upcaster-safe).
|
|
169
|
-
// plaintext
|
|
170
|
-
// billing-foundation process-event #724/#800).
|
|
166
|
+
// 3. PII encryption. Serialize to/cc as JSON BEFORE encryption so the
|
|
167
|
+
// payload contains a ciphertext string rather than an array
|
|
168
|
+
// (primitives only, upcaster-safe). If no KMS is configured, pass
|
|
169
|
+
// through plaintext (engine-off behavior).
|
|
171
170
|
// ---------------------------------------------------------------
|
|
172
171
|
const piiKms = configuredPiiSubjectKms();
|
|
173
172
|
const messagePlainPii = {
|
|
@@ -243,14 +242,14 @@ export const ingestMessageHandler: WriteHandlerDef = {
|
|
|
243
242
|
// concurrent ingests on the same thread (Watch-Push vs.
|
|
244
243
|
// Poll-Reconciliation overlap, or two different messages of the
|
|
245
244
|
// same thread arriving at once) converge on the true count.
|
|
246
|
-
// acquireNamespacedAdvisoryLock below
|
|
245
|
+
// acquireNamespacedAdvisoryLock below serializes this whole
|
|
247
246
|
// countWhere+append section per threadAggId — transaction-scoped,
|
|
248
247
|
// so it survives tryAppendEvent's inner SAVEPOINT and releases at
|
|
249
248
|
// the enclosing TX's commit/rollback. Without it, a concurrent
|
|
250
249
|
// commit landing between countWhere and tryAppendEvent's own fresh
|
|
251
250
|
// version-read makes the append succeed with a stale count instead
|
|
252
251
|
// of a VersionConflictError, so the retry loop below never sees it
|
|
253
|
-
// as a conflict to retry (
|
|
252
|
+
// as a conflict to retry (the original gap). Unlike step 4, a
|
|
254
253
|
// lost version-conflict race here must NOT be treated as a no-op
|
|
255
254
|
// duplicate — skipping would leave this message's contribution to
|
|
256
255
|
// messageCount/lastMessageAt out of the thread forever. Exhausting
|
|
@@ -315,8 +314,8 @@ export const ingestMessageHandler: WriteHandlerDef = {
|
|
|
315
314
|
}
|
|
316
315
|
|
|
317
316
|
// ---------------------------------------------------------------
|
|
318
|
-
// 6.
|
|
319
|
-
//
|
|
317
|
+
// 6. Deduplication anchor. It runs in the same TX as the appends, so
|
|
318
|
+
// if the handler fails, everything is rolled back together.
|
|
320
319
|
// ---------------------------------------------------------------
|
|
321
320
|
await ctx.db.insertOne(seenMessageTable, {
|
|
322
321
|
tenantId,
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// list-accounts — tenant-scoped
|
|
2
|
-
// Connect
|
|
3
|
-
// billing-foundation list-subscriptions
|
|
1
|
+
// list-accounts — tenant-scoped list of connected mailboxes for the
|
|
2
|
+
// Connect/Settings UI. PII (address) is decrypted on read, following the
|
|
3
|
+
// billing-foundation list-subscriptions pattern.
|
|
4
4
|
//
|
|
5
|
-
// **Scope
|
|
6
|
-
// (ownerUserId=null)
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
5
|
+
// **Scope visibility:** authorized users can see shared mailboxes
|
|
6
|
+
// (ownerUserId=null); personal mailboxes are visible only to their owner,
|
|
7
|
+
// TenantAdmin, or SystemAdmin for compliance access. Filtering runs in memory
|
|
8
|
+
// after the tenant-scoped select because a tenant has only a single- to
|
|
9
|
+
// double-digit number of connected mailboxes.
|
|
10
10
|
import {
|
|
11
11
|
configuredPiiSubjectKms,
|
|
12
12
|
decryptPiiFieldValues,
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// list-messages — tenant-scoped
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// list-messages — tenant-scoped message list for the inbox cockpit.
|
|
2
|
+
// Optional filters: accountId (one mailbox), threadKey (one conversation),
|
|
3
|
+
// scope (folder hint). PII (from/to/cc/subject/snippet) is decrypted on read;
|
|
4
|
+
// to/cc remain JSON-stringified strings, which the client parses as documented
|
|
5
|
+
// in the event payload.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// Deliberately no pagination in V1: the projection is tenant-scoped and the
|
|
8
|
+
// inbox cockpit loads bounded time ranges; a `limit` field can be added
|
|
9
|
+
// compatibly without breaking the QN.
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
configuredPiiSubjectKms,
|
|
@@ -42,8 +42,8 @@ export const listMessagesQuery: QueryHandlerDef = {
|
|
|
42
42
|
if (payload.scope) filter["scope"] = payload.scope;
|
|
43
43
|
|
|
44
44
|
const allRows = await ctx.db.selectMany(inboundMessagesProjectionTable, filter);
|
|
45
|
-
// Scope
|
|
46
|
-
//
|
|
45
|
+
// Scope visibility: messages in personal mailboxes are visible only to the
|
|
46
|
+
// owner or TenantAdmin/SystemAdmin.
|
|
47
47
|
const rows = allRows.filter((row) => isVisibleToCaller(row, ctx.user));
|
|
48
48
|
const piiKms = configuredPiiSubjectKms();
|
|
49
49
|
if (!piiKms) return { rows };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// Scope
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// für read_mail_accounts und read_inbound_messages (Scope-Vererbung).
|
|
1
|
+
// Scope visibility: shared rows (`ownerUserId=null`) are visible to any authorized caller;
|
|
2
|
+
// personal rows are visible only to the owner, `TenantAdmin`, or `SystemAdmin` for compliance.
|
|
3
|
+
// The same rule applies to `read_mail_accounts` and `read_inbound_messages`.
|
|
5
4
|
|
|
6
5
|
export function isVisibleToCaller(
|
|
7
6
|
row: Readonly<Record<string, unknown>>,
|
package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// update-account — Account
|
|
2
|
-
// error/backoff, OAuth
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// update-account — Account status transitions: the watch supervisor reports
|
|
2
|
+
// error/backoff, OAuth refresh fails (auth_error), or a tenant admin re-enables
|
|
3
|
+
// the account after fixing its credentials. Full-snapshot event: loads the
|
|
4
|
+
// latest state, merges the delta fields, and appends the new snapshot.
|
|
5
5
|
|
|
6
6
|
import type { WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
7
7
|
import { failNotFound, failUnprocessable } from "@cosmicdrift/kumiko-framework/errors";
|
|
@@ -27,7 +27,7 @@ export const updateAccountSchema = z.object({
|
|
|
27
27
|
/** Ops-Signal ("idle", "watching", "backoff:3", ...). */
|
|
28
28
|
watchState: z.string().max(100).optional(),
|
|
29
29
|
displayName: z.string().max(200).optional(),
|
|
30
|
-
/** Audit
|
|
30
|
+
/** Audit reason for metadata.headers ("watch_supervisor",
|
|
31
31
|
* "oauth_refresh", "tenant_admin"). */
|
|
32
32
|
reason: z.string().min(1).max(100),
|
|
33
33
|
});
|
|
@@ -48,15 +48,15 @@ export const updateAccountHandler: WriteHandlerDef = {
|
|
|
48
48
|
return failNotFound("mail-account", payload.accountId);
|
|
49
49
|
}
|
|
50
50
|
if (current.status === InboundMailAccountStatuses.disconnected) {
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
51
|
+
// Disconnected accounts are final; re-enabling requires a fresh connect
|
|
52
|
+
// (new stream, new secret slot). This prevents a delayed supervisor tick
|
|
53
|
+
// from restoring a disconnected account to active (disconnect vs. poll
|
|
54
|
+
// race).
|
|
55
55
|
return failUnprocessable("account_disconnected", { accountId: payload.accountId });
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
//
|
|
59
|
-
//
|
|
58
|
+
// address/provider/authMethod come unchanged from the latest snapshot
|
|
59
|
+
// (address remains ciphertext—never re-encrypt it).
|
|
60
60
|
const eventPayload: MailAccountEventPayload = {
|
|
61
61
|
...current,
|
|
62
62
|
...(payload.status !== undefined ? { status: payload.status } : {}),
|