@cosmicdrift/kumiko-samples 0.378.0 → 0.379.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/package.json +1 -1
- package/packages/bundled-features/package.json +18 -17
- package/packages/bundled-features/src/account-security/feature.ts +2 -2
- package/packages/bundled-features/src/account-security/index.ts +8 -8
- package/packages/bundled-features/src/account-security/{constants.ts → web/constants.ts} +0 -2
- package/packages/bundled-features/src/account-security/{i18n.ts → web/i18n.ts} +0 -1
- package/packages/bundled-features/src/admin-shell/feature.ts +10 -9
- package/packages/bundled-features/src/admin-shell/index.ts +8 -8
- package/packages/bundled-features/src/admin-shell/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/admin-shell/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/admin-shell/web/default-translations.ts +10 -0
- package/packages/bundled-features/src/admin-shell/web/i18n.ts +51 -9
- package/packages/bundled-features/src/admin-shell/web/index.ts +0 -1
- package/packages/bundled-features/src/audit/changes.json +7 -0
- package/packages/bundled-features/src/audit/feature.ts +72 -64
- package/packages/bundled-features/src/audit/handlers/audit-events.ts +153 -0
- package/packages/bundled-features/src/audit/handlers/audit-system-db.ts +13 -0
- package/packages/bundled-features/src/audit/handlers/details-all-tenants.query.ts +26 -0
- package/packages/bundled-features/src/audit/handlers/details.query.ts +11 -39
- package/packages/bundled-features/src/audit/handlers/list-all-tenants.query.ts +47 -0
- package/packages/bundled-features/src/audit/handlers/list.query.ts +16 -123
- package/packages/bundled-features/src/audit/handlers/resolve-audit-tenant.ts +21 -7
- package/packages/bundled-features/src/audit/index.ts +1 -1
- package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +4 -4
- package/packages/bundled-features/src/audit/screens.ts +82 -0
- package/packages/bundled-features/src/audit/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/audit/{constants.ts → web/constants.ts} +11 -1
- package/packages/bundled-features/src/audit/web/default-translations.ts +7 -0
- package/packages/bundled-features/src/audit/web/i18n.ts +33 -7
- package/packages/bundled-features/src/audit/web/index.ts +0 -2
- package/packages/bundled-features/src/auth-email-password/bootstrap.ts +6 -6
- package/packages/bundled-features/src/auth-email-password/changes.json +6 -0
- package/packages/bundled-features/src/auth-email-password/errors.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/feature.ts +2 -2
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +4 -4
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +38 -4
- package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/reset-password.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/index.ts +6 -1
- package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/signup-activation.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +0 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-form-logic.ts +0 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-redirect.ts +0 -1
- package/packages/bundled-features/src/auth-email-password/web/client-actions.ts +0 -1
- package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +1 -2
- package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/{constants.ts → web/constants.ts} +3 -6
- package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/{i18n.ts → web/i18n.ts} +3 -4
- package/packages/bundled-features/src/auth-email-password/web/index.ts +1 -2
- package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +2 -3
- package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/{mail-i18n.ts → web/mail-i18n.ts} +0 -1
- package/packages/bundled-features/src/auth-email-password/web/request-account-unlock-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/session-bootstrap-error.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/session.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +2 -3
- package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/tenant-menu-items.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +0 -1
- package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +0 -1
- package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +0 -1
- package/packages/bundled-features/src/auth-mfa/changes.json +6 -0
- package/packages/bundled-features/src/auth-mfa/errors.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/index.ts +8 -8
- package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/screens.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +0 -1
- package/packages/bundled-features/src/auth-mfa/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/auth-mfa/web/i18n.ts +0 -1
- package/packages/bundled-features/src/auth-mfa/web/index.ts +0 -1
- package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +0 -1
- package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +1 -2
- package/packages/bundled-features/src/auth-mfa/web/mfa-recovery-codes-reveal.tsx +0 -1
- package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +1 -2
- package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +21 -23
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +0 -1
- package/packages/bundled-features/src/billing-foundation/changes.json +18 -0
- package/packages/bundled-features/src/billing-foundation/checkout-core.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-text.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +11 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +11 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +12 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +12 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +6 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-notify.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +167 -28
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +102 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +43 -12
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +202 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +70 -0
- package/packages/bundled-features/src/billing-foundation/events.ts +20 -2
- package/packages/bundled-features/src/billing-foundation/feature.ts +5 -5
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +82 -9
- package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/index.ts +27 -27
- package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +7 -7
- package/packages/bundled-features/src/billing-foundation/screens.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/types.ts +17 -3
- package/packages/bundled-features/src/billing-foundation/validate-options.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/web/billing-contact-plan.tsx +1 -3
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +5 -7
- package/packages/bundled-features/src/billing-foundation/web/cancel-contract-dialog.tsx +1 -3
- package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +1 -3
- package/packages/bundled-features/src/billing-foundation/web/client-plugin.tsx +1 -2
- package/packages/bundled-features/src/billing-foundation/{constants.ts → web/constants.ts} +37 -31
- package/packages/bundled-features/src/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.ts +0 -1
- package/packages/bundled-features/src/billing-foundation/{contact-card.ts → web/contact-card.ts} +0 -2
- package/packages/bundled-features/src/billing-foundation/web/index.ts +14 -15
- package/packages/bundled-features/src/billing-foundation/web/localized-params.ts +0 -2
- package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +5 -2
- package/packages/bundled-features/src/cap-overview/feature.ts +1 -1
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -1
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -2
- package/packages/bundled-features/src/cap-overview/index.ts +9 -9
- package/packages/bundled-features/src/cap-overview/screens.ts +2 -2
- package/packages/bundled-features/src/cap-overview/web/cap-cards-panel.tsx +1 -2
- package/packages/bundled-features/src/cap-overview/web/cap-usage-bar.tsx +1 -2
- package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +0 -2
- package/packages/bundled-features/src/cap-overview/web/client-plugin.tsx +3 -4
- package/packages/bundled-features/src/cap-overview/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/cap-overview/web/index.ts +0 -1
- package/packages/bundled-features/src/cap-overview/{usage-math.ts → web/usage-math.ts} +1 -2
- package/packages/bundled-features/src/compliance-profiles/feature.ts +5 -5
- package/packages/bundled-features/src/compliance-profiles/index.ts +6 -6
- package/packages/bundled-features/src/compliance-profiles/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/compliance-profiles/web/compliance-profile-catalog.tsx +1 -2
- package/packages/bundled-features/src/compliance-profiles/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/compliance-profiles/web/i18n.ts +0 -1
- package/packages/bundled-features/src/compliance-profiles/web/index.ts +0 -1
- package/packages/bundled-features/src/config/index.ts +6 -6
- package/packages/bundled-features/src/config/web/client-plugin.ts +1 -2
- package/packages/bundled-features/src/config/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/config/web/i18n.ts +0 -1
- package/packages/bundled-features/src/config/web/index.ts +1 -3
- package/packages/bundled-features/src/config/write-helpers.ts +1 -1
- package/packages/bundled-features/src/custom-fields/feature.ts +8 -8
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +4 -4
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/index.ts +8 -8
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +1 -1
- package/packages/bundled-features/src/custom-fields/schemas.ts +1 -1
- package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +1 -2
- package/packages/bundled-features/src/custom-fields/{constants.ts → web/constants.ts} +18 -19
- package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +1 -2
- package/packages/bundled-features/src/custom-fields/web/i18n.ts +0 -1
- package/packages/bundled-features/src/custom-fields/web/index.ts +2 -3
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +1 -2
- package/packages/bundled-features/src/delivery/address-opt-out.ts +1 -1
- package/packages/bundled-features/src/delivery/attempt-log-retention.ts +24 -8
- package/packages/bundled-features/src/delivery/changes.json +6 -0
- package/packages/bundled-features/src/delivery/constants.ts +2 -2
- package/packages/bundled-features/src/delivery/i18n.ts +1 -1
- package/packages/bundled-features/src/delivery/unsubscribe-page.ts +1 -1
- package/packages/bundled-features/src/delivery/web/client-plugin.tsx +6 -7
- package/packages/bundled-features/src/delivery/web/delivery-channel-cell.tsx +0 -1
- package/packages/bundled-features/src/delivery/web/delivery-error-cell.tsx +0 -1
- package/packages/bundled-features/src/delivery/web/delivery-status-cell.tsx +1 -2
- package/packages/bundled-features/src/delivery/web/delivery-time-cell.tsx +0 -1
- package/packages/bundled-features/src/delivery/web/delivery-type-cell.tsx +0 -1
- package/packages/bundled-features/src/delivery/web/index.ts +0 -1
- package/packages/bundled-features/src/delivery/{public-names.ts → web/public-names.ts} +0 -1
- package/packages/bundled-features/src/document-ingest-foundation/changes.json +6 -0
- package/packages/bundled-features/src/document-ingest-foundation/events.ts +4 -0
- package/packages/bundled-features/src/document-ingest-foundation/executor.ts +2 -1
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +18 -4
- package/packages/bundled-features/src/document-ingest-foundation/index.ts +1 -0
- package/packages/bundled-features/src/feature-toggles/feature.ts +7 -7
- package/packages/bundled-features/src/feature-toggles/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -3
- package/packages/bundled-features/src/feature-toggles/index.ts +6 -6
- package/packages/bundled-features/src/feature-toggles/web/client-plugin.tsx +1 -2
- package/packages/bundled-features/src/feature-toggles/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/feature-toggles/web/i18n.ts +0 -1
- package/packages/bundled-features/src/feature-toggles/web/index.ts +0 -1
- package/packages/bundled-features/src/files/changes.json +7 -0
- package/packages/bundled-features/src/folders/feature.ts +1 -1
- package/packages/bundled-features/src/folders/handlers/clear-folder.write.ts +1 -1
- package/packages/bundled-features/src/folders/handlers/delete-folder.write.ts +1 -1
- package/packages/bundled-features/src/folders/handlers/set-folder.write.ts +1 -1
- package/packages/bundled-features/src/folders/index.ts +8 -8
- package/packages/bundled-features/src/folders/web/client-plugin.tsx +1 -3
- package/packages/bundled-features/src/folders/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +1 -2
- package/packages/bundled-features/src/folders/web/folder-section.tsx +1 -2
- package/packages/bundled-features/src/folders/web/i18n.ts +0 -1
- package/packages/bundled-features/src/folders/web/index.ts +1 -2
- package/packages/bundled-features/src/folders/web/tree.ts +0 -1
- package/packages/bundled-features/src/form-draft/changes.json +7 -0
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +25 -11
- package/packages/bundled-features/src/form-draft/decrypt-draft.ts +24 -0
- package/packages/bundled-features/src/form-draft/entity.ts +6 -9
- package/packages/bundled-features/src/form-draft/feature.ts +1 -1
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +26 -5
- package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
- package/packages/bundled-features/src/form-draft/handlers/get.query.ts +6 -7
- package/packages/bundled-features/src/form-draft/handlers/list.query.ts +13 -7
- package/packages/bundled-features/src/form-draft/handlers/save.write.ts +5 -5
- package/packages/bundled-features/src/form-draft/index.ts +8 -8
- package/packages/bundled-features/src/form-draft/lookup.ts +10 -4
- package/packages/bundled-features/src/form-draft/schemas.ts +1 -1
- package/packages/bundled-features/src/form-draft/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/form-draft-user-data/hooks.ts +2 -2
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +10 -10
- package/packages/bundled-features/src/jobs/feature.ts +7 -7
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +1 -1
- package/packages/bundled-features/src/jobs/index.ts +1 -1
- package/packages/bundled-features/src/jobs/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/jobs/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/jobs/web/default-translations.ts +7 -0
- package/packages/bundled-features/src/jobs/web/i18n.ts +53 -7
- package/packages/bundled-features/src/jobs/web/index.ts +0 -1
- package/packages/bundled-features/src/ledger/changes.json +7 -0
- package/packages/bundled-features/src/ledger/entity.ts +1 -1
- package/packages/bundled-features/src/ledger/feature.ts +1 -1
- package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +2 -10
- package/packages/bundled-features/src/ledger/handlers/create-transaction.write.ts +1 -1
- package/packages/bundled-features/src/ledger/handlers/reports.query.ts +1 -1
- package/packages/bundled-features/src/ledger/handlers/reverse-transaction.write.ts +1 -1
- package/packages/bundled-features/src/ledger/index.ts +13 -13
- package/packages/bundled-features/src/ledger/recurring.ts +1 -1
- package/packages/bundled-features/src/ledger/reports.ts +1 -1
- package/packages/bundled-features/src/ledger/schemas.ts +1 -1
- package/packages/bundled-features/src/ledger/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/ledger/web/index.ts +11 -12
- package/packages/bundled-features/src/legal-pages/README.md +1 -1
- package/packages/bundled-features/src/legal-pages/feature.ts +5 -5
- package/packages/bundled-features/src/legal-pages/index.ts +11 -11
- package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +1 -1
- package/packages/bundled-features/src/legal-pages/lib/validate-routes.ts +1 -1
- package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +1 -2
- package/packages/bundled-features/src/legal-pages/{constants.ts → web/constants.ts} +6 -8
- package/packages/bundled-features/src/legal-pages/web/index.ts +0 -1
- package/packages/bundled-features/src/managed-pages/feature.ts +1 -1
- package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +1 -2
- package/packages/bundled-features/src/managed-pages/web/default-translations.ts +17 -0
- package/packages/bundled-features/src/managed-pages/web/i18n.ts +59 -16
- package/packages/bundled-features/src/managed-pages/web/index.ts +1 -2
- package/packages/bundled-features/src/metrics/compute.ts +1 -1
- package/packages/bundled-features/src/metrics/feature.ts +6 -6
- package/packages/bundled-features/src/metrics/index.ts +8 -8
- package/packages/bundled-features/src/metrics/types.ts +1 -1
- package/packages/bundled-features/src/metrics/validate.ts +1 -1
- package/packages/bundled-features/src/metrics/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/metrics/window.ts +1 -1
- package/packages/bundled-features/src/notes-history/feature.ts +1 -1
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
- package/packages/bundled-features/src/notes-history/index.ts +8 -8
- package/packages/bundled-features/src/notes-history/web/client-plugin.tsx +1 -3
- package/packages/bundled-features/src/notes-history/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/notes-history/web/i18n.ts +0 -1
- package/packages/bundled-features/src/notes-history/web/index.ts +2 -3
- package/packages/bundled-features/src/notes-history/web/notes-section.tsx +2 -3
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +12 -10
- package/packages/bundled-features/src/personal-access-tokens/handlers/available-scopes.query.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/hash.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/i18n.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/index.ts +5 -5
- package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/schema/api-token.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/personal-access-tokens/{scopes.ts → web/scopes.ts} +0 -1
- package/packages/bundled-features/src/presets/changes.json +7 -0
- package/packages/bundled-features/src/presets/index.ts +0 -1
- package/packages/bundled-features/src/presets/security-baseline.ts +1 -1
- package/packages/bundled-features/src/renderer-foundation/types.ts +1 -1
- package/packages/bundled-features/src/secrets/feature.ts +1 -1
- package/packages/bundled-features/src/secrets/handlers/delete.write.ts +1 -1
- package/packages/bundled-features/src/secrets/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/secrets/handlers/set.write.ts +1 -1
- package/packages/bundled-features/src/secrets/i18n.ts +1 -1
- package/packages/bundled-features/src/secrets/index.ts +8 -8
- package/packages/bundled-features/src/secrets/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/secrets/write-gate.ts +1 -1
- package/packages/bundled-features/src/sessions/feature.ts +7 -4
- package/packages/bundled-features/src/sessions/{i18n.ts → web/i18n.ts} +0 -1
- package/packages/bundled-features/src/shared/index.ts +6 -1
- package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +10 -2
- package/packages/bundled-features/src/shared/web/translate-or-raw.ts +0 -1
- package/packages/bundled-features/src/subscription-stripe/feature.ts +2 -0
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +19 -0
- package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +1 -0
- package/packages/bundled-features/src/tags/changes.json +6 -0
- package/packages/bundled-features/src/tags/feature.ts +1 -1
- package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +11 -7
- package/packages/bundled-features/src/tags/handlers/create-tag.write.ts +1 -1
- package/packages/bundled-features/src/tags/handlers/delete-tag.write.ts +4 -1
- package/packages/bundled-features/src/tags/handlers/remove-tag.write.ts +1 -1
- package/packages/bundled-features/src/tags/handlers/update-tag.write.ts +1 -1
- package/packages/bundled-features/src/tags/index.ts +12 -12
- package/packages/bundled-features/src/tags/screens.ts +1 -1
- package/packages/bundled-features/src/tags/web/client-plugin.tsx +1 -3
- package/packages/bundled-features/src/tags/{constants.ts → web/constants.ts} +4 -1
- package/packages/bundled-features/src/tags/web/entity-tags.tsx +1 -2
- package/packages/bundled-features/src/tags/web/i18n.ts +2 -2
- package/packages/bundled-features/src/tags/web/index.ts +2 -3
- package/packages/bundled-features/src/tags/web/tag-chip.tsx +0 -1
- package/packages/bundled-features/src/tags/web/tag-filter.tsx +1 -2
- package/packages/bundled-features/src/tags/web/tag-manager.tsx +5 -4
- package/packages/bundled-features/src/tags/web/tag-picker.tsx +0 -1
- package/packages/bundled-features/src/tags/web/tag-section.tsx +1 -2
- package/packages/bundled-features/src/tags/web/tags-cell.tsx +1 -2
- package/packages/bundled-features/src/template-resolver/README.md +1 -1
- package/packages/bundled-features/src/template-resolver/api.ts +75 -28
- package/packages/bundled-features/src/template-resolver/changes.json +43 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -1
- package/packages/bundled-features/src/template-resolver/compile-steps-block.ts +2 -2
- package/packages/bundled-features/src/template-resolver/document-ops.ts +5 -5
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +4 -4
- package/packages/bundled-features/src/template-resolver/feature.ts +13 -4
- package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +6 -1
- package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +6 -2
- package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +19 -2
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +7 -1
- package/packages/bundled-features/src/template-resolver/handlers/discard-draft.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +8 -2
- package/packages/bundled-features/src/template-resolver/handlers/document-blocks.query.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +5 -2
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +4 -2
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +10 -5
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +5 -2
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +68 -10
- package/packages/bundled-features/src/template-resolver/handlers/patch-draft.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +6 -6
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +8 -2
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +4 -2
- package/packages/bundled-features/src/template-resolver/i18n.ts +25 -0
- package/packages/bundled-features/src/template-resolver/index.ts +60 -59
- package/packages/bundled-features/src/template-resolver/layout-appearance.ts +1 -1
- package/packages/bundled-features/src/template-resolver/layout-regions.ts +1 -1
- package/packages/bundled-features/src/template-resolver/seeding.ts +16 -7
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +2 -2
- package/packages/bundled-features/src/template-resolver/table.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-bundle.ts +2 -2
- package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +82 -0
- package/packages/bundled-features/src/template-resolver/template-draft.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-edit-policy.ts +2 -2
- package/packages/bundled-features/src/template-resolver/template-meta.ts +2 -2
- package/packages/bundled-features/src/template-resolver/template-preview.ts +14 -10
- package/packages/bundled-features/src/template-resolver/template-usage.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-validation.ts +2 -2
- package/packages/bundled-features/src/template-resolver/testing.ts +2 -2
- package/packages/bundled-features/src/template-resolver/user-content-table.ts +1 -1
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +4 -5
- package/packages/bundled-features/src/template-resolver/{constants.ts → web/constants.ts} +7 -10
- package/packages/bundled-features/src/template-resolver/{document-blocks.ts → web/document-blocks.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +2 -3
- package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +0 -1
- package/packages/bundled-features/src/template-resolver/{document-images.ts → web/document-images.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/{document-schema.ts → web/document-schema.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/{document-steps.ts → web/document-steps.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +6 -7
- package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +2 -3
- package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +1 -2
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +2 -1
- package/packages/bundled-features/src/template-resolver/web/index.ts +13 -14
- package/packages/bundled-features/src/template-resolver/{mail-constants.ts → web/mail-constants.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/{pdf-constants.ts → web/pdf-constants.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +0 -1
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +5 -4
- package/packages/bundled-features/src/template-resolver/{placeholder-text.ts → web/placeholder-text.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/{qualified-names.ts → web/qualified-names.ts} +0 -1
- package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +0 -1
- package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -1
- package/packages/bundled-features/src/tenant/index.ts +7 -7
- package/packages/bundled-features/src/tenant/invitation-table.ts +1 -1
- package/packages/bundled-features/src/tenant/invited-membership.ts +1 -1
- package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -1
- package/packages/bundled-features/src/tenant/member-role-options.ts +1 -1
- package/packages/bundled-features/src/tenant/screens.ts +2 -2
- package/packages/bundled-features/src/tenant/web/client-plugin.tsx +1 -2
- package/packages/bundled-features/src/tenant/{constants.ts → web/constants.ts} +3 -6
- package/packages/bundled-features/src/tenant/web/index.ts +0 -1
- package/packages/bundled-features/src/tenant/web/member-roles-cell.tsx +0 -1
- package/packages/bundled-features/src/tenant/web/member-status-cell.tsx +0 -1
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +2 -2
- package/packages/bundled-features/src/tier-engine/entity.ts +1 -1
- package/packages/bundled-features/src/tier-engine/feature.ts +7 -7
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +1 -1
- package/packages/bundled-features/src/tier-engine/index.ts +8 -8
- package/packages/bundled-features/src/tier-engine/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/tier-engine/{constants.ts → web/constants.ts} +2 -3
- package/packages/bundled-features/src/tier-engine/{i18n.ts → web/i18n.ts} +0 -1
- package/packages/bundled-features/src/tier-engine/web/index.ts +0 -1
- package/packages/bundled-features/src/user/handlers/create.write.ts +1 -1
- package/packages/bundled-features/src/user/handlers/update-roles.ts +1 -1
- package/packages/bundled-features/src/user/handlers/update.write.ts +1 -1
- package/packages/bundled-features/src/user/index.ts +1 -1
- package/packages/bundled-features/src/user/invited-global-roles.ts +1 -1
- package/packages/bundled-features/src/user/schema/user.ts +1 -1
- package/packages/bundled-features/src/user/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/user-data-rights/changes.json +14 -0
- package/packages/bundled-features/src/user-data-rights/env.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/feature.ts +9 -9
- package/packages/bundled-features/src/user-data-rights/index.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/lib/resolve-tenant-model.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +2 -3
- package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +0 -1
- package/packages/bundled-features/src/user-data-rights/{constants.ts → web/constants.ts} +11 -12
- package/packages/bundled-features/src/user-data-rights/web/default-translations.ts +91 -0
- package/packages/bundled-features/src/user-data-rights/web/i18n.ts +41 -91
- package/packages/bundled-features/src/user-data-rights/web/index.ts +1 -2
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +1 -2
- package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +0 -1
- package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +0 -1
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +10 -1
- package/packages/bundled-features/src/user-profile/feature.ts +2 -2
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +1 -1
- package/packages/bundled-features/src/user-profile/index.ts +3 -2
- package/packages/bundled-features/src/user-profile/web/client-plugin.ts +2 -3
- package/packages/bundled-features/src/user-profile/{constants.ts → web/constants.ts} +0 -1
- package/packages/bundled-features/src/user-profile/{i18n.ts → web/i18n.ts} +0 -1
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -3
- package/packages/bundled-features/src/waitlist/changes.json +6 -0
- package/packages/bundled-features/src/waitlist/entity.ts +1 -1
- package/packages/bundled-features/src/waitlist/feature.ts +5 -5
- package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +3 -3
- package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +5 -1
- package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +3 -3
- package/packages/bundled-features/src/waitlist/import.ts +1 -1
- package/packages/bundled-features/src/waitlist/index.ts +11 -11
- package/packages/bundled-features/src/waitlist/legacy-migrate.ts +1 -1
- package/packages/bundled-features/src/waitlist/link-on-signup.ts +1 -1
- package/packages/bundled-features/src/waitlist/mail.ts +7 -6
- package/packages/bundled-features/src/waitlist/payloads.ts +1 -1
- package/packages/bundled-features/src/waitlist/screens.ts +1 -1
- package/packages/bundled-features/src/waitlist/{constants.ts → web/constants.ts} +0 -1
- package/samples/apps/styleguide/src/features/content/web.tsx +0 -1
- package/samples/apps/ui-walkthrough/src/app/client.tsx +2 -0
- package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +17 -1
- package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +11 -0
- package/samples/apps/ui-walkthrough/src/app/server.ts +2 -1
- package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +35 -7
- package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +6 -0
- package/samples/apps/ui-walkthrough/src/features/rental/entities.ts +27 -0
- package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +61 -7
- package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +48 -24
- package/samples/apps/ui-walkthrough/src/features/rental/invoice-receive.ts +0 -1
- package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +17 -1
- package/samples/apps/ui-walkthrough/src/features/rental/qualified-names.ts +3 -0
- package/samples/apps/ui-walkthrough/src/features/rental/receipts-upload.ts +70 -0
- package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +90 -13
- package/samples/apps/ui-walkthrough/src/features/rental/web/index.ts +0 -2
- package/samples/apps/ui-walkthrough/src/features/subscription-plans/feature.ts +103 -0
- package/samples/apps/ui-walkthrough/src/features/subscription-plans/i18n.ts +36 -0
- package/samples/apps/ui-walkthrough/src/features/subscription-plans/index.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/subscription-plans/seed.ts +21 -0
- package/samples/apps/ui-walkthrough/src/run-config.ts +11 -0
- package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +1 -1
- package/samples/apps/use-all-bundled/feature-manifest.json +4 -4
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +3 -1
- package/samples/recipes/compose-stacks/README.md +1 -2
- package/samples/recipes/embedded/README.md +5 -5
- package/samples/recipes/embedded/src/handlers/invoice-receive.write.ts +0 -1
- package/samples/recipes/embedded/src/screens/invoice-receive.screen.ts +9 -12
- package/samples/recipes/legal-pages/README.md +2 -2
- package/samples/recipes/legal-pages/src/feature.ts +1 -1
- package/samples/recipes/reference-data/src/feature.ts +3 -7
- package/packages/bundled-features/src/admin-shell/i18n.ts +0 -54
- package/packages/bundled-features/src/audit/i18n.ts +0 -25
- package/packages/bundled-features/src/auth-mfa/web/qrcode-browser.d.ts +0 -11
- package/packages/bundled-features/src/jobs/i18n.ts +0 -55
- package/packages/bundled-features/src/managed-pages/i18n.ts +0 -63
- package/packages/bundled-features/src/presets/dsgvo-self-service.ts +0 -35
- package/packages/bundled-features/src/user-data-rights/i18n.ts +0 -44
- package/samples/apps/ui-walkthrough/src/features/rental/web/upload-standard-layout.tsx +0 -61
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// hardcoded mime allowlist or size cap — providers register via
|
|
5
5
|
// EXT_DOCUMENT_INGEST_PROVIDER (see providers.ts).
|
|
6
6
|
|
|
7
|
-
import { entityEventName } from "@cosmicdrift/kumiko-framework/db";
|
|
7
|
+
import { applyEntityEvent, entityEventName } from "@cosmicdrift/kumiko-framework/db";
|
|
8
8
|
import {
|
|
9
9
|
access,
|
|
10
10
|
createTenantConfig,
|
|
@@ -16,8 +16,9 @@ import { normalizeMimeType } from "@cosmicdrift/kumiko-framework/files";
|
|
|
16
16
|
import * as z from "zod";
|
|
17
17
|
import { documentIngestAggregateId } from "./aggregate-id.ts";
|
|
18
18
|
import { validateDocumentIngestProviderWiring } from "./boot-checks.ts";
|
|
19
|
-
import { documentExtractEntity } from "./entity.ts";
|
|
19
|
+
import { documentExtractEntity, documentExtractsTable } from "./entity.ts";
|
|
20
20
|
import {
|
|
21
|
+
DOCUMENT_EXTRACT_AGGREGATE_TYPE,
|
|
21
22
|
DOCUMENT_INGEST_AGGREGATE_TYPE,
|
|
22
23
|
DOCUMENT_INGEST_REQUESTED_EVENT_QN,
|
|
23
24
|
DOCUMENT_INGEST_REQUESTED_EVENT_SHORT,
|
|
@@ -44,9 +45,9 @@ const FILE_REF_CREATED = entityEventName("fileRef", "created");
|
|
|
44
45
|
const FILE_REF_RESTORED = entityEventName("fileRef", "restored");
|
|
45
46
|
const FILE_REF_DELETED = entityEventName("fileRef", "deleted");
|
|
46
47
|
const FILE_REF_FORGOTTEN = entityEventName("fileRef", "forgotten");
|
|
47
|
-
// Executors write under
|
|
48
|
+
// Executors write under DOCUMENT_EXTRACT_AGGREGATE_TYPE (executor.ts), not the
|
|
48
49
|
// camelCase r.entity() name — the event type follows the executor.
|
|
49
|
-
const DOCUMENT_EXTRACT_CREATED = entityEventName(
|
|
50
|
+
const DOCUMENT_EXTRACT_CREATED = entityEventName(DOCUMENT_EXTRACT_AGGREGATE_TYPE, "created");
|
|
50
51
|
|
|
51
52
|
type MspApplyContext = Parameters<MultiStreamApplyFn>[2];
|
|
52
53
|
|
|
@@ -141,6 +142,19 @@ export function createDocumentIngestFoundationFeature() {
|
|
|
141
142
|
r.useExtension(EXT_TENANT_DATA, "documentExtract", {
|
|
142
143
|
destroy: documentExtractTenantDestroyHook,
|
|
143
144
|
});
|
|
145
|
+
// The implicit projection listens for "documentExtract.*"; stored events are
|
|
146
|
+
// "document-extract.*", so a rebuild would otherwise drop every extract row.
|
|
147
|
+
r.extendEntityProjection("documentExtract", {
|
|
148
|
+
sources: [DOCUMENT_EXTRACT_AGGREGATE_TYPE],
|
|
149
|
+
apply: Object.fromEntries(
|
|
150
|
+
(["created", "updated", "deleted", "forgotten"] as const).map((verb) => [
|
|
151
|
+
entityEventName(DOCUMENT_EXTRACT_AGGREGATE_TYPE, verb),
|
|
152
|
+
async (event, tx) => {
|
|
153
|
+
await applyEntityEvent(event, documentExtractsTable, documentExtractEntity, tx);
|
|
154
|
+
},
|
|
155
|
+
]),
|
|
156
|
+
),
|
|
157
|
+
});
|
|
144
158
|
|
|
145
159
|
// No onRegister: resolution happens at boot and per-apply, not on register.
|
|
146
160
|
r.extendsRegistrar(EXT_DOCUMENT_INGEST_PROVIDER, {});
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { defineFeature, type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import {
|
|
3
|
-
FEATURE_TOGGLE_SET_EVENT_NAME,
|
|
4
|
-
FeatureToggleHandlers,
|
|
5
|
-
FeatureToggleQueries,
|
|
6
|
-
TOGGLE_ADMIN_SCREEN_ID,
|
|
7
|
-
} from "./constants.ts";
|
|
8
2
|
import { featureToggleSetSchema } from "./events.ts";
|
|
9
3
|
import { globalFeatureStateTableMeta } from "./global-feature-state-table.ts";
|
|
10
4
|
import { listQuery } from "./handlers/list.query.ts";
|
|
@@ -12,6 +6,12 @@ import { registeredQuery } from "./handlers/registered.query.ts";
|
|
|
12
6
|
import { createSetWriteHandler } from "./handlers/set.write.ts";
|
|
13
7
|
import { FEATURE_TOGGLES_I18N } from "./i18n.ts";
|
|
14
8
|
import type { GlobalFeatureToggleRuntime } from "./toggle-runtime.ts";
|
|
9
|
+
import {
|
|
10
|
+
FEATURE_TOGGLE_SET_EVENT_NAME,
|
|
11
|
+
FeatureToggleHandlers,
|
|
12
|
+
FeatureToggleQueries,
|
|
13
|
+
TOGGLE_ADMIN_SCREEN_ID,
|
|
14
|
+
} from "./web/constants.ts";
|
|
15
15
|
|
|
16
16
|
// IMPORTANT: feature-toggles itself is NOT r.toggleable. Making it
|
|
17
17
|
// toggleable would brick the system — once disabled, no handler of this
|
|
@@ -157,7 +157,6 @@ export function createFeatureTogglesFeature(
|
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
export { FEATURE_TOGGLE_SET_EVENT_NAME, FeatureToggleErrors } from "./constants.ts";
|
|
161
160
|
export {
|
|
162
161
|
globalFeatureStateTable,
|
|
163
162
|
globalFeatureStateTableMeta,
|
|
@@ -170,3 +169,4 @@ export {
|
|
|
170
169
|
type ToggleSyncSignal,
|
|
171
170
|
} from "./toggle-runtime.ts";
|
|
172
171
|
export { createRedisToggleSyncSignal, type RedisToggleSyncSignal } from "./toggle-sync-signal.ts";
|
|
172
|
+
export { FEATURE_TOGGLE_SET_EVENT_NAME, FeatureToggleErrors } from "./web/constants.ts";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../constants.ts";
|
|
4
3
|
import { globalFeatureStateTable } from "../global-feature-state-table.ts";
|
|
4
|
+
import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../web/constants.ts";
|
|
5
5
|
|
|
6
6
|
// List every row in the global_feature_state table — i.e. every feature
|
|
7
7
|
// that has ever been explicitly flipped. Features without a row aren't
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../constants.ts";
|
|
4
3
|
import { globalFeatureStateTable } from "../global-feature-state-table.ts";
|
|
4
|
+
import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../web/constants.ts";
|
|
5
5
|
|
|
6
6
|
// Inventory of every registered feature, annotated with toggle metadata
|
|
7
7
|
// and the current effective state. This is the canonical "what's here,
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
8
8
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
9
9
|
import * as z from "zod";
|
|
10
|
+
import { globalFeatureStateTable } from "../global-feature-state-table.ts";
|
|
11
|
+
import type { GlobalFeatureToggleRuntime } from "../toggle-runtime.ts";
|
|
10
12
|
import {
|
|
11
13
|
FEATURE_TOGGLE_AGGREGATE_TYPE,
|
|
12
14
|
FEATURE_TOGGLE_CROSS_TENANT_REASON,
|
|
13
15
|
FEATURE_TOGGLE_SET_EVENT_NAME,
|
|
14
16
|
FeatureToggleErrors,
|
|
15
|
-
} from "../constants.ts";
|
|
16
|
-
import { globalFeatureStateTable } from "../global-feature-state-table.ts";
|
|
17
|
-
import type { GlobalFeatureToggleRuntime } from "../toggle-runtime.ts";
|
|
17
|
+
} from "../web/constants.ts";
|
|
18
18
|
|
|
19
19
|
// Factory: binds a runtime accessor to the handler at registration time.
|
|
20
20
|
// The runtime holds the in-memory snapshot that the dispatcher's gate
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
export { composeTierResolverWithGlobalToggles } from "./compose-tier-resolver.ts";
|
|
2
|
-
export {
|
|
3
|
-
FEATURE_TOGGLES_FEATURE,
|
|
4
|
-
FeatureToggleHandlers,
|
|
5
|
-
FeatureToggleQueries,
|
|
6
|
-
TOGGLE_ADMIN_SCREEN_ID,
|
|
7
|
-
} from "./constants.ts";
|
|
8
2
|
export {
|
|
9
3
|
createFeatureToggleRuntime,
|
|
10
4
|
createFeatureTogglesFeature,
|
|
@@ -18,3 +12,9 @@ export {
|
|
|
18
12
|
type RedisToggleSyncSignal,
|
|
19
13
|
type ToggleSyncSignal,
|
|
20
14
|
} from "./feature.ts";
|
|
15
|
+
export {
|
|
16
|
+
FEATURE_TOGGLES_FEATURE,
|
|
17
|
+
FeatureToggleHandlers,
|
|
18
|
+
FeatureToggleQueries,
|
|
19
|
+
TOGGLE_ADMIN_SCREEN_ID,
|
|
20
|
+
} from "./web/constants.ts";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// @runtime client
|
|
2
1
|
import { mergeTranslations, type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
3
2
|
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
4
|
-
import { FEATURE_TOGGLES_FEATURE } from "
|
|
3
|
+
import { FEATURE_TOGGLES_FEATURE } from "./constants.ts";
|
|
5
4
|
import { defaultTranslations } from "./i18n.ts";
|
|
6
5
|
|
|
7
6
|
export type FeatureTogglesClientOptions = {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.379.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "File uploads in an actionForm, dropzone display for files fields",
|
|
6
|
+
"detail": "A files or images field of an actionForm screen uploads through POST /files with actionForm=<screen QN> and fieldName; the file is stored pending under the screen and the route checks the caller's access to the screen and its handler before writing bytes. New helpers resolveActionFormFileField and listActionFormFileFields (framework/files), bindPendingFileRef takes bindTo (the target entity file field, checked against its accept and maxSize) and registry, and ACTION_FORM_PSEUDO_ENTITY moves to framework/ui-types. New display \"list\" or \"dropzone\" on FilesFieldDef and ImagesFieldDef; the dropzone works in entityEdit and actionForm and maps server error codes to translated texts. Pending actionForm uploads are removed on user forget and by the forget-subject file purge. New i18n keys kumiko.widget.upload.too-large|invalid-type|max-count|remove, kumiko.field.dropzone.* and errors.file.violatesBindTarget (de, es, fr, it included).",
|
|
7
|
+
"migration": "Custom upload screens such as solon document-upload can become an actionForm with a files field and display \"dropzone\". The form's handler must bind every file it keeps: load it with loadPendingFileRef (entityName = the screen QN) and move it onto a record with bindPendingFileRef({ bindTo, registry: ctx.registry }); unbound uploads are treated as the uploader's personal data and removed on forget."
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"version": "0.372.0",
|
|
4
11
|
"type": "breaking",
|
|
@@ -26,11 +26,11 @@ import {
|
|
|
26
26
|
type FeatureRegistrar,
|
|
27
27
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
28
28
|
import { assertNoWhereRuleInOwnershipWrite } from "../shared/index.ts";
|
|
29
|
-
import { DEFAULT_FOLDER_ACCESS, FOLDERS_FEATURE_NAME } from "./constants.ts";
|
|
30
29
|
import { createFolderAssignmentEntity, folderEntity } from "./entity.ts";
|
|
31
30
|
import { createClearFolderHandler } from "./handlers/clear-folder.write.ts";
|
|
32
31
|
import { createDeleteFolderHandler } from "./handlers/delete-folder.write.ts";
|
|
33
32
|
import { createSetFolderHandler } from "./handlers/set-folder.write.ts";
|
|
33
|
+
import { DEFAULT_FOLDER_ACCESS, FOLDERS_FEATURE_NAME } from "./web/constants.ts";
|
|
34
34
|
|
|
35
35
|
// Opt-in tier-gating: when set, the feature declares itself r.toggleable so the
|
|
36
36
|
// dispatcher gate + feature-toggles + tier-engine can switch the WHOLE feature
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { denyUnlessJoinRowParentVisible } from "../../shared/index.ts";
|
|
3
3
|
import { folderAssignmentAggregateId } from "../aggregate-id.ts";
|
|
4
|
-
import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
|
|
5
4
|
import { folderAssignmentExecutor } from "../executor.ts";
|
|
6
5
|
import { type ClearFolderPayload, clearFolderPayloadSchema } from "../schemas.ts";
|
|
6
|
+
import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
|
|
7
7
|
|
|
8
8
|
// clear-folder — removes a host entity from its folder (back to "unfiled").
|
|
9
9
|
// Idempotent: clearing an entity that isn't in any folder is already the
|
|
@@ -2,8 +2,8 @@ import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/
|
|
|
2
2
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { hostRowIsGone } from "../../shared/index.ts";
|
|
5
|
-
import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
|
|
6
5
|
import { folderAssignmentExecutor, folderExecutor } from "../executor.ts";
|
|
6
|
+
import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
|
|
7
7
|
|
|
8
8
|
const deleteFolderPayloadSchema = z.object({ id: z.uuid() });
|
|
9
9
|
|
|
@@ -2,9 +2,9 @@ import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/
|
|
|
2
2
|
import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
3
|
import { denyUnlessJoinRowParentVisible } from "../../shared/index.ts";
|
|
4
4
|
import { folderAssignmentAggregateId } from "../aggregate-id.ts";
|
|
5
|
-
import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
|
|
6
5
|
import { folderAssignmentExecutor, folderExecutor } from "../executor.ts";
|
|
7
6
|
import { type SetFolderPayload, setFolderPayloadSchema } from "../schemas.ts";
|
|
7
|
+
import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
|
|
8
8
|
|
|
9
9
|
// set-folder — puts a host entity into a folder. Single-membership: the
|
|
10
10
|
// assignment id is deterministic over (tenant, entity) WITHOUT folderId, so an
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
export { folderAssignmentAggregateId } from "./aggregate-id.ts";
|
|
2
|
-
export {
|
|
3
|
-
DEFAULT_FOLDER_ACCESS,
|
|
4
|
-
DEFAULT_FOLDER_ROLES,
|
|
5
|
-
FOLDER_SECTION_EXTENSION_NAME,
|
|
6
|
-
FOLDERS_FEATURE_NAME,
|
|
7
|
-
FoldersHandlers,
|
|
8
|
-
FoldersQueries,
|
|
9
|
-
} from "./constants.ts";
|
|
10
2
|
export { folderAssignmentEntity, folderEntity } from "./entity.ts";
|
|
11
3
|
export {
|
|
12
4
|
createFoldersFeature,
|
|
@@ -20,3 +12,11 @@ export {
|
|
|
20
12
|
type SetFolderPayload,
|
|
21
13
|
setFolderPayloadSchema,
|
|
22
14
|
} from "./schemas.ts";
|
|
15
|
+
export {
|
|
16
|
+
DEFAULT_FOLDER_ACCESS,
|
|
17
|
+
DEFAULT_FOLDER_ROLES,
|
|
18
|
+
FOLDER_SECTION_EXTENSION_NAME,
|
|
19
|
+
FOLDERS_FEATURE_NAME,
|
|
20
|
+
FoldersHandlers,
|
|
21
|
+
FoldersQueries,
|
|
22
|
+
} from "./web/constants.ts";
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
// @runtime client
|
|
2
|
-
|
|
3
1
|
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
4
|
-
import { FOLDER_SECTION_EXTENSION_NAME, FOLDERS_FEATURE_NAME } from "
|
|
2
|
+
import { FOLDER_SECTION_EXTENSION_NAME, FOLDERS_FEATURE_NAME } from "./constants.ts";
|
|
5
3
|
import { FolderSection } from "./folder-section.tsx";
|
|
6
4
|
import { defaultTranslations } from "./i18n.ts";
|
|
7
5
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @runtime client
|
|
2
1
|
// FolderManager — in-screen folder tree the user manages directly: create root
|
|
3
2
|
// folders + subfolders, rename, delete, collapse/expand. KPI-agnostic: a host
|
|
4
3
|
// passes `renderMeta` to hang its own per-folder badges (e.g. money-horse's
|
|
@@ -35,7 +34,7 @@ import {
|
|
|
35
34
|
} from "@cosmicdrift/kumiko-renderer";
|
|
36
35
|
import { ChevronRight, File, Folder, type LucideIcon, Pencil, Plus, Trash2 } from "lucide-react";
|
|
37
36
|
import { type DragEvent, type ReactNode, useEffect, useState } from "react";
|
|
38
|
-
import { FoldersHandlers, FoldersQueries } from "
|
|
37
|
+
import { FoldersHandlers, FoldersQueries } from "./constants.ts";
|
|
39
38
|
import { buildFolderTree, type FolderNode, type FolderRow } from "./tree.ts";
|
|
40
39
|
|
|
41
40
|
type FolderListResponse = { readonly rows: readonly FolderRow[] };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @runtime client
|
|
2
1
|
// FolderSection — drop-in single-folder picker for ANY entity. Unlike tags
|
|
3
2
|
// (many-to-many multi-combobox), an entity lives in exactly ONE folder, so this
|
|
4
3
|
// is a single-select combobox with a "no folder" option plus a compact row to
|
|
@@ -19,7 +18,7 @@ import {
|
|
|
19
18
|
useTranslation,
|
|
20
19
|
} from "@cosmicdrift/kumiko-renderer";
|
|
21
20
|
import { type ReactNode, useState } from "react";
|
|
22
|
-
import { FoldersHandlers, FoldersQueries } from "
|
|
21
|
+
import { FoldersHandlers, FoldersQueries } from "./constants.ts";
|
|
23
22
|
import { type FolderRow, folderPath } from "./tree.ts";
|
|
24
23
|
|
|
25
24
|
type AssignmentRow = {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// @runtime client
|
|
2
|
-
export { FOLDER_SECTION_EXTENSION_NAME, FoldersHandlers, FoldersQueries } from "../constants.ts";
|
|
3
1
|
export { foldersClient } from "./client-plugin.tsx";
|
|
2
|
+
export { FOLDER_SECTION_EXTENSION_NAME, FoldersHandlers, FoldersQueries } from "./constants.ts";
|
|
4
3
|
export { type FolderFiling, type FolderLeaf, FolderManager } from "./folder-manager.tsx";
|
|
5
4
|
export { FolderSection } from "./folder-section.tsx";
|
|
6
5
|
export { buildFolderTree, type FolderNode, type FolderRow, folderPath } from "./tree.ts";
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.379.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "Form draft content is encrypted per owner",
|
|
6
|
+
"detail": "The jsonb field draft carries personal: { of: \"ownerId\" }, so its content is stored as ciphertext in events and in read_form_drafts; the delete event no longer keeps the plaintext in previous. The PII event backfill (jsonb-objects-v3) encrypts existing events once on the next boot and rebuilds the table. The column type stays jsonb, so there is no schema change.",
|
|
7
|
+
"migration": "Nothing to run; the backfill happens on boot. Code that reads read_form_drafts.draft with raw SQL must decrypt it (decryptPiiFieldValues) or use the form-draft lookup helpers; the get and list queries are unchanged for clients."
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"version": "0.370.0",
|
|
4
11
|
"type": "breaking",
|
|
@@ -2,6 +2,7 @@ import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
5
|
+
import { readStoredDraft } from "../../decrypt-draft.ts";
|
|
5
6
|
import type { FormDraftBlob } from "../../schemas.ts";
|
|
6
7
|
|
|
7
8
|
export type StaleDraftRow = {
|
|
@@ -9,7 +10,10 @@ export type StaleDraftRow = {
|
|
|
9
10
|
readonly tenantId: TenantId;
|
|
10
11
|
readonly ownerId: string;
|
|
11
12
|
readonly draftKey: string;
|
|
12
|
-
readonly draft: FormDraftBlob;
|
|
13
|
+
readonly draft: FormDraftBlob | null;
|
|
14
|
+
// Decryption failed (e.g. KMS outage): `draft: null` then does not mean "empty", so the row must
|
|
15
|
+
// not be deleted — its FileRefs could not be released.
|
|
16
|
+
readonly draftUnreadable?: true;
|
|
13
17
|
readonly insertedAt: Temporal.Instant;
|
|
14
18
|
};
|
|
15
19
|
|
|
@@ -28,30 +32,40 @@ export async function selectStaleDraftsBatch(
|
|
|
28
32
|
db: DbConnection,
|
|
29
33
|
olderThanDays: number,
|
|
30
34
|
batchSize: number,
|
|
35
|
+
excludeIds: readonly string[] = [],
|
|
31
36
|
): Promise<readonly StaleDraftRow[]> {
|
|
32
37
|
const rows = await unsafeReadRetrying<{
|
|
33
38
|
id: string;
|
|
34
39
|
tenant_id: string;
|
|
35
40
|
owner_id: string;
|
|
36
41
|
draft_key: string;
|
|
37
|
-
draft:
|
|
42
|
+
draft: unknown;
|
|
38
43
|
inserted_at: Date;
|
|
39
44
|
}>(
|
|
40
45
|
db,
|
|
41
46
|
`SELECT "id", "tenant_id", "owner_id", "draft_key", "draft", "inserted_at" FROM "read_form_drafts"
|
|
42
47
|
WHERE COALESCE("modified_at", "inserted_at") < now() - ($1::int * interval '1 day')
|
|
48
|
+
AND NOT ("id"::text = ANY($3::text[]))
|
|
43
49
|
ORDER BY COALESCE("modified_at", "inserted_at") ASC
|
|
44
50
|
LIMIT $2`,
|
|
45
|
-
[olderThanDays, batchSize],
|
|
51
|
+
[olderThanDays, batchSize, [...excludeIds]],
|
|
52
|
+
);
|
|
53
|
+
return Promise.all(
|
|
54
|
+
rows.map(async (row) => {
|
|
55
|
+
const base = {
|
|
56
|
+
id: row.id,
|
|
57
|
+
tenantId: row.tenant_id as TenantId, // @cast-boundary db-row
|
|
58
|
+
ownerId: row.owner_id,
|
|
59
|
+
draftKey: row.draft_key,
|
|
60
|
+
insertedAt: Temporal.Instant.fromEpochMilliseconds(+row.inserted_at), // @cast-boundary db-row
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
return { ...base, draft: await readStoredDraft(row.draft) };
|
|
64
|
+
} catch {
|
|
65
|
+
return { ...base, draft: null, draftUnreadable: true as const };
|
|
66
|
+
}
|
|
67
|
+
}),
|
|
46
68
|
);
|
|
47
|
-
return rows.map((row) => ({
|
|
48
|
-
id: row.id,
|
|
49
|
-
tenantId: row.tenant_id as TenantId, // @cast-boundary db-row
|
|
50
|
-
ownerId: row.owner_id,
|
|
51
|
-
draftKey: row.draft_key,
|
|
52
|
-
draft: row.draft,
|
|
53
|
-
insertedAt: Temporal.Instant.fromEpochMilliseconds(+row.inserted_at), // @cast-boundary db-row
|
|
54
|
-
}));
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
/** Re-check staleness after the select→release window so a freshly saved draft is not deleted. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { requestContext } from "@cosmicdrift/kumiko-framework/api";
|
|
2
|
+
import {
|
|
3
|
+
configuredPiiSubjectKms,
|
|
4
|
+
decryptPiiFieldValues,
|
|
5
|
+
isPiiCiphertext,
|
|
6
|
+
} from "@cosmicdrift/kumiko-framework/crypto";
|
|
7
|
+
import { type FormDraftBlob, formDraftBlobSchema } from "./schemas.ts";
|
|
8
|
+
|
|
9
|
+
// Raw reads (fetchOne/selectMany/SQL) return the stored column, which is
|
|
10
|
+
// ciphertext once the owner's key exists. The field name is part of the AAD,
|
|
11
|
+
// so it must stay "draft". An erased owner yields the sentinel string, which
|
|
12
|
+
// fails the blob schema and reads as null (no usable draft).
|
|
13
|
+
export async function readStoredDraft(stored: unknown): Promise<FormDraftBlob | null> {
|
|
14
|
+
let plain = stored;
|
|
15
|
+
const kms = configuredPiiSubjectKms();
|
|
16
|
+
if (isPiiCiphertext(stored) && kms) {
|
|
17
|
+
const out = await decryptPiiFieldValues({ draft: stored }, ["draft"], kms, {
|
|
18
|
+
requestId: requestContext.get()?.requestId ?? "form-draft:read",
|
|
19
|
+
});
|
|
20
|
+
plain = out["draft"];
|
|
21
|
+
}
|
|
22
|
+
const parsed = formDraftBlobSchema.safeParse(plain);
|
|
23
|
+
return parsed.success ? parsed.data : null;
|
|
24
|
+
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createJsonbField,
|
|
4
4
|
createTextField,
|
|
5
5
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
6
|
-
import { FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT } from "./constants.ts";
|
|
6
|
+
import { FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT } from "./web/constants.ts";
|
|
7
7
|
|
|
8
8
|
// form-draft — a per-user, pre-submission working copy of an in-progress
|
|
9
9
|
// form (e.g. a wizard-mode EditLayout). `draftKey` is caller-assigned
|
|
@@ -37,14 +37,11 @@ export const formDraftEntity = createEntity({
|
|
|
37
37
|
// The blob shape is fixed by issue #1889, not left to the caller:
|
|
38
38
|
// { values: Record<string, unknown>, stepIndex: number, savedAt: string }.
|
|
39
39
|
// Free-form because `values` mirrors whatever fields the in-progress
|
|
40
|
-
// form has, so it can carry arbitrary user-entered PII.
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
// not crypto-shredding; `ownerId`'s `subjectRef` annotation alone
|
|
46
|
-
// already satisfies the GDPR-hook-coverage boot guard.
|
|
47
|
-
draft: createJsonbField(),
|
|
40
|
+
// form has, so it can carry arbitrary user-entered PII. Encrypted under
|
|
41
|
+
// the owner's key (jsonb ciphertext scalar in the row and in every event
|
|
42
|
+
// that carries it, `previous` of delete included), so forgetting the
|
|
43
|
+
// owner shreds all copies.
|
|
44
|
+
draft: createJsonbField({ personal: { of: "ownerId" } }),
|
|
48
45
|
},
|
|
49
46
|
// One draft per (tenant, owner, draftKey) — save() is an upsert keyed on
|
|
50
47
|
// this index (see handlers/save.write.ts); a resume query must find at
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
9
9
|
import { defineFeature, type FeatureRegistrar } from "@cosmicdrift/kumiko-framework/engine";
|
|
10
|
-
import { FORM_DRAFT_FEATURE_NAME } from "./constants.ts";
|
|
11
10
|
import { formDraftEntity } from "./entity.ts";
|
|
12
11
|
import { cleanupDraftsJob, formDraftRetentionDaysConfig } from "./handlers/cleanup.job.ts";
|
|
13
12
|
import { discardDraftWrite } from "./handlers/discard.write.ts";
|
|
14
13
|
import { getDraftQuery } from "./handlers/get.query.ts";
|
|
15
14
|
import { listDraftsQuery } from "./handlers/list.query.ts";
|
|
16
15
|
import { saveDraftWrite } from "./handlers/save.write.ts";
|
|
16
|
+
import { FORM_DRAFT_FEATURE_NAME } from "./web/constants.ts";
|
|
17
17
|
|
|
18
18
|
const CLEANUP_ESCAPE_HATCH_REASON = "purges stale drafts of every tenant";
|
|
19
19
|
|
|
@@ -126,14 +126,27 @@ export async function deleteStaleDraftsBatch(
|
|
|
126
126
|
db: DbConnection,
|
|
127
127
|
retentionDays: number,
|
|
128
128
|
log: AppContext["log"],
|
|
129
|
-
): Promise<{
|
|
129
|
+
): Promise<{
|
|
130
|
+
readonly deletedRows: readonly StaleDraftRow[];
|
|
131
|
+
readonly skippedCount: number;
|
|
132
|
+
readonly deferredIds: readonly string[];
|
|
133
|
+
}> {
|
|
130
134
|
const deletedRows: StaleDraftRow[] = [];
|
|
135
|
+
const deferredIds: string[] = [];
|
|
131
136
|
let skippedCount = 0;
|
|
132
137
|
const byId = new Map(batch.map((row) => [row.id, row]));
|
|
133
138
|
for (const [tenantId, ids] of groupStaleDraftIdsByTenant(batch)) {
|
|
134
139
|
const systemUser = createSystemUser(tenantId);
|
|
135
140
|
const tenantDb = createTenantDb({ db, tenantId, mode: "system" });
|
|
136
141
|
for (const id of ids) {
|
|
142
|
+
// skip: an unreadable blob hides its FileRefs; deleting now would orphan them, so the next run retries.
|
|
143
|
+
if (byId.get(id)?.draftUnreadable) {
|
|
144
|
+
log?.warn?.(
|
|
145
|
+
`[form-draft:cleanup] draft id=${id} tenant=${tenantId} could not be decrypted — kept for the next run`,
|
|
146
|
+
);
|
|
147
|
+
deferredIds.push(id);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
137
150
|
// Race: user may have saved between select and here — skip if no longer stale.
|
|
138
151
|
if (!(await isDraftStillStale(db, tenantId, id, retentionDays))) {
|
|
139
152
|
skippedCount++;
|
|
@@ -150,7 +163,7 @@ export async function deleteStaleDraftsBatch(
|
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
}
|
|
153
|
-
return { deletedRows, skippedCount };
|
|
166
|
+
return { deletedRows, skippedCount, deferredIds };
|
|
154
167
|
}
|
|
155
168
|
|
|
156
169
|
export async function cleanupDraftsJob(
|
|
@@ -181,9 +194,12 @@ export async function cleanupDraftsJob(
|
|
|
181
194
|
const fileProviderResolver = ctx._fileProviderResolver;
|
|
182
195
|
|
|
183
196
|
let deleted = 0;
|
|
197
|
+
const deferred = new Set<string>();
|
|
184
198
|
while (true) {
|
|
185
199
|
if (ctx.signal?.aborted) break;
|
|
186
|
-
const batch = await selectStaleDraftsBatch(db, retentionDays, DEFAULT_BATCH_SIZE
|
|
200
|
+
const batch = await selectStaleDraftsBatch(db, retentionDays, DEFAULT_BATCH_SIZE, [
|
|
201
|
+
...deferred,
|
|
202
|
+
]);
|
|
187
203
|
if (batch.length === 0) break;
|
|
188
204
|
|
|
189
205
|
// Rows span arbitrary tenants (this job sweeps the whole table under
|
|
@@ -193,12 +209,13 @@ export async function cleanupDraftsJob(
|
|
|
193
209
|
// entirely for rows with no FileRefs in the blob, the common case.
|
|
194
210
|
// Delete first (with staleness re-check), then release binaries from rows
|
|
195
211
|
// that actually disappeared — never release a draft the user just saved.
|
|
196
|
-
const { deletedRows, skippedCount } = await deleteStaleDraftsBatch(
|
|
212
|
+
const { deletedRows, skippedCount, deferredIds } = await deleteStaleDraftsBatch(
|
|
197
213
|
batch,
|
|
198
214
|
db,
|
|
199
215
|
retentionDays,
|
|
200
216
|
ctx.log,
|
|
201
217
|
);
|
|
218
|
+
for (const id of deferredIds) deferred.add(id);
|
|
202
219
|
for (const row of deletedRows) {
|
|
203
220
|
await releaseRowFileRefs(row, db, fileProviderResolver, ctx.log);
|
|
204
221
|
}
|
|
@@ -206,7 +223,11 @@ export async function cleanupDraftsJob(
|
|
|
206
223
|
// A skipped row is no longer stale, so the next select drops it — a fully
|
|
207
224
|
// skipped batch still makes progress. Only a batch with neither deletes nor
|
|
208
225
|
// skips (all failed) would reselect the same rows forever.
|
|
209
|
-
if (
|
|
226
|
+
if (
|
|
227
|
+
deletedRows.length + skippedCount + deferredIds.length === 0 ||
|
|
228
|
+
batch.length < DEFAULT_BATCH_SIZE
|
|
229
|
+
)
|
|
230
|
+
break;
|
|
210
231
|
}
|
|
211
232
|
ctx.log?.info?.(`[form-draft:cleanup] deleted=${deleted} retentionDays=${retentionDays}`);
|
|
212
233
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { fileRefEntity, fileRefsTable } from "@cosmicdrift/kumiko-framework/files";
|
|
4
|
-
import { FORM_DRAFT_ACCESS } from "../constants.ts";
|
|
5
4
|
import { filterOwnedFileRefs } from "../db/queries/owned-file-refs.ts";
|
|
6
5
|
import { formDraftExecutor } from "../executor.ts";
|
|
7
6
|
import { lookupDraft } from "../lookup.ts";
|
|
8
7
|
import { collectDraftFileRefKeys, releaseDraftFileRefs } from "../release-file-refs.ts";
|
|
9
8
|
import { discardDraftPayloadSchema } from "../schemas.ts";
|
|
9
|
+
import { FORM_DRAFT_ACCESS } from "../web/constants.ts";
|
|
10
10
|
|
|
11
11
|
// Same construction as file-routes.ts/user-data-rights-defaults' fileRef
|
|
12
12
|
// hook — self-contained (table + entity), no registry needed. `.forget()`
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import { FORM_DRAFT_ACCESS } from "../constants.ts";
|
|
3
2
|
import { lookupDraft } from "../lookup.ts";
|
|
4
3
|
import type { FormDraftBlob } from "../schemas.ts";
|
|
5
|
-
import {
|
|
4
|
+
import { getDraftPayloadSchema } from "../schemas.ts";
|
|
5
|
+
import { FORM_DRAFT_ACCESS } from "../web/constants.ts";
|
|
6
6
|
|
|
7
7
|
export type GetDraftResult = { readonly draft: FormDraftBlob | null };
|
|
8
8
|
|
|
@@ -24,15 +24,14 @@ export const getDraftQuery = defineQueryHandler({
|
|
|
24
24
|
query.payload.draftKey,
|
|
25
25
|
);
|
|
26
26
|
if (!row) return { draft: null };
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Schema evolution or a corrupt jsonb row: surface it to operators
|
|
27
|
+
if (!row.draft) {
|
|
28
|
+
// Schema evolution or a corrupt/erased row: surface it to operators
|
|
30
29
|
// instead of silently making the user's draft vanish.
|
|
31
30
|
ctx.log?.warn?.(
|
|
32
|
-
`[form-draft:get] stored blob for draftKey=${query.payload.draftKey} failed schema, treating as absent
|
|
31
|
+
`[form-draft:get] stored blob for draftKey=${query.payload.draftKey} failed schema or decryption, treating as absent`,
|
|
33
32
|
);
|
|
34
33
|
return { draft: null };
|
|
35
34
|
}
|
|
36
|
-
return { draft:
|
|
35
|
+
return { draft: row.draft };
|
|
37
36
|
},
|
|
38
37
|
});
|