@cosmicdrift/kumiko-samples 0.388.0 → 0.390.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 +25 -13
- package/packages/bundled-features/src/agent-tools/changes.json +6 -0
- package/packages/bundled-features/src/agent-tools/index.ts +1 -1
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +42 -26
- package/packages/bundled-features/src/audit/feature.ts +2 -1
- package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/bootstrap.ts +13 -1
- package/packages/bundled-features/src/auth-email-password/changes.json +18 -0
- package/packages/bundled-features/src/auth-email-password/feature.ts +2 -2
- package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +7 -7
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +9 -7
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +11 -7
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +4 -4
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +2 -2
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +9 -7
- package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +23 -16
- package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +1 -0
- package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +1 -0
- package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +1 -0
- package/packages/bundled-features/src/auth-email-password/handlers/reset-password.write.ts +3 -2
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +12 -12
- package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +16 -8
- package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +4 -2
- package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +10 -2
- package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +3 -2
- package/packages/bundled-features/src/auth-email-password/magic-link-mail.ts +16 -3
- package/packages/bundled-features/src/auth-email-password/seeding.ts +14 -9
- package/packages/bundled-features/src/auth-email-password/signup-activation.ts +2 -0
- package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +8 -2
- package/packages/bundled-features/src/auth-email-password/web/auth-redirect.ts +23 -21
- package/packages/bundled-features/src/auth-email-password/web/default-auth-pages-gate.tsx +6 -3
- package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -1
- package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -0
- package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +16 -5
- package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +7 -1
- package/packages/bundled-features/src/auth-email-password/web/return-path.ts +35 -0
- package/packages/bundled-features/src/auth-email-password/web/session.tsx +6 -1
- package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +11 -3
- package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +12 -2
- package/packages/bundled-features/src/auth-foundation/feature.ts +13 -4
- package/packages/bundled-features/src/auth-mfa/changes.json +6 -0
- package/packages/bundled-features/src/auth-mfa/config.ts +3 -7
- package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +5 -5
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +24 -14
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +9 -3
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +6 -1
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start.write.ts +3 -1
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +14 -9
- package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -4
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +25 -14
- package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +10 -4
- package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +17 -8
- package/packages/bundled-features/src/auth-mfa/verify-factor.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +5 -5
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +10 -7
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +15 -12
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-open-cancels.ts +22 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-provider-lock.ts +4 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +4 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +17 -58
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +10 -8
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +18 -15
- package/packages/bundled-features/src/billing-foundation/events.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/feature.ts +8 -3
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +5 -5
- package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/projection.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/types.ts +1 -1
- package/packages/bundled-features/src/cap-counter/aggregate-id.ts +1 -1
- package/packages/bundled-features/src/cap-counter/book-cap-usage.ts +5 -4
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +21 -8
- package/packages/bundled-features/src/cap-counter/changes.json +12 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +1 -1
- package/packages/bundled-features/src/cap-counter/feature.ts +3 -2
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +1 -1
- package/packages/bundled-features/src/cap-counter/reservation-chain.ts +1 -1
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +4 -4
- package/packages/bundled-features/src/cap-overview/feature.ts +1 -0
- 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 +1 -1
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +12 -7
- package/packages/bundled-features/src/config/changes.json +6 -0
- package/packages/bundled-features/src/config/feature.ts +6 -6
- package/packages/bundled-features/src/config/handlers/cascade.query.ts +1 -1
- package/packages/bundled-features/src/config/handlers/readiness.query.ts +1 -1
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +23 -13
- package/packages/bundled-features/src/config/handlers/reset.write.ts +3 -3
- package/packages/bundled-features/src/config/handlers/selected-extensions.query.ts +1 -1
- package/packages/bundled-features/src/config/handlers/set.write.ts +22 -5
- package/packages/bundled-features/src/config/handlers/values.query.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/changes.json +12 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +9 -9
- package/packages/bundled-features/src/crypto-shredding/resolve-file-bytes-deleter.ts +3 -3
- package/packages/bundled-features/src/custom-fields/changes.json +6 -0
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-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 +1 -1
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
- package/packages/bundled-features/src/custom-fields/index.ts +4 -0
- package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
- package/packages/bundled-features/src/data-retention/feature.ts +1 -1
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +12 -2
- package/packages/bundled-features/src/delivery/attempt-log.ts +1 -1
- package/packages/bundled-features/src/delivery/changes.json +12 -0
- package/packages/bundled-features/src/delivery/delivery-service.ts +6 -5
- package/packages/bundled-features/src/delivery/feature.ts +3 -2
- package/packages/bundled-features/src/delivery/index.ts +5 -0
- package/packages/bundled-features/src/delivery/jobs.ts +11 -11
- package/packages/bundled-features/src/delivery/system-channel-context.ts +33 -0
- package/packages/bundled-features/src/delivery/testing.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/append-missing-extract-event.ts +84 -0
- package/packages/bundled-features/src/document-ingest-foundation/changes.json +6 -0
- package/packages/bundled-features/src/document-ingest-foundation/events.ts +16 -1
- package/packages/bundled-features/src/document-ingest-foundation/index.ts +11 -0
- package/packages/bundled-features/src/feature-toggles/feature.ts +1 -0
- package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +5 -1
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +7 -5
- package/packages/bundled-features/src/file-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -5
- package/packages/bundled-features/src/file-provider-s3/feature.ts +4 -1
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +8 -8
- package/packages/bundled-features/src/form-draft/feature.ts +1 -1
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +22 -12
- package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +3 -3
- package/packages/bundled-features/src/form-draft/handlers/get.query.ts +1 -1
- package/packages/bundled-features/src/foundation-shared/config-helpers.ts +1 -1
- package/packages/bundled-features/src/host-routing/changes.json +6 -0
- package/packages/bundled-features/src/host-routing/validate-options.ts +5 -0
- package/packages/bundled-features/src/inbound-mail-foundation/events.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +2 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +2 -2
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +10 -10
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +4 -1
- package/packages/bundled-features/src/jobs/changes.json +6 -0
- package/packages/bundled-features/src/jobs/events.ts +1 -1
- package/packages/bundled-features/src/jobs/feature.ts +1 -0
- package/packages/bundled-features/src/jobs/handlers/consumer.write.ts +7 -4
- package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +11 -5
- package/packages/bundled-features/src/jobs/handlers/retention-cleanup.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/stale-run-sweep.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +2 -2
- package/packages/bundled-features/src/jobs/job-run-logger.ts +139 -90
- package/packages/bundled-features/src/ledger/web/index.ts +1 -1
- package/packages/bundled-features/src/legal-pages/README.md +1 -1
- package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +12 -8
- package/packages/bundled-features/src/legal-pages/seed.ts +5 -2
- package/packages/bundled-features/src/mail-foundation/feature.ts +2 -2
- package/packages/bundled-features/src/mail-transport-smtp/changes.json +12 -0
- package/packages/bundled-features/src/mail-transport-smtp/config-keys.ts +1 -1
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +13 -12
- package/packages/bundled-features/src/managed-pages/changes.json +6 -0
- package/packages/bundled-features/src/managed-pages/constants.ts +1 -0
- package/packages/bundled-features/src/managed-pages/feature.ts +3 -1
- package/packages/bundled-features/src/managed-pages/index.ts +1 -0
- package/packages/bundled-features/src/managed-pages/seeding.ts +13 -8
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +2 -1
- package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/rate-limiting/handlers/status.query.ts +2 -2
- package/packages/bundled-features/src/readiness/handlers/status.query.ts +4 -1
- package/packages/bundled-features/src/renderer-foundation/api.ts +3 -3
- package/packages/bundled-features/src/secrets/announce-secret-change.ts +4 -4
- package/packages/bundled-features/src/secrets/changes.json +6 -0
- package/packages/bundled-features/src/secrets/feature.ts +9 -9
- package/packages/bundled-features/src/secrets/handlers/delete.write.ts +4 -3
- package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +13 -8
- package/packages/bundled-features/src/secrets/handlers/set.write.ts +4 -3
- package/packages/bundled-features/src/secrets/secrets-context.ts +16 -6
- package/packages/bundled-features/src/secrets/write-gate.ts +10 -3
- package/packages/bundled-features/src/seo/feature.ts +1 -1
- package/packages/bundled-features/src/sessions/changes.json +19 -0
- package/packages/bundled-features/src/sessions/feature.ts +2 -1
- package/packages/bundled-features/src/sessions/handlers/cleanup.job.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/detail.query.ts +5 -2
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +5 -2
- package/packages/bundled-features/src/sessions/handlers/mine.query.ts +5 -2
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +3 -3
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/sessions/index.ts +1 -1
- package/packages/bundled-features/src/sessions/screens.ts +8 -4
- package/packages/bundled-features/src/sessions/session-callbacks.ts +1 -9
- package/packages/bundled-features/src/sessions/session-revoked-event.ts +1 -1
- package/packages/bundled-features/src/sessions/web/session-device-cell.tsx +10 -12
- package/packages/bundled-features/src/sessions/web/user-agent.ts +12 -0
- package/packages/bundled-features/src/shared/index.ts +15 -0
- package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +36 -4
- package/packages/bundled-features/src/shared/require-for-tenant.ts +7 -5
- package/packages/bundled-features/src/shared/run-in-sub-transaction.ts +5 -5
- package/packages/bundled-features/src/shared/stream-tenant-backfill.ts +201 -0
- package/packages/bundled-features/src/shared/stream-tenant-derived-state.ts +107 -0
- package/packages/bundled-features/src/step-dispatcher/changes.json +6 -0
- package/packages/bundled-features/src/step-dispatcher/deliver-dispatch-request.ts +17 -3
- package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -1
- package/packages/bundled-features/src/step-dispatcher/mail-runner.ts +2 -1
- package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +1 -1
- package/packages/bundled-features/src/subscription-dodo/runtime.ts +7 -7
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +5 -3
- package/packages/bundled-features/src/subscription-stripe/runtime.ts +7 -7
- package/packages/bundled-features/src/tags/feature.ts +1 -0
- package/packages/bundled-features/src/template-resolver/api.ts +3 -3
- package/packages/bundled-features/src/template-resolver/changes.json +54 -0
- package/packages/bundled-features/src/template-resolver/document-ops.ts +20 -1
- package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +5 -4
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +36 -11
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +32 -7
- package/packages/bundled-features/src/template-resolver/handlers/patch-draft.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/send-test-shared.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/send-test-status.query.ts +22 -19
- package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +6 -2
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +4 -2
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/seeding.ts +22 -5
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +68 -19
- package/packages/bundled-features/src/template-resolver/template-resources.ts +4 -4
- package/packages/bundled-features/src/template-resolver/testing.ts +2 -2
- package/packages/bundled-features/src/template-resolver/web/document-insert-fields.tsx +222 -0
- package/packages/bundled-features/src/template-resolver/web/document-insert-model.ts +164 -0
- package/packages/bundled-features/src/template-resolver/web/document-insert-panel.tsx +115 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-bubble.tsx +177 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-content.tsx +38 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-context.ts +119 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +51 -1098
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-helpers.ts +161 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-layout.tsx +83 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-toolbar-groups.tsx +153 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-toolbar.tsx +182 -0
- package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +18 -0
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +6 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +19 -6
- package/packages/bundled-features/src/template-resolver/web/qualified-names.ts +1 -0
- package/packages/bundled-features/src/template-resolver/web/use-document-tiptap-model.ts +138 -0
- package/packages/bundled-features/src/tenant/changes.json +19 -0
- package/packages/bundled-features/src/tenant/feature.ts +1 -0
- package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -2
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +3 -3
- package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -1
- package/packages/bundled-features/src/tenant/index.ts +5 -0
- package/packages/bundled-features/src/tenant/invited-membership.ts +6 -1
- package/packages/bundled-features/src/tenant/schema/tenant.ts +4 -1
- package/packages/bundled-features/src/tenant/seeding.ts +65 -62
- package/packages/bundled-features/src/tenant/stream-tenant-backfill.ts +115 -0
- package/packages/bundled-features/src/tenant/testing.ts +77 -0
- package/packages/bundled-features/src/tenant-handover/events.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/changes.json +6 -0
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +5 -5
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +22 -10
- package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +22 -11
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +23 -12
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +42 -4
- package/packages/bundled-features/src/tenant-lifecycle/testing.ts +9 -8
- package/packages/bundled-features/src/tier-engine/entity.ts +1 -1
- package/packages/bundled-features/src/tier-engine/feature.ts +8 -3
- package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +3 -3
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +7 -1
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +3 -3
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +71 -97
- package/packages/bundled-features/src/user/feature.ts +1 -0
- package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +2 -2
- package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -2
- package/packages/bundled-features/src/user/index.ts +2 -0
- package/packages/bundled-features/src/user/invited-global-roles.ts +6 -1
- package/packages/bundled-features/src/user/principal-status.ts +1 -1
- package/packages/bundled-features/src/user/seeding.ts +24 -6
- package/packages/bundled-features/src/user/testing.ts +22 -0
- package/packages/bundled-features/src/user-data-rights/COMPLIANCE.md +1 -1
- package/packages/bundled-features/src/user-data-rights/README.md +1 -1
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +12 -2
- package/packages/bundled-features/src/user-data-rights/changes.json +36 -0
- package/packages/bundled-features/src/user-data-rights/feature.ts +30 -24
- package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/deletion-grace-period.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +4 -4
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +12 -6
- package/packages/bundled-features/src/user-data-rights/index.ts +8 -1
- package/packages/bundled-features/src/user-data-rights/lib/mail-transport-resolver.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/lib/storage-provider-resolver.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +6 -1
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +8 -2
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +14 -3
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +11 -1
- package/packages/bundled-features/src/user-data-rights/web/constants.ts +16 -0
- package/packages/bundled-features/src/user-data-rights/web/index.ts +6 -0
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +8 -6
- package/packages/bundled-features/src/waitlist/changes.json +18 -0
- package/packages/bundled-features/src/waitlist/feature.ts +1 -0
- package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +1 -1
- package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +2 -2
- package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +34 -10
- package/packages/bundled-features/src/waitlist/import.ts +23 -3
- package/packages/bundled-features/src/waitlist/legacy-migrate.ts +8 -2
- package/packages/bundled-features/src/waitlist/link-on-signup.ts +7 -1
- package/packages/bundled-features/src/waitlist/options.ts +2 -1
- package/packages/bundled-features/src/workflow-runner/changes.json +6 -0
- package/packages/bundled-features/src/workflow-runner/db/queries/due-runs.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -3
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +2 -1
- package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +8 -8
- package/packages/bundled-features/src/workflow-runner/runner.ts +6 -4
- package/samples/apps/cap-billing-demo/src/feature.ts +19 -5
- package/samples/apps/config-demo/src/app/server.ts +1 -1
- package/samples/apps/styleguide/src/app/client.tsx +2 -0
- package/samples/apps/styleguide/src/app/seed.ts +6 -4
- package/samples/apps/styleguide/src/app/server.ts +6 -3
- package/samples/apps/styleguide/src/features/widgets/feature.ts +15 -4
- package/samples/apps/styleguide/src/features/workboard/feature.ts +185 -0
- package/samples/apps/styleguide/src/features/workboard/i18n.ts +27 -0
- package/samples/apps/styleguide/src/features/workboard/seed.ts +121 -0
- package/samples/apps/styleguide/src/features/workboard/web.ts +13 -0
- package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +9 -0
- package/samples/apps/use-all-bundled/bin/main.ts +2 -0
- package/samples/apps/use-all-bundled/feature-manifest.json +17 -1
- package/samples/apps/use-all-bundled/kumiko/schema.ts +2 -0
- package/samples/apps/use-all-bundled/kumiko.config.ts +2 -0
- package/samples/apps/use-all-bundled/package.json +2 -1
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +2 -0
- package/samples/apps/use-all-bundled/src/app/notes-feature.ts +2 -0
- package/samples/apps/use-all-bundled/src/app/seed.ts +12 -2
- package/samples/apps/use-all-bundled/src/bundled-lists.ts +15 -0
- package/samples/apps/user-data-rights-demo/README.md +1 -1
- package/samples/apps/user-data-rights-demo/src/feature.ts +3 -2
- package/samples/recipes/api-worker-split/README.md +2 -1
- package/samples/recipes/api-worker-split/src/feature.ts +2 -1
- package/samples/recipes/cross-feature-events/README.md +5 -5
- package/samples/recipes/cross-feature-events/package.json +1 -1
- package/samples/recipes/cross-feature-events/src/feature.ts +4 -4
- package/samples/recipes/event-sourcing/README.md +5 -5
- package/samples/recipes/event-sourcing/package.json +1 -1
- package/samples/recipes/event-sourcing/src/feature.ts +15 -15
- package/samples/recipes/files-post-processing/README.md +1 -1
- package/samples/recipes/files-post-processing/package.json +1 -1
- package/samples/recipes/files-post-processing/src/feature.ts +6 -4
- package/samples/recipes/golden-path/src/feature.ts +2 -1
- package/samples/recipes/lane-routing/package.json +1 -1
- package/samples/recipes/legal-pages/README.md +2 -2
- package/samples/recipes/lifecycle-hooks/README.md +4 -0
- package/samples/recipes/lifecycle-hooks/src/feature.ts +26 -1
- package/samples/recipes/list-table-options/README.md +50 -0
- package/samples/recipes/list-table-options/package.json +11 -0
- package/samples/recipes/list-table-options/src/feature.ts +221 -0
- package/samples/recipes/managed-config/README.md +3 -3
- package/samples/recipes/pdf-audit-export/src/feature.ts +2 -1
- package/samples/recipes/search/README.md +1 -1
- package/samples/recipes/search/src/feature.ts +3 -3
- package/samples/recipes/secrets-demo/README.md +1 -1
- package/samples/recipes/secrets-demo/src/feature.ts +5 -2
- package/samples/recipes/state-machine/src/events.ts +4 -3
- package/samples/recipes/state-machine/src/reducer.ts +1 -1
- package/samples/recipes/tenant-isolation/README.md +1 -0
- package/samples/recipes/tenant-isolation/src/feature.ts +36 -0
- package/samples/recipes/workflow-engine/src/resume-loop.ts +4 -4
- package/samples/recipes/workflow-engine/src/workflow-runner.ts +2 -2
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// after a rollback, failure result or failed COMMIT only gives back what is still booked, so an
|
|
13
13
|
// unknown COMMIT outcome cannot under-count. No connection is held across the handler. Rows a
|
|
14
14
|
// crashed process left behind expire after CAP_RESERVATION_TTL_MINUTES and are given back before the
|
|
15
|
-
// next reserve of the same cap. Reached through a nested ctx.write the cap is not reserved, so the
|
|
15
|
+
// next reserve of the same cap. Reached through a nested ctx.dispatch.write the cap is not reserved, so the
|
|
16
16
|
// dispatcher rejects that call unless the top-level batch reserved the same handler.
|
|
17
17
|
//
|
|
18
18
|
// The wrapper spreads the wrapped handler and chains its reserveBeforeTransaction: inner reserves
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// (enforce-cap.ts).
|
|
26
26
|
|
|
27
27
|
import type {
|
|
28
|
-
|
|
28
|
+
ReservationContext,
|
|
29
29
|
WriteEvent,
|
|
30
30
|
WriteHandlerDef,
|
|
31
31
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -67,7 +67,7 @@ export type CalendarCapDef = {
|
|
|
67
67
|
* tier from DB. */
|
|
68
68
|
export type CalendarCapResolver = (
|
|
69
69
|
event: WriteEvent,
|
|
70
|
-
ctx:
|
|
70
|
+
ctx: ReservationContext,
|
|
71
71
|
) => Promise<CalendarCapDef> | CalendarCapDef;
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -111,7 +111,7 @@ export type RollingCapDef = {
|
|
|
111
111
|
|
|
112
112
|
export type RollingCapResolver = (
|
|
113
113
|
event: WriteEvent,
|
|
114
|
-
ctx:
|
|
114
|
+
ctx: ReservationContext,
|
|
115
115
|
) => Promise<RollingCapDef> | RollingCapDef;
|
|
116
116
|
|
|
117
117
|
/**
|
|
@@ -61,6 +61,7 @@ export function createCapOverviewFeature(opts: CreateCapOverviewOptions): Featur
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
return defineFeature(CAP_OVERVIEW_FEATURE, (r) => {
|
|
64
|
+
r.adoptsBundledLists();
|
|
64
65
|
r.describe(
|
|
65
66
|
"Read-only visibility into per-tenant tier assignment and cap usage. SystemAdmin gets a platform-wide tenant list with usage bars; tenant admins (or the roles in `usageVisibleTo`) get their own tenant's usage as dashboard cards. Reads tier-engine, billing-foundation, and tenant data plus app-owned usage tables via caller-supplied CapSpec callbacks — never writes.",
|
|
66
67
|
);
|
|
@@ -76,7 +76,7 @@ export function createCapsUsageQuery(
|
|
|
76
76
|
|
|
77
77
|
// Override path: limits must read the TARGET tenant's config, not the
|
|
78
78
|
// SystemAdmin caller's.
|
|
79
|
-
const config = override === undefined ? ctx.config : ctx.
|
|
79
|
+
const config = override === undefined ? ctx.config : ctx.tenants.config?.(targetTenantId);
|
|
80
80
|
|
|
81
81
|
const rows: CapUsageWithMeta[] = await Promise.all(
|
|
82
82
|
caps.map(async (cap) => {
|
|
@@ -251,7 +251,7 @@ export function createTenantCapsListQuery(caps: readonly CapSpec[], listCaps: re
|
|
|
251
251
|
const limitByTenantAndCap = await resolveLimitsByTenantAndCap(
|
|
252
252
|
listedCaps,
|
|
253
253
|
page,
|
|
254
|
-
ctx.
|
|
254
|
+
ctx.tenants.config,
|
|
255
255
|
);
|
|
256
256
|
|
|
257
257
|
const rows: TenantCapsListRow[] = page.map((row) => {
|
|
@@ -20,12 +20,12 @@ import {
|
|
|
20
20
|
type DbConnection,
|
|
21
21
|
fetchOne,
|
|
22
22
|
} from "@cosmicdrift/kumiko-framework/db";
|
|
23
|
-
import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
24
23
|
import {
|
|
25
|
-
|
|
26
|
-
type
|
|
27
|
-
|
|
28
|
-
} from "@cosmicdrift/kumiko-framework/
|
|
24
|
+
createSystemUser,
|
|
25
|
+
type SessionUser,
|
|
26
|
+
type TenantId,
|
|
27
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
28
|
+
import { runEventStoreSeed, type SeedIfExists } from "@cosmicdrift/kumiko-framework/seeding";
|
|
29
29
|
|
|
30
30
|
import {
|
|
31
31
|
tenantComplianceProfileEntity,
|
|
@@ -52,8 +52,13 @@ export async function seedComplianceProfile(
|
|
|
52
52
|
): Promise<{ id: string }> {
|
|
53
53
|
// user.tenantId must equal opts.tenantId so the Event Store stream
|
|
54
54
|
// and projection remain in the same tenant bucket.
|
|
55
|
-
const by = opts.by ??
|
|
56
|
-
const tdb = createTenantDb({
|
|
55
|
+
const by = opts.by ?? createSystemUser(opts.tenantId);
|
|
56
|
+
const tdb = createTenantDb({
|
|
57
|
+
db,
|
|
58
|
+
tenantId: opts.tenantId,
|
|
59
|
+
mode: "system",
|
|
60
|
+
reason: "seeding writes the compliance profile into an explicitly named tenant",
|
|
61
|
+
});
|
|
57
62
|
const overrideJson = opts.override !== undefined ? JSON.stringify(opts.override) : null;
|
|
58
63
|
|
|
59
64
|
const existing = (await fetchOne(db, tenantComplianceProfileTable, {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.389.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "config:write:set passes readCascade to validators",
|
|
6
|
+
"detail": "The set handler binds readCascade to the config resolver, the tenant-scoped db and the secrets reader, so validators see the same cascade as the value queries."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.388.0",
|
|
4
10
|
"type": "improvement",
|
|
@@ -111,15 +111,15 @@ export function createConfigAccessorFactory(
|
|
|
111
111
|
// session reads "config feature not wired into AppContext" instead of a
|
|
112
112
|
// generic "configResolver missing".
|
|
113
113
|
export function requireConfigResolver(ctx: HandlerContext, handlerName: string): ConfigResolver {
|
|
114
|
-
if (!ctx.configResolver) {
|
|
114
|
+
if (!ctx.services.configResolver) {
|
|
115
115
|
throw new InternalError({
|
|
116
116
|
message:
|
|
117
|
-
`[${handlerName}] ctx.configResolver missing — pass createConfigAccessorFactory's ` +
|
|
117
|
+
`[${handlerName}] ctx.services.configResolver missing — pass createConfigAccessorFactory's ` +
|
|
118
118
|
`output via extraContext.configAccessorFactory and the resolver via ` +
|
|
119
119
|
`extraContext.configResolver at boot.`,
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
|
-
return ctx.configResolver;
|
|
122
|
+
return ctx.services.configResolver;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// Config declares r.systemScope() (raw ctx.db is unfiltered across tenants
|
|
@@ -156,14 +156,14 @@ export function requireSystemDb(
|
|
|
156
156
|
// if a handler tries to write an encrypted key without the provider in
|
|
157
157
|
// place, pointing at the exact wiring gap).
|
|
158
158
|
export function requireConfigEncryption(ctx: HandlerContext, handlerName: string): EnvelopeCipher {
|
|
159
|
-
if (!ctx.configEncryption) {
|
|
159
|
+
if (!ctx.services.configEncryption) {
|
|
160
160
|
throw new InternalError({
|
|
161
161
|
message:
|
|
162
|
-
`[${handlerName}] ctx.configEncryption missing — at least one config key declares ` +
|
|
162
|
+
`[${handlerName}] ctx.services.configEncryption missing — at least one config key declares ` +
|
|
163
163
|
`encrypted: true, so the boot wiring must pass an EnvelopeCipher via ` +
|
|
164
164
|
`extraContext.configEncryption (run{Prod,Dev}App wire it automatically from ` +
|
|
165
165
|
`KUMIKO_SECRETS_MASTER_KEY_V<n>; same instance the resolver was built with).`,
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
-
return ctx.configEncryption;
|
|
168
|
+
return ctx.services.configEncryption;
|
|
169
169
|
}
|
|
@@ -106,7 +106,7 @@ export async function collectMissingRequiredConfig(
|
|
|
106
106
|
user.tenantId,
|
|
107
107
|
user.id,
|
|
108
108
|
db,
|
|
109
|
-
ctx.secrets,
|
|
109
|
+
ctx.services.secrets,
|
|
110
110
|
);
|
|
111
111
|
for (const [qualifiedKey, keyDef] of candidates) {
|
|
112
112
|
// Deliberately the unredacted cascade value: readiness asks "does this
|
|
@@ -69,22 +69,22 @@ export type ReencryptJobResult = {
|
|
|
69
69
|
|
|
70
70
|
export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void> => {
|
|
71
71
|
const payload = rawPayload as ReencryptJobPayload; // @cast-boundary engine-payload
|
|
72
|
-
const maybeCipher = ctx.configEncryption;
|
|
72
|
+
const maybeCipher = ctx.services.configEncryption;
|
|
73
73
|
if (!maybeCipher) {
|
|
74
74
|
throw new InternalError({
|
|
75
75
|
message:
|
|
76
|
-
"[config:reencrypt] ctx.configEncryption missing — provide a master key " +
|
|
76
|
+
"[config:reencrypt] ctx.services.configEncryption missing — provide a master key " +
|
|
77
77
|
"(KUMIKO_SECRETS_MASTER_KEY_V<n>) so the boot wires the envelope cipher.",
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
// hoisted function declarations below capture these — pin the narrowed
|
|
81
81
|
// type explicitly so TS keeps it inside the closures
|
|
82
82
|
const cipher: EnvelopeCipher = maybeCipher;
|
|
83
|
-
const provider = ctx.masterKeyProvider;
|
|
83
|
+
const provider = ctx.services.masterKeyProvider;
|
|
84
84
|
if (!provider) {
|
|
85
85
|
throw new InternalError({
|
|
86
86
|
message:
|
|
87
|
-
"[config:reencrypt] ctx.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
|
|
87
|
+
"[config:reencrypt] ctx.services.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
if (!ctx.registry) {
|
|
@@ -116,8 +116,8 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
116
116
|
handler: "config:job:reencrypt",
|
|
117
117
|
tenantId,
|
|
118
118
|
actor: "system",
|
|
119
|
-
sink: ctx._escapeHatchAuditSink,
|
|
120
|
-
log: ctx.log,
|
|
119
|
+
sink: ctx.services._escapeHatchAuditSink,
|
|
120
|
+
log: ctx.obs.log,
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -125,7 +125,12 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
125
125
|
function tdbFor(tenantId: TenantId): TenantDb {
|
|
126
126
|
let existing = tdbCache.get(tenantId);
|
|
127
127
|
if (!existing) {
|
|
128
|
-
existing = createTenantDb({
|
|
128
|
+
existing = createTenantDb({
|
|
129
|
+
db,
|
|
130
|
+
tenantId,
|
|
131
|
+
mode: "system",
|
|
132
|
+
reason: "KEK rotation job re-encrypts config values of every tenant",
|
|
133
|
+
});
|
|
129
134
|
tdbCache.set(tenantId, existing);
|
|
130
135
|
}
|
|
131
136
|
return existing;
|
|
@@ -146,7 +151,12 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
146
151
|
// tenant's writes — sharing it with sdbFor(SYSTEM_TENANT_ID) would make a
|
|
147
152
|
// write-path cache entry double as the scan's ack gate.
|
|
148
153
|
const scanDb = createSystemDbView(
|
|
149
|
-
createTenantDb({
|
|
154
|
+
createTenantDb({
|
|
155
|
+
db,
|
|
156
|
+
tenantId: SYSTEM_TENANT_ID,
|
|
157
|
+
mode: "system",
|
|
158
|
+
reason: "KEK rotation scan enumerates config values across all tenants",
|
|
159
|
+
}),
|
|
150
160
|
undefined,
|
|
151
161
|
reportEscapeHatchFor(SYSTEM_TENANT_ID),
|
|
152
162
|
);
|
|
@@ -219,7 +229,7 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
219
229
|
// format) — never a supported re-encrypt input, so fail loudly
|
|
220
230
|
// instead of relying on cipher.decrypt to reject it. Log only the
|
|
221
231
|
// row id, never the value (ciphertext-adjacent).
|
|
222
|
-
ctx.log?.warn?.(
|
|
232
|
+
ctx.obs.log?.warn?.(
|
|
223
233
|
`[config:reencrypt] row ${row.id} is not a current-cipher envelope, not re-encryptable`,
|
|
224
234
|
);
|
|
225
235
|
return "failed";
|
|
@@ -244,7 +254,7 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
244
254
|
// holds a fresh envelope written by the set handler — already fine.
|
|
245
255
|
if (!result.isSuccess) {
|
|
246
256
|
if (result.error.code === "version_conflict") return "skipped";
|
|
247
|
-
ctx.log?.warn?.(`[config:reencrypt] executor rejected row ${row.id}`, {
|
|
257
|
+
ctx.obs.log?.warn?.(`[config:reencrypt] executor rejected row ${row.id}`, {
|
|
248
258
|
code: result.error.code,
|
|
249
259
|
});
|
|
250
260
|
return "failed";
|
|
@@ -257,9 +267,9 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
257
267
|
migrateRow,
|
|
258
268
|
maxFailures,
|
|
259
269
|
deadlineAt: deadline,
|
|
260
|
-
signal: ctx.signal,
|
|
270
|
+
signal: ctx.lifecycle.signal,
|
|
261
271
|
onRowError: ({ row }, err) => {
|
|
262
|
-
ctx.log?.warn?.(`[config:reencrypt] failed to re-encrypt row ${row.id}`, { err });
|
|
272
|
+
ctx.obs.log?.warn?.(`[config:reencrypt] failed to re-encrypt row ${row.id}`, { err });
|
|
263
273
|
},
|
|
264
274
|
});
|
|
265
275
|
|
|
@@ -269,5 +279,5 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
|
|
|
269
279
|
alreadyCurrent,
|
|
270
280
|
stoppedReason: outcome.stoppedReason,
|
|
271
281
|
};
|
|
272
|
-
ctx.log?.info?.(`[config:reencrypt] complete: ${JSON.stringify(result)}`);
|
|
282
|
+
ctx.obs.log?.info?.(`[config:reencrypt] complete: ${JSON.stringify(result)}`);
|
|
273
283
|
};
|
|
@@ -48,14 +48,14 @@ export const resetWrite = defineWriteHandler({
|
|
|
48
48
|
// backing="secrets": clear the secret from the secrets store. delete() is
|
|
49
49
|
// idempotent (returns false if absent) — mirrors the config no-op contract.
|
|
50
50
|
if (keyDef.backing === "secrets") {
|
|
51
|
-
if (!ctx.secrets) {
|
|
51
|
+
if (!ctx.services.secrets) {
|
|
52
52
|
throw new InternalError({
|
|
53
53
|
message:
|
|
54
54
|
`[config:write:reset] key "${event.payload.key}" declares backing="secrets" but ` +
|
|
55
|
-
`ctx.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
55
|
+
`ctx.services.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
-
await ctx.secrets.delete(SYSTEM_TENANT_ID, event.payload.key, {
|
|
58
|
+
await ctx.services.secrets.delete(SYSTEM_TENANT_ID, event.payload.key, {
|
|
59
59
|
deletedBy: event.user.id,
|
|
60
60
|
});
|
|
61
61
|
return { isSuccess: true, data: { key: event.payload.key, scope } };
|
|
@@ -53,7 +53,7 @@ export const selectedExtensionsQuery = defineQueryHandler({
|
|
|
53
53
|
query.user.tenantId,
|
|
54
54
|
query.user.id,
|
|
55
55
|
db,
|
|
56
|
-
ctx.secrets,
|
|
56
|
+
ctx.services.secrets,
|
|
57
57
|
);
|
|
58
58
|
const selected: Record<string, string> = {};
|
|
59
59
|
for (const [selectorKey, keyDef] of readableSelectors) {
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
writeFailure,
|
|
19
19
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
20
20
|
import * as z from "zod";
|
|
21
|
-
import { requireConfigEncryption, requireSystemDb } from "../feature.ts";
|
|
21
|
+
import { requireConfigEncryption, requireConfigResolver, requireSystemDb } from "../feature.ts";
|
|
22
22
|
import { MASKED } from "../read-redaction.ts";
|
|
23
23
|
import { configValueEntity, configValuesTable } from "../table.ts";
|
|
24
24
|
import {
|
|
@@ -106,13 +106,30 @@ export const setWrite = defineWriteHandler({
|
|
|
106
106
|
if (patternError) return writeFailure(patternError);
|
|
107
107
|
|
|
108
108
|
if (keyDef.validate) {
|
|
109
|
+
const validateDb = scopeTenantDbToTenant(db, tenantId);
|
|
109
110
|
try {
|
|
110
111
|
await keyDef.validate(event.payload.value, {
|
|
111
112
|
key: event.payload.key,
|
|
112
113
|
scope,
|
|
113
114
|
tenantId,
|
|
114
115
|
userId,
|
|
115
|
-
db:
|
|
116
|
+
db: validateDb,
|
|
117
|
+
readCascade: (qualifiedKey) => {
|
|
118
|
+
const cascadeKeyDef = ctx.registry.getConfigKey(qualifiedKey);
|
|
119
|
+
if (!cascadeKeyDef) {
|
|
120
|
+
throw new InternalError({
|
|
121
|
+
message: `[config:write:set] readCascade: unknown config key "${qualifiedKey}"`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return requireConfigResolver(ctx, "config:write:set").getCascade(
|
|
125
|
+
qualifiedKey,
|
|
126
|
+
cascadeKeyDef,
|
|
127
|
+
tenantId,
|
|
128
|
+
event.user.id,
|
|
129
|
+
validateDb,
|
|
130
|
+
ctx.services.secrets,
|
|
131
|
+
);
|
|
132
|
+
},
|
|
116
133
|
});
|
|
117
134
|
} catch (error) {
|
|
118
135
|
if (isKumikoError(error)) return writeFailure(error);
|
|
@@ -129,14 +146,14 @@ export const setWrite = defineWriteHandler({
|
|
|
129
146
|
// serialization as a config row so the read path round-trips via
|
|
130
147
|
// deserializeValue. system-scope is guaranteed by the boot-guard.
|
|
131
148
|
if (keyDef.backing === "secrets") {
|
|
132
|
-
if (!ctx.secrets) {
|
|
149
|
+
if (!ctx.services.secrets) {
|
|
133
150
|
throw new InternalError({
|
|
134
151
|
message:
|
|
135
152
|
`[config:write:set] key "${event.payload.key}" declares backing="secrets" but ` +
|
|
136
|
-
`ctx.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
153
|
+
`ctx.services.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
137
154
|
});
|
|
138
155
|
}
|
|
139
|
-
await ctx.secrets.set(
|
|
156
|
+
await ctx.services.secrets.set(
|
|
140
157
|
SYSTEM_TENANT_ID,
|
|
141
158
|
event.payload.key,
|
|
142
159
|
JSON.stringify(event.payload.value),
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.389.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Tests pin the erasure write purpose in forget-subject and the forget cleanup",
|
|
6
|
+
"detail": "A pre-KMS user whose key was already erased still ends deleted, loses its tokens and gets the erased sentinel in the update event."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.389.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "The subject file purge reads candidate rows in pages",
|
|
12
|
+
"detail": "A user owning many records no longer loads them all into memory at once; every page is purged, not only the first."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.388.0",
|
|
4
16
|
"type": "fix",
|
|
@@ -257,7 +257,7 @@ async function appendDenialAuditEvent(
|
|
|
257
257
|
new InternalError({
|
|
258
258
|
message:
|
|
259
259
|
"[crypto-shredding] forget-subject denial audit event cannot be appended without " +
|
|
260
|
-
"ctx.
|
|
260
|
+
"ctx.db.outsideTransaction — dispatch wiring is missing the outside-tx db source.",
|
|
261
261
|
}),
|
|
262
262
|
);
|
|
263
263
|
}
|
|
@@ -340,11 +340,11 @@ async function sweepDerivedSubjectData(
|
|
|
340
340
|
|
|
341
341
|
// Derived search index still holds plaintext — purge next to the
|
|
342
342
|
// blind-index sweep. No adapter → no-op (apps without search).
|
|
343
|
-
if (ctx.searchAdapter) {
|
|
343
|
+
if (ctx.services.searchAdapter) {
|
|
344
344
|
await purgeSearchDocumentsForSubject(
|
|
345
345
|
crossTenantSubjectRunner,
|
|
346
346
|
ctx.registry.features,
|
|
347
|
-
ctx.searchAdapter,
|
|
347
|
+
ctx.services.searchAdapter,
|
|
348
348
|
subjectKey,
|
|
349
349
|
subject,
|
|
350
350
|
);
|
|
@@ -432,7 +432,7 @@ async function appendSubjectForgotten(
|
|
|
432
432
|
outsideRunner: DbRunner | undefined,
|
|
433
433
|
): Promise<void> {
|
|
434
434
|
if (!outsideRunner) {
|
|
435
|
-
await ctx.
|
|
435
|
+
await ctx.events.unsafeAppend({
|
|
436
436
|
aggregateId,
|
|
437
437
|
aggregateType: CRYPTO_SHREDDING_AGGREGATE_TYPE,
|
|
438
438
|
type: SUBJECT_FORGOTTEN_EVENT_NAME,
|
|
@@ -521,7 +521,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
521
521
|
subjectKey,
|
|
522
522
|
raw.kind,
|
|
523
523
|
denialReasonOf(tenantScopeDenial),
|
|
524
|
-
ctx.
|
|
524
|
+
ctx.db.outsideTransaction?.unsafeRaw(),
|
|
525
525
|
);
|
|
526
526
|
return auditFailure ?? tenantScopeDenial;
|
|
527
527
|
}
|
|
@@ -537,7 +537,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
537
537
|
subjectKey,
|
|
538
538
|
raw.kind,
|
|
539
539
|
TARGET_RECORD_RETENTION_BLOCK_DELETE,
|
|
540
|
-
ctx.
|
|
540
|
+
ctx.db.outsideTransaction?.unsafeRaw(),
|
|
541
541
|
);
|
|
542
542
|
return auditFailure ?? retentionDenial;
|
|
543
543
|
}
|
|
@@ -562,7 +562,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
562
562
|
// - user.updated as lifecycle event (updateUserLifecycle), so a
|
|
563
563
|
// read_users rebuild doesn't wipe the flip
|
|
564
564
|
// - sessions don't need active revocation — session-callbacks
|
|
565
|
-
// re-validate user
|
|
565
|
+
// re-validate the user row on every request (isPrincipalRowBlocked
|
|
566
566
|
// blocks Deleted).
|
|
567
567
|
// Both idempotent (status set / revokedAt IS NULL filter), retry after
|
|
568
568
|
// crash recovery is safe. User-feature guard: without the user feature
|
|
@@ -575,7 +575,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
575
575
|
await closeUserLoginDoor(
|
|
576
576
|
ctx,
|
|
577
577
|
raw.userId,
|
|
578
|
-
ctx.
|
|
578
|
+
ctx.db.outsideTransaction?.unsafeRaw(),
|
|
579
579
|
ctx.db.unsafeRaw(),
|
|
580
580
|
);
|
|
581
581
|
}
|
|
@@ -599,7 +599,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
599
599
|
forgottenBy: event.user.id,
|
|
600
600
|
...(cleanupError !== undefined && { cleanupError }),
|
|
601
601
|
},
|
|
602
|
-
ctx.
|
|
602
|
+
ctx.db.outsideTransaction?.unsafeRaw(),
|
|
603
603
|
);
|
|
604
604
|
|
|
605
605
|
if (cleanupError !== undefined) {
|
|
@@ -5,16 +5,16 @@ import type { DeleteFileBytes } from "../shared/index.ts";
|
|
|
5
5
|
|
|
6
6
|
const ERROR_CONTEXT = "crypto-shredding:forget-subject";
|
|
7
7
|
|
|
8
|
-
// The upload resolver, not ctx.files: ctx.files is bound to the acting user's tenant, while a
|
|
8
|
+
// The upload resolver, not ctx.services.files: ctx.services.files is bound to the acting user's tenant, while a
|
|
9
9
|
// subject's rows can live in any tenant. Resolved eagerly so a missing provider surfaces as
|
|
10
10
|
// missing_file_storage instead of a failed delete.
|
|
11
11
|
export function resolveFileBytesDeleter(
|
|
12
12
|
ctx: HandlerContext,
|
|
13
13
|
): (tenantId: TenantId) => Promise<DeleteFileBytes | undefined> {
|
|
14
14
|
return async (tenantId) => {
|
|
15
|
-
const resolver = ctx._fileProviderResolver;
|
|
15
|
+
const resolver = ctx.services._fileProviderResolver;
|
|
16
16
|
if (resolver === undefined) {
|
|
17
|
-
const own = tenantId === ctx.user.tenantId ? ctx.files : undefined;
|
|
17
|
+
const own = tenantId === ctx.user.tenantId ? ctx.services.files : undefined;
|
|
18
18
|
return own && ((key) => deleteFileRefBytes(own, { storageKey: key }, ERROR_CONTEXT));
|
|
19
19
|
}
|
|
20
20
|
try {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.390.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "wireCustomFieldsUserDataRightsFor is exported from ./custom-fields",
|
|
6
|
+
"detail": "The helper that adds custom fields to the user-data-rights export is documented as an app call but was missing from the subpath exports. It is exported again together with its options type."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.370.0",
|
|
4
10
|
"type": "breaking",
|
|
@@ -59,7 +59,7 @@ export const clearCustomFieldHandler: WriteHandlerDef = {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
await ctx.
|
|
62
|
+
await ctx.events.unsafeAppend({
|
|
63
63
|
aggregateId: payload.entityId,
|
|
64
64
|
aggregateType: payload.entityName,
|
|
65
65
|
type: createCustomFieldsFeature().exports.clearedEvent.name,
|
|
@@ -34,7 +34,7 @@ export const deleteSystemFieldHandler: WriteHandlerDef = {
|
|
|
34
34
|
// Cascade-cleanup event — host-entity MSPs remove orphaned values from their
|
|
35
35
|
// customFields jsonb in the same transaction for atomicity.
|
|
36
36
|
if (result.isSuccess) {
|
|
37
|
-
await ctx.
|
|
37
|
+
await ctx.events.unsafeAppend({
|
|
38
38
|
aggregateId,
|
|
39
39
|
aggregateType: FIELD_DEFINITION_AGGREGATE_TYPE,
|
|
40
40
|
type: createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name,
|
|
@@ -55,7 +55,7 @@ export function createDeleteTenantFieldHandler(
|
|
|
55
55
|
// registered via wireCustomFieldsFor consume it and remove orphaned values
|
|
56
56
|
// from their customFields jsonb. The same transaction makes cleanup atomic.
|
|
57
57
|
if (result.isSuccess) {
|
|
58
|
-
await ctx.
|
|
58
|
+
await ctx.events.unsafeAppend({
|
|
59
59
|
aggregateId,
|
|
60
60
|
aggregateType: FIELD_DEFINITION_AGGREGATE_TYPE,
|
|
61
61
|
type: createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name,
|
|
@@ -97,7 +97,7 @@ export const setCustomFieldHandler: WriteHandlerDef = {
|
|
|
97
97
|
// cross-feature augmentation for this event type; the qualified string
|
|
98
98
|
// name is used directly. The value is ALWAYS included in the event
|
|
99
99
|
// (custom fields carry no PII), so replay fully reproduces the projection.
|
|
100
|
-
await ctx.
|
|
100
|
+
await ctx.events.unsafeAppend({
|
|
101
101
|
aggregateId: payload.entityId,
|
|
102
102
|
aggregateType: payload.entityName,
|
|
103
103
|
type: createCustomFieldsFeature().exports.setEvent.name,
|
|
@@ -37,3 +37,7 @@ export {
|
|
|
37
37
|
type SupportedFieldType,
|
|
38
38
|
} from "./web/constants.ts";
|
|
39
39
|
export { customFieldsField, wireCustomFieldsFor } from "./wire-for-entity.ts";
|
|
40
|
+
export {
|
|
41
|
+
type WireCustomFieldsUserDataRightsOptions,
|
|
42
|
+
wireCustomFieldsUserDataRightsFor,
|
|
43
|
+
} from "./wire-user-data-rights.ts";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Centralised parser for `fieldDefinition.serializedField`.
|
|
2
2
|
//
|
|
3
3
|
// The column is stored as `text` in B1 (entity.ts) — what the db row hands
|
|
4
|
-
// back depends on the driver:
|
|
4
|
+
// back depends on the driver: text normally arrives as a `string`, but
|
|
5
5
|
// jsonb-tolerant drivers and middleware can deliver an already-parsed
|
|
6
6
|
// object. This helper normalises both, validates the shape, and centralises
|
|
7
7
|
// the single boundary cast so callers don't sprinkle `as { … }`-narrowings
|
|
@@ -101,7 +101,7 @@ export function createDataRetentionFeature(): FeatureDefinition {
|
|
|
101
101
|
tenantId,
|
|
102
102
|
preloadedTenantPreset: tenantPreset,
|
|
103
103
|
now: T.Now.instant(),
|
|
104
|
-
files: ctx.files,
|
|
104
|
+
files: ctx.services.files,
|
|
105
105
|
});
|
|
106
106
|
if (result.skipped.length > 0) {
|
|
107
107
|
// biome-ignore lint/suspicious/noConsole: operator-visibility for skipped entities
|
|
@@ -254,7 +254,12 @@ async function forgetRowAndEraseKeys(args: {
|
|
|
254
254
|
readonly registry: Registry;
|
|
255
255
|
}): Promise<{ readonly isSuccess: boolean }> {
|
|
256
256
|
return runInSubTransaction(args.db, async (sp) => {
|
|
257
|
-
const tdb = createTenantDb({
|
|
257
|
+
const tdb = createTenantDb({
|
|
258
|
+
db: sp,
|
|
259
|
+
tenantId: args.tenantId,
|
|
260
|
+
mode: "system",
|
|
261
|
+
reason: "retention sweep forgets rows of the tenant being swept, outside any request scope",
|
|
262
|
+
});
|
|
258
263
|
const result = await args.executor.forget({ id: args.rowId }, args.systemUser, tdb);
|
|
259
264
|
if (!result.isSuccess) return { isSuccess: false };
|
|
260
265
|
await eraseHardDeletedRowKeys({
|
|
@@ -508,7 +513,12 @@ export async function runRetentionCleanup(
|
|
|
508
513
|
// the daily cron converges (hardDelete removes rows, softDelete's isDeleted
|
|
509
514
|
// filter shrinks the set). A single batched forget/delete event is a follow-up.
|
|
510
515
|
const systemUser = createSystemUser(tenantId);
|
|
511
|
-
const tdb = createTenantDb({
|
|
516
|
+
const tdb = createTenantDb({
|
|
517
|
+
db,
|
|
518
|
+
tenantId,
|
|
519
|
+
mode: "system",
|
|
520
|
+
reason: "retention sweep forgets rows of the tenant being swept, outside any request scope",
|
|
521
|
+
});
|
|
512
522
|
const fileHolders = collectSingleFileHolders(registry);
|
|
513
523
|
|
|
514
524
|
// Pre-load every override row for this tenant ONCE — N entities × M
|
|
@@ -63,7 +63,7 @@ async function writeAttemptEvent(
|
|
|
63
63
|
): Promise<void> {
|
|
64
64
|
const { tenantId, ...rest } = entry;
|
|
65
65
|
// Masked here, the only place attempt events are written, so no event or projection row ever holds the full address.
|
|
66
|
-
// Schema-parse to match ctx.
|
|
66
|
+
// Schema-parse to match ctx.events.append's guarantee: a payload drift between
|
|
67
67
|
// service/job + feature-registration fails loudly here instead of landing on
|
|
68
68
|
// the events-table and crashing a consumer later.
|
|
69
69
|
const payload = deliveryAttemptSchema.parse({
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.389.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Unsubscribe link origin is looked up once per notify call",
|
|
6
|
+
"detail": "The tenantOrigin callback runs once per tenant for a notify call with many recipients, and a fallback warning is logged once. A callback that hangs is still not guarded by a timeout, so keep it fast."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.389.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "buildSystemChannelContext for system tenant mails outside a handler",
|
|
12
|
+
"detail": "buildSystemChannelContext(deps, { config, secrets }) returns a ChannelContext for the system tenant whose readAttachment reads file and inline attachments. SystemWireDeps (wire hook and runWorkerApp wireComponents) has a new required filesForTenant that deps can pass straight in."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.388.0",
|
|
4
16
|
"type": "fix",
|