@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,14 +1,15 @@
|
|
|
1
|
-
// HMAC-
|
|
1
|
+
// HMAC-signed OAuth-`state` parameter for the connect flow.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Binds {tenantId, ownerUserId?, providerKey, mailbox, nonce} to the
|
|
4
|
+
// redirect: the anonymous callback (outside /api/*) trusts only the
|
|
5
|
+
// verified state, preventing CSRF and cross-tenant or cross-user claiming
|
|
6
|
+
// because an attacker cannot redirect the callback to another tenant or
|
|
7
|
+
// user without breaking the signature.
|
|
8
8
|
//
|
|
9
9
|
// Format: <payload-base64url>.<expiresAtMs>.<hmac-base64url>
|
|
10
|
-
//
|
|
11
|
-
// HMAC
|
|
10
|
+
// Patterned after auth-email-password/signed-token.ts (HMAC-SHA256, purpose
|
|
11
|
+
// in the HMAC input, timing-safe comparison, expiry in the clear-text
|
|
12
|
+
// segment).
|
|
12
13
|
|
|
13
14
|
import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
14
15
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
@@ -18,14 +19,14 @@ const STATE_PURPOSE = "inbound-mail-oauth-connect";
|
|
|
18
19
|
|
|
19
20
|
export type OAuthStatePayload = {
|
|
20
21
|
readonly tenantId: string;
|
|
21
|
-
/** null = shared
|
|
22
|
+
/** null = shared mailbox; otherwise this user's personal mailbox. */
|
|
22
23
|
readonly ownerUserId: string | null;
|
|
23
24
|
readonly providerKey: string;
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
25
|
+
/** Mailbox address from the connect request; after token exchange, it is
|
|
26
|
+
* stored in the MailAccount. */
|
|
26
27
|
readonly mailbox: string;
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
28
|
+
/** One-time nonce makes each state unique, preventing replay across
|
|
29
|
+
* two parallel connect flows. */
|
|
29
30
|
readonly nonce: string;
|
|
30
31
|
};
|
|
31
32
|
|
|
@@ -72,8 +73,8 @@ export function verifyOAuthState(
|
|
|
72
73
|
const expected = sign(hmacInput(payloadB64, expiresAtMs), secret);
|
|
73
74
|
const expectedBuf = Buffer.from(expected, "base64url");
|
|
74
75
|
const providedBuf = Buffer.from(providedSig, "base64url");
|
|
75
|
-
//
|
|
76
|
-
//
|
|
76
|
+
// Check the length before timingSafeEqual: it throws on a length mismatch,
|
|
77
|
+
// and the throw itself leaks information through timing.
|
|
77
78
|
if (expectedBuf.length !== providedBuf.length) return { ok: false, reason: "bad_signature" };
|
|
78
79
|
if (!timingSafeEqual(expectedBuf, providedBuf)) return { ok: false, reason: "bad_signature" };
|
|
79
80
|
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
// Inline
|
|
1
|
+
// Inline projections for the three event-sourced streams:
|
|
2
2
|
// mail-account → read_mail_accounts (UPSERT, current state)
|
|
3
3
|
// inbound-message → read_inbound_messages (INSERT-ignore, append-only)
|
|
4
|
-
// mail-thread → read_mail_threads (UPSERT,
|
|
4
|
+
// mail-thread → read_mail_threads (UPSERT, rollup)
|
|
5
5
|
//
|
|
6
|
-
// Apply
|
|
7
|
-
// own-write
|
|
6
|
+
// Apply runs in the same transaction as ctx.unsafeAppendEvent, providing
|
|
7
|
+
// read-your-own-write without waiting for a dispatcher tick (as in
|
|
8
|
+
// billing-foundation).
|
|
8
9
|
//
|
|
9
|
-
// **Production-deployment caveat** (
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
10
|
+
// **Production-deployment caveat** (same as billing-foundation):
|
|
11
|
+
// The tables are registered as raw drizzle-pgTable instances in r.projection,
|
|
12
|
+
// NOT as r.entity. Apps must include them in their drizzle/generate.ts
|
|
13
|
+
// (via *-ProjectionTable imports). setupTestStack pushes them automatically
|
|
14
|
+
// via r.projection.table.
|
|
14
15
|
//
|
|
15
|
-
// **PII:**
|
|
16
|
-
//
|
|
17
|
-
// write
|
|
18
|
-
// in
|
|
16
|
+
// **PII:** The payload fields (address/from/to/cc/subject/snippet) already
|
|
17
|
+
// arrive as ciphertext because they are encrypted BEFORE the append in the
|
|
18
|
+
// write handler. The applies only copy them through; decryption happens only
|
|
19
|
+
// in the list queries.
|
|
19
20
|
|
|
20
21
|
import {
|
|
21
22
|
buildEntityTable,
|
|
@@ -32,8 +33,8 @@ import type {
|
|
|
32
33
|
MailThreadEventPayload,
|
|
33
34
|
} from "./events.ts";
|
|
34
35
|
|
|
35
|
-
// Drizzle
|
|
36
|
-
// projection
|
|
36
|
+
// Drizzle table instances derived from the entity shapes, shared between
|
|
37
|
+
// projection applies and list queries to provide one column namespace.
|
|
37
38
|
export const mailAccountsProjectionTable = buildEntityTable("mail-account", mailAccountEntity);
|
|
38
39
|
export const inboundMessagesProjectionTable = buildEntityTable(
|
|
39
40
|
"inbound-message",
|
|
@@ -57,9 +58,10 @@ const mailThreadsProjectionMeta: EntityTableMeta = requireEntityTableMeta(
|
|
|
57
58
|
);
|
|
58
59
|
|
|
59
60
|
// =============================================================================
|
|
60
|
-
// mail-account — connected/updated/disconnected
|
|
61
|
-
//
|
|
62
|
-
// defensive consistency
|
|
61
|
+
// mail-account — connected/updated/disconnected share the payload shape;
|
|
62
|
+
// the event type identifies what happened. All three perform a full UPSERT
|
|
63
|
+
// for defensive consistency during from-scratch rebuilds and out-of-order
|
|
64
|
+
// processing.
|
|
63
65
|
// =============================================================================
|
|
64
66
|
|
|
65
67
|
const applyMailAccountUpsert = defineApply<MailAccountEventPayload>(async (event, tx) => {
|
|
@@ -91,16 +93,16 @@ const applyMailAccountUpsert = defineApply<MailAccountEventPayload>(async (event
|
|
|
91
93
|
|
|
92
94
|
/** mail-account-connected → UPSERT full. */
|
|
93
95
|
export const applyMailAccountConnected = applyMailAccountUpsert;
|
|
94
|
-
/** mail-account-updated → UPSERT
|
|
96
|
+
/** mail-account-updated → full UPSERT for status/watchState transitions. */
|
|
95
97
|
export const applyMailAccountUpdated = applyMailAccountUpsert;
|
|
96
|
-
/** mail-account-disconnected → UPSERT
|
|
97
|
-
*
|
|
98
|
+
/** mail-account-disconnected → full UPSERT (payload.status=disconnected).
|
|
99
|
+
* The row and stream remain for audit visibility in the account list. */
|
|
98
100
|
export const applyMailAccountDisconnected = applyMailAccountUpsert;
|
|
99
101
|
|
|
100
102
|
// =============================================================================
|
|
101
|
-
// inbound-message —
|
|
102
|
-
// aggregateId). INSERT-ignore
|
|
103
|
-
//
|
|
103
|
+
// inbound-message — exactly one received event per stream (deterministic
|
|
104
|
+
// aggregateId). INSERT-ignore makes replays no-ops on the primary key;
|
|
105
|
+
// there is no update case.
|
|
104
106
|
// =============================================================================
|
|
105
107
|
|
|
106
108
|
/** inbound-message-received → INSERT ... ON CONFLICT DO NOTHING. */
|
|
@@ -127,13 +129,13 @@ export const applyInboundMessageReceived = defineApply<InboundMessageEventPayloa
|
|
|
127
129
|
);
|
|
128
130
|
|
|
129
131
|
// =============================================================================
|
|
130
|
-
// mail-thread —
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
132
|
+
// mail-thread — rollup per (tenantId, threadKey). The write handler computes
|
|
133
|
+
// messageCount/lastMessageAt and appends the updated event with the NEW state.
|
|
134
|
+
// The apply performs a full UPSERT rather than incrementing, because
|
|
135
|
+
// replays would otherwise not be idempotent.
|
|
134
136
|
// =============================================================================
|
|
135
137
|
|
|
136
|
-
/** mail-thread-updated → UPSERT
|
|
138
|
+
/** mail-thread-updated → full UPSERT with the payload snapshot. */
|
|
137
139
|
export const applyMailThreadUpdated = defineApply<MailThreadEventPayload>(async (event, tx) => {
|
|
138
140
|
const p = event.payload;
|
|
139
141
|
const mutable = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// Provider
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// per
|
|
5
|
-
//
|
|
1
|
+
// Provider factory — mirrors mail-foundation's createTransportForTenant, including
|
|
2
|
+
// the three error paths (missing registry, unregistered provider, invalid plugin
|
|
3
|
+
// shape). Unlike the outbound pattern, there is no per-tenant config selector:
|
|
4
|
+
// the provider is specified per MailAccount (`account.provider`), so a tenant can
|
|
5
|
+
// use multiple providers in parallel.
|
|
6
6
|
|
|
7
7
|
import { INBOUND_MAIL_FOUNDATION_FEATURE, INBOUND_MAIL_PROVIDER_EXTENSION } from "./constants.ts";
|
|
8
8
|
import {
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
type MailAccountRecord,
|
|
13
13
|
} from "./types.ts";
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
15
|
+
/** Looks up a provider by key ("imap", "m365-graph", ...); used by OAuth
|
|
16
|
+
* connect routes before an account exists. */
|
|
17
17
|
export function resolveInboundProviderForKey(
|
|
18
18
|
ctx: InboundMailContext,
|
|
19
19
|
providerKey: string,
|
|
@@ -42,8 +42,8 @@ export function resolveInboundProviderForKey(
|
|
|
42
42
|
return usage.options;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
45
|
+
/** Looks up the provider for a specific account; the standard path for poll jobs
|
|
46
|
+
* and the watch supervisor. */
|
|
47
47
|
export function resolveInboundProviderForAccount(
|
|
48
48
|
ctx: InboundMailContext,
|
|
49
49
|
account: MailAccountRecord,
|
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
// Inbound-mail data
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// event-sourced
|
|
1
|
+
// Inbound-mail data retention. DSGVO Art. 5 (data minimization):
|
|
2
|
+
// without retention, read_inbound_messages and the file-storage bodies grow
|
|
3
|
+
// without bound. Two targets, two mechanisms—the difference is
|
|
4
|
+
// event-sourced versus unmanaged:
|
|
5
5
|
//
|
|
6
|
-
// read_inbound_messages (event-sourced,
|
|
7
|
-
//
|
|
8
|
-
// (+ bodyRef
|
|
9
|
-
//
|
|
10
|
-
// forgotten-
|
|
11
|
-
// forget
|
|
12
|
-
// received
|
|
13
|
-
// loadAggregate
|
|
14
|
-
//
|
|
6
|
+
// read_inbound_messages (event-sourced, EXPLICIT r.projection):
|
|
7
|
+
// each Row older than messageRetentionDays → archiveStream + Row delete
|
|
8
|
+
// (+ delete the bodyRef object). archiveStream instead of executor.forget
|
|
9
|
+
// because the projection maps only the received domain event, not the
|
|
10
|
+
// forgotten auto-verb (which only ImplicitProjection registers). A
|
|
11
|
+
// forget event would be ignored during a rebuild, causing the Row to be
|
|
12
|
+
// resurrected from the received event. The archived stream makes
|
|
13
|
+
// loadAggregate empty, so received is not replicated in the first place.
|
|
14
|
+
// Same pattern as tenant-destroy-hook, but with a per-Row cutoff instead
|
|
15
|
+
// of an entire Tenant.
|
|
15
16
|
//
|
|
16
|
-
// store_mail_seen_messages (unmanaged, direct-write,
|
|
17
|
-
//
|
|
18
|
-
// via plain deleteMany,
|
|
19
|
-
// tenant_id
|
|
17
|
+
// store_mail_seen_messages (unmanaged, direct-write, not event-sourced):
|
|
18
|
+
// The deduplication anchor is needed only for the backfill/replay window →
|
|
19
|
+
// seenAt cutoff via plain deleteMany, with no stream/archive. Scoped
|
|
20
|
+
// directly through the table's tenant_id column (table-builder convention),
|
|
21
|
+
// without an Account join.
|
|
20
22
|
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
23
|
+
// LIMITATION: the PII in the message events remains decryptable under the
|
|
24
|
+
// TENANT subject key—per-Row retention does not shred a key. Actual Art.-17
|
|
25
|
+
// erasure of event payloads happens only during tenant-destroy (key erasure).
|
|
26
|
+
// The read Row and body file are gone after the sweep; the event log is
|
|
27
|
+
// append-only by design.
|
|
26
28
|
|
|
27
29
|
import { type DbRunner, deleteMany, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
28
30
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -35,8 +37,8 @@ import { seenMessageTable } from "./entities.ts";
|
|
|
35
37
|
import { INBOUND_MESSAGE_AGGREGATE_TYPE } from "./events.ts";
|
|
36
38
|
import { inboundMessagesProjectionTable } from "./projection.ts";
|
|
37
39
|
|
|
38
|
-
// Temporal.Instant
|
|
39
|
-
// (
|
|
40
|
+
// Provides Temporal.Instant without forcing the caller to obtain it from
|
|
41
|
+
// globalThis (same pattern as data-retention/keep-for.ts).
|
|
40
42
|
type Instant = InstanceType<ReturnType<typeof getTemporal>["Instant"]>;
|
|
41
43
|
|
|
42
44
|
export const MESSAGE_RETENTION_DAYS = 365;
|
|
@@ -48,12 +50,14 @@ const REASON = "retention_expired";
|
|
|
48
50
|
export interface InboundRetentionArgs {
|
|
49
51
|
readonly db: DbRunner;
|
|
50
52
|
readonly tenantId: TenantId;
|
|
51
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Injects the current time so tests can pin it without a date mock (pattern from keep-for.ts).
|
|
55
|
+
*/
|
|
52
56
|
readonly now: Instant;
|
|
53
57
|
readonly messageRetentionDays?: number;
|
|
54
58
|
readonly seenRetentionDays?: number;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
59
|
+
/** Deletes a file-storage body object by bodyRef key. Wired lazily by the job
|
|
60
|
+
* (createFileProviderForTenant); if absent, no body is deleted. */
|
|
57
61
|
readonly deleteBodyObject?: (bodyRef: string) => Promise<void>;
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -88,18 +92,18 @@ async function purgeExpiredMessages(
|
|
|
88
92
|
let bodyObjectsDeleted = 0;
|
|
89
93
|
let bodyObjectErrors = 0;
|
|
90
94
|
|
|
91
|
-
// Drain
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
// select
|
|
96
|
-
//
|
|
95
|
+
// Drain loop: each page deletes the Rows it reads, so the next page is fresh.
|
|
96
|
+
// Run archiveStream BEFORE deletion: if a crash occurs in between, the next
|
|
97
|
+
// run re-archives idempotently and deletes the Row. Delete strictly by the
|
|
98
|
+
// archived IDs, never with a cutoff WHERE; otherwise an old mail arriving
|
|
99
|
+
// between select and delete could be deleted without being archived and
|
|
100
|
+
// resurrected during a rebuild.
|
|
97
101
|
//
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
102
|
+
// A Row whose deleteBodyObject fails is NOT deleted; otherwise the only
|
|
103
|
+
// reference to the now-orphaned file object would be lost (no retry or
|
|
104
|
+
// dead-letter). The Row remains for the next sweep (archiveStream is
|
|
105
|
+
// idempotent). failedIds prevents such a Row from being selected endlessly
|
|
106
|
+
// during THIS run.
|
|
103
107
|
const failedIds = new Set<string>();
|
|
104
108
|
for (;;) {
|
|
105
109
|
const rows = (
|
|
@@ -153,9 +157,9 @@ async function purgeExpiredSeenAnchors(
|
|
|
153
157
|
tenantId: TenantId,
|
|
154
158
|
cutoff: Instant,
|
|
155
159
|
): Promise<number> {
|
|
156
|
-
// Seen
|
|
157
|
-
//
|
|
158
|
-
//
|
|
160
|
+
// Seen anchors inherit tenantId (table-builder: every Entity has tenant_id) →
|
|
161
|
+
// scoped directly to the tenant, without an Account join. This also includes
|
|
162
|
+
// anchors whose Account has already been disconnected or deleted.
|
|
159
163
|
const where = { tenantId, seenAt: { lt: cutoff } };
|
|
160
164
|
const expired = await selectMany<{ accountId: string }>(db, seenMessageTable, where);
|
|
161
165
|
if (expired.length === 0) return 0;
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
// Tenant-destroy hooks
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// entity-genau), jeweils:
|
|
1
|
+
// Tenant-destroy hooks remove all inbound-mail traces belonging to the tenant.
|
|
2
|
+
// One hook per tenant-subject entity (the gdpr-storage boot validator checks
|
|
3
|
+
// the EXT_TENANT_DATA registration per entity), each of which:
|
|
5
4
|
//
|
|
6
|
-
// 1.
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// VOR dem Delete eingesammelt.
|
|
5
|
+
// 1. Archives streams so a future projection rebuild cannot resurrect
|
|
6
|
+
// deleted data. Message streams are numerous, so loop over the
|
|
7
|
+
// projection rows (row PK = stream ID); tenant-destroy is a rare batch
|
|
8
|
+
// operation, so O(n) is acceptable.
|
|
9
|
+
// 2. Deletes the projection rows.
|
|
10
|
+
// 3. For mail-account only, deletes unmanaged sync state (cursors,
|
|
11
|
+
// seen anchors), which is keyed by accountId and must therefore be
|
|
12
|
+
// collected from the account rows BEFORE deletion.
|
|
15
13
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
14
|
+
// The actual PII erasure uses crypto-shredding: eraseSubjectKeys deletes the
|
|
15
|
+
// tenant subject key, making event-log payloads AND any ciphertext copies
|
|
16
|
+
// unreadable. These hooks dispose of the rows.
|
|
19
17
|
|
|
20
18
|
import type { EntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
|
|
21
19
|
import { declareEscapeHatch, type TenantDataHookCtx } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// Provider
|
|
1
|
+
// Provider contract for inbound-mail provider plugins.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// Mirrored from mail-foundation's MailTransportContext/-Plugin —
|
|
4
|
+
// the Foundation/provider separation and slim context are identical.
|
|
5
5
|
//
|
|
6
|
-
// **
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
6
|
+
// **Why not a full HandlerContext?** fetch()/watch() run in the worker
|
|
7
|
+
// path (poll cron, IDLE supervisor), where there is no per-request
|
|
8
|
+
// `tx`/`actor`. A plugin that reads more would break the worker path at
|
|
9
|
+
// runtime, and this would only be noticed in production. Plugins that need
|
|
10
|
+
// more must explicitly extend InboundMailContext (a visible breaking change)
|
|
11
|
+
// instead of casting ctx.
|
|
12
12
|
|
|
13
13
|
import type { ConfigAccessor, Registry } from "@cosmicdrift/kumiko-framework/engine";
|
|
14
14
|
import type { MetricsHandle } from "@cosmicdrift/kumiko-framework/observability";
|
|
@@ -36,23 +36,23 @@ export type InboundMailContext = {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Plaintext
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* withPiiCiphertextGuard
|
|
39
|
+
* Plaintext view of a connected mailbox exposed to providers.
|
|
40
|
+
* The Foundation decrypts `address` BEFORE the provider call; providers
|
|
41
|
+
* never receive `kumiko-pii:` ciphertext (guard analogous to
|
|
42
|
+
* withPiiCiphertextGuard in the transport path).
|
|
43
43
|
*/
|
|
44
44
|
export type MailAccountRecord = {
|
|
45
|
-
/** = aggregateId
|
|
45
|
+
/** = aggregateId of the mail-account stream and the secret-slot key. */
|
|
46
46
|
readonly id: string;
|
|
47
47
|
readonly tenantId: string;
|
|
48
|
-
/** Provider
|
|
48
|
+
/** Provider key registered with the extension ("imap", "m365-graph",
|
|
49
49
|
* "gmail-rest"). */
|
|
50
50
|
readonly provider: string;
|
|
51
|
-
/** "password" | "xoauth2" | "oauth" — imap
|
|
52
|
-
*
|
|
51
|
+
/** "password" | "xoauth2" | "oauth" — imap uses this to distinguish
|
|
52
|
+
* form-based connect from the XOAUTH2 fallback. */
|
|
53
53
|
readonly authMethod: string;
|
|
54
|
-
/** null = tenant-
|
|
55
|
-
*
|
|
54
|
+
/** null = tenant-shared mailbox; otherwise this user's personal mailbox
|
|
55
|
+
* (visibility scope). */
|
|
56
56
|
readonly ownerUserId: string | null;
|
|
57
57
|
/** Postfach-Adresse, Plaintext (decrypted). */
|
|
58
58
|
readonly address: string;
|
|
@@ -62,36 +62,35 @@ export type MailAccountRecord = {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
66
|
-
* Provider-
|
|
67
|
-
*
|
|
65
|
+
* Normalized incoming mail — provider output and ingest input.
|
|
66
|
+
* Provider-specific structures (IMAP flags, Graph objects) remain in the
|
|
67
|
+
* provider; this type contains only the domain-level boundary.
|
|
68
68
|
*/
|
|
69
69
|
export type RawInboundMessage = {
|
|
70
|
-
/** Provider-native
|
|
71
|
-
*
|
|
70
|
+
/** Provider-native message ID (IMAP UID, Graph id, Gmail id) — the
|
|
71
|
+
* idempotency anchor together with providerName. */
|
|
72
72
|
readonly providerMessageId: string;
|
|
73
|
-
/** RFC-5322 Message-ID
|
|
74
|
-
* (Foundation
|
|
73
|
+
/** RFC-5322 Message-ID header without <>; null when the header is missing
|
|
74
|
+
* (the Foundation falls back to a deterministic replacement). */
|
|
75
75
|
readonly messageIdHeader: string | null;
|
|
76
|
-
/** Provider-native
|
|
77
|
-
* conversationId, Gmail threadId); Foundation
|
|
78
|
-
* References
|
|
76
|
+
/** Provider-native thread/conversation ID when available (Graph
|
|
77
|
+
* conversationId, Gmail threadId); the Foundation prefers it over the
|
|
78
|
+
* References chain when building threadKey. */
|
|
79
79
|
readonly providerThreadId: string | null;
|
|
80
|
-
/** References/In-Reply-To
|
|
80
|
+
/** References/In-Reply-To chain (message IDs without <>), oldest first. */
|
|
81
81
|
readonly references: readonly string[];
|
|
82
82
|
readonly from: string;
|
|
83
83
|
readonly to: readonly string[];
|
|
84
84
|
readonly cc: readonly string[];
|
|
85
85
|
readonly subject: string;
|
|
86
|
-
/** Plaintext
|
|
86
|
+
/** Plaintext preview generated by the provider or truncated from the body. */
|
|
87
87
|
readonly snippet: string;
|
|
88
|
-
/** ISO
|
|
88
|
+
/** ISO instant — INTERNALDATE or receivedDateTime, not ingest time. */
|
|
89
89
|
readonly receivedAtIso: string;
|
|
90
|
-
/** Raw MIME; null
|
|
91
|
-
* file-foundation
|
|
92
|
-
* blob-frei. */
|
|
90
|
+
/** Raw MIME; null in snippet-only mode. The Foundation persists it through
|
|
91
|
+
* file-foundation and writes bodyRef, so the event store remains blob-free. */
|
|
93
92
|
readonly rawMime: Uint8Array | null;
|
|
94
|
-
/**
|
|
93
|
+
/** Generic scope hint ("inbox", folder name), with no application semantics. */
|
|
95
94
|
readonly scope: string;
|
|
96
95
|
};
|
|
97
96
|
|
|
@@ -103,8 +102,8 @@ export type SyncCursorPayload = Readonly<Record<string, unknown>>;
|
|
|
103
102
|
export type InboundFetchResult = {
|
|
104
103
|
readonly messages: readonly RawInboundMessage[];
|
|
105
104
|
readonly nextCursor: SyncCursorPayload;
|
|
106
|
-
/** true ⇒ Foundation
|
|
107
|
-
* (
|
|
105
|
+
/** true ⇒ the Foundation calls fetch again in the same poll tick
|
|
106
|
+
* (pagination) until false or the maxMessages budget is exhausted. */
|
|
108
107
|
readonly hasMore: boolean;
|
|
109
108
|
};
|
|
110
109
|
|
|
@@ -117,13 +116,13 @@ export type OAuthTokenSet = {
|
|
|
117
116
|
};
|
|
118
117
|
|
|
119
118
|
/**
|
|
120
|
-
* OAuth
|
|
121
|
-
*
|
|
122
|
-
* `/inbound-mail/oauth/callback`)
|
|
123
|
-
*
|
|
119
|
+
* OAuth portion of the contract — OAuth providers only; imap in password
|
|
120
|
+
* mode omits `oauth`. The Foundation provides the routes
|
|
121
|
+
* (`/inbound-mail/connect`, `/inbound-mail/oauth/callback`) generically;
|
|
122
|
+
* providers MUST NOT register their own routes.
|
|
124
123
|
*/
|
|
125
124
|
export type InboundOAuthFlow = {
|
|
126
|
-
/** Scopes:
|
|
125
|
+
/** Scopes: request receive AND send in a SINGLE consent; re-consent is costly. */
|
|
127
126
|
readonly scopes: {
|
|
128
127
|
readonly receive: readonly string[];
|
|
129
128
|
readonly send?: readonly string[];
|
|
@@ -150,17 +149,17 @@ export type InboundOAuthFlow = {
|
|
|
150
149
|
};
|
|
151
150
|
|
|
152
151
|
/**
|
|
153
|
-
* Inbound-
|
|
154
|
-
* (inbound-provider-imap, -m365-graph, -gmail-rest)
|
|
155
|
-
*
|
|
152
|
+
* Inbound-mail provider plugin contract. Each provider feature
|
|
153
|
+
* (inbound-provider-imap, -m365-graph, -gmail-rest) registers an
|
|
154
|
+
* implementation via `r.useExtension(INBOUND_MAIL_PROVIDER_EXTENSION,
|
|
156
155
|
* "<key>", plugin)`.
|
|
157
156
|
*/
|
|
158
157
|
export type InboundMailProviderPlugin = {
|
|
159
|
-
/**
|
|
160
|
-
*
|
|
158
|
+
/** Credential/reachability check during the connect flow — throws a
|
|
159
|
+
* typed error (InboundAuthError, etc.) and returns no value. */
|
|
161
160
|
readonly verify: (ctx: InboundMailContext, account: MailAccountRecord) => Promise<void>;
|
|
162
|
-
/**
|
|
163
|
-
*
|
|
161
|
+
/** Fetch since cursor. `cursor === null` means initial population,
|
|
162
|
+
* limited by backfillWindowDays. */
|
|
164
163
|
readonly fetch: (
|
|
165
164
|
ctx: InboundMailContext,
|
|
166
165
|
account: MailAccountRecord,
|
|
@@ -183,11 +182,11 @@ export type InboundMailProviderPlugin = {
|
|
|
183
182
|
) => Promise<InboundFetchResult>;
|
|
184
183
|
/** Nur OAuth-Provider. */
|
|
185
184
|
readonly oauth?: InboundOAuthFlow;
|
|
186
|
-
/** Optional
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
185
|
+
/** Optional live push (IMAP IDLE, later Graph/Gmail webhooks).
|
|
186
|
+
* Returns stop(). Polling remains reconciliation: watch optimizes
|
|
187
|
+
* latency but is never the correctness anchor. `onError` reports a dead
|
|
188
|
+
* live connection (drop, auth revocation) to the supervisor, which
|
|
189
|
+
* restarts it with backoff; the provider does NOT reconnect itself. */
|
|
191
190
|
readonly watch?: (
|
|
192
191
|
ctx: InboundMailContext,
|
|
193
192
|
account: MailAccountRecord,
|
|
@@ -201,8 +200,9 @@ export type InboundMailProviderPlugin = {
|
|
|
201
200
|
) => Promise<() => Promise<void>>;
|
|
202
201
|
};
|
|
203
202
|
|
|
204
|
-
//
|
|
205
|
-
//
|
|
203
|
+
// `options` in the extension usage is an engine payload (unknown), so
|
|
204
|
+
// validate its structure instead of casting blindly (patterned after
|
|
205
|
+
// isMailTransportPlugin).
|
|
206
206
|
export function isInboundMailProviderPlugin(o: unknown): o is InboundMailProviderPlugin {
|
|
207
207
|
return (
|
|
208
208
|
typeof o === "object" &&
|
|
@@ -222,18 +222,17 @@ declare module "@cosmicdrift/kumiko-framework/engine" {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// =============================================================================
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
// InboundTransientError → Job-Retry (retries: 3, exponential)
|
|
225
|
+
// Typed errors handled uniformly by the Foundation during polling:
|
|
226
|
+
// InboundAuthError → status=auth_error, no retry
|
|
227
|
+
// InboundRateLimitError → abort poll, wait for the next cron tick
|
|
228
|
+
// InboundCursorInvalidError → reset cursor + full resync in the backfill
|
|
229
|
+
// window; deduplication handles duplicates
|
|
230
|
+
// InboundTransientError → job retry (retries: 3, exponential)
|
|
232
231
|
// =============================================================================
|
|
233
232
|
//
|
|
234
|
-
// `kind
|
|
235
|
-
//
|
|
236
|
-
//
|
|
233
|
+
// Use a `kind` discriminant instead of instanceof: plugins and the Foundation
|
|
234
|
+
// may run in separate bundles (dual-package-hazard), and instanceof is
|
|
235
|
+
// unreliable across realm or package-copy boundaries.
|
|
237
236
|
|
|
238
237
|
export class InboundAuthError extends Error {
|
|
239
238
|
readonly kind = "inbound-auth-error" as const;
|