@cosmicdrift/kumiko-samples 0.338.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 +57 -0
- package/README.md +14 -0
- package/package.json +34 -0
- package/packages/bundled-features/package.json +647 -0
- package/packages/bundled-features/src/admin-shell/changes.json +27 -0
- package/packages/bundled-features/src/admin-shell/constants.ts +11 -0
- package/packages/bundled-features/src/admin-shell/feature.ts +184 -0
- package/packages/bundled-features/src/admin-shell/i18n.ts +54 -0
- package/packages/bundled-features/src/admin-shell/index.ts +17 -0
- package/packages/bundled-features/src/admin-shell/overview-allowlist.ts +47 -0
- package/packages/bundled-features/src/admin-shell/overview-panels.ts +225 -0
- package/packages/bundled-features/src/admin-shell/web/client-plugin.tsx +16 -0
- package/packages/bundled-features/src/admin-shell/web/i18n.ts +11 -0
- package/packages/bundled-features/src/admin-shell/web/index.ts +2 -0
- package/packages/bundled-features/src/agent-tools/agent-doc-lint.ts +166 -0
- package/packages/bundled-features/src/agent-tools/agent-manifest.ts +460 -0
- package/packages/bundled-features/src/agent-tools/changes.json +40 -0
- package/packages/bundled-features/src/agent-tools/feature.ts +36 -0
- package/packages/bundled-features/src/agent-tools/filter-ops.ts +5 -0
- package/packages/bundled-features/src/agent-tools/index.ts +25 -0
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +658 -0
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +374 -0
- package/packages/bundled-features/src/agent-tools/types.ts +222 -0
- package/packages/bundled-features/src/audit/changes.json +40 -0
- package/packages/bundled-features/src/audit/constants.ts +26 -0
- package/packages/bundled-features/src/audit/escape-hatch-audit-sink.ts +52 -0
- package/packages/bundled-features/src/audit/feature.ts +145 -0
- package/packages/bundled-features/src/audit/handlers/details.query.ts +49 -0
- package/packages/bundled-features/src/audit/handlers/list.query.ts +130 -0
- package/packages/bundled-features/src/audit/i18n.ts +22 -0
- package/packages/bundled-features/src/audit/index.ts +3 -0
- package/packages/bundled-features/src/audit/web/client-plugin.tsx +16 -0
- package/packages/bundled-features/src/audit/web/i18n.ts +8 -0
- package/packages/bundled-features/src/audit/web/index.ts +3 -0
- package/packages/bundled-features/src/auth-email-password/auth-paths.ts +28 -0
- package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +51 -0
- package/packages/bundled-features/src/auth-email-password/changes.json +143 -0
- package/packages/bundled-features/src/auth-email-password/constants.ts +146 -0
- package/packages/bundled-features/src/auth-email-password/email-templates.ts +198 -0
- package/packages/bundled-features/src/auth-email-password/errors.ts +112 -0
- package/packages/bundled-features/src/auth-email-password/feature.ts +269 -0
- package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +70 -0
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts +61 -0
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +148 -0
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +290 -0
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +195 -0
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +232 -0
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +90 -0
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +221 -0
- package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +344 -0
- package/packages/bundled-features/src/auth-email-password/handlers/logout.write.ts +16 -0
- package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +40 -0
- package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +37 -0
- package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +39 -0
- package/packages/bundled-features/src/auth-email-password/handlers/reset-password.write.ts +62 -0
- package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +26 -0
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +249 -0
- package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +229 -0
- package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +170 -0
- package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +62 -0
- package/packages/bundled-features/src/auth-email-password/i18n.ts +153 -0
- package/packages/bundled-features/src/auth-email-password/index.ts +47 -0
- package/packages/bundled-features/src/auth-email-password/invite-token-store.ts +78 -0
- package/packages/bundled-features/src/auth-email-password/lockout-store.ts +34 -0
- package/packages/bundled-features/src/auth-email-password/magic-link-mail.ts +87 -0
- package/packages/bundled-features/src/auth-email-password/password-policy.ts +2108 -0
- package/packages/bundled-features/src/auth-email-password/reset-token.ts +30 -0
- package/packages/bundled-features/src/auth-email-password/seeding.ts +368 -0
- package/packages/bundled-features/src/auth-email-password/self-registration-toggle.ts +25 -0
- package/packages/bundled-features/src/auth-email-password/signed-token.ts +4 -0
- package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +155 -0
- package/packages/bundled-features/src/auth-email-password/testing.ts +5 -0
- package/packages/bundled-features/src/auth-email-password/unlock-token.ts +28 -0
- package/packages/bundled-features/src/auth-email-password/verification-token.ts +29 -0
- package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +472 -0
- package/packages/bundled-features/src/auth-email-password/web/auth-form-logic.ts +40 -0
- package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +112 -0
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +179 -0
- package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +69 -0
- package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +96 -0
- package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +47 -0
- package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +111 -0
- package/packages/bundled-features/src/auth-email-password/web/index.ts +81 -0
- package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +272 -0
- package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +298 -0
- package/packages/bundled-features/src/auth-email-password/web/request-account-unlock-screen.tsx +112 -0
- package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +149 -0
- package/packages/bundled-features/src/auth-email-password/web/session-bootstrap-error.tsx +66 -0
- package/packages/bundled-features/src/auth-email-password/web/session.tsx +231 -0
- package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +181 -0
- package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +128 -0
- package/packages/bundled-features/src/auth-email-password/web/tenant-menu-items.tsx +47 -0
- package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +123 -0
- package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +37 -0
- package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +149 -0
- package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +99 -0
- package/packages/bundled-features/src/auth-foundation/boot-checks.ts +150 -0
- package/packages/bundled-features/src/auth-foundation/changes.json +20 -0
- package/packages/bundled-features/src/auth-foundation/feature.ts +157 -0
- package/packages/bundled-features/src/auth-foundation/index.ts +37 -0
- package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +62 -0
- package/packages/bundled-features/src/auth-foundation/types.ts +180 -0
- package/packages/bundled-features/src/auth-mfa/base32.ts +51 -0
- package/packages/bundled-features/src/auth-mfa/changes.json +62 -0
- package/packages/bundled-features/src/auth-mfa/config.ts +26 -0
- package/packages/bundled-features/src/auth-mfa/constants.ts +47 -0
- package/packages/bundled-features/src/auth-mfa/db/queries.ts +45 -0
- package/packages/bundled-features/src/auth-mfa/errors.ts +66 -0
- package/packages/bundled-features/src/auth-mfa/feature.ts +251 -0
- package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +83 -0
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +242 -0
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +123 -0
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +104 -0
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start.write.ts +95 -0
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +223 -0
- package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +88 -0
- package/packages/bundled-features/src/auth-mfa/handlers/status.query.ts +32 -0
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +203 -0
- package/packages/bundled-features/src/auth-mfa/hmac-token-codec.ts +79 -0
- package/packages/bundled-features/src/auth-mfa/i18n.ts +50 -0
- package/packages/bundled-features/src/auth-mfa/index.ts +30 -0
- package/packages/bundled-features/src/auth-mfa/mfa-challenge-token.ts +39 -0
- package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +45 -0
- package/packages/bundled-features/src/auth-mfa/mfa-preauth-setup-token.ts +38 -0
- package/packages/bundled-features/src/auth-mfa/mfa-setup-token.ts +96 -0
- package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +98 -0
- package/packages/bundled-features/src/auth-mfa/mfa-verify-attempts.ts +32 -0
- package/packages/bundled-features/src/auth-mfa/otpauth-uri.ts +21 -0
- package/packages/bundled-features/src/auth-mfa/recovery-codes.ts +54 -0
- package/packages/bundled-features/src/auth-mfa/schema/user-mfa.ts +65 -0
- package/packages/bundled-features/src/auth-mfa/screens.ts +124 -0
- package/packages/bundled-features/src/auth-mfa/testing.ts +5 -0
- package/packages/bundled-features/src/auth-mfa/token-secrets.ts +41 -0
- package/packages/bundled-features/src/auth-mfa/totp.ts +67 -0
- package/packages/bundled-features/src/auth-mfa/verify-factor.ts +58 -0
- package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +36 -0
- package/packages/bundled-features/src/auth-mfa/web/i18n.ts +66 -0
- package/packages/bundled-features/src/auth-mfa/web/index.ts +25 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +196 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +70 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-recovery-codes-reveal.tsx +53 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +69 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +269 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +117 -0
- package/packages/bundled-features/src/auth-mfa/web/qrcode-browser.d.ts +11 -0
- package/packages/bundled-features/src/auth-mfa-user-data/changes.json +1 -0
- package/packages/bundled-features/src/auth-mfa-user-data/hooks.ts +60 -0
- package/packages/bundled-features/src/auth-mfa-user-data/index.ts +21 -0
- package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +74 -0
- package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +95 -0
- package/packages/bundled-features/src/billing-foundation/changes.json +162 -0
- package/packages/bundled-features/src/billing-foundation/checkout-core.ts +395 -0
- package/packages/bundled-features/src/billing-foundation/constants.ts +237 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +170 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +140 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-locale.ts +18 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-text.ts +55 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +200 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +97 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +39 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +128 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +339 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +206 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +377 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +242 -0
- package/packages/bundled-features/src/billing-foundation/db/queries/payment-projection.ts +19 -0
- package/packages/bundled-features/src/billing-foundation/db/queries/subscription-projection.ts +15 -0
- package/packages/bundled-features/src/billing-foundation/entities.ts +132 -0
- package/packages/bundled-features/src/billing-foundation/events.ts +215 -0
- package/packages/bundled-features/src/billing-foundation/feature.ts +290 -0
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +58 -0
- package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +54 -0
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +132 -0
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +103 -0
- package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +37 -0
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +244 -0
- package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +122 -0
- package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +100 -0
- package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +109 -0
- package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +163 -0
- package/packages/bundled-features/src/billing-foundation/i18n.ts +133 -0
- package/packages/bundled-features/src/billing-foundation/index.ts +92 -0
- package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +235 -0
- package/packages/bundled-features/src/billing-foundation/projection.ts +227 -0
- package/packages/bundled-features/src/billing-foundation/screens.ts +25 -0
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +175 -0
- package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +81 -0
- package/packages/bundled-features/src/billing-foundation/types.ts +478 -0
- package/packages/bundled-features/src/billing-foundation/validate-options.ts +111 -0
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +361 -0
- package/packages/bundled-features/src/billing-foundation/web/cancel-contract-dialog.tsx +201 -0
- package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +146 -0
- package/packages/bundled-features/src/billing-foundation/web/client-plugin.tsx +21 -0
- package/packages/bundled-features/src/billing-foundation/web/index.ts +23 -0
- package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +165 -0
- package/packages/bundled-features/src/cap-counter/aggregate-id.ts +49 -0
- package/packages/bundled-features/src/cap-counter/book-cap-usage.ts +205 -0
- package/packages/bundled-features/src/cap-counter/changes.json +47 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +34 -0
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +415 -0
- package/packages/bundled-features/src/cap-counter/entity.ts +57 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +135 -0
- package/packages/bundled-features/src/cap-counter/handlers/get-counter.query.ts +37 -0
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +80 -0
- package/packages/bundled-features/src/cap-counter/handlers/increment.write.ts +51 -0
- package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +30 -0
- package/packages/bundled-features/src/cap-counter/i18n.ts +13 -0
- package/packages/bundled-features/src/cap-counter/index.ts +50 -0
- package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +80 -0
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +183 -0
- package/packages/bundled-features/src/cap-overview/access.ts +35 -0
- package/packages/bundled-features/src/cap-overview/changes.json +57 -0
- package/packages/bundled-features/src/cap-overview/constants.ts +26 -0
- package/packages/bundled-features/src/cap-overview/feature.ts +87 -0
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +109 -0
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +306 -0
- package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +35 -0
- package/packages/bundled-features/src/cap-overview/i18n.ts +31 -0
- package/packages/bundled-features/src/cap-overview/index.ts +21 -0
- package/packages/bundled-features/src/cap-overview/screens.ts +109 -0
- package/packages/bundled-features/src/cap-overview/types.ts +66 -0
- package/packages/bundled-features/src/cap-overview/usage-math.ts +34 -0
- package/packages/bundled-features/src/cap-overview/web/cap-cards-panel.tsx +119 -0
- package/packages/bundled-features/src/cap-overview/web/cap-usage-bar.tsx +56 -0
- package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +21 -0
- package/packages/bundled-features/src/cap-overview/web/client-plugin.tsx +27 -0
- package/packages/bundled-features/src/cap-overview/web/index.ts +10 -0
- package/packages/bundled-features/src/channel-email/changes.json +15 -0
- package/packages/bundled-features/src/channel-email/email-channel.ts +127 -0
- package/packages/bundled-features/src/channel-email/feature.ts +26 -0
- package/packages/bundled-features/src/channel-email/index.ts +10 -0
- package/packages/bundled-features/src/channel-email/pii-guard.ts +55 -0
- package/packages/bundled-features/src/channel-email/smtp-transport.ts +111 -0
- package/packages/bundled-features/src/channel-email/types.ts +43 -0
- package/packages/bundled-features/src/channel-in-app/changes.json +1 -0
- package/packages/bundled-features/src/channel-in-app/constants.ts +11 -0
- package/packages/bundled-features/src/channel-in-app/feature.ts +45 -0
- package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +30 -0
- package/packages/bundled-features/src/channel-in-app/handlers/mark-all-read.write.ts +27 -0
- package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +34 -0
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +29 -0
- package/packages/bundled-features/src/channel-in-app/in-app-channel.ts +41 -0
- package/packages/bundled-features/src/channel-in-app/index.ts +4 -0
- package/packages/bundled-features/src/channel-in-app/tables.ts +31 -0
- package/packages/bundled-features/src/channel-push/changes.json +1 -0
- package/packages/bundled-features/src/channel-push/feature.ts +25 -0
- package/packages/bundled-features/src/channel-push/index.ts +3 -0
- package/packages/bundled-features/src/channel-push/push-channel.ts +34 -0
- package/packages/bundled-features/src/channel-push/types.ts +22 -0
- package/packages/bundled-features/src/compliance-profiles/README.md +88 -0
- package/packages/bundled-features/src/compliance-profiles/_internal/parse-override.ts +20 -0
- package/packages/bundled-features/src/compliance-profiles/changes.json +8 -0
- package/packages/bundled-features/src/compliance-profiles/constants.ts +20 -0
- package/packages/bundled-features/src/compliance-profiles/feature.ts +114 -0
- package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +50 -0
- package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +52 -0
- package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +75 -0
- package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +142 -0
- package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +46 -0
- package/packages/bundled-features/src/compliance-profiles/i18n.ts +31 -0
- package/packages/bundled-features/src/compliance-profiles/index.ts +13 -0
- package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +57 -0
- package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +53 -0
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +101 -0
- package/packages/bundled-features/src/compliance-profiles/web/client-plugin.tsx +25 -0
- package/packages/bundled-features/src/compliance-profiles/web/compliance-profile-catalog.tsx +55 -0
- package/packages/bundled-features/src/compliance-profiles/web/i18n.ts +9 -0
- package/packages/bundled-features/src/compliance-profiles/web/index.ts +6 -0
- package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +56 -0
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +34 -0
- package/packages/bundled-features/src/config/changes.json +35 -0
- package/packages/bundled-features/src/config/constants.ts +30 -0
- package/packages/bundled-features/src/config/db/queries/resolver.ts +51 -0
- package/packages/bundled-features/src/config/feature.ts +169 -0
- package/packages/bundled-features/src/config/handlers/cascade.query.ts +94 -0
- package/packages/bundled-features/src/config/handlers/readiness.query.ts +164 -0
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +274 -0
- package/packages/bundled-features/src/config/handlers/reset.write.ts +76 -0
- package/packages/bundled-features/src/config/handlers/schema.query.ts +36 -0
- package/packages/bundled-features/src/config/handlers/selected-extensions.query.ts +71 -0
- package/packages/bundled-features/src/config/handlers/set.write.ts +227 -0
- package/packages/bundled-features/src/config/handlers/values.query.ts +92 -0
- package/packages/bundled-features/src/config/i18n.ts +4 -0
- package/packages/bundled-features/src/config/index.ts +38 -0
- package/packages/bundled-features/src/config/read-redaction.ts +64 -0
- package/packages/bundled-features/src/config/resolver.ts +687 -0
- package/packages/bundled-features/src/config/table.ts +40 -0
- package/packages/bundled-features/src/config/web/client-plugin.ts +24 -0
- package/packages/bundled-features/src/config/web/i18n.ts +48 -0
- package/packages/bundled-features/src/config/web/index.ts +7 -0
- package/packages/bundled-features/src/config/write-helpers.ts +377 -0
- package/packages/bundled-features/src/crypto-shredding/changes.json +58 -0
- package/packages/bundled-features/src/crypto-shredding/constants.ts +11 -0
- package/packages/bundled-features/src/crypto-shredding/feature.ts +30 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +454 -0
- package/packages/bundled-features/src/crypto-shredding/index.ts +13 -0
- package/packages/bundled-features/src/custom-fields/aggregate-id.ts +34 -0
- package/packages/bundled-features/src/custom-fields/changes.json +15 -0
- package/packages/bundled-features/src/custom-fields/constants.ts +79 -0
- package/packages/bundled-features/src/custom-fields/db/queries/field-access.ts +17 -0
- package/packages/bundled-features/src/custom-fields/db/queries/projection.ts +84 -0
- package/packages/bundled-features/src/custom-fields/db/queries/quota.ts +20 -0
- package/packages/bundled-features/src/custom-fields/db/queries/retention.ts +43 -0
- package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +39 -0
- package/packages/bundled-features/src/custom-fields/entity.ts +112 -0
- package/packages/bundled-features/src/custom-fields/events.ts +25 -0
- package/packages/bundled-features/src/custom-fields/executor.ts +10 -0
- package/packages/bundled-features/src/custom-fields/feature.ts +289 -0
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +82 -0
- package/packages/bundled-features/src/custom-fields/handlers/define-system-field.write.ts +45 -0
- package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +108 -0
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +49 -0
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +74 -0
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +124 -0
- package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +98 -0
- package/packages/bundled-features/src/custom-fields/index.ts +40 -0
- package/packages/bundled-features/src/custom-fields/lib/define-or-resurrect.ts +52 -0
- package/packages/bundled-features/src/custom-fields/lib/field-access.ts +75 -0
- package/packages/bundled-features/src/custom-fields/lib/field-definition-row.ts +33 -0
- package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +64 -0
- package/packages/bundled-features/src/custom-fields/lib/quota.ts +5 -0
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +91 -0
- package/packages/bundled-features/src/custom-fields/run-retention.ts +201 -0
- package/packages/bundled-features/src/custom-fields/schemas.ts +98 -0
- package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +27 -0
- package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +247 -0
- package/packages/bundled-features/src/custom-fields/web/i18n.ts +22 -0
- package/packages/bundled-features/src/custom-fields/web/index.ts +8 -0
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +226 -0
- package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +79 -0
- package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +34 -0
- package/packages/bundled-features/src/data-retention/changes.json +50 -0
- package/packages/bundled-features/src/data-retention/feature.ts +123 -0
- package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +46 -0
- package/packages/bundled-features/src/data-retention/index.ts +20 -0
- package/packages/bundled-features/src/data-retention/keep-for.ts +75 -0
- package/packages/bundled-features/src/data-retention/override-schema.ts +37 -0
- package/packages/bundled-features/src/data-retention/presets.ts +72 -0
- package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +84 -0
- package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +54 -0
- package/packages/bundled-features/src/data-retention/resolver.ts +107 -0
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +814 -0
- package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +50 -0
- package/packages/bundled-features/src/delivery/address-opt-out.ts +204 -0
- package/packages/bundled-features/src/delivery/attempt-log.ts +66 -0
- package/packages/bundled-features/src/delivery/changes.json +86 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +17 -0
- package/packages/bundled-features/src/delivery/constants.ts +36 -0
- package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +23 -0
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +32 -0
- package/packages/bundled-features/src/delivery/delivery-service.ts +625 -0
- package/packages/bundled-features/src/delivery/events.ts +24 -0
- package/packages/bundled-features/src/delivery/feature.ts +206 -0
- package/packages/bundled-features/src/delivery/handlers/log.query.ts +177 -0
- package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +42 -0
- package/packages/bundled-features/src/delivery/handlers/resubscribe-address.write.ts +42 -0
- package/packages/bundled-features/src/delivery/handlers/resubscribe-user.write.ts +41 -0
- package/packages/bundled-features/src/delivery/handlers/set-preference.write.ts +47 -0
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-address.write.ts +40 -0
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-user.write.ts +43 -0
- package/packages/bundled-features/src/delivery/i18n.ts +11 -0
- package/packages/bundled-features/src/delivery/index.ts +52 -0
- package/packages/bundled-features/src/delivery/jobs.ts +169 -0
- package/packages/bundled-features/src/delivery/public-names.ts +60 -0
- package/packages/bundled-features/src/delivery/tables.ts +155 -0
- package/packages/bundled-features/src/delivery/testing.ts +53 -0
- package/packages/bundled-features/src/delivery/types.ts +121 -0
- package/packages/bundled-features/src/delivery/unsubscribe.ts +429 -0
- package/packages/bundled-features/src/delivery/upsert-preference.ts +154 -0
- package/packages/bundled-features/src/delivery/web/client-plugin.tsx +19 -0
- package/packages/bundled-features/src/delivery/web/delivery-status-cell.tsx +26 -0
- package/packages/bundled-features/src/delivery/web/index.ts +3 -0
- package/packages/bundled-features/src/derivatives-sharp/changes.json +19 -0
- package/packages/bundled-features/src/derivatives-sharp/feature.ts +22 -0
- package/packages/bundled-features/src/derivatives-sharp/index.ts +2 -0
- package/packages/bundled-features/src/derivatives-sharp/render.ts +431 -0
- package/packages/bundled-features/src/document-ingest-foundation/boot-checks.ts +58 -0
- package/packages/bundled-features/src/document-ingest-foundation/changes.json +44 -0
- package/packages/bundled-features/src/document-ingest-foundation/entity.ts +59 -0
- package/packages/bundled-features/src/document-ingest-foundation/events.ts +43 -0
- package/packages/bundled-features/src/document-ingest-foundation/executor.ts +12 -0
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +226 -0
- package/packages/bundled-features/src/document-ingest-foundation/file-ref-liveness.ts +10 -0
- package/packages/bundled-features/src/document-ingest-foundation/forget-extract-with-file-ref.ts +84 -0
- package/packages/bundled-features/src/document-ingest-foundation/index.ts +34 -0
- package/packages/bundled-features/src/document-ingest-foundation/pages.ts +34 -0
- package/packages/bundled-features/src/document-ingest-foundation/providers.ts +87 -0
- package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +34 -0
- package/packages/bundled-features/src/document-ingest-foundation/write-document-extract.ts +57 -0
- package/packages/bundled-features/src/feature-toggles/changes.json +31 -0
- package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +134 -0
- package/packages/bundled-features/src/feature-toggles/constants.ts +40 -0
- package/packages/bundled-features/src/feature-toggles/events.ts +18 -0
- package/packages/bundled-features/src/feature-toggles/feature.ts +173 -0
- package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +47 -0
- package/packages/bundled-features/src/feature-toggles/handlers/list.query.ts +45 -0
- package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +87 -0
- package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +194 -0
- package/packages/bundled-features/src/feature-toggles/i18n.ts +11 -0
- package/packages/bundled-features/src/feature-toggles/index.ts +20 -0
- package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +135 -0
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +64 -0
- package/packages/bundled-features/src/feature-toggles/web/client-plugin.tsx +18 -0
- package/packages/bundled-features/src/feature-toggles/web/i18n.ts +17 -0
- package/packages/bundled-features/src/feature-toggles/web/index.ts +5 -0
- package/packages/bundled-features/src/file-derivatives/changes.json +27 -0
- package/packages/bundled-features/src/file-derivatives/feature.ts +236 -0
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +57 -0
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +156 -0
- package/packages/bundled-features/src/file-derivatives/index.ts +11 -0
- package/packages/bundled-features/src/file-derivatives/presets.ts +10 -0
- package/packages/bundled-features/src/file-foundation/changes.json +9 -0
- package/packages/bundled-features/src/file-foundation/feature.ts +72 -0
- package/packages/bundled-features/src/file-foundation/index.ts +9 -0
- package/packages/bundled-features/src/file-provider-inmemory/changes.json +1 -0
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +84 -0
- package/packages/bundled-features/src/file-provider-inmemory/index.ts +3 -0
- package/packages/bundled-features/src/file-provider-s3/changes.json +1 -0
- package/packages/bundled-features/src/file-provider-s3/feature.ts +176 -0
- package/packages/bundled-features/src/file-provider-s3/index.ts +3 -0
- package/packages/bundled-features/src/file-provider-s3-env/changes.json +1 -0
- package/packages/bundled-features/src/file-provider-s3-env/feature.ts +58 -0
- package/packages/bundled-features/src/file-provider-s3-env/index.ts +3 -0
- package/packages/bundled-features/src/files/README.md +50 -0
- package/packages/bundled-features/src/files/changes.json +1 -0
- package/packages/bundled-features/src/files/feature.ts +7 -0
- package/packages/bundled-features/src/files/index.ts +1 -0
- package/packages/bundled-features/src/files-provider-s3/changes.json +1 -0
- package/packages/bundled-features/src/files-provider-s3/env-helper.ts +49 -0
- package/packages/bundled-features/src/files-provider-s3/index.ts +3 -0
- package/packages/bundled-features/src/files-provider-s3/s3-provider.ts +196 -0
- package/packages/bundled-features/src/files-tenant-data/changes.json +9 -0
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +168 -0
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +203 -0
- package/packages/bundled-features/src/files-tenant-data/index.ts +68 -0
- package/packages/bundled-features/src/folders/aggregate-id.ts +23 -0
- package/packages/bundled-features/src/folders/changes.json +9 -0
- package/packages/bundled-features/src/folders/constants.ts +40 -0
- package/packages/bundled-features/src/folders/entity.ts +87 -0
- package/packages/bundled-features/src/folders/executor.ts +11 -0
- package/packages/bundled-features/src/folders/feature.ts +192 -0
- package/packages/bundled-features/src/folders/handlers/clear-folder.write.ts +51 -0
- package/packages/bundled-features/src/folders/handlers/delete-folder.write.ts +43 -0
- package/packages/bundled-features/src/folders/handlers/set-folder.write.ts +99 -0
- package/packages/bundled-features/src/folders/index.ts +23 -0
- package/packages/bundled-features/src/folders/schemas.ts +18 -0
- package/packages/bundled-features/src/folders/web/client-plugin.tsx +16 -0
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +562 -0
- package/packages/bundled-features/src/folders/web/folder-section.tsx +205 -0
- package/packages/bundled-features/src/folders/web/i18n.ts +34 -0
- package/packages/bundled-features/src/folders/web/index.ts +6 -0
- package/packages/bundled-features/src/folders/web/tree.ts +65 -0
- package/packages/bundled-features/src/folders-user-data/changes.json +1 -0
- package/packages/bundled-features/src/folders-user-data/hooks.ts +76 -0
- package/packages/bundled-features/src/folders-user-data/index.ts +33 -0
- package/packages/bundled-features/src/form-draft/changes.json +1 -0
- package/packages/bundled-features/src/form-draft/constants.ts +50 -0
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +72 -0
- package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +21 -0
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +74 -0
- package/packages/bundled-features/src/form-draft/entity.ts +59 -0
- package/packages/bundled-features/src/form-draft/executor.ts +7 -0
- package/packages/bundled-features/src/form-draft/feature.ts +59 -0
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +200 -0
- package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +110 -0
- package/packages/bundled-features/src/form-draft/handlers/get.query.ts +38 -0
- package/packages/bundled-features/src/form-draft/handlers/list.query.ts +54 -0
- package/packages/bundled-features/src/form-draft/handlers/save.write.ts +86 -0
- package/packages/bundled-features/src/form-draft/index.ts +28 -0
- package/packages/bundled-features/src/form-draft/lookup.ts +62 -0
- package/packages/bundled-features/src/form-draft/release-file-refs.ts +69 -0
- package/packages/bundled-features/src/form-draft/schemas.ts +61 -0
- package/packages/bundled-features/src/form-draft-user-data/changes.json +1 -0
- package/packages/bundled-features/src/form-draft-user-data/hooks.ts +57 -0
- package/packages/bundled-features/src/form-draft-user-data/index.ts +21 -0
- package/packages/bundled-features/src/foundation-shared/changes.json +1 -0
- package/packages/bundled-features/src/foundation-shared/config-helpers.ts +97 -0
- package/packages/bundled-features/src/foundation-shared/host-allowlist.ts +17 -0
- package/packages/bundled-features/src/foundation-shared/index.ts +14 -0
- package/packages/bundled-features/src/foundation-shared/mail-host-policy.ts +60 -0
- package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +40 -0
- package/packages/bundled-features/src/inbound-mail-foundation/changes.json +32 -0
- package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +253 -0
- package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +80 -0
- package/packages/bundled-features/src/inbound-mail-foundation/db/queries/inbound-projections.ts +38 -0
- package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +222 -0
- package/packages/bundled-features/src/inbound-mail-foundation/events.ts +147 -0
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +265 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +23 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +118 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +72 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +339 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +44 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +59 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +14 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +80 -0
- package/packages/bundled-features/src/inbound-mail-foundation/index.ts +96 -0
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +103 -0
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +155 -0
- package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +53 -0
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +168 -0
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +88 -0
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +257 -0
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +678 -0
- package/packages/bundled-features/src/inbound-provider-imap/changes.json +14 -0
- package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +51 -0
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +286 -0
- package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +216 -0
- package/packages/bundled-features/src/inbound-provider-imap/index.ts +17 -0
- package/packages/bundled-features/src/inbound-provider-inmemory/changes.json +1 -0
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +154 -0
- package/packages/bundled-features/src/inbound-provider-inmemory/index.ts +12 -0
- package/packages/bundled-features/src/jobs/changes.json +47 -0
- package/packages/bundled-features/src/jobs/constants.ts +33 -0
- package/packages/bundled-features/src/jobs/db/queries/retention.ts +60 -0
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +84 -0
- package/packages/bundled-features/src/jobs/events.ts +36 -0
- package/packages/bundled-features/src/jobs/feature.ts +256 -0
- package/packages/bundled-features/src/jobs/handlers/catalog.query.ts +42 -0
- package/packages/bundled-features/src/jobs/handlers/detail.query.ts +69 -0
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +79 -0
- package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +43 -0
- package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +56 -0
- package/packages/bundled-features/src/jobs/handlers/retention-cleanup.job.ts +23 -0
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +100 -0
- package/packages/bundled-features/src/jobs/handlers/stale-run-sweep.job.ts +30 -0
- package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +73 -0
- package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +85 -0
- package/packages/bundled-features/src/jobs/i18n.ts +54 -0
- package/packages/bundled-features/src/jobs/index.ts +7 -0
- package/packages/bundled-features/src/jobs/is-manual-trigger.ts +5 -0
- package/packages/bundled-features/src/jobs/job-instant.ts +9 -0
- package/packages/bundled-features/src/jobs/job-run-logger.ts +457 -0
- package/packages/bundled-features/src/jobs/job-run-table.ts +101 -0
- package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +38 -0
- package/packages/bundled-features/src/jobs/web/client-plugin.tsx +16 -0
- package/packages/bundled-features/src/jobs/web/i18n.ts +8 -0
- package/packages/bundled-features/src/jobs/web/index.ts +2 -0
- package/packages/bundled-features/src/ledger/changes.json +16 -0
- package/packages/bundled-features/src/ledger/constants.ts +60 -0
- package/packages/bundled-features/src/ledger/entity.ts +177 -0
- package/packages/bundled-features/src/ledger/executor.ts +18 -0
- package/packages/bundled-features/src/ledger/feature.ts +180 -0
- package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +134 -0
- package/packages/bundled-features/src/ledger/handlers/create-transaction.write.ts +48 -0
- package/packages/bundled-features/src/ledger/handlers/reports.query.ts +84 -0
- package/packages/bundled-features/src/ledger/handlers/reverse-transaction.write.ts +95 -0
- package/packages/bundled-features/src/ledger/index.ts +71 -0
- package/packages/bundled-features/src/ledger/recurring.ts +149 -0
- package/packages/bundled-features/src/ledger/reports.ts +164 -0
- package/packages/bundled-features/src/ledger/schemas.ts +71 -0
- package/packages/bundled-features/src/ledger/subject-reference.ts +10 -0
- package/packages/bundled-features/src/ledger/web/index.ts +36 -0
- package/packages/bundled-features/src/legal-pages/README.md +238 -0
- package/packages/bundled-features/src/legal-pages/changes.json +8 -0
- package/packages/bundled-features/src/legal-pages/constants.ts +54 -0
- package/packages/bundled-features/src/legal-pages/feature.ts +287 -0
- package/packages/bundled-features/src/legal-pages/index.ts +16 -0
- package/packages/bundled-features/src/legal-pages/markdown.ts +7 -0
- package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +81 -0
- package/packages/bundled-features/src/legal-pages/web/index.ts +4 -0
- package/packages/bundled-features/src/mail-foundation/changes.json +1 -0
- package/packages/bundled-features/src/mail-foundation/feature.ts +233 -0
- package/packages/bundled-features/src/mail-foundation/index.ts +17 -0
- package/packages/bundled-features/src/mail-transport-inmemory/changes.json +1 -0
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +97 -0
- package/packages/bundled-features/src/mail-transport-inmemory/index.ts +3 -0
- package/packages/bundled-features/src/mail-transport-smtp/changes.json +20 -0
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +268 -0
- package/packages/bundled-features/src/mail-transport-smtp/index.ts +8 -0
- package/packages/bundled-features/src/managed-pages/branding.ts +173 -0
- package/packages/bundled-features/src/managed-pages/changes.json +25 -0
- package/packages/bundled-features/src/managed-pages/css-gate.ts +24 -0
- package/packages/bundled-features/src/managed-pages/feature.ts +267 -0
- package/packages/bundled-features/src/managed-pages/handlers/branding.query.ts +37 -0
- package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +40 -0
- package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +55 -0
- package/packages/bundled-features/src/managed-pages/handlers/page-crud.ts +49 -0
- package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +133 -0
- package/packages/bundled-features/src/managed-pages/i18n.ts +62 -0
- package/packages/bundled-features/src/managed-pages/index.ts +30 -0
- package/packages/bundled-features/src/managed-pages/screens/branding-screen.ts +115 -0
- package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +89 -0
- package/packages/bundled-features/src/managed-pages/seeding.ts +99 -0
- package/packages/bundled-features/src/managed-pages/table.ts +80 -0
- package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +22 -0
- package/packages/bundled-features/src/managed-pages/web/i18n.ts +19 -0
- package/packages/bundled-features/src/managed-pages/web/index.ts +3 -0
- package/packages/bundled-features/src/metrics/changes.json +21 -0
- package/packages/bundled-features/src/metrics/compute.ts +243 -0
- package/packages/bundled-features/src/metrics/constants.ts +22 -0
- package/packages/bundled-features/src/metrics/default-metrics.ts +133 -0
- package/packages/bundled-features/src/metrics/feature.ts +159 -0
- package/packages/bundled-features/src/metrics/i18n.ts +18 -0
- package/packages/bundled-features/src/metrics/index.ts +33 -0
- package/packages/bundled-features/src/metrics/types.ts +81 -0
- package/packages/bundled-features/src/metrics/validate.ts +73 -0
- package/packages/bundled-features/src/metrics/window.ts +89 -0
- package/packages/bundled-features/src/notes-history/changes.json +30 -0
- package/packages/bundled-features/src/notes-history/constants.ts +34 -0
- package/packages/bundled-features/src/notes-history/entity.ts +128 -0
- package/packages/bundled-features/src/notes-history/executor.ts +22 -0
- package/packages/bundled-features/src/notes-history/feature.ts +150 -0
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +118 -0
- package/packages/bundled-features/src/notes-history/i18n.ts +3 -0
- package/packages/bundled-features/src/notes-history/index.ts +25 -0
- package/packages/bundled-features/src/notes-history/schemas.ts +17 -0
- package/packages/bundled-features/src/notes-history/web/client-plugin.tsx +16 -0
- package/packages/bundled-features/src/notes-history/web/i18n.ts +22 -0
- package/packages/bundled-features/src/notes-history/web/index.ts +8 -0
- package/packages/bundled-features/src/notes-history/web/notes-section.tsx +190 -0
- package/packages/bundled-features/src/notes-history-user-data/changes.json +8 -0
- package/packages/bundled-features/src/notes-history-user-data/hooks.ts +131 -0
- package/packages/bundled-features/src/notes-history-user-data/index.ts +34 -0
- package/packages/bundled-features/src/page-render/branding.ts +100 -0
- package/packages/bundled-features/src/page-render/cached-page-response.ts +25 -0
- package/packages/bundled-features/src/page-render/changes.json +14 -0
- package/packages/bundled-features/src/page-render/css-sanitize.ts +344 -0
- package/packages/bundled-features/src/page-render/index.ts +22 -0
- package/packages/bundled-features/src/page-render/layout.ts +115 -0
- package/packages/bundled-features/src/page-render/markdown.ts +31 -0
- package/packages/bundled-features/src/page-render/security-headers.ts +19 -0
- package/packages/bundled-features/src/page-render/web.ts +14 -0
- package/packages/bundled-features/src/personal-access-tokens/changes.json +25 -0
- package/packages/bundled-features/src/personal-access-tokens/constants.ts +45 -0
- package/packages/bundled-features/src/personal-access-tokens/expiry.ts +7 -0
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +184 -0
- package/packages/bundled-features/src/personal-access-tokens/handlers/available-scopes.query.ts +29 -0
- package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +124 -0
- package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +117 -0
- package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +62 -0
- package/packages/bundled-features/src/personal-access-tokens/hash.ts +17 -0
- package/packages/bundled-features/src/personal-access-tokens/i18n.ts +64 -0
- package/packages/bundled-features/src/personal-access-tokens/index.ts +43 -0
- package/packages/bundled-features/src/personal-access-tokens/pat-revoked-event.ts +23 -0
- package/packages/bundled-features/src/personal-access-tokens/resolver.ts +53 -0
- package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +62 -0
- package/packages/bundled-features/src/personal-access-tokens/roles.ts +37 -0
- package/packages/bundled-features/src/personal-access-tokens/schema/api-token.ts +93 -0
- package/packages/bundled-features/src/personal-access-tokens/scopes.ts +43 -0
- package/packages/bundled-features/src/personal-access-tokens/screens.ts +131 -0
- package/packages/bundled-features/src/presets/changes.json +8 -0
- package/packages/bundled-features/src/presets/dsgvo-self-service.ts +33 -0
- package/packages/bundled-features/src/presets/index.ts +2 -0
- package/packages/bundled-features/src/presets/security-baseline.ts +19 -0
- package/packages/bundled-features/src/rate-limiting/changes.json +14 -0
- package/packages/bundled-features/src/rate-limiting/constants.ts +10 -0
- package/packages/bundled-features/src/rate-limiting/feature.ts +30 -0
- package/packages/bundled-features/src/rate-limiting/handlers/bucket-access.ts +45 -0
- package/packages/bundled-features/src/rate-limiting/handlers/status.query.ts +60 -0
- package/packages/bundled-features/src/rate-limiting/i18n.ts +10 -0
- package/packages/bundled-features/src/rate-limiting/index.ts +2 -0
- package/packages/bundled-features/src/readiness/changes.json +1 -0
- package/packages/bundled-features/src/readiness/constants.ts +7 -0
- package/packages/bundled-features/src/readiness/feature.ts +31 -0
- package/packages/bundled-features/src/readiness/handlers/status.query.ts +55 -0
- package/packages/bundled-features/src/readiness/index.ts +3 -0
- package/packages/bundled-features/src/renderer-foundation/README.md +86 -0
- package/packages/bundled-features/src/renderer-foundation/api.ts +106 -0
- package/packages/bundled-features/src/renderer-foundation/changes.json +8 -0
- package/packages/bundled-features/src/renderer-foundation/constants.ts +25 -0
- package/packages/bundled-features/src/renderer-foundation/feature.ts +52 -0
- package/packages/bundled-features/src/renderer-foundation/index.ts +28 -0
- package/packages/bundled-features/src/renderer-foundation/types.ts +131 -0
- package/packages/bundled-features/src/renderer-simple/changes.json +1 -0
- package/packages/bundled-features/src/renderer-simple/feature.ts +57 -0
- package/packages/bundled-features/src/renderer-simple/index.ts +2 -0
- package/packages/bundled-features/src/renderer-simple/resolve-variables.ts +57 -0
- package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +65 -0
- package/packages/bundled-features/src/secrets/changes.json +29 -0
- package/packages/bundled-features/src/secrets/constants.ts +12 -0
- package/packages/bundled-features/src/secrets/db/queries/read.ts +16 -0
- package/packages/bundled-features/src/secrets/feature.ts +197 -0
- package/packages/bundled-features/src/secrets/handlers/delete.write.ts +29 -0
- package/packages/bundled-features/src/secrets/handlers/list.query.ts +40 -0
- package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +166 -0
- package/packages/bundled-features/src/secrets/handlers/set.write.ts +60 -0
- package/packages/bundled-features/src/secrets/i18n.ts +10 -0
- package/packages/bundled-features/src/secrets/index.ts +23 -0
- package/packages/bundled-features/src/secrets/secrets-context.ts +261 -0
- package/packages/bundled-features/src/secrets/table.ts +69 -0
- package/packages/bundled-features/src/secrets/write-gate.ts +62 -0
- package/packages/bundled-features/src/seo/changes.json +20 -0
- package/packages/bundled-features/src/seo/constants.ts +60 -0
- package/packages/bundled-features/src/seo/feature.ts +317 -0
- package/packages/bundled-features/src/seo/handlers/seo-config.query.ts +38 -0
- package/packages/bundled-features/src/seo/index.ts +24 -0
- package/packages/bundled-features/src/seo/llms-txt.ts +33 -0
- package/packages/bundled-features/src/seo/robots-txt.ts +33 -0
- package/packages/bundled-features/src/seo/schema-builders.ts +57 -0
- package/packages/bundled-features/src/seo/sitemap.ts +33 -0
- package/packages/bundled-features/src/sessions/changes.json +45 -0
- package/packages/bundled-features/src/sessions/constants.ts +58 -0
- package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +21 -0
- package/packages/bundled-features/src/sessions/feature.ts +240 -0
- package/packages/bundled-features/src/sessions/handlers/cleanup.job.ts +83 -0
- package/packages/bundled-features/src/sessions/handlers/detail.query.ts +51 -0
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +92 -0
- package/packages/bundled-features/src/sessions/handlers/mine.query.ts +67 -0
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +122 -0
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +68 -0
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +94 -0
- package/packages/bundled-features/src/sessions/i18n.ts +33 -0
- package/packages/bundled-features/src/sessions/index.ts +25 -0
- package/packages/bundled-features/src/sessions/schema/user-session.ts +91 -0
- package/packages/bundled-features/src/sessions/screens.ts +157 -0
- package/packages/bundled-features/src/sessions/session-callbacks.ts +302 -0
- package/packages/bundled-features/src/sessions/session-revoked-event.ts +37 -0
- package/packages/bundled-features/src/sessions/testing.ts +55 -0
- package/packages/bundled-features/src/shared/assert-erased.ts +26 -0
- package/packages/bundled-features/src/shared/changes.json +14 -0
- package/packages/bundled-features/src/shared/chunked-entity-migration.ts +89 -0
- package/packages/bundled-features/src/shared/classify-stored-envelope.ts +21 -0
- package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +26 -0
- package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +29 -0
- package/packages/bundled-features/src/shared/entities-of.ts +17 -0
- package/packages/bundled-features/src/shared/grace-period.ts +21 -0
- package/packages/bundled-features/src/shared/has-where-rule.ts +11 -0
- package/packages/bundled-features/src/shared/identity-v3-hash.ts +97 -0
- package/packages/bundled-features/src/shared/index.ts +53 -0
- package/packages/bundled-features/src/shared/is-tenant-db.ts +9 -0
- package/packages/bundled-features/src/shared/lockout-counter.ts +108 -0
- package/packages/bundled-features/src/shared/map-with-concurrency.ts +38 -0
- package/packages/bundled-features/src/shared/parent-visibility.ts +104 -0
- package/packages/bundled-features/src/shared/password-hashing.ts +55 -0
- package/packages/bundled-features/src/shared/row-bound-grant.ts +128 -0
- package/packages/bundled-features/src/shared/run-in-sub-transaction.ts +35 -0
- package/packages/bundled-features/src/shared/session-locale-field.ts +9 -0
- package/packages/bundled-features/src/shared/session-timezone-field.ts +8 -0
- package/packages/bundled-features/src/shared/signed-token.ts +101 -0
- package/packages/bundled-features/src/shared/signup-handover.ts +67 -0
- package/packages/bundled-features/src/shared/single-use-token-store.ts +148 -0
- package/packages/bundled-features/src/shared/system-query.ts +5 -0
- package/packages/bundled-features/src/shared/token-burn-store.ts +57 -0
- package/packages/bundled-features/src/step-dispatcher/changes.json +32 -0
- package/packages/bundled-features/src/step-dispatcher/feature.ts +299 -0
- package/packages/bundled-features/src/step-dispatcher/index.ts +25 -0
- package/packages/bundled-features/src/step-dispatcher/mail-runner.ts +39 -0
- package/packages/bundled-features/src/step-dispatcher/webhook-runner.ts +221 -0
- package/packages/bundled-features/src/subscription-mollie/changes.json +28 -0
- package/packages/bundled-features/src/subscription-mollie/constants.ts +33 -0
- package/packages/bundled-features/src/subscription-mollie/feature.ts +169 -0
- package/packages/bundled-features/src/subscription-mollie/index.ts +14 -0
- package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +97 -0
- package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +259 -0
- package/packages/bundled-features/src/subscription-stripe/changes.json +80 -0
- package/packages/bundled-features/src/subscription-stripe/constants.ts +35 -0
- package/packages/bundled-features/src/subscription-stripe/feature.ts +251 -0
- package/packages/bundled-features/src/subscription-stripe/index.ts +18 -0
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +646 -0
- package/packages/bundled-features/src/subscription-stripe/runtime.ts +193 -0
- package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +436 -0
- package/packages/bundled-features/src/tags/aggregate-id.ts +23 -0
- package/packages/bundled-features/src/tags/changes.json +16 -0
- package/packages/bundled-features/src/tags/constants.ts +61 -0
- package/packages/bundled-features/src/tags/entity.ts +99 -0
- package/packages/bundled-features/src/tags/executor.ts +24 -0
- package/packages/bundled-features/src/tags/feature.ts +219 -0
- package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +101 -0
- package/packages/bundled-features/src/tags/handlers/create-tag.write.ts +27 -0
- package/packages/bundled-features/src/tags/handlers/delete-tag.write.ts +60 -0
- package/packages/bundled-features/src/tags/handlers/remove-tag.write.ts +53 -0
- package/packages/bundled-features/src/tags/handlers/update-tag.write.ts +36 -0
- package/packages/bundled-features/src/tags/i18n.ts +9 -0
- package/packages/bundled-features/src/tags/index.ts +48 -0
- package/packages/bundled-features/src/tags/schemas.ts +61 -0
- package/packages/bundled-features/src/tags/screens.ts +70 -0
- package/packages/bundled-features/src/tags/web/client-plugin.tsx +30 -0
- package/packages/bundled-features/src/tags/web/entity-tags.tsx +54 -0
- package/packages/bundled-features/src/tags/web/i18n.ts +34 -0
- package/packages/bundled-features/src/tags/web/index.ts +18 -0
- package/packages/bundled-features/src/tags/web/tag-chip.tsx +65 -0
- package/packages/bundled-features/src/tags/web/tag-filter.tsx +100 -0
- package/packages/bundled-features/src/tags/web/tag-manager.tsx +391 -0
- package/packages/bundled-features/src/tags/web/tag-picker.tsx +55 -0
- package/packages/bundled-features/src/tags/web/tag-section.tsx +179 -0
- package/packages/bundled-features/src/tags/web/tags-cell.tsx +46 -0
- package/packages/bundled-features/src/template-resolver/README.md +255 -0
- package/packages/bundled-features/src/template-resolver/api.ts +202 -0
- package/packages/bundled-features/src/template-resolver/changes.json +16 -0
- package/packages/bundled-features/src/template-resolver/constants.ts +54 -0
- package/packages/bundled-features/src/template-resolver/feature.ts +99 -0
- package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +61 -0
- package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +63 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +53 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +56 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +117 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-shared.ts +90 -0
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +44 -0
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +60 -0
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +126 -0
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +51 -0
- package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +46 -0
- package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +81 -0
- package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +105 -0
- package/packages/bundled-features/src/template-resolver/index.ts +44 -0
- package/packages/bundled-features/src/template-resolver/qualified-names.ts +40 -0
- package/packages/bundled-features/src/template-resolver/seeding.ts +323 -0
- package/packages/bundled-features/src/template-resolver/table.ts +90 -0
- package/packages/bundled-features/src/template-resolver/testing.ts +199 -0
- package/packages/bundled-features/src/template-resolver/user-content-table.ts +68 -0
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +516 -0
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +25 -0
- package/packages/bundled-features/src/template-resolver/web/index.ts +8 -0
- package/packages/bundled-features/src/template-resolver-user-data/hooks.ts +40 -0
- package/packages/bundled-features/src/template-resolver-user-data/index.ts +25 -0
- package/packages/bundled-features/src/tenant/cancel-pending-invitation.ts +43 -0
- package/packages/bundled-features/src/tenant/changes.json +105 -0
- package/packages/bundled-features/src/tenant/command-schemas.ts +37 -0
- package/packages/bundled-features/src/tenant/constants.ts +78 -0
- package/packages/bundled-features/src/tenant/feature.ts +213 -0
- package/packages/bundled-features/src/tenant/handlers/active-tenant-ids.query.ts +30 -0
- package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +64 -0
- package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +68 -0
- package/packages/bundled-features/src/tenant/handlers/create.write.ts +37 -0
- package/packages/bundled-features/src/tenant/handlers/invitations.query.ts +58 -0
- package/packages/bundled-features/src/tenant/handlers/is-system-admin.ts +5 -0
- package/packages/bundled-features/src/tenant/handlers/list.query.ts +30 -0
- package/packages/bundled-features/src/tenant/handlers/me.query.ts +38 -0
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +108 -0
- package/packages/bundled-features/src/tenant/handlers/members.query.ts +73 -0
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +58 -0
- package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +142 -0
- package/packages/bundled-features/src/tenant/handlers/resolve-user-ids.query.ts +44 -0
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +257 -0
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +71 -0
- package/packages/bundled-features/src/tenant/handlers/toggle-enabled.write.ts +37 -0
- package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +208 -0
- package/packages/bundled-features/src/tenant/handlers/update.write.ts +55 -0
- package/packages/bundled-features/src/tenant/i18n.ts +61 -0
- package/packages/bundled-features/src/tenant/index.ts +24 -0
- package/packages/bundled-features/src/tenant/invitation-table.ts +104 -0
- package/packages/bundled-features/src/tenant/invited-membership.ts +97 -0
- package/packages/bundled-features/src/tenant/is-tenant-serving-public-content.ts +13 -0
- package/packages/bundled-features/src/tenant/last-tenant-admin.ts +43 -0
- package/packages/bundled-features/src/tenant/membership-roles.ts +34 -0
- package/packages/bundled-features/src/tenant/membership-table.ts +32 -0
- package/packages/bundled-features/src/tenant/schema/tenant.ts +73 -0
- package/packages/bundled-features/src/tenant/screens.ts +221 -0
- package/packages/bundled-features/src/tenant/seeding.ts +335 -0
- package/packages/bundled-features/src/tenant/testing.ts +8 -0
- package/packages/bundled-features/src/tenant/web/client-plugin.tsx +25 -0
- package/packages/bundled-features/src/tenant/web/index.ts +4 -0
- package/packages/bundled-features/src/tenant/web/member-roles-cell.tsx +21 -0
- package/packages/bundled-features/src/tenant/web/member-status-cell.tsx +27 -0
- package/packages/bundled-features/src/tenant/web/translate-or-raw.ts +13 -0
- package/packages/bundled-features/src/tenant-handover/changes.json +34 -0
- package/packages/bundled-features/src/tenant-handover/events.ts +32 -0
- package/packages/bundled-features/src/tenant-handover/feature.ts +46 -0
- package/packages/bundled-features/src/tenant-handover/grant.ts +43 -0
- package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +134 -0
- package/packages/bundled-features/src/tenant-handover/index.ts +9 -0
- package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +355 -0
- package/packages/bundled-features/src/tenant-handover/root-anchor.ts +50 -0
- package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +62 -0
- package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +128 -0
- package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +79 -0
- package/packages/bundled-features/src/tenant-lifecycle/changes.json +8 -0
- package/packages/bundled-features/src/tenant-lifecycle/constants.ts +56 -0
- package/packages/bundled-features/src/tenant-lifecycle/events.ts +46 -0
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +150 -0
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +86 -0
- package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +94 -0
- package/packages/bundled-features/src/tenant-lifecycle/index.ts +7 -0
- package/packages/bundled-features/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +16 -0
- package/packages/bundled-features/src/tenant-lifecycle/lifecycle-gate.ts +87 -0
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +387 -0
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +242 -0
- package/packages/bundled-features/src/tenant-settings/changes.json +1 -0
- package/packages/bundled-features/src/tenant-settings/config.ts +43 -0
- package/packages/bundled-features/src/tenant-settings/constants.ts +21 -0
- package/packages/bundled-features/src/tenant-settings/feature.ts +55 -0
- package/packages/bundled-features/src/tenant-settings/index.ts +8 -0
- package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +78 -0
- package/packages/bundled-features/src/tier-engine/aggregate-id.ts +28 -0
- package/packages/bundled-features/src/tier-engine/changes.json +16 -0
- package/packages/bundled-features/src/tier-engine/compose-app.ts +153 -0
- package/packages/bundled-features/src/tier-engine/constants.ts +28 -0
- package/packages/bundled-features/src/tier-engine/entity.ts +55 -0
- package/packages/bundled-features/src/tier-engine/feature.ts +549 -0
- package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +25 -0
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +32 -0
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +108 -0
- package/packages/bundled-features/src/tier-engine/i18n.ts +31 -0
- package/packages/bundled-features/src/tier-engine/index.ts +32 -0
- package/packages/bundled-features/src/tier-engine/tier-resolver.ts +38 -0
- package/packages/bundled-features/src/tier-engine/trial.ts +26 -0
- package/packages/bundled-features/src/tier-engine/web/client-plugin.tsx +21 -0
- package/packages/bundled-features/src/tier-engine/web/index.ts +7 -0
- package/packages/bundled-features/src/user/changes.json +48 -0
- package/packages/bundled-features/src/user/command-schemas.ts +15 -0
- package/packages/bundled-features/src/user/constants.ts +32 -0
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +113 -0
- package/packages/bundled-features/src/user/feature.ts +61 -0
- package/packages/bundled-features/src/user/handlers/create.write.ts +136 -0
- package/packages/bundled-features/src/user/handlers/detail.query.ts +34 -0
- package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +51 -0
- package/packages/bundled-features/src/user/handlers/list.query.ts +123 -0
- package/packages/bundled-features/src/user/handlers/me.query.ts +38 -0
- package/packages/bundled-features/src/user/handlers/update-roles.ts +203 -0
- package/packages/bundled-features/src/user/handlers/update.write.ts +112 -0
- package/packages/bundled-features/src/user/i18n.ts +23 -0
- package/packages/bundled-features/src/user/index.ts +19 -0
- package/packages/bundled-features/src/user/principal-status.ts +47 -0
- package/packages/bundled-features/src/user/roles-input-schema.ts +20 -0
- package/packages/bundled-features/src/user/schema/user.ts +215 -0
- package/packages/bundled-features/src/user/screens.ts +54 -0
- package/packages/bundled-features/src/user/seeding.ts +139 -0
- package/packages/bundled-features/src/user/testing.ts +5 -0
- package/packages/bundled-features/src/user-data-rights/COMPLIANCE.md +202 -0
- package/packages/bundled-features/src/user-data-rights/README.md +109 -0
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +125 -0
- package/packages/bundled-features/src/user-data-rights/boot-checks.ts +71 -0
- package/packages/bundled-features/src/user-data-rights/changes.json +116 -0
- package/packages/bundled-features/src/user-data-rights/constants.ts +63 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/export-jobs.ts +28 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +25 -0
- package/packages/bundled-features/src/user-data-rights/deletion-token.ts +58 -0
- package/packages/bundled-features/src/user-data-rights/email-templates.ts +175 -0
- package/packages/bundled-features/src/user-data-rights/feature.ts +808 -0
- package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +83 -0
- package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +107 -0
- package/packages/bundled-features/src/user-data-rights/handlers/deletion-grace-period.ts +138 -0
- package/packages/bundled-features/src/user-data-rights/handlers/download-attempt-list.query.ts +20 -0
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +220 -0
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +259 -0
- package/packages/bundled-features/src/user-data-rights/handlers/export-job-detail.query.ts +13 -0
- package/packages/bundled-features/src/user-data-rights/handlers/export-job-list.query.ts +14 -0
- package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +75 -0
- package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +88 -0
- package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +49 -0
- package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +87 -0
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +127 -0
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +117 -0
- package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +165 -0
- package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +133 -0
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +95 -0
- package/packages/bundled-features/src/user-data-rights/i18n.ts +39 -0
- package/packages/bundled-features/src/user-data-rights/index.ts +33 -0
- package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +120 -0
- package/packages/bundled-features/src/user-data-rights/lib/deny-if-target-outside-admin-tenant.ts +32 -0
- package/packages/bundled-features/src/user-data-rights/lib/is-admin-actor.ts +19 -0
- package/packages/bundled-features/src/user-data-rights/lib/mail-transport-resolver.ts +50 -0
- package/packages/bundled-features/src/user-data-rights/lib/resolve-tenant-model.ts +34 -0
- package/packages/bundled-features/src/user-data-rights/lib/storage-provider-resolver.ts +49 -0
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +126 -0
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +998 -0
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +665 -0
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +346 -0
- package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +57 -0
- package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +119 -0
- package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +174 -0
- package/packages/bundled-features/src/user-data-rights/screens.ts +77 -0
- package/packages/bundled-features/src/user-data-rights/token-helpers.ts +67 -0
- package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +52 -0
- package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +97 -0
- package/packages/bundled-features/src/user-data-rights/web/i18n.ts +93 -0
- package/packages/bundled-features/src/user-data-rights/web/index.ts +15 -0
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +185 -0
- package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +42 -0
- package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +104 -0
- package/packages/bundled-features/src/user-data-rights/zip-path.ts +94 -0
- package/packages/bundled-features/src/user-data-rights-defaults/changes.json +13 -0
- package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +136 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/api-token.userdata-hook.ts +36 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/config-value.userdata-hook.ts +57 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +36 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/feature-mounted.ts +10 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +280 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/in-app-message.userdata-hook.ts +37 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +34 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +63 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/tenant-invitation.userdata-hook.ts +144 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +41 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +126 -0
- package/packages/bundled-features/src/user-data-rights-defaults/index.ts +32 -0
- package/packages/bundled-features/src/user-profile/changes.json +21 -0
- package/packages/bundled-features/src/user-profile/constants.ts +35 -0
- package/packages/bundled-features/src/user-profile/feature.ts +154 -0
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +99 -0
- package/packages/bundled-features/src/user-profile/i18n.ts +46 -0
- package/packages/bundled-features/src/user-profile/index.ts +11 -0
- package/packages/bundled-features/src/user-profile/web/client-plugin.ts +45 -0
- package/packages/bundled-features/src/user-profile/web/index.ts +6 -0
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +234 -0
- package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +20 -0
- package/packages/bundled-features/src/workflow-runner/changes.json +20 -0
- package/packages/bundled-features/src/workflow-runner/db/queries/due-runs.ts +24 -0
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +113 -0
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +121 -0
- package/packages/bundled-features/src/workflow-runner/feature.ts +96 -0
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +358 -0
- package/packages/bundled-features/src/workflow-runner/index.ts +12 -0
- package/packages/bundled-features/src/workflow-runner/pending-projection.ts +158 -0
- package/packages/bundled-features/src/workflow-runner/runner.ts +153 -0
- package/packages/bundled-features/src/workflow-runner/tables.ts +95 -0
- package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +23 -0
- package/samples/apps/admin-console/README.md +90 -0
- package/samples/apps/admin-console/package.json +22 -0
- package/samples/apps/admin-console/playwright.config.ts +13 -0
- package/samples/apps/admin-console/src/app/auth-constants.ts +10 -0
- package/samples/apps/admin-console/src/app/client.tsx +29 -0
- package/samples/apps/admin-console/src/app/home-screen.tsx +14 -0
- package/samples/apps/admin-console/src/app/seed-users.ts +42 -0
- package/samples/apps/admin-console/src/app/server.ts +35 -0
- package/samples/apps/admin-console/src/app/shell.tsx +48 -0
- package/samples/apps/admin-console/src/run-config.ts +60 -0
- package/samples/apps/admin-console/tsconfig.json +23 -0
- package/samples/apps/cap-billing-demo/README.md +151 -0
- package/samples/apps/cap-billing-demo/bin/server.ts +37 -0
- package/samples/apps/cap-billing-demo/package.json +16 -0
- package/samples/apps/cap-billing-demo/src/feature.ts +208 -0
- package/samples/apps/cap-billing-demo/src/run-config.ts +51 -0
- package/samples/apps/cap-billing-demo/src/tier-map.ts +46 -0
- package/samples/apps/cap-billing-demo/tsconfig.json +21 -0
- package/samples/apps/config-demo/README.md +81 -0
- package/samples/apps/config-demo/package.json +22 -0
- package/samples/apps/config-demo/playwright.config.ts +11 -0
- package/samples/apps/config-demo/src/app/client.tsx +12 -0
- package/samples/apps/config-demo/src/app/server.ts +31 -0
- package/samples/apps/config-demo/src/app/shell.tsx +31 -0
- package/samples/apps/config-demo/src/features/demo/feature.ts +84 -0
- package/samples/apps/config-demo/src/features/demo/i18n.ts +23 -0
- package/samples/apps/config-demo/src/features/demo/web/index.ts +7 -0
- package/samples/apps/config-demo/tsconfig.json +41 -0
- package/samples/apps/marketing-demo/README.md +89 -0
- package/samples/apps/marketing-demo/package.json +22 -0
- package/samples/apps/marketing-demo/playwright.config.ts +16 -0
- package/samples/apps/marketing-demo/src/app/client.tsx +13 -0
- package/samples/apps/marketing-demo/src/app/seed-data.ts +443 -0
- package/samples/apps/marketing-demo/src/app/seed.ts +143 -0
- package/samples/apps/marketing-demo/src/app/server.ts +25 -0
- package/samples/apps/marketing-demo/src/app/shell.tsx +37 -0
- package/samples/apps/marketing-demo/src/db/queries/seed-counts.ts +18 -0
- package/samples/apps/marketing-demo/src/features/assets/feature.ts +54 -0
- package/samples/apps/marketing-demo/src/features/assets/i18n.ts +103 -0
- package/samples/apps/marketing-demo/src/features/assets/schema/asset.ts +129 -0
- package/samples/apps/marketing-demo/src/features/assets/schema/index.ts +11 -0
- package/samples/apps/marketing-demo/src/features/assets/web/index.ts +10 -0
- package/samples/apps/marketing-demo/src/features/helpdesk/feature.ts +52 -0
- package/samples/apps/marketing-demo/src/features/helpdesk/i18n.ts +100 -0
- package/samples/apps/marketing-demo/src/features/helpdesk/schema/index.ts +13 -0
- package/samples/apps/marketing-demo/src/features/helpdesk/schema/ticket.ts +136 -0
- package/samples/apps/marketing-demo/src/features/helpdesk/web/index.ts +7 -0
- package/samples/apps/marketing-demo/tsconfig.json +23 -0
- package/samples/apps/showcase/README.md +123 -0
- package/samples/apps/showcase/kumiko.config.ts +10 -0
- package/samples/apps/showcase/package.json +23 -0
- package/samples/apps/showcase/playwright.config.ts +13 -0
- package/samples/apps/showcase/src/app/client.tsx +15 -0
- package/samples/apps/showcase/src/app/mount-public-screenshots.ts +26 -0
- package/samples/apps/showcase/src/app/seed-items.ts +129 -0
- package/samples/apps/showcase/src/app/server.ts +30 -0
- package/samples/apps/showcase/src/app/shell.tsx +110 -0
- package/samples/apps/showcase/src/features/demos/feature.ts +168 -0
- package/samples/apps/showcase/src/features/demos/i18n.ts +45 -0
- package/samples/apps/showcase/src/features/demos/index.ts +5 -0
- package/samples/apps/showcase/src/features/demos/web/components/page.tsx +50 -0
- package/samples/apps/showcase/src/features/demos/web/index.ts +30 -0
- package/samples/apps/showcase/src/features/demos/web/pages/banner.tsx +36 -0
- package/samples/apps/showcase/src/features/demos/web/pages/buttons.tsx +55 -0
- package/samples/apps/showcase/src/features/demos/web/pages/dialog.tsx +89 -0
- package/samples/apps/showcase/src/features/demos/web/pages/inputs.tsx +242 -0
- package/samples/apps/showcase/src/features/demos/web/pages/layout.tsx +203 -0
- package/samples/apps/showcase/src/features/demos/web/pages/sidebar-panel.tsx +144 -0
- package/samples/apps/showcase/src/features/demos/web/pages/text.tsx +27 -0
- package/samples/apps/showcase/src/features/demos/web/pages/toast.tsx +71 -0
- package/samples/apps/showcase/src/features/items/feature.ts +109 -0
- package/samples/apps/showcase/src/features/items/i18n.ts +79 -0
- package/samples/apps/showcase/src/features/items/index.ts +6 -0
- package/samples/apps/showcase/src/features/items/schema/index.ts +13 -0
- package/samples/apps/showcase/src/features/items/schema/item.ts +215 -0
- package/samples/apps/showcase/src/features/items/web/index.ts +15 -0
- package/samples/apps/styleguide/README.md +47 -0
- package/samples/apps/styleguide/package.json +22 -0
- package/samples/apps/styleguide/playwright.config.ts +11 -0
- package/samples/apps/styleguide/src/app/client.tsx +28 -0
- package/samples/apps/styleguide/src/app/seed.ts +58 -0
- package/samples/apps/styleguide/src/app/server.ts +51 -0
- package/samples/apps/styleguide/src/app/shell.tsx +66 -0
- package/samples/apps/styleguide/src/features/ai-settings/catalog.ts +82 -0
- package/samples/apps/styleguide/src/features/ai-settings/feature.ts +295 -0
- package/samples/apps/styleguide/src/features/ai-settings/i18n.ts +54 -0
- package/samples/apps/styleguide/src/features/ai-settings/seed.ts +29 -0
- package/samples/apps/styleguide/src/features/ai-settings/web.ts +14 -0
- package/samples/apps/styleguide/src/features/content/feature.ts +39 -0
- package/samples/apps/styleguide/src/features/content/web.tsx +160 -0
- package/samples/apps/styleguide/src/features/demo/feature.ts +288 -0
- package/samples/apps/styleguide/src/features/demo/i18n.ts +38 -0
- package/samples/apps/styleguide/src/features/demo/web.ts +13 -0
- package/samples/apps/styleguide/src/features/examples/feature.ts +173 -0
- package/samples/apps/styleguide/src/features/examples/i18n.ts +69 -0
- package/samples/apps/styleguide/src/features/examples/web.ts +14 -0
- package/samples/apps/styleguide/src/features/gallery/feature.ts +35 -0
- package/samples/apps/styleguide/src/features/gallery/web/Gallery.tsx +832 -0
- package/samples/apps/styleguide/src/features/gallery/web/index.ts +16 -0
- package/samples/apps/styleguide/src/features/shared-i18n.ts +16 -0
- package/samples/apps/styleguide/src/features/widgets/ai-text-demo.ts +70 -0
- package/samples/apps/styleguide/src/features/widgets/feature.ts +314 -0
- package/samples/apps/styleguide/src/features/widgets/i18n.ts +208 -0
- package/samples/apps/styleguide/src/features/widgets/lib/format.ts +32 -0
- package/samples/apps/styleguide/src/features/widgets/web/DashboardFilterEcho.tsx +21 -0
- package/samples/apps/styleguide/src/features/widgets/web/DashboardKpiIcon.tsx +20 -0
- package/samples/apps/styleguide/src/features/widgets/web/FormExamples.tsx +352 -0
- package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +656 -0
- package/samples/apps/styleguide/src/features/widgets/web/index.ts +30 -0
- package/samples/apps/styleguide/tsconfig.json +41 -0
- package/samples/apps/ui-walkthrough/README.md +105 -0
- package/samples/apps/ui-walkthrough/kumiko/schema.ts +14 -0
- package/samples/apps/ui-walkthrough/package.json +23 -0
- package/samples/apps/ui-walkthrough/playwright.config.ts +29 -0
- package/samples/apps/ui-walkthrough/scripts/emit-e2e-data.ts +19 -0
- package/samples/apps/ui-walkthrough/src/app/assistant-action.tsx +49 -0
- package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +20 -0
- package/samples/apps/ui-walkthrough/src/app/client.tsx +21 -0
- package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +266 -0
- package/samples/apps/ui-walkthrough/src/app/seed-vehicles.ts +172 -0
- package/samples/apps/ui-walkthrough/src/app/seed.ts +25 -0
- package/samples/apps/ui-walkthrough/src/app/server.ts +56 -0
- package/samples/apps/ui-walkthrough/src/app/shell.tsx +67 -0
- package/samples/apps/ui-walkthrough/src/db/queries/row-counts.ts +24 -0
- package/samples/apps/ui-walkthrough/src/db/queries/task-counts.ts +10 -0
- package/samples/apps/ui-walkthrough/src/features/rental/entities.ts +57 -0
- package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +258 -0
- package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +214 -0
- package/samples/apps/ui-walkthrough/src/features/rental/index.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +110 -0
- package/samples/apps/ui-walkthrough/src/features/rental/qualified-names.ts +12 -0
- package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +450 -0
- package/samples/apps/ui-walkthrough/src/features/rental/web/index.ts +12 -0
- package/samples/apps/ui-walkthrough/src/features/rental/web/lease-hub-components.tsx +29 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/feature.ts +49 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/i18n.ts +39 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/index.ts +4 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/schema/index.ts +3 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/schema/task.ts +85 -0
- package/samples/apps/ui-walkthrough/src/features/tasks/web/index.ts +10 -0
- package/samples/apps/ui-walkthrough/src/features/translations.ts +17 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/campaign-support.ts +22 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/entities.ts +89 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/feature.ts +95 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/i18n.ts +222 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/index.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/qualified-names.ts +7 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/screens.ts +188 -0
- package/samples/apps/ui-walkthrough/src/features/vehicles/web/index.ts +7 -0
- package/samples/apps/ui-walkthrough/src/run-config.ts +15 -0
- package/samples/apps/ui-walkthrough/tsconfig.json +19 -0
- package/samples/apps/use-all-bundled/README.md +57 -0
- package/samples/apps/use-all-bundled/bin/main.ts +53 -0
- package/samples/apps/use-all-bundled/feature-manifest.json +2963 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0003_notes-history.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0005_user-content-entries.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0007_form-draft.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0008_ledger-date-column-1924.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0009_form-draft-owner-required.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0012_add-user-email-unique-index.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0015_pii-field-api-v2-bidx.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0023_add-note-mentions.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0028_add-ledger-account-code-unique-index.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/schema.ts +24 -0
- package/samples/apps/use-all-bundled/kumiko.config.ts +24 -0
- package/samples/apps/use-all-bundled/package.json +30 -0
- package/samples/apps/use-all-bundled/playwright.config.ts +10 -0
- package/samples/apps/use-all-bundled/schema/generate.ts +577 -0
- package/samples/apps/use-all-bundled/schema/migrations/meta/0000_snapshot.json +3055 -0
- package/samples/apps/use-all-bundled/schema/migrations/meta/_journal.json +13 -0
- package/samples/apps/use-all-bundled/schema/schema.generated.ts +88 -0
- package/samples/apps/use-all-bundled/schema/schema.ts +9 -0
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +203 -0
- package/samples/apps/use-all-bundled/scripts/gen-feature-manifest.ts +85 -0
- package/samples/apps/use-all-bundled/scripts/gen-sample-index.ts +290 -0
- package/samples/apps/use-all-bundled/src/app/auth-constants.ts +16 -0
- package/samples/apps/use-all-bundled/src/app/cap-overview-caps.ts +71 -0
- package/samples/apps/use-all-bundled/src/app/cap-overview-labels-feature.ts +18 -0
- package/samples/apps/use-all-bundled/src/app/client.tsx +126 -0
- package/samples/apps/use-all-bundled/src/app/collection-labels-feature.ts +16 -0
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +75 -0
- package/samples/apps/use-all-bundled/src/app/notes-feature.ts +174 -0
- package/samples/apps/use-all-bundled/src/app/screens-feature.ts +39 -0
- package/samples/apps/use-all-bundled/src/app/seed.ts +429 -0
- package/samples/apps/use-all-bundled/src/app/server.ts +5 -0
- package/samples/apps/use-all-bundled/src/app/shell.tsx +62 -0
- package/samples/apps/use-all-bundled/src/run-config.ts +433 -0
- package/samples/apps/use-all-bundled/tsconfig.json +31 -0
- package/samples/apps/user-data-rights-demo/README.md +159 -0
- package/samples/apps/user-data-rights-demo/bin/server.ts +35 -0
- package/samples/apps/user-data-rights-demo/package.json +16 -0
- package/samples/apps/user-data-rights-demo/src/feature.ts +200 -0
- package/samples/apps/user-data-rights-demo/src/run-config.ts +48 -0
- package/samples/apps/user-data-rights-demo/tsconfig.json +21 -0
- package/samples/apps/workspaces/README.md +69 -0
- package/samples/apps/workspaces/package.json +20 -0
- package/samples/apps/workspaces/playwright.config.ts +18 -0
- package/samples/apps/workspaces/src/app/auth-constants.ts +6 -0
- package/samples/apps/workspaces/src/app/client.tsx +11 -0
- package/samples/apps/workspaces/src/app/server.ts +47 -0
- package/samples/apps/workspaces/src/app/shell.tsx +51 -0
- package/samples/apps/workspaces/src/features/demo/feature.ts +89 -0
- package/samples/apps/workspaces/src/features/demo/i18n.ts +20 -0
- package/samples/apps/workspaces/src/features/demo/index.ts +2 -0
- package/samples/apps/workspaces/src/features/demo/schema/index.ts +1 -0
- package/samples/apps/workspaces/src/features/demo/schema/order.ts +43 -0
- package/samples/apps/workspaces/src/features/demo/web/index.ts +7 -0
- package/samples/apps/workspaces/src/features/demo-driver/feature.ts +31 -0
- package/samples/apps/workspaces/src/features/demo-driver/i18n.ts +10 -0
- package/samples/apps/workspaces/src/features/demo-driver/index.ts +2 -0
- package/samples/apps/workspaces/src/features/demo-driver/web/index.ts +7 -0
- package/samples/recipes/access-control/README.md +21 -0
- package/samples/recipes/access-control/package.json +8 -0
- package/samples/recipes/access-control/src/feature.ts +145 -0
- package/samples/recipes/anonymous-access/README.md +21 -0
- package/samples/recipes/anonymous-access/package.json +8 -0
- package/samples/recipes/anonymous-access/src/feature.ts +132 -0
- package/samples/recipes/anonymous-access-multitenant/README.md +21 -0
- package/samples/recipes/anonymous-access-multitenant/package.json +8 -0
- package/samples/recipes/anonymous-access-multitenant/src/feature.ts +65 -0
- package/samples/recipes/anonymous-access-multitenant/src/subdomain-resolver.ts +105 -0
- package/samples/recipes/apex-landing/README.md +32 -0
- package/samples/recipes/apex-landing/package.json +16 -0
- package/samples/recipes/apex-landing/playwright.config.ts +23 -0
- package/samples/recipes/apex-landing/src/constants.ts +7 -0
- package/samples/recipes/apex-landing/src/feature.ts +307 -0
- package/samples/recipes/apex-surface-auth/README.md +114 -0
- package/samples/recipes/apex-surface-auth/package.json +9 -0
- package/samples/recipes/apex-surface-auth/src/feature.ts +113 -0
- package/samples/recipes/api-worker-split/README.md +68 -0
- package/samples/recipes/api-worker-split/bin/api.ts +13 -0
- package/samples/recipes/api-worker-split/bin/kumiko.ts +7 -0
- package/samples/recipes/api-worker-split/bin/worker.ts +24 -0
- package/samples/recipes/api-worker-split/package.json +16 -0
- package/samples/recipes/api-worker-split/src/feature.ts +167 -0
- package/samples/recipes/auth-claims/README.md +21 -0
- package/samples/recipes/auth-claims/package.json +8 -0
- package/samples/recipes/auth-claims/src/feature.ts +123 -0
- package/samples/recipes/auth-foundation-providers/README.md +19 -0
- package/samples/recipes/auth-foundation-providers/package.json +9 -0
- package/samples/recipes/auth-foundation-providers/src/feature.ts +76 -0
- package/samples/recipes/auth-mfa/README.md +67 -0
- package/samples/recipes/auth-mfa/package.json +9 -0
- package/samples/recipes/auth-mfa/src/feature.ts +72 -0
- package/samples/recipes/basic-entity/README.md +64 -0
- package/samples/recipes/basic-entity/package.json +8 -0
- package/samples/recipes/basic-entity/src/feature.ts +45 -0
- package/samples/recipes/boot-check/README.md +54 -0
- package/samples/recipes/boot-check/package.json +8 -0
- package/samples/recipes/boot-check/src/feature.ts +29 -0
- package/samples/recipes/compliance-profiles-demo/README.md +68 -0
- package/samples/recipes/compliance-profiles-demo/package.json +9 -0
- package/samples/recipes/compliance-profiles-demo/src/feature.ts +27 -0
- package/samples/recipes/cross-feature-events/README.md +63 -0
- package/samples/recipes/cross-feature-events/package.json +9 -0
- package/samples/recipes/cross-feature-events/src/feature.ts +122 -0
- package/samples/recipes/crypto-shredding-hr/README.md +74 -0
- package/samples/recipes/crypto-shredding-hr/package.json +8 -0
- package/samples/recipes/crypto-shredding-hr/src/feature.ts +38 -0
- package/samples/recipes/currencies-global/README.md +21 -0
- package/samples/recipes/currencies-global/package.json +8 -0
- package/samples/recipes/currencies-global/src/entities/currency.ts +15 -0
- package/samples/recipes/currencies-global/src/entities/invoice.ts +18 -0
- package/samples/recipes/currencies-global/src/entities/tenant-currency.ts +19 -0
- package/samples/recipes/currencies-global/src/feature.ts +62 -0
- package/samples/recipes/currencies-global/src/handlers/invoice-create.write.ts +68 -0
- package/samples/recipes/currencies-global/src/handlers/invoice-detail.query.ts +19 -0
- package/samples/recipes/currencies-global/src/handlers/tenant-currency-assign.write.ts +40 -0
- package/samples/recipes/currencies-per-tenant/README.md +21 -0
- package/samples/recipes/currencies-per-tenant/package.json +8 -0
- package/samples/recipes/currencies-per-tenant/src/entities/currency.ts +20 -0
- package/samples/recipes/currencies-per-tenant/src/entities/invoice.ts +18 -0
- package/samples/recipes/currencies-per-tenant/src/feature.ts +29 -0
- package/samples/recipes/currencies-per-tenant/src/handlers/currency-create.write.ts +24 -0
- package/samples/recipes/currencies-per-tenant/src/handlers/invoice-create.write.ts +66 -0
- package/samples/recipes/currencies-per-tenant/src/handlers/invoice-detail.query.ts +19 -0
- package/samples/recipes/custom-fields-basic/README.md +84 -0
- package/samples/recipes/custom-fields-basic/package.json +9 -0
- package/samples/recipes/custom-fields-basic/src/feature.ts +98 -0
- package/samples/recipes/custom-handlers/README.md +46 -0
- package/samples/recipes/custom-handlers/package.json +8 -0
- package/samples/recipes/custom-handlers/src/feature.ts +118 -0
- package/samples/recipes/delivery-notifications/README.md +48 -0
- package/samples/recipes/delivery-notifications/package.json +9 -0
- package/samples/recipes/delivery-notifications/src/feature.ts +108 -0
- package/samples/recipes/designer-demo/README.md +16 -0
- package/samples/recipes/designer-demo/package.json +8 -0
- package/samples/recipes/designer-demo/src/feature.ts +55 -0
- package/samples/recipes/e2e-generator/README.md +19 -0
- package/samples/recipes/e2e-generator/package.json +8 -0
- package/samples/recipes/e2e-generator/src/feature.ts +83 -0
- package/samples/recipes/embedded/README.md +33 -0
- package/samples/recipes/embedded/package.json +8 -0
- package/samples/recipes/embedded/src/entities/contact.ts +46 -0
- package/samples/recipes/embedded/src/entities/invoice.ts +35 -0
- package/samples/recipes/embedded/src/entities/product.ts +14 -0
- package/samples/recipes/embedded/src/feature.ts +58 -0
- package/samples/recipes/embedded/src/handlers/contact-create.write.ts +45 -0
- package/samples/recipes/embedded/src/handlers/contact-detail.query.ts +20 -0
- package/samples/recipes/embedded-entity-form/README.md +65 -0
- package/samples/recipes/embedded-entity-form/package.json +14 -0
- package/samples/recipes/embedded-entity-form/src/entities/prospect.ts +21 -0
- package/samples/recipes/embedded-entity-form/src/entities/suggestion.ts +22 -0
- package/samples/recipes/embedded-entity-form/src/feature.ts +120 -0
- package/samples/recipes/embedded-entity-form/src/screens/prospect-accept-screen.ts +13 -0
- package/samples/recipes/embedded-entity-form/src/web/accept-suggestion-drawer.tsx +125 -0
- package/samples/recipes/embedded-entity-form/tsconfig.json +8 -0
- package/samples/recipes/encrypted-tenant-config/README.md +131 -0
- package/samples/recipes/encrypted-tenant-config/package.json +9 -0
- package/samples/recipes/encrypted-tenant-config/src/feature.ts +100 -0
- package/samples/recipes/error-contract/README.md +97 -0
- package/samples/recipes/error-contract/package.json +8 -0
- package/samples/recipes/error-contract/src/feature.ts +238 -0
- package/samples/recipes/event-sourcing/README.md +70 -0
- package/samples/recipes/event-sourcing/package.json +9 -0
- package/samples/recipes/event-sourcing/src/feature.ts +486 -0
- package/samples/recipes/event-sourcing/tsconfig.json +26 -0
- package/samples/recipes/feature-toggles/README.md +21 -0
- package/samples/recipes/feature-toggles/package.json +9 -0
- package/samples/recipes/feature-toggles/src/feature.ts +111 -0
- package/samples/recipes/field-access/README.md +71 -0
- package/samples/recipes/field-access/package.json +8 -0
- package/samples/recipes/field-access/src/feature.ts +32 -0
- package/samples/recipes/files-post-processing/README.md +21 -0
- package/samples/recipes/files-post-processing/package.json +12 -0
- package/samples/recipes/files-post-processing/src/feature.ts +138 -0
- package/samples/recipes/i18n/README.md +36 -0
- package/samples/recipes/i18n/package.json +8 -0
- package/samples/recipes/i18n/src/feature.ts +52 -0
- package/samples/recipes/idempotency/README.md +21 -0
- package/samples/recipes/idempotency/package.json +8 -0
- package/samples/recipes/idempotency/src/feature.ts +50 -0
- package/samples/recipes/inbound-mail-triage/README.md +30 -0
- package/samples/recipes/inbound-mail-triage/package.json +9 -0
- package/samples/recipes/inbound-mail-triage/src/feature.ts +68 -0
- package/samples/recipes/lane-routing/README.md +21 -0
- package/samples/recipes/lane-routing/package.json +8 -0
- package/samples/recipes/lane-routing/src/feature.ts +106 -0
- package/samples/recipes/ledger-banking/README.md +47 -0
- package/samples/recipes/ledger-banking/package.json +9 -0
- package/samples/recipes/ledger-banking/src/usage.ts +86 -0
- package/samples/recipes/ledger-invoicing/README.md +54 -0
- package/samples/recipes/ledger-invoicing/package.json +9 -0
- package/samples/recipes/ledger-invoicing/src/usage.ts +93 -0
- package/samples/recipes/legal-pages/README.md +204 -0
- package/samples/recipes/legal-pages/package.json +9 -0
- package/samples/recipes/legal-pages/src/feature.ts +50 -0
- package/samples/recipes/lifecycle-hooks/README.md +46 -0
- package/samples/recipes/lifecycle-hooks/package.json +8 -0
- package/samples/recipes/lifecycle-hooks/src/feature.ts +104 -0
- package/samples/recipes/managed-config/README.md +136 -0
- package/samples/recipes/managed-config/package.json +9 -0
- package/samples/recipes/managed-config/src/feature.ts +88 -0
- package/samples/recipes/managed-pages/README.md +158 -0
- package/samples/recipes/managed-pages/package.json +9 -0
- package/samples/recipes/managed-pages/src/feature.ts +25 -0
- package/samples/recipes/notes-history-basic/README.md +93 -0
- package/samples/recipes/notes-history-basic/package.json +9 -0
- package/samples/recipes/notes-history-basic/src/feature.ts +72 -0
- package/samples/recipes/notes-history-basic/src/usage.ts +42 -0
- package/samples/recipes/ownership/README.md +21 -0
- package/samples/recipes/ownership/package.json +8 -0
- package/samples/recipes/ownership/src/feature.ts +98 -0
- package/samples/recipes/pipeline-basics/README.md +106 -0
- package/samples/recipes/pipeline-basics/package.json +8 -0
- package/samples/recipes/pipeline-basics/src/feature.ts +424 -0
- package/samples/recipes/pipeline-basics/tsconfig.json +15 -0
- package/samples/recipes/public-share-token/README.md +37 -0
- package/samples/recipes/public-share-token/package.json +8 -0
- package/samples/recipes/public-share-token/src/feature.ts +197 -0
- package/samples/recipes/rate-limiting/README.md +21 -0
- package/samples/recipes/rate-limiting/package.json +8 -0
- package/samples/recipes/rate-limiting/src/feature.ts +26 -0
- package/samples/recipes/realtime-sse/README.md +21 -0
- package/samples/recipes/realtime-sse/package.json +8 -0
- package/samples/recipes/realtime-sse/src/feature.ts +27 -0
- package/samples/recipes/record-detail-layout/README.md +25 -0
- package/samples/recipes/record-detail-layout/package.json +22 -0
- package/samples/recipes/record-detail-layout/src/feature.ts +140 -0
- package/samples/recipes/reference-data/README.md +21 -0
- package/samples/recipes/reference-data/package.json +8 -0
- package/samples/recipes/reference-data/src/feature.ts +37 -0
- package/samples/recipes/relations/README.md +21 -0
- package/samples/recipes/relations/package.json +8 -0
- package/samples/recipes/relations/src/feature.ts +81 -0
- package/samples/recipes/screens-nav/README.md +19 -0
- package/samples/recipes/screens-nav/package.json +8 -0
- package/samples/recipes/screens-nav/src/feature.ts +142 -0
- package/samples/recipes/search/README.md +21 -0
- package/samples/recipes/search/package.json +8 -0
- package/samples/recipes/search/src/feature.ts +72 -0
- package/samples/recipes/secrets-demo/README.md +21 -0
- package/samples/recipes/secrets-demo/package.json +9 -0
- package/samples/recipes/secrets-demo/src/feature.ts +88 -0
- package/samples/recipes/security-baseline/README.md +81 -0
- package/samples/recipes/security-baseline/package.json +9 -0
- package/samples/recipes/security-baseline/src/feature.ts +19 -0
- package/samples/recipes/seed-migration/README.md +81 -0
- package/samples/recipes/seed-migration/package.json +10 -0
- package/samples/recipes/seed-migration/scripts/smoke.ts +125 -0
- package/samples/recipes/seed-migration/seeds/2026-01-01-initial-tenants.ts +32 -0
- package/samples/recipes/seed-migration/seeds/2026-02-01-fix-admin-roles.ts +38 -0
- package/samples/recipes/session-revocation/README.md +49 -0
- package/samples/recipes/session-revocation/package.json +9 -0
- package/samples/recipes/session-revocation/src/feature.ts +50 -0
- package/samples/recipes/state-machine/README.md +21 -0
- package/samples/recipes/state-machine/package.json +9 -0
- package/samples/recipes/state-machine/src/entities/invoice.ts +35 -0
- package/samples/recipes/state-machine/src/events.ts +32 -0
- package/samples/recipes/state-machine/src/feature.ts +89 -0
- package/samples/recipes/state-machine/src/handlers/_helpers.ts +68 -0
- package/samples/recipes/state-machine/src/handlers/create.ts +27 -0
- package/samples/recipes/state-machine/src/handlers/transitions.ts +137 -0
- package/samples/recipes/state-machine/src/reducer.ts +50 -0
- package/samples/recipes/state-machine/tsconfig.json +26 -0
- package/samples/recipes/tags-basic/README.md +100 -0
- package/samples/recipes/tags-basic/package.json +9 -0
- package/samples/recipes/tags-basic/src/feature.ts +71 -0
- package/samples/recipes/tags-basic/src/usage.ts +50 -0
- package/samples/recipes/tenant-isolation/README.md +21 -0
- package/samples/recipes/tenant-isolation/package.json +8 -0
- package/samples/recipes/tenant-isolation/src/feature.ts +28 -0
- package/samples/recipes/tenant-settings/README.md +112 -0
- package/samples/recipes/tenant-settings/package.json +9 -0
- package/samples/recipes/tenant-settings/src/feature.ts +35 -0
- package/samples/recipes/tier-admin/README.md +80 -0
- package/samples/recipes/tier-admin/package.json +9 -0
- package/samples/recipes/tier-admin/src/feature.ts +60 -0
- package/samples/recipes/timezones/README.md +97 -0
- package/samples/recipes/timezones/package.json +8 -0
- package/samples/recipes/timezones/src/feature.ts +72 -0
- package/samples/recipes/tsconfig.base.json +23 -0
- package/samples/recipes/user-data-rights/README.md +100 -0
- package/samples/recipes/user-data-rights/package.json +9 -0
- package/samples/recipes/user-data-rights/src/feature.ts +97 -0
- package/samples/recipes/user-profile/README.md +86 -0
- package/samples/recipes/user-profile/package.json +9 -0
- package/samples/recipes/user-profile/src/feature.ts +73 -0
- package/samples/recipes/webhook-step/README.md +47 -0
- package/samples/recipes/webhook-step/package.json +9 -0
- package/samples/recipes/webhook-step/src/feature.ts +203 -0
- package/samples/recipes/webhook-step/tsconfig.json +18 -0
- package/samples/recipes/wizard-form/README.md +79 -0
- package/samples/recipes/wizard-form/package.json +23 -0
- package/samples/recipes/wizard-form/src/entities/listing.ts +27 -0
- package/samples/recipes/wizard-form/src/feature.ts +48 -0
- package/samples/recipes/wizard-form/src/web/index.ts +16 -0
- package/samples/recipes/wizard-form/src/web/listing-review-section.tsx +21 -0
- package/samples/recipes/wizard-form/tsconfig.json +8 -0
- package/samples/recipes/workflow-engine/README.md +21 -0
- package/samples/recipes/workflow-engine/package.json +9 -0
- package/samples/recipes/workflow-engine/src/cron-scheduler.ts +110 -0
- package/samples/recipes/workflow-engine/src/db/queries/suspended-runs.ts +14 -0
- package/samples/recipes/workflow-engine/src/event-trigger.ts +84 -0
- package/samples/recipes/workflow-engine/src/feature.ts +167 -0
- package/samples/recipes/workflow-engine/src/postgres-resume-loop.ts +98 -0
- package/samples/recipes/workflow-engine/src/resume-loop.ts +209 -0
- package/samples/recipes/workflow-engine/src/workflow-runner.ts +97 -0
- package/samples/recipes/workflow-engine/tsconfig.json +21 -0
- package/samples/recipes/writeform-section/README.md +30 -0
- package/samples/recipes/writeform-section/package.json +23 -0
- package/samples/recipes/writeform-section/src/feature.ts +123 -0
- package/samples/recipes/writeform-section/src/note-fixture.ts +8 -0
- package/samples/recipes/writeform-section/tsconfig.json +8 -0
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
// Async Export-Job Worker (S2.U3 Atom 3b) — pure Pipeline-Function.
|
|
2
|
+
//
|
|
3
|
+
// Spec: docs/plans/architecture/user-data-rights.md "Async Export-Pipeline".
|
|
4
|
+
// Cron-getriggert (siehe r.job-Wrap im feature.ts), iteriert ueber alle
|
|
5
|
+
// pending-Jobs in einem Pass, fuehrt pro Job aus:
|
|
6
|
+
//
|
|
7
|
+
// 1. Claim: `crud.update({status: running, startedAt})` mit
|
|
8
|
+
// optimistic-locking via version-Spalte. Wenn 2 Worker-Replicas
|
|
9
|
+
// denselben Job picken wollen, gewinnt der erste, der zweite
|
|
10
|
+
// kriegt VersionConflictError + skippt.
|
|
11
|
+
//
|
|
12
|
+
// 2. Bundle bauen: runUserExport({db, registry, userId, now}) →
|
|
13
|
+
// UserExportBundle (siehe run-user-export.ts). Cross-Tenant-
|
|
14
|
+
// Iteration ueber Memberships ist dort implementiert.
|
|
15
|
+
//
|
|
16
|
+
// 3. Profile-Resolution: `resolveProfileForTenant(requestedFromTenantId)`
|
|
17
|
+
// liefert effective compliance-profile. exportDownloadTtl wird
|
|
18
|
+
// fuer expiresAt-Berechnung gebraucht.
|
|
19
|
+
//
|
|
20
|
+
// 4. Storage-Provider builden: `buildStorageProvider(ctx, requestedFromTenantId)`
|
|
21
|
+
// — file-foundation's createFileProviderForTenant-Pattern.
|
|
22
|
+
// Pro Tenant unterschiedlicher Provider moeglich (S3 vs lokal).
|
|
23
|
+
//
|
|
24
|
+
// 5. ZIP-Stream: `createZipStream(bundleAsZipEntries(bundle))` →
|
|
25
|
+
// AsyncIterable<Uint8Array>. Wir wrappen das in einen tracking-
|
|
26
|
+
// Iterator der bytesWritten zaehlt.
|
|
27
|
+
//
|
|
28
|
+
// 6. Storage-Write: provider.writeStream(storageKey, zipStream).
|
|
29
|
+
// Atomar via tmp+rename (lokal) bzw. multipart-upload (S3).
|
|
30
|
+
//
|
|
31
|
+
// 7. Job=done: `crud.update({status: "done", completedAt, expiresAt,
|
|
32
|
+
// downloadStorageKey, bytesWritten})`.
|
|
33
|
+
//
|
|
34
|
+
// Bei Throw zwischen 2-7: Job=failed mit errorMessage. Storage-Write
|
|
35
|
+
// ist atomar (writeStream rollback bei Error im Source-Stream), keine
|
|
36
|
+
// halb-fertigen ZIPs am final-Pfad.
|
|
37
|
+
//
|
|
38
|
+
// **Stale-Detection:** vor dem Pickup-Pass laeuft ein separater
|
|
39
|
+
// Stale-Pass: Jobs in `running` mit `startedAt + exportStaleTimeoutMinutes
|
|
40
|
+
// < now` werden auf `failed` geflippt. Worker-Crashes / OOM-Kills /
|
|
41
|
+
// Replica-Restarts hinterlassen sonst stuck-running-Jobs.
|
|
42
|
+
//
|
|
43
|
+
// **Storage-Cleanup:** dritter Pass loescht abgelaufene downloadStorageKeys
|
|
44
|
+
// (`expiresAt + exportStorageCleanupGraceHours < now`) — abgelaufene ZIPs
|
|
45
|
+
// auf S3 sollen nicht ewig liegen.
|
|
46
|
+
|
|
47
|
+
import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
48
|
+
import { addDurationSpec } from "@cosmicdrift/kumiko-framework/compliance";
|
|
49
|
+
import { PII_ERASED_SENTINEL } from "@cosmicdrift/kumiko-framework/crypto";
|
|
50
|
+
import type { DbConnection, DbRunner } from "@cosmicdrift/kumiko-framework/db";
|
|
51
|
+
import { createEventStoreExecutor, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
52
|
+
import type {
|
|
53
|
+
EscapeHatchAuditSink,
|
|
54
|
+
Registry,
|
|
55
|
+
TenantId,
|
|
56
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
57
|
+
import { createSystemUser } from "@cosmicdrift/kumiko-framework/engine";
|
|
58
|
+
import {
|
|
59
|
+
createZipStream,
|
|
60
|
+
type FileStorageProvider,
|
|
61
|
+
tenantExportPrefix,
|
|
62
|
+
type ZipEntry,
|
|
63
|
+
} from "@cosmicdrift/kumiko-framework/files";
|
|
64
|
+
import type { MetricsHandle } from "@cosmicdrift/kumiko-framework/observability";
|
|
65
|
+
import type { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
66
|
+
import { resolveProfileForTenant } from "../compliance-profiles/index.js";
|
|
67
|
+
import { decryptStoredPii } from "../shared/index.js";
|
|
68
|
+
import { userTable } from "../user/index.js";
|
|
69
|
+
import { selectExportJobsForStorageCleanup } from "./db/queries/export-jobs.js";
|
|
70
|
+
import { runUserExport, type UserExportBundle } from "./run-user-export.js";
|
|
71
|
+
import { exportDownloadTokenEntity, exportDownloadTokensTable } from "./schema/download-token.js";
|
|
72
|
+
import { EXPORT_JOB_STATUS, exportJobEntity, exportJobsTable } from "./schema/export-job.js";
|
|
73
|
+
import { generateDownloadToken } from "./token-helpers.js";
|
|
74
|
+
|
|
75
|
+
type Instant = InstanceType<ReturnType<typeof getTemporal>["Instant"]>;
|
|
76
|
+
|
|
77
|
+
// Gauge short name (feature.ts registers it via r.metric + resolves ctx.meter
|
|
78
|
+
// into a MetricsHandle — jobs get no bound ctx.metrics, see feature.ts).
|
|
79
|
+
// No "_seconds"/"_total" suffix: validateMetricName rejects both on a gauge.
|
|
80
|
+
// Unit lives in the r.metric() `unit: "seconds"` declaration instead.
|
|
81
|
+
export const EXPORT_CLEANUP_BACKLOG_AGE_METRIC = "export_cleanup_backlog_age";
|
|
82
|
+
|
|
83
|
+
// Unix seconds of the last storage-cleanup pass that ran to completion. A
|
|
84
|
+
// gauge keeps its last value in-process (no TTL), so a dead cron does not make
|
|
85
|
+
// the backlog gauge disappear — alert on `time() - this > interval + buffer`.
|
|
86
|
+
export const EXPORT_CLEANUP_LAST_RUN_TIMESTAMP_METRIC = "export_cleanup_last_run_timestamp";
|
|
87
|
+
|
|
88
|
+
const crud = createEventStoreExecutor(exportJobsTable, exportJobEntity, {
|
|
89
|
+
entityName: "export-job",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Atom 4a — separater ES-Executor fuer Download-Tokens. crud.create
|
|
93
|
+
// emittiert `exportDownloadToken.created`-Event in den event-store +
|
|
94
|
+
// projected synchron auf read_export_download_tokens. KEIN direct-INSERT
|
|
95
|
+
// (Memory `feedback_no_fake_dispatcher`).
|
|
96
|
+
//
|
|
97
|
+
// Exportiert weil Atom 4b's download-handler tokenCrud.update fuer
|
|
98
|
+
// Audit-Felder (useCount, lastUsedAt, IP, UA) nutzt — ES-konsistent.
|
|
99
|
+
export const tokenCrud = createEventStoreExecutor(
|
|
100
|
+
exportDownloadTokensTable,
|
|
101
|
+
exportDownloadTokenEntity,
|
|
102
|
+
{ entityName: "export-download-token" },
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Notification-Callback fuer den done-Pfad. Pattern matched
|
|
107
|
+
* auth-routes.PasswordResetConfig.sendResetEmail. Plain-Token bleibt
|
|
108
|
+
* ephemeral (nicht in DB/event-store/jobRunsTable). App-Author wired
|
|
109
|
+
* den Callback an seinen Email-Provider:
|
|
110
|
+
* - existing `delivery.notify` (multi-channel + delivery_attempts-Log)
|
|
111
|
+
* - `mailFoundation.send` direkt
|
|
112
|
+
* - Custom Resend/SES/etc.
|
|
113
|
+
*
|
|
114
|
+
* **Best-effort:** Throw vom Callback bubbelt zum r.job-Wrap; jobs-
|
|
115
|
+
* Feature persistiert den Worker-Run als failed in jobRunsTable. Der
|
|
116
|
+
* Failed-Pfad wird in `jobs/__tests__/jobs-feature.integration.ts`
|
|
117
|
+
* Scenario 2 gepinnt — wir verweisen darauf statt end-zu-end zu
|
|
118
|
+
* duplizieren. Operator sieht's im /jobs-Dashboard, kann via
|
|
119
|
+
* jobs:write:retry den Worker-Run erneut anstossen (Job selbst bleibt
|
|
120
|
+
* done; retry findet keinen pending mehr, aber Audit-Log zeigt den
|
|
121
|
+
* Failure).
|
|
122
|
+
*
|
|
123
|
+
* **Plain-Token-Recovery bei Email-Fail:** plain ist ephemeral. Wenn
|
|
124
|
+
* der Callback throwt, ist der plain verloren. Operator-Eingriff
|
|
125
|
+
* noetig: Job auf pending flippen — NUR das. Die Token-Row NICHT
|
|
126
|
+
* loeschen (eventloser Read-Side-Delete → Rebuild-Kollision, fw#832);
|
|
127
|
+
* der naechste Worker-Run rotiert das Token in place auf demselben
|
|
128
|
+
* Aggregat. Atom 5b (Re-issue-handler) wird das automatisieren.
|
|
129
|
+
*/
|
|
130
|
+
export type SendExportReadyEmailFn = (args: {
|
|
131
|
+
readonly userId: string;
|
|
132
|
+
readonly userEmail: string;
|
|
133
|
+
/** Stored user.locale (free-form, e.g. "de"/"en"/"de-DE"/null) — lets the
|
|
134
|
+
* default mailer render in the recipient's language. */
|
|
135
|
+
readonly userLocale: string | null;
|
|
136
|
+
readonly tenantId: TenantId;
|
|
137
|
+
readonly jobId: string;
|
|
138
|
+
readonly downloadUrl: string;
|
|
139
|
+
readonly expiresAt: string;
|
|
140
|
+
readonly bytesWritten: number | null;
|
|
141
|
+
}) => Promise<void>;
|
|
142
|
+
|
|
143
|
+
export type SendExportFailedEmailFn = (args: {
|
|
144
|
+
readonly userId: string;
|
|
145
|
+
readonly userEmail: string;
|
|
146
|
+
readonly userLocale: string | null;
|
|
147
|
+
readonly tenantId: TenantId;
|
|
148
|
+
readonly jobId: string;
|
|
149
|
+
readonly errorMessage: string;
|
|
150
|
+
}) => Promise<void>;
|
|
151
|
+
|
|
152
|
+
export interface RunExportJobsArgs {
|
|
153
|
+
readonly db: DbConnection;
|
|
154
|
+
readonly registry: Registry;
|
|
155
|
+
/**
|
|
156
|
+
* Per-Tenant Storage-Provider-Builder. App-Bootstrap liefert den
|
|
157
|
+
* file-foundation-Resolver via `createFileProviderForTenant` —
|
|
158
|
+
* Worker bekommt eine kleinere Surface ohne HandlerContext-Dep.
|
|
159
|
+
*/
|
|
160
|
+
readonly buildStorageProvider: (tenantId: TenantId) => Promise<FileStorageProvider>;
|
|
161
|
+
/** Now-Injection — Tests pinnen den Wert ohne Date-Mock. */
|
|
162
|
+
readonly now: Instant;
|
|
163
|
+
|
|
164
|
+
/** S2.U3 Atom 5 — Email-Notification beim done-flip. Optional;
|
|
165
|
+
* wenn nicht gesetzt, sendet der Worker keine notification (User
|
|
166
|
+
* kann aber via export-status.query polln + UI-Klick). */
|
|
167
|
+
readonly sendExportReadyEmail?: SendExportReadyEmailFn;
|
|
168
|
+
/** Optional Email beim failed-flip. */
|
|
169
|
+
readonly sendExportFailedEmail?: SendExportFailedEmailFn;
|
|
170
|
+
/** Base-URL fuer den Magic-Link. App-Author setzt das (z.B.
|
|
171
|
+
* "https://app.example.com/user-export/by-token"). Worker baut
|
|
172
|
+
* a URL fragment (not a query param — see issue #1271) and passes that
|
|
173
|
+
* Callback durch. Required wenn sendExportReadyEmail gesetzt. */
|
|
174
|
+
readonly appExportDownloadUrl?: string;
|
|
175
|
+
|
|
176
|
+
// fw#2914 — sourced from the owning job's ctx (_escapeHatchAuditSink,
|
|
177
|
+
// systemUser.id); threaded into runUserExport's per-hook TenantDb.
|
|
178
|
+
readonly escapeHatchAuditSink?: EscapeHatchAuditSink;
|
|
179
|
+
readonly actor?: string;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Reports EXPORT_CLEANUP_BACKLOG_AGE_METRIC after the storage-cleanup
|
|
183
|
+
* pass. Optional so callers without an observability provider still work.
|
|
184
|
+
*/
|
|
185
|
+
readonly metrics?: MetricsHandle;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ExportJobError {
|
|
189
|
+
readonly jobId: string;
|
|
190
|
+
readonly userId: string;
|
|
191
|
+
readonly phase: "claim" | "bundle" | "zip-write" | "complete";
|
|
192
|
+
readonly message: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface RunExportJobsResult {
|
|
196
|
+
/** Job-IDs die in diesem Pass von pending → done geflippt wurden. */
|
|
197
|
+
readonly completedJobIds: readonly string[];
|
|
198
|
+
/** Job-IDs die in diesem Pass von pending → failed geflippt wurden. */
|
|
199
|
+
readonly failedJobIds: readonly string[];
|
|
200
|
+
/** Job-IDs die als stuck-running auf failed geflippt wurden (Stale-Pass). */
|
|
201
|
+
readonly staleFailedJobIds: readonly string[];
|
|
202
|
+
/** Job-IDs deren downloadStorageKey im Cleanup-Pass geloescht wurde. */
|
|
203
|
+
readonly cleanedJobIds: readonly string[];
|
|
204
|
+
readonly errors: readonly ExportJobError[];
|
|
205
|
+
/**
|
|
206
|
+
* Plain-Tokens fuer in diesem Pass completed-Jobs. Map<jobId, plain>.
|
|
207
|
+
* Atom 5 (Notification) liest das + versendet plain per Email.
|
|
208
|
+
* NIEMALS persistiert — nur in-memory zwischen Worker-Run und
|
|
209
|
+
* Notification-Hook. NACH dem Run ist plain nur via DB-Hash
|
|
210
|
+
* verifizierbar (Atom 4b's Download-Endpoint).
|
|
211
|
+
*/
|
|
212
|
+
readonly tokenByJobId: ReadonlyMap<string, string>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export async function runExportJobs(args: RunExportJobsArgs): Promise<RunExportJobsResult> {
|
|
216
|
+
const { db, registry, buildStorageProvider, now, sendExportReadyEmail, sendExportFailedEmail } =
|
|
217
|
+
args;
|
|
218
|
+
|
|
219
|
+
// Boot-Misconfig-Check: wer sendExportReadyEmail setzt aber URL
|
|
220
|
+
// vergisst, soll einen klaren Error sehen — VOR dem Pass-Loop, damit
|
|
221
|
+
// der Throw nicht vom per-Job-try/catch (Atom 5.fix3) geschluckt wird.
|
|
222
|
+
// Runtime-Callback-Failures sind best-effort, Boot-Misconfig ist hard-
|
|
223
|
+
// fail (App-Author-Bug, kein Network-Hiccup).
|
|
224
|
+
if (sendExportReadyEmail && args.appExportDownloadUrl === undefined) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
"user-data-rights: sendExportReadyEmail gesetzt aber appExportDownloadUrl fehlt — beide muessen zusammen konfiguriert sein",
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Pass 1: Stale-Detection — running jobs die laenger als das tenant-
|
|
231
|
+
// spezifische exportStaleTimeoutMinutes haengen werden gefailed.
|
|
232
|
+
// Wird VOR dem pickup-pass ausgefuehrt damit ein neuer Worker-Run
|
|
233
|
+
// den vorhergehenden Crash erstmal als failed markiert.
|
|
234
|
+
const staleFailedJobIds = await staleDetectionPass({ db, now });
|
|
235
|
+
|
|
236
|
+
// Pass 2: Pickup pending jobs + Process them.
|
|
237
|
+
const completedJobIds: string[] = [];
|
|
238
|
+
const failedJobIds: string[] = [];
|
|
239
|
+
const errors: ExportJobError[] = [];
|
|
240
|
+
const tokenByJobId = new Map<string, string>();
|
|
241
|
+
|
|
242
|
+
const pendingJobs = await fetchPendingJobs(db);
|
|
243
|
+
for (const job of pendingJobs) {
|
|
244
|
+
const outcome = await processJob({
|
|
245
|
+
db,
|
|
246
|
+
registry,
|
|
247
|
+
buildStorageProvider,
|
|
248
|
+
now,
|
|
249
|
+
job,
|
|
250
|
+
escapeHatchAuditSink: args.escapeHatchAuditSink,
|
|
251
|
+
actor: args.actor,
|
|
252
|
+
});
|
|
253
|
+
if (outcome.kind === "done") {
|
|
254
|
+
completedJobIds.push(job.id);
|
|
255
|
+
// Worker hat plain im Memory; weitergeben fuer downstream-callbacks
|
|
256
|
+
// + Atom-5-Tests (RunExportJobsResult.tokenByJobId). Plain landet
|
|
257
|
+
// NICHT in Logs/Telemetry/jobRunsTable.
|
|
258
|
+
tokenByJobId.set(job.id, outcome.tokenPlain);
|
|
259
|
+
|
|
260
|
+
// Atom 5: Email-Notification beim done-flip.
|
|
261
|
+
//
|
|
262
|
+
// Best-effort (Atom 5.fix3): Throw fuer Job A darf den Batch nicht
|
|
263
|
+
// abwuergen — Job-Status ist bereits done committed, restliche
|
|
264
|
+
// pending-Jobs muessen noch verarbeitet werden. Throw waere ein
|
|
265
|
+
// Bug: r.job-Wrap markiert den Run failed, retry findet keinen
|
|
266
|
+
// pending-Job mehr (Status=done) → silent miss + ZIP laeuft nach
|
|
267
|
+
// TTL ab ohne dass der User die Email je bekommt. console.warn ist
|
|
268
|
+
// die einzige Operator-Sichtbarkeit (runExportJobs-args fuehren
|
|
269
|
+
// AppContext.log nicht durch — pure-function-Pattern).
|
|
270
|
+
if (sendExportReadyEmail) {
|
|
271
|
+
try {
|
|
272
|
+
await fireExportReadyCallback({
|
|
273
|
+
db,
|
|
274
|
+
job,
|
|
275
|
+
plainToken: outcome.tokenPlain,
|
|
276
|
+
bytesWritten: outcome.bytesWritten,
|
|
277
|
+
expiresAt: outcome.expiresAt,
|
|
278
|
+
appExportDownloadUrl: args.appExportDownloadUrl,
|
|
279
|
+
send: sendExportReadyEmail,
|
|
280
|
+
});
|
|
281
|
+
} catch (err) {
|
|
282
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility for email-send-failure
|
|
283
|
+
console.warn(
|
|
284
|
+
`[user-data-rights:run-export-jobs] sendExportReadyEmail failed jobId=${job.id} userId=${job.userId} err=${err instanceof Error ? err.message : String(err)}`,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
} else if (outcome.kind === "failed") {
|
|
289
|
+
failedJobIds.push(job.id);
|
|
290
|
+
errors.push(outcome.error);
|
|
291
|
+
|
|
292
|
+
// Atom 5: Email-Notification beim failed-flip — User soll wissen
|
|
293
|
+
// dass er neuen Export anfordern muss. Best-effort analog
|
|
294
|
+
// sendExportReadyEmail (Atom 5.fix3) — Email-Send-Throw darf den
|
|
295
|
+
// Batch nicht killen.
|
|
296
|
+
if (sendExportFailedEmail) {
|
|
297
|
+
try {
|
|
298
|
+
await fireExportFailedCallback({
|
|
299
|
+
db,
|
|
300
|
+
job,
|
|
301
|
+
errorMessage: outcome.error.message,
|
|
302
|
+
send: sendExportFailedEmail,
|
|
303
|
+
});
|
|
304
|
+
} catch (err) {
|
|
305
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility for email-send-failure
|
|
306
|
+
console.warn(
|
|
307
|
+
`[user-data-rights:run-export-jobs] sendExportFailedEmail failed jobId=${job.id} userId=${job.userId} err=${err instanceof Error ? err.message : String(err)}`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// "skipped" (claim race lost) wird still passiert — kein error,
|
|
313
|
+
// anderer Worker hat den Job bereits.
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Pass 3: Storage-Cleanup — abgelaufene done-Jobs (expiresAt+grace < now)
|
|
317
|
+
// bekommen ihren downloadStorageKey aus dem Storage-Provider geloescht
|
|
318
|
+
// + im DB-Row genullt.
|
|
319
|
+
const cleanedJobIds = await storageCleanupPass({
|
|
320
|
+
db,
|
|
321
|
+
buildStorageProvider,
|
|
322
|
+
now,
|
|
323
|
+
metrics: args.metrics,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
completedJobIds,
|
|
328
|
+
failedJobIds,
|
|
329
|
+
staleFailedJobIds,
|
|
330
|
+
cleanedJobIds,
|
|
331
|
+
errors,
|
|
332
|
+
tokenByJobId,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
interface JobRow {
|
|
337
|
+
readonly id: string;
|
|
338
|
+
readonly version: number;
|
|
339
|
+
readonly userId: string;
|
|
340
|
+
readonly requestedFromTenantId: TenantId;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// @wrapper-known semantic-alias
|
|
344
|
+
async function fetchPendingJobs(db: DbRunner): Promise<readonly JobRow[]> {
|
|
345
|
+
return selectMany<JobRow>(
|
|
346
|
+
db,
|
|
347
|
+
exportJobsTable,
|
|
348
|
+
{ status: EXPORT_JOB_STATUS.Pending },
|
|
349
|
+
{
|
|
350
|
+
orderBy: { col: "requestedAt", direction: "asc" },
|
|
351
|
+
},
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
type ProcessOutcome =
|
|
356
|
+
| {
|
|
357
|
+
kind: "done";
|
|
358
|
+
tokenPlain: string;
|
|
359
|
+
expiresAt: Instant;
|
|
360
|
+
bytesWritten: number;
|
|
361
|
+
}
|
|
362
|
+
| { kind: "failed"; error: ExportJobError }
|
|
363
|
+
| { kind: "skipped" }; // claim-race-loss (anderer Worker)
|
|
364
|
+
|
|
365
|
+
async function processJob(args: {
|
|
366
|
+
db: DbConnection;
|
|
367
|
+
registry: Registry;
|
|
368
|
+
buildStorageProvider: (tenantId: TenantId) => Promise<FileStorageProvider>;
|
|
369
|
+
now: Instant;
|
|
370
|
+
job: JobRow;
|
|
371
|
+
escapeHatchAuditSink?: EscapeHatchAuditSink;
|
|
372
|
+
actor?: string;
|
|
373
|
+
}): Promise<ProcessOutcome> {
|
|
374
|
+
const { db, registry, buildStorageProvider, now, job } = args;
|
|
375
|
+
const executor = createSystemUser(job.requestedFromTenantId);
|
|
376
|
+
// crud.update braucht TenantDb fuer Stream-Identity (Memory
|
|
377
|
+
// feedback_event_store_tenant_consistency). system-mode bypassed
|
|
378
|
+
// den auto-tenant-filter; Stream wird ueber requestedFromTenantId
|
|
379
|
+
// konsistent gehalten.
|
|
380
|
+
const tdb = systemTenantDb(db, job.requestedFromTenantId);
|
|
381
|
+
|
|
382
|
+
// Phase 1: Claim — version-bumped update, scheitert via VersionConflict
|
|
383
|
+
// wenn paralleler Worker schon claimed hat.
|
|
384
|
+
//
|
|
385
|
+
// **Path-pre-claim** (Atom 4a.fix): downloadStorageKey wird HIER schon
|
|
386
|
+
// persistiert (deterministischer Pfad aus job.id). Begründung: wenn
|
|
387
|
+
// Worker zwischen ZIP-write und done-flip crashed, hat der Job-Row
|
|
388
|
+
// bereits den Pfad → storageCleanupPass kann den orphan-ZIP via
|
|
389
|
+
// failed-Job-Cleanup-Pass loeschen (sonst forever-leak im S3).
|
|
390
|
+
const storageKey = buildExportStorageKey(job);
|
|
391
|
+
const claimResult = await crud.update(
|
|
392
|
+
{
|
|
393
|
+
id: job.id,
|
|
394
|
+
version: job.version,
|
|
395
|
+
changes: {
|
|
396
|
+
status: EXPORT_JOB_STATUS.Running,
|
|
397
|
+
startedAt: now,
|
|
398
|
+
downloadStorageKey: storageKey,
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
executor,
|
|
402
|
+
tdb,
|
|
403
|
+
);
|
|
404
|
+
if (!claimResult.isSuccess) {
|
|
405
|
+
// Race-Loss: anderer Worker hat den Job claimed. Skip silently.
|
|
406
|
+
return { kind: "skipped" };
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Phase 2-6: Bundle bauen + ZIP-streamen + Storage-Write.
|
|
410
|
+
// Errors bis zur completion werden als job=failed materialisiert.
|
|
411
|
+
try {
|
|
412
|
+
const bundle = await runUserExport({
|
|
413
|
+
db,
|
|
414
|
+
registry,
|
|
415
|
+
userId: job.userId,
|
|
416
|
+
now,
|
|
417
|
+
escapeHatchAuditSink: args.escapeHatchAuditSink,
|
|
418
|
+
actor: args.actor,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const profile = await resolveProfileForTenant({
|
|
422
|
+
db,
|
|
423
|
+
tenantId: job.requestedFromTenantId,
|
|
424
|
+
});
|
|
425
|
+
const ttl = profile.profile.userRights.exportDownloadTtl;
|
|
426
|
+
|
|
427
|
+
// Per-Tenant-Provider-Cache: Cross-Tenant-fileRefs (Alice Member von
|
|
428
|
+
// Tenant A + B → File-Refs aus beiden) brauchen pro Tenant separat
|
|
429
|
+
// einen Provider-Build (S3-Bucket pro Tenant, andere config). Job-
|
|
430
|
+
// Tenant ist die Identitaet fuer den write-Pfad; read-Pfade gehen
|
|
431
|
+
// ueber den fileRef.tenantId.
|
|
432
|
+
const providerCache = new Map<TenantId, FileStorageProvider>();
|
|
433
|
+
const cachedProvider = async (tenantId: TenantId): Promise<FileStorageProvider> => {
|
|
434
|
+
let p = providerCache.get(tenantId);
|
|
435
|
+
if (!p) {
|
|
436
|
+
p = await buildStorageProvider(tenantId);
|
|
437
|
+
providerCache.set(tenantId, p);
|
|
438
|
+
}
|
|
439
|
+
return p;
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const writeProvider = await cachedProvider(job.requestedFromTenantId);
|
|
443
|
+
// writeStream + readStream sind im FileStorageProvider-Type required
|
|
444
|
+
// (Atom 3c.fix Type-Honesty) — keine Runtime-Optional-Checks mehr noetig.
|
|
445
|
+
|
|
446
|
+
const tracker = countingStream(
|
|
447
|
+
createZipStream(bundleToZipEntries(bundle, now, cachedProvider)),
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
await writeProvider.writeStream(storageKey, tracker.stream, {
|
|
451
|
+
mimeType: "application/zip",
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Phase 7: Token VOR done-flip (Atom 4a.fix Sequencing).
|
|
455
|
+
//
|
|
456
|
+
// Wenn Token-Create failt, bleibt Job in `running` → catch-Pfad
|
|
457
|
+
// flippt auf failed (monotone Status-Transition). Wenn Token-Create
|
|
458
|
+
// VOR und done-flip NACH: tightes Race-Window in dem ein Worker-
|
|
459
|
+
// Crash zwischen den zwei calls einen Token + ZIP orphans. Beides
|
|
460
|
+
// catched die Stale-Detection im naechsten Pass — Job=failed,
|
|
461
|
+
// Storage-Cleanup-Pass clearted den ZIP (path-pre-claim oben).
|
|
462
|
+
//
|
|
463
|
+
// Plain-Token bleibt im Worker-Memory + wird via RunExportJobsResult
|
|
464
|
+
// an Atom 5 (Notification) weitergegeben. NUR der hash landet in DB.
|
|
465
|
+
// ES via tokenCrud.create — kein direct-INSERT.
|
|
466
|
+
//
|
|
467
|
+
// **Re-Run (fw#832):** Flippt ein Operator einen done/failed-Job
|
|
468
|
+
// zurueck auf pending (Plain-Token verloren, Email-Fail), existiert
|
|
469
|
+
// fuers jobId schon eine Token-Row. Ein zweites create wuerde ein
|
|
470
|
+
// zweites `created`-Event auf frischem Aggregat emittieren — der
|
|
471
|
+
// Projection-Rebuild kollidiert dann dauerhaft am one_per_job-Index.
|
|
472
|
+
// Stattdessen: Token-Rotation in place auf demselben Aggregat
|
|
473
|
+
// (update mit frischem Hash + Reset der Audit-Felder).
|
|
474
|
+
const expiresAt = addDurationSpec(now, ttl);
|
|
475
|
+
const { plain: tokenPlain, hash: tokenHash } = await generateDownloadToken();
|
|
476
|
+
const existingToken = await fetchOne<{ id: string; version: number }>(
|
|
477
|
+
db,
|
|
478
|
+
exportDownloadTokensTable,
|
|
479
|
+
{ jobId: job.id },
|
|
480
|
+
);
|
|
481
|
+
const tokenCreateResult = existingToken
|
|
482
|
+
? await tokenCrud.update(
|
|
483
|
+
{
|
|
484
|
+
id: existingToken.id,
|
|
485
|
+
version: existingToken.version,
|
|
486
|
+
changes: {
|
|
487
|
+
tokenHash,
|
|
488
|
+
issuedAt: now,
|
|
489
|
+
expiresAt,
|
|
490
|
+
useCount: 0,
|
|
491
|
+
lastUsedAt: null,
|
|
492
|
+
lastUsedFromIp: null,
|
|
493
|
+
lastUsedUserAgent: null,
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
executor,
|
|
497
|
+
tdb,
|
|
498
|
+
)
|
|
499
|
+
: await tokenCrud.create(
|
|
500
|
+
{
|
|
501
|
+
jobId: job.id,
|
|
502
|
+
tokenHash,
|
|
503
|
+
issuedAt: now,
|
|
504
|
+
expiresAt,
|
|
505
|
+
// Atom 4a.fix: useCount explizit 0 statt default null. 4b's
|
|
506
|
+
// Verify-Pfad incrementiert via `useCount + 1` ohne COALESCE-
|
|
507
|
+
// Defensiv-Code.
|
|
508
|
+
useCount: 0,
|
|
509
|
+
},
|
|
510
|
+
executor,
|
|
511
|
+
tdb,
|
|
512
|
+
);
|
|
513
|
+
if (!tokenCreateResult.isSuccess) {
|
|
514
|
+
// Token-Creation failed VOR done-flip → Job bleibt running.
|
|
515
|
+
// Catch-Pfad flippt auf failed mit klarer Diagnose. Storage-
|
|
516
|
+
// Cleanup-Pass clearted den orphan-ZIP (path bereits via claim
|
|
517
|
+
// persistiert).
|
|
518
|
+
throw new Error(
|
|
519
|
+
`Job ${job.id}: Token-Creation failed before done-flip. ` +
|
|
520
|
+
`${(tokenCreateResult as { error?: { code?: string } }).error?.code ?? "unknown"}`, // @cast-boundary engine-payload
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Phase 8: Job=done. expiresAt wurde oben fuer Token gesetzt; identisch
|
|
525
|
+
// hier persistiert (denormalisiert in beiden Tabellen).
|
|
526
|
+
const doneResult = await crud.update(
|
|
527
|
+
{
|
|
528
|
+
id: job.id,
|
|
529
|
+
version: job.version + 1, // +1 weil wir bereits via claim einen update gemacht haben
|
|
530
|
+
changes: {
|
|
531
|
+
status: EXPORT_JOB_STATUS.Done,
|
|
532
|
+
completedAt: now,
|
|
533
|
+
// downloadStorageKey ist beim claim bereits gesetzt — kein
|
|
534
|
+
// Re-Set hier noetig (waere identisch).
|
|
535
|
+
expiresAt,
|
|
536
|
+
bytesWritten: tracker.bytes,
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
executor,
|
|
540
|
+
tdb,
|
|
541
|
+
);
|
|
542
|
+
if (!doneResult.isSuccess) {
|
|
543
|
+
// Sehr unerwartet — wir haben gerade claimed (version+1), niemand
|
|
544
|
+
// sollte den Job zwischenzeitlich aendern. Materialisieren als
|
|
545
|
+
// failed damit der Operator das sieht. Token-Row bleibt orphan
|
|
546
|
+
// bis Atom-spaeter-Cleanup; Storage-ZIP wird via failed-Cleanup
|
|
547
|
+
// gecleared.
|
|
548
|
+
throw new Error(
|
|
549
|
+
`Job ${job.id}: failed to flip status=done after successful Token-Create. ` +
|
|
550
|
+
`${(doneResult as { error?: { code?: string } }).error?.code ?? "unknown"}`, // @cast-boundary engine-payload
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return { kind: "done", tokenPlain, expiresAt, bytesWritten: tracker.bytes };
|
|
555
|
+
} catch (e) {
|
|
556
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
557
|
+
// Best-effort failure-flip. Wenn auch das failed (DB down etc.),
|
|
558
|
+
// bleibt der Job in running stehen — Stale-Detection im naechsten
|
|
559
|
+
// Worker-Run faengt ihn dann auf.
|
|
560
|
+
await crud
|
|
561
|
+
.update(
|
|
562
|
+
{
|
|
563
|
+
id: job.id,
|
|
564
|
+
version: job.version + 1,
|
|
565
|
+
changes: {
|
|
566
|
+
status: EXPORT_JOB_STATUS.Failed,
|
|
567
|
+
completedAt: now,
|
|
568
|
+
errorMessage: message,
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
executor,
|
|
572
|
+
tdb,
|
|
573
|
+
)
|
|
574
|
+
.catch(() => {
|
|
575
|
+
/* swallow — stale-detection kommt im nachsten Pass */
|
|
576
|
+
});
|
|
577
|
+
return {
|
|
578
|
+
kind: "failed",
|
|
579
|
+
error: {
|
|
580
|
+
jobId: job.id,
|
|
581
|
+
userId: job.userId,
|
|
582
|
+
phase: "zip-write",
|
|
583
|
+
message,
|
|
584
|
+
},
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async function staleDetectionPass(args: {
|
|
590
|
+
db: DbConnection;
|
|
591
|
+
now: Instant;
|
|
592
|
+
}): Promise<readonly string[]> {
|
|
593
|
+
const { db, now } = args;
|
|
594
|
+
|
|
595
|
+
// **Kein Coarse-Filter** — der vorherige `startedAt <= now-1h` Filter
|
|
596
|
+
// war fragile: profile.exportStaleTimeoutMinutes hat Default 30min und
|
|
597
|
+
// erlaubt per-Tenant-Override auf z.B. 5min. Ein 60min-Coarse-Filter
|
|
598
|
+
// wuerde 30-60min-alte stale-Jobs UNERKANNT lassen. Cron laeuft alle
|
|
599
|
+
// 60s, zu jedem Zeitpunkt sind nur wenige Jobs in `running` —
|
|
600
|
+
// alle fetchen + profile-resolve im Loop ist bezahlbar + korrekt.
|
|
601
|
+
const candidates = await selectMany<{
|
|
602
|
+
id: string;
|
|
603
|
+
version: number;
|
|
604
|
+
userId: string;
|
|
605
|
+
requestedFromTenantId: TenantId;
|
|
606
|
+
startedAt: Instant | null;
|
|
607
|
+
}>(db, exportJobsTable, { status: EXPORT_JOB_STATUS.Running });
|
|
608
|
+
|
|
609
|
+
const failed: string[] = [];
|
|
610
|
+
for (const c of candidates) {
|
|
611
|
+
const profile = await resolveProfileForTenant({
|
|
612
|
+
db,
|
|
613
|
+
tenantId: c.requestedFromTenantId,
|
|
614
|
+
});
|
|
615
|
+
const cutoffMs =
|
|
616
|
+
now.epochMilliseconds - profile.profile.userRights.exportStaleTimeoutMinutes * 60 * 1000;
|
|
617
|
+
const startedMs = c.startedAt?.epochMilliseconds ?? Number.MAX_SAFE_INTEGER;
|
|
618
|
+
if (startedMs < cutoffMs) {
|
|
619
|
+
const result = await crud.update(
|
|
620
|
+
{
|
|
621
|
+
id: c.id,
|
|
622
|
+
version: c.version,
|
|
623
|
+
changes: {
|
|
624
|
+
status: EXPORT_JOB_STATUS.Failed,
|
|
625
|
+
completedAt: now,
|
|
626
|
+
errorMessage: "stale: worker crashed mid-run",
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
createSystemUser(c.requestedFromTenantId),
|
|
630
|
+
systemTenantDb(db, c.requestedFromTenantId),
|
|
631
|
+
);
|
|
632
|
+
if (result.isSuccess) failed.push(c.id);
|
|
633
|
+
// Race-loss (Worker hat das Job parallel completed) → skip
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return failed;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async function storageCleanupPass(args: {
|
|
640
|
+
db: DbConnection;
|
|
641
|
+
buildStorageProvider: (tenantId: TenantId) => Promise<FileStorageProvider>;
|
|
642
|
+
now: Instant;
|
|
643
|
+
metrics?: MetricsHandle;
|
|
644
|
+
}): Promise<readonly string[]> {
|
|
645
|
+
const { db, buildStorageProvider, now, metrics } = args;
|
|
646
|
+
|
|
647
|
+
// Zwei Cleanup-Pfade:
|
|
648
|
+
//
|
|
649
|
+
// 1. **Done-Jobs** (TTL-expired): expiresAt + grace < now → cleanup.
|
|
650
|
+
// Per-Tenant-Grace aus Profile (default 24h post-expiry damit
|
|
651
|
+
// gleichzeitige Re-Downloads bei Connection-Abbrueche moeglich).
|
|
652
|
+
//
|
|
653
|
+
// 2. **Failed-Jobs mit downloadStorageKey** (Atom 4a.fix orphan-cleanup):
|
|
654
|
+
// Worker hat ZIP geschrieben, dann ist VOR done-flip etwas
|
|
655
|
+
// schiefgegangen (Token-Create-Fail, done-flip-Fail, Stale-
|
|
656
|
+
// Detection mid-write). Job=failed mit gesetztem downloadStorageKey =
|
|
657
|
+
// ZIP-Orphan in Storage, kein User-Pfad zum download.
|
|
658
|
+
//
|
|
659
|
+
// **Strategie failed-Jobs: SOFORTIGE Cleanup ohne Grace.**
|
|
660
|
+
//
|
|
661
|
+
// Trade-off (DSGVO vs Audit-Forensik):
|
|
662
|
+
// - DSGVO: User-Daten-ZIP einer failed-export-Anfrage hat keinen
|
|
663
|
+
// legitimen Aufbewahrungs-Grund — hier ueberwiegt das Recht auf
|
|
664
|
+
// Loeschung
|
|
665
|
+
// - Audit-Forensik: forensische Untersuchung ("was ist im ZIP gelandet,
|
|
666
|
+
// warum failed der Job") wuerde von einer Grace-Periode profitieren —
|
|
667
|
+
// ABER: Token wurde nie ausgegeben (kein User hat das ZIP gesehen),
|
|
668
|
+
// also keine User-Schaden-Forensik. Operator-Audit hat job.errorMessage
|
|
669
|
+
// + Stack-Trace, das reicht
|
|
670
|
+
// → Trade-off zugunsten DSGVO entschieden. Wenn ein Operator forensik
|
|
671
|
+
// braucht, muss er das vor dem Cleanup-Pass capturen (out-of-band).
|
|
672
|
+
//
|
|
673
|
+
// **SQL-Filter:** status IN (done, failed) + downloadStorageKey IS NOT NULL
|
|
674
|
+
// via selectMany (db/queries/export-jobs.ts).
|
|
675
|
+
const candidates = await selectExportJobsForStorageCleanup(
|
|
676
|
+
db,
|
|
677
|
+
EXPORT_JOB_STATUS.Done,
|
|
678
|
+
EXPORT_JOB_STATUS.Failed,
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
const cleaned: string[] = [];
|
|
682
|
+
// Candidates past their due-instant, keyed by that instant — used below to
|
|
683
|
+
// report how far cleanup has fallen behind if a candidate is still standing
|
|
684
|
+
// (delete threw, or the version-checked null-out lost a race) once the pass
|
|
685
|
+
// is done. Done jobs are due at expiresAt+grace; Failed jobs (orphaned ZIPs,
|
|
686
|
+
// no TTL) are due at completedAt ?? startedAt, i.e. from the first pass.
|
|
687
|
+
const overdueDoneCleanupAfterMs = new Map<string, number>();
|
|
688
|
+
let passCompleted = false;
|
|
689
|
+
try {
|
|
690
|
+
for (const c of candidates) {
|
|
691
|
+
if (!c.downloadStorageKey) continue;
|
|
692
|
+
|
|
693
|
+
// Done jobs need the expiresAt+grace check. Failed jobs pass straight
|
|
694
|
+
// through (no user path, so clean up immediately).
|
|
695
|
+
if (c.status === EXPORT_JOB_STATUS.Done) {
|
|
696
|
+
if (!c.expiresAt) continue;
|
|
697
|
+
// Count the candidate as overdue (lower bound, grace unknown) before the
|
|
698
|
+
// throwing profile lookup, so a failing pass still shows a backlog.
|
|
699
|
+
overdueDoneCleanupAfterMs.set(c.id, c.expiresAt.epochMilliseconds);
|
|
700
|
+
const profile = await resolveProfileForTenant({
|
|
701
|
+
db,
|
|
702
|
+
tenantId: c.requestedFromTenantId,
|
|
703
|
+
});
|
|
704
|
+
const cleanupAfter =
|
|
705
|
+
c.expiresAt.epochMilliseconds +
|
|
706
|
+
profile.profile.userRights.exportStorageCleanupGraceHours * 60 * 60 * 1000;
|
|
707
|
+
if (now.epochMilliseconds < cleanupAfter) {
|
|
708
|
+
overdueDoneCleanupAfterMs.delete(c.id);
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
overdueDoneCleanupAfterMs.set(c.id, cleanupAfter);
|
|
712
|
+
}
|
|
713
|
+
// Failed-job branch: no TTL check, clean up immediately.
|
|
714
|
+
else {
|
|
715
|
+
const failedAt = c.completedAt ?? c.startedAt;
|
|
716
|
+
if (failedAt) overdueDoneCleanupAfterMs.set(c.id, failedAt.epochMilliseconds);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Delete the storage file and null the DB column.
|
|
720
|
+
try {
|
|
721
|
+
const provider = await buildStorageProvider(c.requestedFromTenantId);
|
|
722
|
+
await provider.delete(c.downloadStorageKey);
|
|
723
|
+
} catch {
|
|
724
|
+
// best-effort; if the storage delete fails, retry on the next pass
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
const result = await crud.update(
|
|
728
|
+
{
|
|
729
|
+
id: c.id,
|
|
730
|
+
version: c.version,
|
|
731
|
+
changes: { downloadStorageKey: null },
|
|
732
|
+
},
|
|
733
|
+
createSystemUser(c.requestedFromTenantId),
|
|
734
|
+
systemTenantDb(db, c.requestedFromTenantId),
|
|
735
|
+
);
|
|
736
|
+
if (result.isSuccess) cleaned.push(c.id);
|
|
737
|
+
}
|
|
738
|
+
passCompleted = true;
|
|
739
|
+
} finally {
|
|
740
|
+
reportOldestOverdueAge(metrics, overdueDoneCleanupAfterMs, cleaned, now);
|
|
741
|
+
if (passCompleted) reportCleanupLastRun(metrics, now);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return cleaned;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Seconds since the longest-overdue bundle (Done: expiresAt+grace passed;
|
|
748
|
+
// Failed: completedAt ?? startedAt) should have been deleted but still isn't — 0 when the pass
|
|
749
|
+
// cleaned everything that was due, or nothing was due.
|
|
750
|
+
function oldestOverdueAgeSeconds(
|
|
751
|
+
overdueDoneCleanupAfterMs: ReadonlyMap<string, number>,
|
|
752
|
+
cleanedIds: readonly string[],
|
|
753
|
+
now: Instant,
|
|
754
|
+
): number {
|
|
755
|
+
const cleaned = new Set(cleanedIds);
|
|
756
|
+
let oldestAgeSeconds = 0;
|
|
757
|
+
for (const [id, cleanupAfterMs] of overdueDoneCleanupAfterMs) {
|
|
758
|
+
if (cleaned.has(id)) continue;
|
|
759
|
+
const ageSeconds = (now.epochMilliseconds - cleanupAfterMs) / 1000;
|
|
760
|
+
if (ageSeconds > oldestAgeSeconds) oldestAgeSeconds = ageSeconds;
|
|
761
|
+
}
|
|
762
|
+
return oldestAgeSeconds;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Best-effort like the email callbacks above: an observability hiccup
|
|
766
|
+
// (metric not yet registered on this meter, provider misconfig) must not
|
|
767
|
+
// fail a pass that otherwise cleaned up fine.
|
|
768
|
+
function reportOldestOverdueAge(
|
|
769
|
+
metrics: MetricsHandle | undefined,
|
|
770
|
+
overdueDoneCleanupAfterMs: ReadonlyMap<string, number>,
|
|
771
|
+
cleanedIds: readonly string[],
|
|
772
|
+
now: Instant,
|
|
773
|
+
): void {
|
|
774
|
+
// skip: no meter configured means there is nothing to report — the cleanup pass itself already ran to completion.
|
|
775
|
+
if (!metrics) return;
|
|
776
|
+
try {
|
|
777
|
+
metrics.set(
|
|
778
|
+
EXPORT_CLEANUP_BACKLOG_AGE_METRIC,
|
|
779
|
+
oldestOverdueAgeSeconds(overdueDoneCleanupAfterMs, cleanedIds, now),
|
|
780
|
+
);
|
|
781
|
+
} catch (err) {
|
|
782
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility for observability-emit-failure
|
|
783
|
+
console.warn(
|
|
784
|
+
`[user-data-rights:run-export-jobs] metrics.set(${EXPORT_CLEANUP_BACKLOG_AGE_METRIC}) failed err=${err instanceof Error ? err.message : String(err)}`,
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function reportCleanupLastRun(metrics: MetricsHandle | undefined, now: Instant): void {
|
|
790
|
+
// skip: no meter configured means there is nothing to report.
|
|
791
|
+
if (!metrics) return;
|
|
792
|
+
try {
|
|
793
|
+
metrics.set(EXPORT_CLEANUP_LAST_RUN_TIMESTAMP_METRIC, now.epochMilliseconds / 1000);
|
|
794
|
+
} catch (err) {
|
|
795
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility for observability-emit-failure
|
|
796
|
+
console.warn(
|
|
797
|
+
`[user-data-rights:run-export-jobs] metrics.set(${EXPORT_CLEANUP_LAST_RUN_TIMESTAMP_METRIC}) failed err=${err instanceof Error ? err.message : String(err)}`,
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Wrapper: crud.update braucht TenantDb. ExportJob ist tenant-agnostisch
|
|
803
|
+
// (1 Job pro userId), aber der event-store-Stream-Lookup erwartet einen
|
|
804
|
+
// Tenant-Context. system-mode TenantDb bypassed den auto-tenant-filter
|
|
805
|
+
// — wir nutzen `requestedFromTenantId` als Stream-Identity damit der
|
|
806
|
+
// Stream-Counter konsistent bleibt (Memory feedback_event_store_tenant_consistency).
|
|
807
|
+
// @wrapper-known semantic-alias
|
|
808
|
+
function systemTenantDb(db: DbConnection, tenantId: TenantId) {
|
|
809
|
+
return createTenantDb(db, tenantId, "system");
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
function buildExportStorageKey(job: JobRow): string {
|
|
813
|
+
return `${tenantExportPrefix(job.requestedFromTenantId)}${job.id}.zip`;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Konvertiert das UserExportBundle in eine `AsyncIterable<ZipEntry>`
|
|
818
|
+
* fuer createZipStream.
|
|
819
|
+
*
|
|
820
|
+
* Bundle-Layout (Atom 3c):
|
|
821
|
+
* bundle.json — Top-Level-Bundle-Metadata
|
|
822
|
+
* + tenant-sections + flat
|
|
823
|
+
* fileRefs[] mit zipPath
|
|
824
|
+
* pro Datei
|
|
825
|
+
* files/<tenantId>/<fileRefId>-<name> — File-Binaries, Pfad
|
|
826
|
+
* identisch zu fileRef.zipPath
|
|
827
|
+
* im JSON. Bytes via
|
|
828
|
+
* provider.readStream — kein
|
|
829
|
+
* Memory-Spike, auch grosse
|
|
830
|
+
* PDFs streamen durch.
|
|
831
|
+
*
|
|
832
|
+
* `getProvider` ist ein async-cached Resolver pro tenantId. Caller
|
|
833
|
+
* (processJob) baut die Caching-Map damit jeder Tenant nur EINMAL
|
|
834
|
+
* via `buildStorageProvider` materialisiert wird.
|
|
835
|
+
*/
|
|
836
|
+
async function* bundleToZipEntries(
|
|
837
|
+
bundle: UserExportBundle,
|
|
838
|
+
mtime: Instant,
|
|
839
|
+
getProvider: (tenantId: TenantId) => Promise<FileStorageProvider>,
|
|
840
|
+
): AsyncIterable<ZipEntry> {
|
|
841
|
+
// bundle.json zuerst — Reader-Tools koennen das frueh parsen.
|
|
842
|
+
const bundleJson = JSON.stringify(bundle, null, 2);
|
|
843
|
+
yield {
|
|
844
|
+
path: "bundle.json",
|
|
845
|
+
data: oneShot(new TextEncoder().encode(bundleJson)),
|
|
846
|
+
mtime,
|
|
847
|
+
};
|
|
848
|
+
|
|
849
|
+
// File-Binaries: pro fileRef einen ZIP-Entry. data ist der readStream
|
|
850
|
+
// direkt — der ZIP-Builder konsumiert chunk-fuer-chunk, kein Upfront-
|
|
851
|
+
// Memory-Spike pro File. Bei 50 PDFs à 10MB werden trotzdem max. ~64KB
|
|
852
|
+
// (default highWaterMark) gleichzeitig im Heap gehalten.
|
|
853
|
+
for (const ref of bundle.fileRefs) {
|
|
854
|
+
const provider = await getProvider(ref.tenantId);
|
|
855
|
+
// readStream ist required im FileStorageProvider-Type (Atom 3c.fix
|
|
856
|
+
// Type-Honesty) — kein Runtime-Optional-Check noetig.
|
|
857
|
+
yield {
|
|
858
|
+
path: ref.zipPath,
|
|
859
|
+
data: provider.readStream(ref.storageKey),
|
|
860
|
+
mtime,
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
async function* oneShot(bytes: Uint8Array): AsyncIterable<Uint8Array> {
|
|
866
|
+
yield bytes;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Wraps an `AsyncIterable<Uint8Array>` und zaehlt total-bytes. Nach
|
|
871
|
+
* `for await` ist `tracker.bytes` der finale Wert. Verwendet fuer
|
|
872
|
+
* bytesWritten im Job-Row.
|
|
873
|
+
*/
|
|
874
|
+
function countingStream(source: AsyncIterable<Uint8Array>): {
|
|
875
|
+
stream: AsyncIterable<Uint8Array>;
|
|
876
|
+
readonly bytes: number;
|
|
877
|
+
} {
|
|
878
|
+
const tracker = { bytes: 0 };
|
|
879
|
+
const stream: AsyncIterable<Uint8Array> = {
|
|
880
|
+
async *[Symbol.asyncIterator]() {
|
|
881
|
+
for await (const chunk of source) {
|
|
882
|
+
tracker.bytes += chunk.byteLength;
|
|
883
|
+
yield chunk;
|
|
884
|
+
}
|
|
885
|
+
},
|
|
886
|
+
};
|
|
887
|
+
return {
|
|
888
|
+
stream,
|
|
889
|
+
get bytes() {
|
|
890
|
+
return tracker.bytes;
|
|
891
|
+
},
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Atom 5 — userEmail-Lookup fuer notification-callback.
|
|
896
|
+
//
|
|
897
|
+
// **Direct-DB statt queryAs:** Worker-AppContext hat kein queryAs
|
|
898
|
+
// (anders als HandlerContext im request-Pfad). Pattern matched
|
|
899
|
+
// runUserExport's Cross-Tenant-Iteration die ebenso direkt
|
|
900
|
+
// tenantMembershipsTable liest. Cross-feature-API via dispatcher
|
|
901
|
+
// haette einen JobContext-Wrapper gebraucht den der framework noch
|
|
902
|
+
// nicht hat — wenn das mal kommt, ist der hier Refactor-Kandidat.
|
|
903
|
+
//
|
|
904
|
+
// **tenant-agnostic:** userTable.id ist UNIQUE (PK). Cross-Tenant
|
|
905
|
+
// (Alice in Tenant A+B) hat trotzdem nur 1 user-Row mit ihrer
|
|
906
|
+
// Heim-Tenant als tenantId. Lookup ohne tenantId-filter findet sie
|
|
907
|
+
// aus jedem Worker-Tenant-Context.
|
|
908
|
+
async function lookupUserContact(
|
|
909
|
+
db: DbConnection,
|
|
910
|
+
userId: string,
|
|
911
|
+
): Promise<{ email: string; locale: string | null } | null> {
|
|
912
|
+
// @cast-boundary db-row.
|
|
913
|
+
const row = (await fetchOne(db, userTable, { id: userId })) as {
|
|
914
|
+
email: string | null;
|
|
915
|
+
locale: string | null;
|
|
916
|
+
} | null;
|
|
917
|
+
if (!row?.email) return null;
|
|
918
|
+
const email = await decryptStoredPii(row.email, "email", "user-data-rights:export-ready");
|
|
919
|
+
if (email === PII_ERASED_SENTINEL) return null;
|
|
920
|
+
return { email, locale: row.locale ?? null };
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// Atom 5 — Email-Notification beim done-flip. Best-effort:
|
|
924
|
+
// Throw vom Callback bubbelt zum r.job-handler hoch + Worker-Run wird
|
|
925
|
+
// als failed in jobRunsTable gemerkt. Operator kann via jobs:write:retry
|
|
926
|
+
// den Worker-Run erneut anstossen — der Job selbst bleibt done, das
|
|
927
|
+
// retry findet keinen pending-Job mehr aber die Audit-Log zeigt den
|
|
928
|
+
// Failure.
|
|
929
|
+
async function fireExportReadyCallback(args: {
|
|
930
|
+
readonly db: DbConnection;
|
|
931
|
+
readonly job: JobRow;
|
|
932
|
+
readonly plainToken: string;
|
|
933
|
+
readonly expiresAt: Instant;
|
|
934
|
+
readonly bytesWritten: number;
|
|
935
|
+
readonly appExportDownloadUrl: string | undefined;
|
|
936
|
+
readonly send: SendExportReadyEmailFn;
|
|
937
|
+
}): Promise<void> {
|
|
938
|
+
const contact = await lookupUserContact(args.db, args.job.userId);
|
|
939
|
+
if (!contact) {
|
|
940
|
+
// User-Row fehlt (z.B. forget-Pfad mid-export). Skip-Notification mit
|
|
941
|
+
// Operator-Alert via job-run-Log statt Throw — Job bleibt done, User
|
|
942
|
+
// hat ja seinen Token via export-status.query erreichbar (UI-Pfad).
|
|
943
|
+
// **console.warn statt ctx.log:** runExportJobs-args fuehren AppContext.log
|
|
944
|
+
// aktuell nicht durch (Worker-pure-function-Pattern). console.warn ist
|
|
945
|
+
// die einzige Operator-Sichtbarkeit fuer den missing-user-edge-case.
|
|
946
|
+
// Wenn jobs-Feature spaeter ctx.log threadet oder Worker-args erweitert
|
|
947
|
+
// werden, hier Refactor-Kandidat.
|
|
948
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility for missing-user edge-case
|
|
949
|
+
console.warn(
|
|
950
|
+
`[user-data-rights:run-export-jobs] userId=${args.job.userId} hat kein userEmail — sendExportReadyEmail skipped`,
|
|
951
|
+
);
|
|
952
|
+
// skip: missing user-email row; console.warn above provides operator visibility
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
const baseUrl = args.appExportDownloadUrl;
|
|
956
|
+
if (!baseUrl) {
|
|
957
|
+
throw new Error(
|
|
958
|
+
"user-data-rights: sendExportReadyEmail gesetzt aber appExportDownloadUrl fehlt — beide muessen zusammen konfiguriert sein",
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
const downloadUrl = `${baseUrl}#token=${encodeURIComponent(args.plainToken)}`;
|
|
962
|
+
await args.send({
|
|
963
|
+
userId: args.job.userId,
|
|
964
|
+
userEmail: contact.email,
|
|
965
|
+
userLocale: contact.locale,
|
|
966
|
+
tenantId: args.job.requestedFromTenantId,
|
|
967
|
+
jobId: args.job.id,
|
|
968
|
+
downloadUrl,
|
|
969
|
+
expiresAt: args.expiresAt.toString(),
|
|
970
|
+
bytesWritten: args.bytesWritten,
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// Atom 5 — Email-Notification beim failed-flip.
|
|
975
|
+
async function fireExportFailedCallback(args: {
|
|
976
|
+
readonly db: DbConnection;
|
|
977
|
+
readonly job: JobRow;
|
|
978
|
+
readonly errorMessage: string;
|
|
979
|
+
readonly send: SendExportFailedEmailFn;
|
|
980
|
+
}): Promise<void> {
|
|
981
|
+
const contact = await lookupUserContact(args.db, args.job.userId);
|
|
982
|
+
if (!contact) {
|
|
983
|
+
// biome-ignore lint/suspicious/noConsole: operator-visibility
|
|
984
|
+
console.warn(
|
|
985
|
+
`[user-data-rights:run-export-jobs] userId=${args.job.userId} hat kein userEmail — sendExportFailedEmail skipped`,
|
|
986
|
+
);
|
|
987
|
+
// skip: missing user-email row; console.warn above provides operator visibility
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
await args.send({
|
|
991
|
+
userId: args.job.userId,
|
|
992
|
+
userEmail: contact.email,
|
|
993
|
+
userLocale: contact.locale,
|
|
994
|
+
tenantId: args.job.requestedFromTenantId,
|
|
995
|
+
jobId: args.job.id,
|
|
996
|
+
errorMessage: args.errorMessage,
|
|
997
|
+
});
|
|
998
|
+
}
|