@cosmicdrift/kumiko-samples 0.386.0 → 0.388.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 +9 -2
- package/packages/bundled-features/src/agent-tools/changes.json +6 -0
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +9 -9
- package/packages/bundled-features/src/audit/changes.json +12 -0
- package/packages/bundled-features/src/audit/handlers/audit-events.ts +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/auth-mfa/feature-exports.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/feature.ts +6 -0
- 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 +9 -4
- 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-code-or-recovery-field.tsx +68 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +23 -13
- package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +23 -13
- package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +15 -6
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +71 -24
- package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
- package/packages/bundled-features/src/billing-foundation/changes.json +55 -0
- package/packages/bundled-features/src/billing-foundation/checkout-core.ts +32 -42
- package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +8 -2
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +14 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +3 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +12 -6
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +35 -19
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +12 -8
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +14 -8
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +5 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/withdrawal-period.ts +8 -10
- package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
- package/packages/bundled-features/src/billing-foundation/events.ts +23 -21
- package/packages/bundled-features/src/billing-foundation/feature.ts +45 -44
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
- package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +71 -6
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +19 -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/plan-switch-preview.query.ts +65 -0
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +29 -22
- package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +44 -8
- package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +72 -82
- package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +14 -1
- package/packages/bundled-features/src/billing-foundation/i18n.ts +22 -0
- package/packages/bundled-features/src/billing-foundation/index.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +62 -27
- package/packages/bundled-features/src/billing-foundation/plan-switch.ts +84 -0
- 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 +144 -66
- package/packages/bundled-features/src/billing-foundation/validate-options.ts +19 -0
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +123 -51
- package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +89 -42
- package/packages/bundled-features/src/billing-foundation/web/constants.ts +4 -0
- package/packages/bundled-features/src/billing-foundation/web/plan-price.ts +55 -0
- package/packages/bundled-features/src/billing-foundation/web/plan-switch-confirm-dialog.tsx +224 -0
- 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/cap-reservation.ts +5 -1
- package/packages/bundled-features/src/cap-counter/changes.json +18 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +66 -68
- 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 +9 -2
- 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/changes.json +6 -0
- package/packages/bundled-features/src/channel-email/feature.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/changes.json +12 -0
- package/packages/bundled-features/src/config/handlers/cascade.query.ts +4 -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/handlers/values.query.ts +4 -2
- 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 +28 -9
- package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +23 -21
- 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/changes.json +30 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +9 -3
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +2 -2
- package/packages/bundled-features/src/delivery/delivery-service.ts +35 -5
- 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/handlers/preferences.query.ts +20 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-page-chrome.query.ts +1 -1
- package/packages/bundled-features/src/delivery/tables.ts +9 -8
- package/packages/bundled-features/src/delivery/unsubscribe-link.ts +3 -1
- package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +1 -0
- package/packages/bundled-features/src/delivery/unsubscribe-page.ts +6 -0
- package/packages/bundled-features/src/delivery/unsubscribe.ts +40 -19
- 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-foundation/index.ts +1 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -1
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/env-named-feature.ts +0 -2
- 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/README.md +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +3 -3
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
- package/packages/bundled-features/src/form-draft/decrypt-draft.ts +4 -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/host-routing/README.md +1 -1
- package/packages/bundled-features/src/host-routing/changes.json +6 -0
- package/packages/bundled-features/src/host-routing/dispatch.ts +16 -17
- package/packages/bundled-features/src/host-routing/options.ts +2 -1
- package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
- package/packages/bundled-features/src/inbound-mail-foundation/changes.json +18 -0
- 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 +27 -15
- package/packages/bundled-features/src/inbound-mail-foundation/i18n.ts +0 -1
- 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/screens.ts +0 -3
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +70 -70
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +101 -84
- 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/changes.json +13 -0
- 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 +20 -11
- 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/handlers/tenant-failures.query.ts +45 -40
- package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +63 -59
- package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +19 -19
- 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/README.md +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/mail-foundation/feature.ts +31 -30
- 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 +9 -6
- 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/renderer-pdf/changes.json +6 -0
- package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +27 -10
- 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 +16 -11
- 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 +11 -1
- package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
- package/packages/bundled-features/src/shared/index.ts +1 -1
- package/packages/bundled-features/src/shared/mail-template-body.ts +10 -3
- 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/step-dispatcher/changes.json +6 -0
- package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -0
- package/packages/bundled-features/src/subscription-dodo/changes.json +14 -0
- package/packages/bundled-features/src/subscription-dodo/client.ts +45 -0
- package/packages/bundled-features/src/subscription-dodo/constants.ts +24 -0
- package/packages/bundled-features/src/subscription-dodo/feature.ts +207 -0
- package/packages/bundled-features/src/subscription-dodo/index.ts +16 -0
- package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +345 -0
- package/packages/bundled-features/src/subscription-dodo/runtime.ts +126 -0
- package/packages/bundled-features/src/subscription-dodo/verify-webhook.ts +262 -0
- 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/changes.json +12 -0
- package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
- package/packages/bundled-features/src/subscription-stripe/feature.ts +45 -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 +9 -8
- 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 +41 -14
- package/packages/bundled-features/src/template-resolver/changes.json +48 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -0
- package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +27 -5
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +8 -7
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +19 -20
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +15 -5
- 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/tenant-override-counts.query.ts +9 -5
- package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +8 -6
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +44 -5
- 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/handlers/usage.query.ts +37 -26
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +7 -2
- package/packages/bundled-features/src/template-resolver/seeding.ts +36 -18
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +22 -4
- package/packages/bundled-features/src/template-resolver/table.ts +13 -14
- package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +0 -11
- package/packages/bundled-features/src/template-resolver/template-meta.ts +12 -4
- package/packages/bundled-features/src/template-resolver/template-preview.ts +11 -3
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
- package/packages/bundled-features/src/template-resolver/web/constants.ts +7 -5
- package/packages/bundled-features/src/template-resolver/web/index.ts +7 -0
- package/packages/bundled-features/src/template-resolver/web/mail-layout-constants.ts +8 -0
- package/packages/bundled-features/src/tenant/changes.json +6 -0
- package/packages/bundled-features/src/tenant/feature.ts +7 -7
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +10 -4
- 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 +8 -5
- 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/changes.json +6 -0
- package/packages/bundled-features/src/tenant-lifecycle/constants.ts +5 -0
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +7 -3
- 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/changes.json +6 -0
- 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 +12 -9
- 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/constants.ts +3 -3
- 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 +169 -280
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +87 -108
- 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/waitlist/changes.json +18 -0
- package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +2 -1
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +5 -5
- package/packages/bundled-features/src/waitlist/import.ts +5 -0
- package/packages/bundled-features/src/waitlist/legacy-migrate.ts +22 -3
- package/packages/bundled-features/src/waitlist/link-on-signup.ts +20 -10
- package/packages/bundled-features/src/waitlist/options.ts +3 -0
- 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
- package/samples/apps/styleguide/src/features/widgets/i18n.ts +11 -0
- package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +24 -0
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-constants.ts +5 -0
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +90 -15
- package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +16 -6
- package/samples/apps/use-all-bundled/feature-manifest.json +120 -3
- package/samples/apps/use-all-bundled/src/run-config.ts +9 -3
- package/samples/recipes/auth-mfa/README.md +5 -0
- package/samples/recipes/auth-mfa/package.json +5 -2
- package/samples/recipes/auth-mfa/src/web/confirmation-code-step.tsx +49 -0
- package/samples/recipes/auth-mfa/tsconfig.json +8 -0
- package/samples/recipes/env-composition/README.md +3 -1
- package/samples/recipes/env-composition/src/env.ts +2 -0
- package/samples/recipes/legal-pages/README.md +1 -1
- package/samples/recipes/rate-limiting/README.md +18 -0
- package/samples/recipes/rate-limiting/src/feature.ts +12 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +0 -12
|
@@ -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
|
|
|
5
5
|
import {
|
|
6
6
|
BlockedHostError,
|
|
@@ -95,9 +95,9 @@ export async function createImapClient(
|
|
|
95
95
|
|
|
96
96
|
/** Server-Fehler → typisierte Foundation-Fehlerklassen (Plan §2). */
|
|
97
97
|
export function mapImapError(err: unknown, host: string): Error {
|
|
98
|
-
// imapflow
|
|
99
|
-
// message
|
|
100
|
-
// authenticationFailed
|
|
98
|
+
// imapflow errors carry the server response in responseText; the
|
|
99
|
+
// message is only "Command failed", so both are included in the match;
|
|
100
|
+
// authenticationFailed is the reliable flag.
|
|
101
101
|
const carrier = isPlainObject(err) ? err : undefined;
|
|
102
102
|
const responseText = typeof carrier?.["responseText"] === "string" ? carrier["responseText"] : "";
|
|
103
103
|
const msg = `${err instanceof Error ? err.message : String(err)} ${responseText}`.trim();
|
|
@@ -129,9 +129,9 @@ export function parseImapCursor(cursor: SyncCursorPayload | null): ImapCursor |
|
|
|
129
129
|
return { uidValidity, lastUid };
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
132
|
+
/** Throws InboundCursorInvalidError when UIDVALIDITY changes; the
|
|
133
|
+
* foundation resets the cursor and performs a full resync within the
|
|
134
|
+
* backfill window (deduplication catches duplicates). */
|
|
135
135
|
export function assertUidValidity(cursor: ImapCursor | null, serverUidValidity: string): void {
|
|
136
136
|
if (cursor && cursor.uidValidity !== serverUidValidity) {
|
|
137
137
|
throw new InboundCursorInvalidError(
|
|
@@ -148,8 +148,9 @@ function stripAngles(id: string): string {
|
|
|
148
148
|
return id.replace(/^<|>$/g, "").trim();
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
/** References
|
|
152
|
-
* | undefined;
|
|
151
|
+
/** Normalizes the References chain: mailparser returns string | string[]
|
|
152
|
+
* | undefined; when References is missing, In-Reply-To provides the thread
|
|
153
|
+
* anchor. */
|
|
153
154
|
export function normalizeReferences(parsed: {
|
|
154
155
|
references?: string | string[];
|
|
155
156
|
inReplyTo?: string;
|
|
@@ -170,16 +171,16 @@ function addressList(a: AddressObject | AddressObject[] | undefined): string[] {
|
|
|
170
171
|
return arr.map((x) => x.text).filter((t): t is string => Boolean(t));
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
/** imapflow
|
|
174
|
-
*
|
|
175
|
-
* no-date-api)
|
|
176
|
-
* Date
|
|
174
|
+
/** imapflow provides internalDate as either a Date or string depending on
|
|
175
|
+
* the code path. The string form is deliberately discarded (no date parsing
|
|
176
|
+
* in feature code, no-date-api); toRawInboundMessage then falls back to the
|
|
177
|
+
* mailparser Date header, which is always a real Date. */
|
|
177
178
|
export function coerceDate(d: Date | string | undefined): Date | undefined {
|
|
178
179
|
return d instanceof Date ? d : undefined;
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
/** providerMessageId: UID
|
|
182
|
-
*
|
|
182
|
+
/** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
|
|
183
|
+
* they form the stable idempotency anchor. */
|
|
183
184
|
export function buildProviderMessageId(uidValidity: string, uid: number): string {
|
|
184
185
|
return `${uidValidity}:${uid}`;
|
|
185
186
|
}
|
|
@@ -204,8 +205,8 @@ export async function toRawInboundMessage(args: {
|
|
|
204
205
|
cc: addressList(parsed.cc),
|
|
205
206
|
subject: parsed.subject ?? "",
|
|
206
207
|
snippet: text.slice(0, SNIPPET_MAX),
|
|
207
|
-
// Lib-
|
|
208
|
-
//
|
|
208
|
+
// Lib-boundary bridge (Date from imapflow/mailparser) → Temporal;
|
|
209
|
+
// when no date exists, Epoch is the honest marker.
|
|
209
210
|
receivedAtIso: (receivedAt
|
|
210
211
|
? legacyDateToInstant(receivedAt)
|
|
211
212
|
: Temporal.Instant.fromEpochMilliseconds(0)
|
|
@@ -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
|
|
|
14
14
|
import type {
|
|
15
15
|
InboundFetchResult,
|
|
@@ -24,8 +24,8 @@ const FEATURE_NAME = "inbound-provider-inmemory";
|
|
|
24
24
|
export const INMEMORY_PROVIDER_KEY = "inmemory";
|
|
25
25
|
|
|
26
26
|
// =============================================================================
|
|
27
|
-
// Module-level
|
|
28
|
-
//
|
|
27
|
+
// Module-level state — per account: an append-only message log, like a real
|
|
28
|
+
// mailbox; active watch handlers and one-shot error injection.
|
|
29
29
|
// =============================================================================
|
|
30
30
|
|
|
31
31
|
type WatchHandlers = {
|
|
@@ -51,28 +51,28 @@ function stateFor(accountId: string): AccountState {
|
|
|
51
51
|
return state;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/** Test
|
|
55
|
-
*
|
|
56
|
-
* cursor
|
|
54
|
+
/** Test helper: adds a message to the mailbox. If a watch is active, it is
|
|
55
|
+
* pushed immediately (IDLE simulation); the next fetch also returns it by
|
|
56
|
+
* cursor — the foundation's deduplication makes this idempotent. */
|
|
57
57
|
export async function seedInboundMessage(accountId: string, msg: RawInboundMessage): Promise<void> {
|
|
58
58
|
const state = stateFor(accountId);
|
|
59
59
|
state.log.push(msg);
|
|
60
60
|
if (state.watch) await state.watch.onMessages([msg]);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/** Test
|
|
64
|
-
* InboundAuthError
|
|
63
|
+
/** Test helper: injects a one-shot error into the next fetch (e.g.
|
|
64
|
+
* InboundAuthError or InboundCursorInvalidError). */
|
|
65
65
|
export function failNextFetchWith(accountId: string, err: unknown): void {
|
|
66
66
|
stateFor(accountId).nextFetchError = err;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/** Test
|
|
69
|
+
/** Test helper: injects a one-shot error into the next verify. */
|
|
70
70
|
export function failNextVerifyWith(accountId: string, err: unknown): void {
|
|
71
71
|
stateFor(accountId).nextVerifyError = err;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/** Test
|
|
75
|
-
*
|
|
74
|
+
/** Test helper: simulates the live connection terminating (the supervisor
|
|
75
|
+
* must restart with backoff). */
|
|
76
76
|
export function emitWatchError(accountId: string, err: unknown): void {
|
|
77
77
|
const state = accounts.get(accountId);
|
|
78
78
|
if (state?.watch) {
|
|
@@ -82,7 +82,7 @@ export function emitWatchError(accountId: string, err: unknown): void {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/** Test
|
|
85
|
+
/** Test helper: reports whether an account currently has an active watch. */
|
|
86
86
|
export function isWatching(accountId: string): boolean {
|
|
87
87
|
return accounts.get(accountId)?.watch != null;
|
|
88
88
|
}
|
|
@@ -94,7 +94,7 @@ export function resetInboundInMemory(): void {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// =============================================================================
|
|
97
|
-
// Plugin — cursor = { offset: number }
|
|
97
|
+
// Plugin — cursor = { offset: number } over the append-only log.
|
|
98
98
|
// =============================================================================
|
|
99
99
|
|
|
100
100
|
function offsetOf(cursor: SyncCursorPayload | null): number {
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.388.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "readRoles for tenant job status",
|
|
6
|
+
"detail": "`createJobsFeature({ readRoles: [\"PropertyManager\"] })` lets those app roles call `jobs:query:failures` and `jobs:query:tenant-runs` for their own tenant. They are added to the default `User`, `Editor` and admin roles, which stay. Before, a member who only holds app roles got access_denied.",
|
|
7
|
+
"migration": "Optional. Apps whose members hold only their own roles pass `createJobsFeature({ readRoles: [...] })`."
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"version": "0.388.0",
|
|
11
|
+
"type": "fix",
|
|
12
|
+
"title": "Deduplicated job add keeps the finished tenant run row",
|
|
13
|
+
"detail": "JobQueuedMeta carries the BullMQ creation time of the job. The queued hook only removes finished rows queued before that time (leftovers of a Redis reset), so re-announcing an already finished job no longer turns its row back into queued."
|
|
14
|
+
},
|
|
2
15
|
{
|
|
3
16
|
"version": "0.384.0",
|
|
4
17
|
"type": "improvement",
|
|
@@ -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
|
|
@@ -44,7 +44,7 @@ export async function deleteStaleJobRuns(
|
|
|
44
44
|
{ limit: RETENTION_DELETE_BATCH_SIZE },
|
|
45
45
|
);
|
|
46
46
|
|
|
47
|
-
// Same window for the tenant-visible failure records
|
|
47
|
+
// Same window for the tenant-visible failure records: the run
|
|
48
48
|
// they point at is gone by now, and a job whose subject never ran again
|
|
49
49
|
// would otherwise keep its record forever.
|
|
50
50
|
const tenantFailuresResult = await deleteManyBatched(
|
|
@@ -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
|
|
@@ -48,7 +48,7 @@ export async function markStaleJobRunsFailed(
|
|
|
48
48
|
// user subject annotation as job-run-logger.ts's onJobFailed path
|
|
49
49
|
// (personal: { of: "triggeredById" } on job-run-table.ts), so it is encrypted
|
|
50
50
|
// under the triggering user's DEK, or the system tenant key when
|
|
51
|
-
// triggeredById is null (whenAbsent: "tenant"
|
|
51
|
+
// triggeredById is null (whenAbsent: "tenant"). Runs are grouped by
|
|
52
52
|
// that subject: one encrypt and one updateMany per subject instead of per run.
|
|
53
53
|
const stale = await selectMany<{ id: string; triggeredById: string | null }>(db, jobRunsTable, {
|
|
54
54
|
status: "running",
|
|
@@ -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
|
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
createStaleRunSweepJob,
|
|
24
24
|
DEFAULT_JOB_RUN_STALE_TIMEOUT_HOURS,
|
|
25
25
|
} from "./handlers/stale-run-sweep.job.ts";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import { createTenantFailuresQuery } from "./handlers/tenant-failures.query.ts";
|
|
27
|
+
import { createTenantRunsQuery } from "./handlers/tenant-runs.query.ts";
|
|
28
28
|
import { triggerWrite } from "./handlers/trigger.write.ts";
|
|
29
29
|
import { jobRunLogsTableMeta, jobRunsTableMeta } from "./job-run-table.ts";
|
|
30
30
|
import {
|
|
@@ -44,16 +44,26 @@ export type JobsFeatureOptions = {
|
|
|
44
44
|
// which a tenant-visible "queued" row counts as lost and is dropped by the stale-run sweep.
|
|
45
45
|
readonly retentionDays?: number;
|
|
46
46
|
// How long a run can sit at status "running" before the hourly
|
|
47
|
-
// stale-run-sweep job marks it "failed"
|
|
47
|
+
// stale-run-sweep job marks it "failed" — a process kill mid-run
|
|
48
48
|
// never fires onJobComplete/onJobFailed, so nothing else ever revisits
|
|
49
49
|
// it). Must clear any legitimately long-running job (reindexEntity,
|
|
50
50
|
// projectionRebuild) — set high, not tight.
|
|
51
51
|
readonly staleRunTimeoutHours?: number;
|
|
52
|
+
// Additional app roles that may read their own tenant's job status and
|
|
53
|
+
// failures (jobs:query:failures, jobs:query:tenant-runs). Added to the default
|
|
54
|
+
// User/Editor/admin roles, which stay; the scope stays the caller's own tenant.
|
|
55
|
+
readonly readRoles?: readonly string[];
|
|
52
56
|
};
|
|
53
57
|
|
|
54
58
|
export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefinition {
|
|
55
59
|
const retentionDays = options.retentionDays ?? DEFAULT_JOB_RUN_RETENTION_DAYS;
|
|
56
60
|
const staleRunTimeoutHours = options.staleRunTimeoutHours ?? DEFAULT_JOB_RUN_STALE_TIMEOUT_HOURS;
|
|
61
|
+
const readRoles = options.readRoles ?? [];
|
|
62
|
+
if (readRoles.includes("anonymous")) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`createJobsFeature: readRoles must not contain "anonymous" — job status and failures are only readable by members of the tenant.`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
57
67
|
return defineFeature("jobs", (r) => {
|
|
58
68
|
r.describe(
|
|
59
69
|
"Persistence and operator tooling for background jobs registered via `r.job(...)`. Every job execution writes directly into `store_job_runs` (current status + duration) and `store_job_run_logs` (per-line log rows) from the BullMQ callbacks — no event stream in between (#2243). A daily `retention-cleanup` job deletes runs (and their logs) older than `retentionDays`; an hourly `stale-run-sweep` job marks runs stuck at status `running` past `staleRunTimeoutHours` as `failed` (#2246 — a crashed worker never fires the completion callback, so nothing else ever revisits the row). Exposes `jobs:write:trigger` (manual run) and `jobs:write:retry` (operator retry of a failed run), plus `jobs:query:list`, `jobs:query:details`, and `jobs:query:catalog` (manual jobs) for the operator UI. A job that declares `tenantVisibleFailure` also records its last failed attempt per tenant and subject in `store_tenant_job_failures`, which the tenant itself reads through `jobs:query:failures` — a translation key only, never the provider's message (fw#3079). A job that declares `tenantVisibleRun` also keeps its run state per tenant and subject in `store_tenant_job_runs` (queued, running, plus the latest completed or failed run, no payload, error text or logs), which the tenant reads through `jobs:query:tenant-runs` (fw#3616); the stale-run sweep fails its stuck `running` rows and drops `queued` rows older than `retentionDays`.",
|
|
@@ -67,11 +77,10 @@ export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefi
|
|
|
67
77
|
r.storeTable(jobRunsTableMeta, {
|
|
68
78
|
reason: "direct_write.job_runs",
|
|
69
79
|
// payload/error carry personal:{of:"triggeredById"} (job-run-table.ts): encrypted under the
|
|
70
|
-
// triggering user's DEK, or the system tenant key when triggeredById is null
|
|
71
|
-
// (whenAbsent: "tenant", fw#3654).
|
|
80
|
+
// triggering user's DEK, or the system tenant key when triggeredById is null.
|
|
72
81
|
// job-run-logger.ts manually encrypts both before every insert/update
|
|
73
82
|
// (encryptStartedPayload/encryptFailureError) since this store bypasses
|
|
74
|
-
// the executor's automatic PII pipeline
|
|
83
|
+
// the executor's automatic PII pipeline.
|
|
75
84
|
piiEncryptedOnWrite: true,
|
|
76
85
|
});
|
|
77
86
|
r.storeTable(jobRunLogsTableMeta, {
|
|
@@ -91,7 +100,7 @@ export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefi
|
|
|
91
100
|
projectionRebuildJob,
|
|
92
101
|
);
|
|
93
102
|
|
|
94
|
-
// Retroactive search backfill
|
|
103
|
+
// Retroactive search backfill — manual + perTenant, so one
|
|
95
104
|
// `jobs:write:trigger` call with { entity } fans out to every active
|
|
96
105
|
// tenant (job-runner.ts perTenant dispatch applies to manual triggers
|
|
97
106
|
// too, not just cron).
|
|
@@ -107,7 +116,7 @@ export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefi
|
|
|
107
116
|
);
|
|
108
117
|
|
|
109
118
|
// store_job_runs/store_job_run_logs are direct-write, unbounded-growth
|
|
110
|
-
// stores
|
|
119
|
+
// stores — nothing else purges them.
|
|
111
120
|
r.job(
|
|
112
121
|
"retention-cleanup",
|
|
113
122
|
{ trigger: { cron: "0 3 * * *" }, concurrency: "skip" },
|
|
@@ -115,7 +124,7 @@ export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefi
|
|
|
115
124
|
);
|
|
116
125
|
|
|
117
126
|
// Sweeps store_job_runs for rows stuck at status "running" past the
|
|
118
|
-
// timeout
|
|
127
|
+
// timeout. Hourly matches the timeout's own granularity —
|
|
119
128
|
// frequent enough to catch a stuck run soon after it crosses the
|
|
120
129
|
// threshold, cheap enough that an (almost always empty) result set
|
|
121
130
|
// doesn't matter.
|
|
@@ -138,8 +147,8 @@ export function createJobsFeature(options: JobsFeatureOptions = {}): FeatureDefi
|
|
|
138
147
|
list: r.queryHandler(listQuery),
|
|
139
148
|
detail: r.queryHandler(detailQuery),
|
|
140
149
|
catalog: r.queryHandler(catalogQuery),
|
|
141
|
-
failures: r.queryHandler(
|
|
142
|
-
tenantRuns: r.queryHandler(
|
|
150
|
+
failures: r.queryHandler(createTenantFailuresQuery(readRoles)),
|
|
151
|
+
tenantRuns: r.queryHandler(createTenantRunsQuery(readRoles)),
|
|
143
152
|
consumers: r.queryHandler(consumersQuery),
|
|
144
153
|
consumerDetails: r.queryHandler(consumerDetailQuery),
|
|
145
154
|
};
|
|
@@ -32,12 +32,12 @@ export const detailQuery = defineQueryHandler({
|
|
|
32
32
|
|
|
33
33
|
if (!row) return null;
|
|
34
34
|
|
|
35
|
-
// payload is stored encrypted under the triggering user's DEK
|
|
35
|
+
// payload is stored encrypted under the triggering user's DEK.
|
|
36
36
|
if (typeof row["payload"] === "string") {
|
|
37
37
|
row["payload"] = await decryptStoredPii(row["payload"], "payload", "job-run-detail");
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// error is stored encrypted under the triggering user's DEK
|
|
40
|
+
// error is stored encrypted under the triggering user's DEK,
|
|
41
41
|
// same mechanism as row.payload above.
|
|
42
42
|
if (typeof row["error"] === "string") {
|
|
43
43
|
row["error"] = await decryptStoredPii(row["error"], "error", "job-run-detail");
|
|
@@ -52,8 +52,8 @@ export const detailQuery = defineQueryHandler({
|
|
|
52
52
|
},
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
-
// message is stored encrypted under the triggering user's DEK
|
|
56
|
-
// same mechanism as row.payload above. Bounded concurrency
|
|
55
|
+
// message is stored encrypted under the triggering user's DEK,
|
|
56
|
+
// same mechanism as row.payload above. Bounded concurrency —
|
|
57
57
|
// unbounded Promise.all would fire one decrypt per log line at once
|
|
58
58
|
// against the KMS adapter's pool.
|
|
59
59
|
const decryptedLogs = await mapWithConcurrency(logs, KMS_POOL_CONCURRENCY, async (log) => {
|
|
@@ -109,7 +109,7 @@ export const listQuery = defineQueryHandler({
|
|
|
109
109
|
// capped at the page size and would silently undercount the total.
|
|
110
110
|
const total =
|
|
111
111
|
query.payload.totalCount === true ? await countWhere(db, jobRunsTable, where) : undefined;
|
|
112
|
-
// payload/error are stored encrypted under the triggering user's DEK
|
|
112
|
+
// payload/error are stored encrypted under the triggering user's DEK.
|
|
113
113
|
return {
|
|
114
114
|
rows: await mapWithConcurrency(rows, KMS_POOL_CONCURRENCY, decryptRunRow),
|
|
115
115
|
nextCursor: hasMore ? encodeCursor(String(offset + limit)) : null,
|
|
@@ -8,7 +8,7 @@ import * as z from "zod";
|
|
|
8
8
|
|
|
9
9
|
export const projectionRebuildPayloadSchema = z.object({
|
|
10
10
|
projection: z.string().min(1),
|
|
11
|
-
// Quarantine mode
|
|
11
|
+
// Quarantine mode: skip + dead-letter poison events instead of
|
|
12
12
|
// failing the whole rebuild. Operator opt-in per run.
|
|
13
13
|
skipApplyErrors: z.boolean().optional(),
|
|
14
14
|
});
|
|
@@ -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
|
|
@@ -58,7 +58,7 @@ export const retryWrite = defineWriteHandler({
|
|
|
58
58
|
);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
// payload is stored encrypted under the triggering user's DEK
|
|
61
|
+
// payload is stored encrypted under the triggering user's DEK,
|
|
62
62
|
// same mechanism as detail.query.ts/list.query.ts — decrypt before
|
|
63
63
|
// parsing it as JSON. A key erased since the run finished decrypts to
|
|
64
64
|
// PII_ERASED_SENTINEL, which is not JSON; reject the retry rather than
|
|
@@ -30,44 +30,49 @@ function parseSubject(stored: string | null): Record<string, unknown> | null {
|
|
|
30
30
|
return Object.fromEntries(parsed.filter(isSubjectEntry));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
export function createTenantFailuresQuery(readRoles: readonly string[]) {
|
|
34
|
+
return defineQueryHandler({
|
|
35
|
+
name: "failures",
|
|
36
|
+
description:
|
|
37
|
+
"Lists the calling tenant's own failed jobs — one record per job and subject, newest first, each carrying a translation key for the reason, never the provider's own error message; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to tell a tenant that their asynchronous job failed instead of leaving the screen waiting.",
|
|
38
|
+
schema: z.object({
|
|
39
|
+
jobName: z.string().optional(),
|
|
40
|
+
subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
41
|
+
limit: z.number().int().min(1).max(200).optional(),
|
|
42
|
+
}),
|
|
43
|
+
// Every membership rank: a failure record carries a job name and a
|
|
44
|
+
// translation key, nothing a team member of the tenant may not see.
|
|
45
|
+
access: {
|
|
46
|
+
roles: [...new Set([...access.roles("User", "Editor", ...access.admin), ...readRoles])],
|
|
47
|
+
},
|
|
48
|
+
handler: async (query, ctx) => {
|
|
49
|
+
if (!ctx.systemDb) {
|
|
50
|
+
throw new InternalError({
|
|
51
|
+
message:
|
|
52
|
+
"jobs:query:failures requires ctx.systemDb (feature must declare r.systemScope())",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// assertTenantMatch is a self-check on the caller and returns the same
|
|
56
|
+
// unfiltered system-mode db (tenant-db.ts) — the explicit tenantId below
|
|
57
|
+
// is the filter, assertRowsTenant the second net. There is no
|
|
58
|
+
// cross-tenant mode here: SystemAdmin reads runs via jobs:query:list.
|
|
59
|
+
const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
|
|
60
|
+
const where: Record<string, unknown> = { tenantId: [query.user.tenantId] };
|
|
61
|
+
if (query.payload.jobName) where["jobName"] = query.payload.jobName;
|
|
62
|
+
if (query.payload.subject) where["subject"] = serializeJobSubject(query.payload.subject);
|
|
63
|
+
const rows = await selectMany<TenantJobFailureRow>(db, tenantJobFailuresTable, where, {
|
|
64
|
+
orderBy: { col: "failedAt", direction: "desc" },
|
|
65
|
+
limit: query.payload.limit ?? DEFAULT_LIMIT,
|
|
49
66
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
return {
|
|
64
|
-
rows: ctx.systemDb.assertRowsTenant(rows, "tenantId").map((row) => ({
|
|
65
|
-
jobName: row.jobName,
|
|
66
|
-
subject: parseSubject(row.subject),
|
|
67
|
-
messageKey: row.messageKey,
|
|
68
|
-
failedAt: row.failedAt,
|
|
69
|
-
})),
|
|
70
|
-
nextCursor: null,
|
|
71
|
-
};
|
|
72
|
-
},
|
|
73
|
-
});
|
|
67
|
+
return {
|
|
68
|
+
rows: ctx.systemDb.assertRowsTenant(rows, "tenantId").map((row) => ({
|
|
69
|
+
jobName: row.jobName,
|
|
70
|
+
subject: parseSubject(row.subject),
|
|
71
|
+
messageKey: row.messageKey,
|
|
72
|
+
failedAt: row.failedAt,
|
|
73
|
+
})),
|
|
74
|
+
nextCursor: null,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -32,63 +32,67 @@ function parseSubject(stored: string | null): Record<string, unknown> | null {
|
|
|
32
32
|
return Object.fromEntries(parsed.filter(isSubjectEntry));
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
export function createTenantRunsQuery(readRoles: readonly string[]) {
|
|
36
|
+
return defineQueryHandler({
|
|
37
|
+
name: "tenant-runs",
|
|
38
|
+
description:
|
|
39
|
+
"Lists the calling tenant's own job runs that opted in via tenantVisibleRun — per job and subject every queued or running run plus the latest completed or failed one, active runs first, then newest first; each row carries only status and queuedAt/startedAt/finishedAt, never payloads, error text or logs; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to show whether work for a subject is waiting, running or done, and to tell a failed run from a finished one.",
|
|
40
|
+
schema: z.object({
|
|
41
|
+
jobName: z.string().optional(),
|
|
42
|
+
subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
43
|
+
limit: z.number().int().min(1).max(200).optional(),
|
|
44
|
+
}),
|
|
45
|
+
// Every membership rank: a run state carries a job name, a status and
|
|
46
|
+
// times, nothing a team member of the tenant may not see.
|
|
47
|
+
access: {
|
|
48
|
+
roles: [...new Set([...access.roles("User", "Editor", ...access.admin), ...readRoles])],
|
|
49
|
+
},
|
|
50
|
+
handler: async (query, ctx) => {
|
|
51
|
+
if (!ctx.systemDb) {
|
|
52
|
+
throw new InternalError({
|
|
53
|
+
message:
|
|
54
|
+
"jobs:query:tenant-runs requires ctx.systemDb (feature must declare r.systemScope())",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// assertTenantMatch returns the same unfiltered system-mode db — the
|
|
58
|
+
// explicit tenantId below is the filter, assertRowsTenant the second net.
|
|
59
|
+
const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
|
|
60
|
+
const where: Record<string, unknown> = { tenantId: [query.user.tenantId] };
|
|
61
|
+
if (query.payload.jobName) where["jobName"] = query.payload.jobName;
|
|
62
|
+
if (query.payload.subject) where["subject"] = serializeJobSubject(query.payload.subject);
|
|
63
|
+
const limit = query.payload.limit ?? DEFAULT_LIMIT;
|
|
64
|
+
const newestFirst = { col: "updatedAt", direction: "desc" } as const;
|
|
65
|
+
const activeRows = await selectMany<TenantJobRunRow>(
|
|
66
|
+
db,
|
|
67
|
+
tenantJobRunsTable,
|
|
68
|
+
{ ...where, status: { in: ["queued", "running"] } },
|
|
69
|
+
{ orderBy: newestFirst, limit },
|
|
70
|
+
);
|
|
71
|
+
const finishedRows = await selectMany<TenantJobRunRow>(
|
|
72
|
+
db,
|
|
73
|
+
tenantJobRunsTable,
|
|
74
|
+
{ ...where, status: { in: ["completed", "failed"] } },
|
|
75
|
+
{ orderBy: newestFirst, limit },
|
|
76
|
+
);
|
|
77
|
+
const seenFinishedKeys = new Set<string>();
|
|
78
|
+
const finishedNewestPerKey = finishedRows.filter((row) => {
|
|
79
|
+
const key = JSON.stringify([row.jobName, row.subject]);
|
|
80
|
+
if (seenFinishedKeys.has(key)) return false;
|
|
81
|
+
seenFinishedKeys.add(key);
|
|
82
|
+
return true;
|
|
52
83
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const finishedRows = await selectMany<TenantJobRunRow>(
|
|
69
|
-
db,
|
|
70
|
-
tenantJobRunsTable,
|
|
71
|
-
{ ...where, status: { in: ["completed", "failed"] } },
|
|
72
|
-
{ orderBy: newestFirst, limit },
|
|
73
|
-
);
|
|
74
|
-
const seenFinishedKeys = new Set<string>();
|
|
75
|
-
const finishedNewestPerKey = finishedRows.filter((row) => {
|
|
76
|
-
const key = JSON.stringify([row.jobName, row.subject]);
|
|
77
|
-
if (seenFinishedKeys.has(key)) return false;
|
|
78
|
-
seenFinishedKeys.add(key);
|
|
79
|
-
return true;
|
|
80
|
-
});
|
|
81
|
-
const activeFirst = [...activeRows, ...finishedNewestPerKey];
|
|
82
|
-
return {
|
|
83
|
-
rows: ctx.systemDb.assertRowsTenant(activeFirst.slice(0, limit), "tenantId").map((row) => ({
|
|
84
|
-
jobName: row.jobName,
|
|
85
|
-
subject: parseSubject(row.subject),
|
|
86
|
-
status: row.status,
|
|
87
|
-
queuedAt: row.queuedAt,
|
|
88
|
-
startedAt: row.startedAt,
|
|
89
|
-
finishedAt: row.finishedAt,
|
|
90
|
-
})),
|
|
91
|
-
nextCursor: null,
|
|
92
|
-
};
|
|
93
|
-
},
|
|
94
|
-
});
|
|
84
|
+
const activeFirst = [...activeRows, ...finishedNewestPerKey];
|
|
85
|
+
return {
|
|
86
|
+
rows: ctx.systemDb.assertRowsTenant(activeFirst.slice(0, limit), "tenantId").map((row) => ({
|
|
87
|
+
jobName: row.jobName,
|
|
88
|
+
subject: parseSubject(row.subject),
|
|
89
|
+
status: row.status,
|
|
90
|
+
queuedAt: row.queuedAt,
|
|
91
|
+
startedAt: row.startedAt,
|
|
92
|
+
finishedAt: row.finishedAt,
|
|
93
|
+
})),
|
|
94
|
+
nextCursor: null,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// The five value-position Temporal.Instant.from
|
|
4
4
|
// call sites in feature.ts live inside defineApply callbacks with no
|
|
5
5
|
// exported seam, so this thin wrapper gives the ambient-global-independence
|
|
6
6
|
// regression test something to import directly.
|