@cosmicdrift/kumiko-bundled-features 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/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.js +0 -2
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// inbound-provider-imap — IMAP
|
|
4
|
-
// foundation
|
|
5
|
-
// Strato, GMX/Web.de, mailbox.org, Hetzner, all-inkl) via
|
|
6
|
-
//
|
|
7
|
-
// M365
|
|
8
|
-
//
|
|
3
|
+
// inbound-provider-imap — IMAP implementation of the inbound-mail-
|
|
4
|
+
// foundation plugin API. Covers the DACH long tail (IONOS, Telekom,
|
|
5
|
+
// Strato, GMX/Web.de, mailbox.org, Hetzner, all-inkl) via password/
|
|
6
|
+
// app-password authentication, without OAuth. XOAUTH2 is available as
|
|
7
|
+
// a fallback for M365/Gmail accounts (access token from the secret slot;
|
|
8
|
+
// token refresh is handled by the OAuth providers).
|
|
9
9
|
//
|
|
10
|
-
// **
|
|
11
|
-
// 1. Plugin
|
|
10
|
+
// **What this feature provides:**
|
|
11
|
+
// 1. Plugin registration via r.useExtension("inboundMailProvider",
|
|
12
12
|
// "imap", { verify, fetch, watch }).
|
|
13
|
-
// 2. verify: connect+logout
|
|
14
|
-
// 3. fetch:
|
|
15
|
-
// UIDVALIDITY
|
|
16
|
-
//
|
|
17
|
-
// SEARCH since=backfillWindowDays.
|
|
18
|
-
// 4. watch: IMAP IDLE via imapflow — 'exists'
|
|
19
|
-
//
|
|
20
|
-
//
|
|
13
|
+
// 2. verify: connect+logout with typed error mapping.
|
|
14
|
+
// 3. fetch: incremental sync using a UIDVALIDITY:lastUid cursor —
|
|
15
|
+
// a UIDVALIDITY change throws InboundCursorInvalidError (the
|
|
16
|
+
// foundation resets and resyncs within the backfill window). Initial
|
|
17
|
+
// population uses SEARCH since=backfillWindowDays.
|
|
18
|
+
// 4. watch: IMAP IDLE via imapflow — the 'exists' event triggers fetching
|
|
19
|
+
// new UIDs and then onMessages; connection loss triggers onError (the
|
|
20
|
+
// supervisor restarts with backoff; the provider does not reconnect).
|
|
21
21
|
//
|
|
22
|
-
// Credentials: JSON
|
|
23
|
-
// (credential-document.ts)
|
|
24
|
-
//
|
|
22
|
+
// Credentials: JSON document in the per-account secret slot
|
|
23
|
+
// (credential-document.ts), not tenant configuration, because one tenant
|
|
24
|
+
// can have multiple accounts with different hosts.
|
|
25
25
|
import { mailAllowedPrivateHostsEnvSchema } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
26
26
|
import { INBOUND_MAIL_PROVIDER_EXTENSION, InboundAuthError, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
27
27
|
import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
|
|
@@ -63,18 +63,18 @@ async function fetchMessages(ctx, account, cursor, opts) {
|
|
|
63
63
|
const serverUidValidity = String(mailbox.uidValidity);
|
|
64
64
|
const parsedCursor = parseImapCursor(cursor);
|
|
65
65
|
assertUidValidity(parsedCursor, serverUidValidity);
|
|
66
|
-
// UID
|
|
67
|
-
//
|
|
66
|
+
// Determine the UID set: incrementally from lastUid+1, or use a backfill
|
|
67
|
+
// via SEARCH since (the window limits the initial population).
|
|
68
68
|
let uids;
|
|
69
69
|
if (parsedCursor) {
|
|
70
70
|
const found = await client.search({ uid: `${parsedCursor.lastUid + 1}:*` }, { uid: true });
|
|
71
|
-
// `N
|
|
72
|
-
//
|
|
71
|
+
// `N:*` gotcha: when N exceeds the highest UID, IMAP still returns the
|
|
72
|
+
// last message, so filter it out.
|
|
73
73
|
uids = (found || []).filter((uid) => uid > parsedCursor.lastUid);
|
|
74
74
|
}
|
|
75
75
|
else {
|
|
76
76
|
const since = Temporal.Now.instant().subtract({ hours: opts.backfillWindowDays * 24 });
|
|
77
|
-
// imapflow
|
|
77
|
+
// imapflow API boundary: search() requires a JS Date.
|
|
78
78
|
uids = (await client.search({ since: instantToLegacyDate(since) }, { uid: true })) || [];
|
|
79
79
|
}
|
|
80
80
|
uids.sort((a, b) => a - b);
|
|
@@ -111,8 +111,8 @@ async function fetchMessages(ctx, account, cursor, opts) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
// =============================================================================
|
|
114
|
-
// watch — IMAP IDLE (imapflow
|
|
115
|
-
//
|
|
114
|
+
// watch — IMAP IDLE (imapflow idles automatically while the mailbox is open
|
|
115
|
+
// and emits 'exists' for new messages).
|
|
116
116
|
// =============================================================================
|
|
117
117
|
async function watchMailbox(ctx, account, handlers) {
|
|
118
118
|
const doc = await readCredentialDocument(ctx, account);
|
|
@@ -122,13 +122,14 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
122
122
|
await client.connect();
|
|
123
123
|
const mailbox = (await client.mailboxOpen(IMAP_MAILBOX));
|
|
124
124
|
const uidValidity = String(mailbox.uidValidity);
|
|
125
|
-
// uidNext
|
|
125
|
+
// uidNext is the next UID to be assigned, so everything from here is
|
|
126
|
+
// "new".
|
|
126
127
|
let nextUid = Number(mailbox.uidNext ?? 1);
|
|
127
128
|
const drainNew = async () => {
|
|
128
129
|
const messages = [];
|
|
129
130
|
let maxSeen = nextUid - 1;
|
|
130
131
|
for await (const msg of client.fetch(`${nextUid}:*`, { uid: true, internalDate: true, source: true }, { uid: true })) {
|
|
131
|
-
// `N
|
|
132
|
+
// `N:*` gotcha (see fetch): filter out the previous last message.
|
|
132
133
|
if (msg.uid < nextUid || !msg.source)
|
|
133
134
|
continue;
|
|
134
135
|
messages.push(await toRawInboundMessage({
|
|
@@ -145,7 +146,7 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
145
146
|
await handlers.onMessages(messages);
|
|
146
147
|
};
|
|
147
148
|
client.on("exists", () => {
|
|
148
|
-
// skip:
|
|
149
|
+
// skip: ignore delayed exists events after the watcher has stopped.
|
|
149
150
|
if (stopped)
|
|
150
151
|
return;
|
|
151
152
|
void drainNew().catch((err) => {
|
|
@@ -154,7 +155,7 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
154
155
|
});
|
|
155
156
|
});
|
|
156
157
|
const die = (err) => {
|
|
157
|
-
// skip:
|
|
158
|
+
// skip: already stopped or terminated; fire onError only once.
|
|
158
159
|
if (stopped)
|
|
159
160
|
return;
|
|
160
161
|
stopped = true;
|
|
@@ -162,10 +163,10 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
162
163
|
};
|
|
163
164
|
client.on("error", die);
|
|
164
165
|
client.on("close", () => die(new Error("connection closed")));
|
|
165
|
-
// IDLE
|
|
166
|
-
// (
|
|
167
|
-
//
|
|
168
|
-
//
|
|
166
|
+
// IDLE loop: 'exists' fires ONLY while client.idle() is running
|
|
167
|
+
// (verified empirically against greenmail). Each intervening command
|
|
168
|
+
// (drainNew-fetch) ends idle(), so the loop re-enters idle() until
|
|
169
|
+
// stop() closes the connection.
|
|
169
170
|
void (async () => {
|
|
170
171
|
while (!stopped) {
|
|
171
172
|
try {
|
|
@@ -174,7 +175,8 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
174
175
|
catch (err) {
|
|
175
176
|
if (!stopped)
|
|
176
177
|
die(err);
|
|
177
|
-
// skip: idle
|
|
178
|
+
// skip: the idle loop ends; die() has informed the supervisor (or stop()
|
|
179
|
+
// was the cause).
|
|
178
180
|
return;
|
|
179
181
|
}
|
|
180
182
|
}
|
|
@@ -195,8 +197,8 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
195
197
|
// =============================================================================
|
|
196
198
|
// Plugin + Feature-definition
|
|
197
199
|
// =============================================================================
|
|
198
|
-
/**
|
|
199
|
-
*
|
|
200
|
+
/** Exported for the live test (imap-live.integration.test.ts) —
|
|
201
|
+
* applications use the feature, never the plugin directly. */
|
|
200
202
|
export const imapInboundMailPlugin = {
|
|
201
203
|
verify: async (ctx, account) => {
|
|
202
204
|
const doc = await readCredentialDocument(ctx, account);
|
|
@@ -213,9 +215,9 @@ export const imapInboundMailPlugin = {
|
|
|
213
215
|
},
|
|
214
216
|
fetch: fetchMessages,
|
|
215
217
|
watch: watchMailbox,
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
218
|
+
// No oauth block: password authentication runs through the credential
|
|
219
|
+
// form (connect-account + Secret-Write); XOAUTH2 token flows belong to
|
|
220
|
+
// the OAuth providers (M365/Gmail).
|
|
219
221
|
};
|
|
220
222
|
export function createInboundProviderImapFeature() {
|
|
221
223
|
return defineFeature(FEATURE_NAME, (r) => {
|
|
@@ -13,23 +13,24 @@ export type ImapCursor = {
|
|
|
13
13
|
readonly lastUid: number;
|
|
14
14
|
};
|
|
15
15
|
export declare function parseImapCursor(cursor: SyncCursorPayload | null): ImapCursor | null;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
/** Throws InboundCursorInvalidError when UIDVALIDITY changes; the
|
|
17
|
+
* foundation resets the cursor and performs a full resync within the
|
|
18
|
+
* backfill window (deduplication catches duplicates). */
|
|
19
19
|
export declare function assertUidValidity(cursor: ImapCursor | null, serverUidValidity: string): void;
|
|
20
|
-
/** References
|
|
21
|
-
* | undefined;
|
|
20
|
+
/** Normalizes the References chain: mailparser returns string | string[]
|
|
21
|
+
* | undefined; when References is missing, In-Reply-To provides the thread
|
|
22
|
+
* anchor. */
|
|
22
23
|
export declare function normalizeReferences(parsed: {
|
|
23
24
|
references?: string | string[];
|
|
24
25
|
inReplyTo?: string;
|
|
25
26
|
}): string[];
|
|
26
|
-
/** imapflow
|
|
27
|
-
*
|
|
28
|
-
* no-date-api)
|
|
29
|
-
* Date
|
|
27
|
+
/** imapflow provides internalDate as either a Date or string depending on
|
|
28
|
+
* the code path. The string form is deliberately discarded (no date parsing
|
|
29
|
+
* in feature code, no-date-api); toRawInboundMessage then falls back to the
|
|
30
|
+
* mailparser Date header, which is always a real Date. */
|
|
30
31
|
export declare function coerceDate(d: Date | string | undefined): Date | undefined;
|
|
31
|
-
/** providerMessageId: UID
|
|
32
|
-
*
|
|
32
|
+
/** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
|
|
33
|
+
* they form the stable idempotency anchor. */
|
|
33
34
|
export declare function buildProviderMessageId(uidValidity: string, uid: number): string;
|
|
34
35
|
export declare function toRawInboundMessage(args: {
|
|
35
36
|
readonly source: Uint8Array;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// imapflow
|
|
2
|
-
//
|
|
3
|
-
// UIDVALIDITY:lastUid
|
|
1
|
+
// imapflow wiring and pure helpers for IMAP providers.
|
|
2
|
+
// Reference implementation: /Users/marc/code/doc-o-mat (HEINZ), but uses an
|
|
3
|
+
// incremental UIDVALIDITY:lastUid cursor instead of a '1:*' full scan.
|
|
4
4
|
import { BlockedHostError, readAllowedPrivateMailHostsFromEnv, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
5
5
|
import { InboundAuthError, InboundCursorInvalidError, InboundTransientError, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
6
6
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
@@ -71,9 +71,9 @@ export async function createImapClient(doc, hostGuard = {}) {
|
|
|
71
71
|
}
|
|
72
72
|
/** Server-Fehler → typisierte Foundation-Fehlerklassen (Plan §2). */
|
|
73
73
|
export function mapImapError(err, host) {
|
|
74
|
-
// imapflow
|
|
75
|
-
// message
|
|
76
|
-
// authenticationFailed
|
|
74
|
+
// imapflow errors carry the server response in responseText; the
|
|
75
|
+
// message is only "Command failed", so both are included in the match;
|
|
76
|
+
// authenticationFailed is the reliable flag.
|
|
77
77
|
const carrier = isPlainObject(err) ? err : undefined;
|
|
78
78
|
const responseText = typeof carrier?.["responseText"] === "string" ? carrier["responseText"] : "";
|
|
79
79
|
const msg = `${err instanceof Error ? err.message : String(err)} ${responseText}`.trim();
|
|
@@ -95,9 +95,9 @@ export function parseImapCursor(cursor) {
|
|
|
95
95
|
return null;
|
|
96
96
|
return { uidValidity, lastUid };
|
|
97
97
|
}
|
|
98
|
-
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
98
|
+
/** Throws InboundCursorInvalidError when UIDVALIDITY changes; the
|
|
99
|
+
* foundation resets the cursor and performs a full resync within the
|
|
100
|
+
* backfill window (deduplication catches duplicates). */
|
|
101
101
|
export function assertUidValidity(cursor, serverUidValidity) {
|
|
102
102
|
if (cursor && cursor.uidValidity !== serverUidValidity) {
|
|
103
103
|
throw new InboundCursorInvalidError(`UIDVALIDITY changed (${cursor.uidValidity} → ${serverUidValidity}) — full resync required`);
|
|
@@ -109,8 +109,9 @@ export function assertUidValidity(cursor, serverUidValidity) {
|
|
|
109
109
|
function stripAngles(id) {
|
|
110
110
|
return id.replace(/^<|>$/g, "").trim();
|
|
111
111
|
}
|
|
112
|
-
/** References
|
|
113
|
-
* | undefined;
|
|
112
|
+
/** Normalizes the References chain: mailparser returns string | string[]
|
|
113
|
+
* | undefined; when References is missing, In-Reply-To provides the thread
|
|
114
|
+
* anchor. */
|
|
114
115
|
export function normalizeReferences(parsed) {
|
|
115
116
|
const raw = parsed.references;
|
|
116
117
|
const list = raw === undefined ? [] : Array.isArray(raw) ? raw : raw.split(/\s+/);
|
|
@@ -128,15 +129,15 @@ function addressList(a) {
|
|
|
128
129
|
const arr = Array.isArray(a) ? a : [a];
|
|
129
130
|
return arr.map((x) => x.text).filter((t) => Boolean(t));
|
|
130
131
|
}
|
|
131
|
-
/** imapflow
|
|
132
|
-
*
|
|
133
|
-
* no-date-api)
|
|
134
|
-
* Date
|
|
132
|
+
/** imapflow provides internalDate as either a Date or string depending on
|
|
133
|
+
* the code path. The string form is deliberately discarded (no date parsing
|
|
134
|
+
* in feature code, no-date-api); toRawInboundMessage then falls back to the
|
|
135
|
+
* mailparser Date header, which is always a real Date. */
|
|
135
136
|
export function coerceDate(d) {
|
|
136
137
|
return d instanceof Date ? d : undefined;
|
|
137
138
|
}
|
|
138
|
-
/** providerMessageId: UID
|
|
139
|
-
*
|
|
139
|
+
/** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
|
|
140
|
+
* they form the stable idempotency anchor. */
|
|
140
141
|
export function buildProviderMessageId(uidValidity, uid) {
|
|
141
142
|
return `${uidValidity}:${uid}`;
|
|
142
143
|
}
|
|
@@ -155,8 +156,8 @@ export async function toRawInboundMessage(args) {
|
|
|
155
156
|
cc: addressList(parsed.cc),
|
|
156
157
|
subject: parsed.subject ?? "",
|
|
157
158
|
snippet: text.slice(0, SNIPPET_MAX),
|
|
158
|
-
// Lib-
|
|
159
|
-
//
|
|
159
|
+
// Lib-boundary bridge (Date from imapflow/mailparser) → Temporal;
|
|
160
|
+
// when no date exists, Epoch is the honest marker.
|
|
160
161
|
receivedAtIso: (receivedAt
|
|
161
162
|
? legacyDateToInstant(receivedAt)
|
|
162
163
|
: Temporal.Instant.fromEpochMilliseconds(0)).toString(),
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { InboundMailProviderPlugin, RawInboundMessage } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
2
|
export declare const INMEMORY_PROVIDER_KEY = "inmemory";
|
|
3
|
-
/** Test
|
|
4
|
-
*
|
|
5
|
-
* cursor
|
|
3
|
+
/** Test helper: adds a message to the mailbox. If a watch is active, it is
|
|
4
|
+
* pushed immediately (IDLE simulation); the next fetch also returns it by
|
|
5
|
+
* cursor — the foundation's deduplication makes this idempotent. */
|
|
6
6
|
export declare function seedInboundMessage(accountId: string, msg: RawInboundMessage): Promise<void>;
|
|
7
|
-
/** Test
|
|
8
|
-
* InboundAuthError
|
|
7
|
+
/** Test helper: injects a one-shot error into the next fetch (e.g.
|
|
8
|
+
* InboundAuthError or InboundCursorInvalidError). */
|
|
9
9
|
export declare function failNextFetchWith(accountId: string, err: unknown): void;
|
|
10
|
-
/** Test
|
|
10
|
+
/** Test helper: injects a one-shot error into the next verify. */
|
|
11
11
|
export declare function failNextVerifyWith(accountId: string, err: unknown): void;
|
|
12
|
-
/** Test
|
|
13
|
-
*
|
|
12
|
+
/** Test helper: simulates the live connection terminating (the supervisor
|
|
13
|
+
* must restart with backoff). */
|
|
14
14
|
export declare function emitWatchError(accountId: string, err: unknown): void;
|
|
15
|
-
/** Test
|
|
15
|
+
/** Test helper: reports whether an account currently has an active watch. */
|
|
16
16
|
export declare function isWatching(accountId: string): boolean;
|
|
17
17
|
/** Test-Helper: kompletter State-Reset (Test-Isolation — Mock-States
|
|
18
18
|
* nie zwischen Tests teilen). */
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// inbound-provider-inmemory —
|
|
4
|
-
// inbound-mail-foundation
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// (IDLE
|
|
8
|
-
// (
|
|
9
|
-
//
|
|
3
|
+
// inbound-provider-inmemory — scriptable in-memory provider for the
|
|
4
|
+
// inbound-mail-foundation plugin API. For tests, demos, and sample apps:
|
|
5
|
+
// messages are supplied via `seedInboundMessage()` instead of being fetched
|
|
6
|
+
// from a real mailbox; `watch()` immediately pushes seeded messages
|
|
7
|
+
// (IDLE simulation), while `fetch()` returns them by cursor
|
|
8
|
+
// (reconciliation path). Together, both paths exercise the foundation's
|
|
9
|
+
// deduplication guarantee exactly.
|
|
10
10
|
//
|
|
11
|
-
// **Pattern
|
|
12
|
-
//
|
|
11
|
+
// **Pattern basis:** mail-transport-inmemory (module-level state +
|
|
12
|
+
// test-helper exports). Not for production.
|
|
13
13
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
14
14
|
const FEATURE_NAME = "inbound-provider-inmemory";
|
|
15
15
|
export const INMEMORY_PROVIDER_KEY = "inmemory";
|
|
@@ -22,26 +22,26 @@ function stateFor(accountId) {
|
|
|
22
22
|
}
|
|
23
23
|
return state;
|
|
24
24
|
}
|
|
25
|
-
/** Test
|
|
26
|
-
*
|
|
27
|
-
* cursor
|
|
25
|
+
/** Test helper: adds a message to the mailbox. If a watch is active, it is
|
|
26
|
+
* pushed immediately (IDLE simulation); the next fetch also returns it by
|
|
27
|
+
* cursor — the foundation's deduplication makes this idempotent. */
|
|
28
28
|
export async function seedInboundMessage(accountId, msg) {
|
|
29
29
|
const state = stateFor(accountId);
|
|
30
30
|
state.log.push(msg);
|
|
31
31
|
if (state.watch)
|
|
32
32
|
await state.watch.onMessages([msg]);
|
|
33
33
|
}
|
|
34
|
-
/** Test
|
|
35
|
-
* InboundAuthError
|
|
34
|
+
/** Test helper: injects a one-shot error into the next fetch (e.g.
|
|
35
|
+
* InboundAuthError or InboundCursorInvalidError). */
|
|
36
36
|
export function failNextFetchWith(accountId, err) {
|
|
37
37
|
stateFor(accountId).nextFetchError = err;
|
|
38
38
|
}
|
|
39
|
-
/** Test
|
|
39
|
+
/** Test helper: injects a one-shot error into the next verify. */
|
|
40
40
|
export function failNextVerifyWith(accountId, err) {
|
|
41
41
|
stateFor(accountId).nextVerifyError = err;
|
|
42
42
|
}
|
|
43
|
-
/** Test
|
|
44
|
-
*
|
|
43
|
+
/** Test helper: simulates the live connection terminating (the supervisor
|
|
44
|
+
* must restart with backoff). */
|
|
45
45
|
export function emitWatchError(accountId, err) {
|
|
46
46
|
const state = accounts.get(accountId);
|
|
47
47
|
if (state?.watch) {
|
|
@@ -50,7 +50,7 @@ export function emitWatchError(accountId, err) {
|
|
|
50
50
|
handlers.onError(err);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
/** Test
|
|
53
|
+
/** Test helper: reports whether an account currently has an active watch. */
|
|
54
54
|
export function isWatching(accountId) {
|
|
55
55
|
return accounts.get(accountId)?.watch != null;
|
|
56
56
|
}
|
|
@@ -60,7 +60,7 @@ export function resetInboundInMemory() {
|
|
|
60
60
|
accounts.clear();
|
|
61
61
|
}
|
|
62
62
|
// =============================================================================
|
|
63
|
-
// Plugin — cursor = { offset: number }
|
|
63
|
+
// Plugin — cursor = { offset: number } over the append-only log.
|
|
64
64
|
// =============================================================================
|
|
65
65
|
function offsetOf(cursor) {
|
|
66
66
|
const raw = cursor?.["offset"];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Job-run retention
|
|
1
|
+
// Job-run retention: store_job_runs/store_job_run_logs are
|
|
2
2
|
// direct-write stores now, not event-sourced projections — nothing else
|
|
3
3
|
// purges them, so without this query they grow forever with the run count
|
|
4
4
|
// instead of the runtime. Not the retention-cleanup executor: that executor
|
|
@@ -18,7 +18,7 @@ export async function deleteStaleJobRuns(db, retentionDays) {
|
|
|
18
18
|
const cutoff = Temporal.Now.instant().subtract({ hours: retentionDays * 24 });
|
|
19
19
|
const logsResult = await deleteManyBatched(db, jobRunLogsTable, { timestamp: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
|
|
20
20
|
const runsResult = await deleteManyBatched(db, jobRunsTable, { insertedAt: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
|
|
21
|
-
// Same window for the tenant-visible failure records
|
|
21
|
+
// Same window for the tenant-visible failure records: the run
|
|
22
22
|
// they point at is gone by now, and a job whose subject never ran again
|
|
23
23
|
// would otherwise keep its record forever.
|
|
24
24
|
const tenantFailuresResult = await deleteManyBatched(db, tenantJobFailuresTable, { failedAt: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Stale job-run sweep
|
|
2
|
-
//
|
|
1
|
+
// Stale job-run sweep: store_job_runs is a direct-write store
|
|
2
|
+
// Status is set to "running" once at onJobStart and only ever
|
|
3
3
|
// flipped to "completed"/"failed" by onJobComplete/onJobFailed. If the
|
|
4
4
|
// process dies mid-run (crash, OOM, kill -9), those callbacks never fire and
|
|
5
5
|
// the row is stuck on "running" forever — nothing else on the read side
|
|
@@ -31,7 +31,7 @@ export async function markStaleJobRunsFailed(db, timeoutHours, queuedRetentionDa
|
|
|
31
31
|
// user subject annotation as job-run-logger.ts's onJobFailed path
|
|
32
32
|
// (personal: { of: "triggeredById" } on job-run-table.ts), so it is encrypted
|
|
33
33
|
// under the triggering user's DEK, or the system tenant key when
|
|
34
|
-
// triggeredById is null (whenAbsent: "tenant"
|
|
34
|
+
// triggeredById is null (whenAbsent: "tenant"). Runs are grouped by
|
|
35
35
|
// that subject: one encrypt and one updateMany per subject instead of per run.
|
|
36
36
|
const stale = await selectMany(db, jobRunsTable, {
|
|
37
37
|
status: "running",
|
package/dist/jobs/events.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Payload schemas for the jobRun direct-write path
|
|
1
|
+
// Payload schemas for the jobRun direct-write path. Previously these
|
|
2
2
|
// backed jobRun's event-store payloads (r.defineEvent + inline projections);
|
|
3
3
|
// now job-run-logger.ts parses against them before writing straight into
|
|
4
4
|
// jobRunsTable/jobRunLogsTable, so an out-of-dispatcher write still gets the
|
package/dist/jobs/feature.js
CHANGED
|
@@ -31,11 +31,10 @@ export function createJobsFeature(options = {}) {
|
|
|
31
31
|
r.storeTable(jobRunsTableMeta, {
|
|
32
32
|
reason: "direct_write.job_runs",
|
|
33
33
|
// payload/error carry personal:{of:"triggeredById"} (job-run-table.ts): encrypted under the
|
|
34
|
-
// triggering user's DEK, or the system tenant key when triggeredById is null
|
|
35
|
-
// (whenAbsent: "tenant", fw#3654).
|
|
34
|
+
// triggering user's DEK, or the system tenant key when triggeredById is null.
|
|
36
35
|
// job-run-logger.ts manually encrypts both before every insert/update
|
|
37
36
|
// (encryptStartedPayload/encryptFailureError) since this store bypasses
|
|
38
|
-
// the executor's automatic PII pipeline
|
|
37
|
+
// the executor's automatic PII pipeline.
|
|
39
38
|
piiEncryptedOnWrite: true,
|
|
40
39
|
});
|
|
41
40
|
r.storeTable(jobRunLogsTableMeta, {
|
|
@@ -49,7 +48,7 @@ export function createJobsFeature(options = {}) {
|
|
|
49
48
|
});
|
|
50
49
|
// Framework-provided rebuild job — available whenever `jobs` is composed; enqueueProjectionRebuild dispatches it.
|
|
51
50
|
r.job("projectionRebuild", { trigger: { manual: true }, concurrency: "skip", schema: projectionRebuildPayloadSchema }, projectionRebuildJob);
|
|
52
|
-
// Retroactive search backfill
|
|
51
|
+
// Retroactive search backfill — manual + perTenant, so one
|
|
53
52
|
// `jobs:write:trigger` call with { entity } fans out to every active
|
|
54
53
|
// tenant (job-runner.ts perTenant dispatch applies to manual triggers
|
|
55
54
|
// too, not just cron).
|
|
@@ -60,10 +59,10 @@ export function createJobsFeature(options = {}) {
|
|
|
60
59
|
schema: reindexEntityPayloadSchema,
|
|
61
60
|
}, reindexEntityJob);
|
|
62
61
|
// store_job_runs/store_job_run_logs are direct-write, unbounded-growth
|
|
63
|
-
// stores
|
|
62
|
+
// stores — nothing else purges them.
|
|
64
63
|
r.job("retention-cleanup", { trigger: { cron: "0 3 * * *" }, concurrency: "skip" }, createRetentionCleanupJob(retentionDays));
|
|
65
64
|
// Sweeps store_job_runs for rows stuck at status "running" past the
|
|
66
|
-
// timeout
|
|
65
|
+
// timeout. Hourly matches the timeout's own granularity —
|
|
67
66
|
// frequent enough to catch a stuck run soon after it crosses the
|
|
68
67
|
// threshold, cheap enough that an (almost always empty) result set
|
|
69
68
|
// doesn't matter.
|
|
@@ -27,11 +27,11 @@ export const detailQuery = defineQueryHandler({
|
|
|
27
27
|
const row = await fetchOne(db, jobRunsTable, { id: query.payload.runId });
|
|
28
28
|
if (!row)
|
|
29
29
|
return null;
|
|
30
|
-
// payload is stored encrypted under the triggering user's DEK
|
|
30
|
+
// payload is stored encrypted under the triggering user's DEK.
|
|
31
31
|
if (typeof row["payload"] === "string") {
|
|
32
32
|
row["payload"] = await decryptStoredPii(row["payload"], "payload", "job-run-detail");
|
|
33
33
|
}
|
|
34
|
-
// error is stored encrypted under the triggering user's DEK
|
|
34
|
+
// error is stored encrypted under the triggering user's DEK,
|
|
35
35
|
// same mechanism as row.payload above.
|
|
36
36
|
if (typeof row["error"] === "string") {
|
|
37
37
|
row["error"] = await decryptStoredPii(row["error"], "error", "job-run-detail");
|
|
@@ -39,8 +39,8 @@ export const detailQuery = defineQueryHandler({
|
|
|
39
39
|
const logs = await selectMany(db, jobRunLogsTable, { runId: query.payload.runId }, {
|
|
40
40
|
orderBy: { col: "id", direction: "asc" },
|
|
41
41
|
});
|
|
42
|
-
// message is stored encrypted under the triggering user's DEK
|
|
43
|
-
// same mechanism as row.payload above. Bounded concurrency
|
|
42
|
+
// message is stored encrypted under the triggering user's DEK,
|
|
43
|
+
// same mechanism as row.payload above. Bounded concurrency —
|
|
44
44
|
// unbounded Promise.all would fire one decrypt per log line at once
|
|
45
45
|
// against the KMS adapter's pool.
|
|
46
46
|
const decryptedLogs = await mapWithConcurrency(logs, KMS_POOL_CONCURRENCY, async (log) => {
|
|
@@ -88,7 +88,7 @@ export const listQuery = defineQueryHandler({
|
|
|
88
88
|
// countWhere reruns the SAME `where` without the limit — `rows.length` is
|
|
89
89
|
// capped at the page size and would silently undercount the total.
|
|
90
90
|
const total = query.payload.totalCount === true ? await countWhere(db, jobRunsTable, where) : undefined;
|
|
91
|
-
// payload/error are stored encrypted under the triggering user's DEK
|
|
91
|
+
// payload/error are stored encrypted under the triggering user's DEK.
|
|
92
92
|
return {
|
|
93
93
|
rows: await mapWithConcurrency(rows, KMS_POOL_CONCURRENCY, decryptRunRow),
|
|
94
94
|
nextCursor: hasMore ? encodeCursor(String(offset + limit)) : null,
|
|
@@ -4,7 +4,7 @@ import { rebuildProjectionOrMultiStream } from "@cosmicdrift/kumiko-framework/mi
|
|
|
4
4
|
import * as z from "zod";
|
|
5
5
|
export const projectionRebuildPayloadSchema = z.object({
|
|
6
6
|
projection: z.string().min(1),
|
|
7
|
-
// Quarantine mode
|
|
7
|
+
// Quarantine mode: skip + dead-letter poison events instead of
|
|
8
8
|
// failing the whole rebuild. Operator opt-in per run.
|
|
9
9
|
skipApplyErrors: z.boolean().optional(),
|
|
10
10
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Manual, perTenant backfill job
|
|
1
|
+
// Manual, perTenant backfill job — indexes existing rows for
|
|
2
2
|
// an entity that only got `searchable: true` after rows already existed.
|
|
3
3
|
// perTenant fan-out (job-runner.ts) also applies to a manual dispatch, not
|
|
4
4
|
// just cron: one `jobs:write:trigger` call with { entity } re-runs once per
|
|
@@ -35,7 +35,7 @@ export const retryWrite = defineWriteHandler({
|
|
|
35
35
|
details: { status: run.status },
|
|
36
36
|
}));
|
|
37
37
|
}
|
|
38
|
-
// payload is stored encrypted under the triggering user's DEK
|
|
38
|
+
// payload is stored encrypted under the triggering user's DEK,
|
|
39
39
|
// same mechanism as detail.query.ts/list.query.ts — decrypt before
|
|
40
40
|
// parsing it as JSON. A key erased since the run finished decrypts to
|
|
41
41
|
// PII_ERASED_SENTINEL, which is not JSON; reject the retry rather than
|
package/dist/jobs/job-instant.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
|
-
//
|
|
2
|
+
// The five value-position Temporal.Instant.from
|
|
3
3
|
// call sites in feature.ts live inside defineApply callbacks with no
|
|
4
4
|
// exported seam, so this thin wrapper gives the ambient-global-independence
|
|
5
5
|
// regression test something to import directly.
|