@cosmicdrift/kumiko-samples 0.389.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/audit/feature.ts +1 -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 +6 -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/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 +12 -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 +2 -2
- package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +3 -2
- package/packages/bundled-features/src/auth-email-password/seeding.ts +14 -9
- package/packages/bundled-features/src/auth-foundation/feature.ts +13 -4
- 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 +9 -3
- 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 +1 -1
- package/packages/bundled-features/src/cap-counter/constants.ts +1 -1
- package/packages/bundled-features/src/cap-counter/feature.ts +2 -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/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/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 +4 -4
- package/packages/bundled-features/src/config/handlers/values.query.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +8 -8
- 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/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/delivery-service.ts +6 -5
- package/packages/bundled-features/src/delivery/feature.ts +2 -2
- package/packages/bundled-features/src/delivery/jobs.ts +11 -11
- package/packages/bundled-features/src/delivery/testing.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/events.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 +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/inbound-mail-foundation/events.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +1 -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/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/legal-pages/README.md +1 -1
- package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +12 -8
- package/packages/bundled-features/src/mail-foundation/feature.ts +2 -2
- package/packages/bundled-features/src/mail-transport-smtp/changes.json +6 -0
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +4 -1
- package/packages/bundled-features/src/managed-pages/seeding.ts +13 -8
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +1 -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/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 +1 -1
- package/packages/bundled-features/src/seo/feature.ts +1 -1
- package/packages/bundled-features/src/sessions/changes.json +12 -0
- package/packages/bundled-features/src/sessions/feature.ts +1 -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/screens.ts +8 -4
- 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 +12 -2
- package/packages/bundled-features/src/shared/require-for-tenant.ts +7 -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/feature.ts +1 -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/template-resolver/api.ts +3 -3
- package/packages/bundled-features/src/template-resolver/changes.json +18 -0
- 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/overview.query.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/send-test-shared.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/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 +12 -2
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +18 -13
- 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/placeholder-line-editor.tsx +19 -6
- 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/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/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/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 +7 -3
- 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/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 +24 -0
- package/packages/bundled-features/src/user-data-rights/feature.ts +29 -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 +2 -0
- 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 +10 -0
- package/packages/bundled-features/src/user-data-rights/web/index.ts +6 -1
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +8 -6
- 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 +9 -4
- package/packages/bundled-features/src/waitlist/legacy-migrate.ts +6 -1
- package/packages/bundled-features/src/waitlist/link-on-signup.ts +7 -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/server.ts +2 -2
- package/samples/apps/use-all-bundled/feature-manifest.json +1 -1
- package/samples/apps/use-all-bundled/src/app/seed.ts +12 -2
- 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/lane-routing/package.json +1 -1
- package/samples/recipes/legal-pages/README.md +2 -2
- package/samples/recipes/lifecycle-hooks/README.md +2 -2
- package/samples/recipes/lifecycle-hooks/src/feature.ts +1 -1
- package/samples/recipes/managed-config/README.md +3 -3
- 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 +1 -1
- package/samples/recipes/state-machine/src/reducer.ts +1 -1
- package/samples/recipes/workflow-engine/src/resume-loop.ts +4 -4
- package/samples/recipes/workflow-engine/src/workflow-runner.ts +2 -2
|
@@ -19,7 +19,7 @@ import { CONSENT_LOCALES } from "./web/consumer-protection/consent-locale.ts";
|
|
|
19
19
|
export const SUBSCRIPTION_AGGREGATE_TYPE = "subscription" as const;
|
|
20
20
|
|
|
21
21
|
// Event-name constants — short form (for r.defineEvent) and qualified
|
|
22
|
-
// FQN (for ctx.
|
|
22
|
+
// FQN (for ctx.events.unsafeAppend and projection-apply keys).
|
|
23
23
|
export const SUBSCRIPTION_CREATED_EVENT_SHORT = "subscription-created" as const;
|
|
24
24
|
export const SUBSCRIPTION_UPDATED_EVENT_SHORT = "subscription-updated" as const;
|
|
25
25
|
export const SUBSCRIPTION_CANCELED_EVENT_SHORT = "subscription-canceled" as const;
|
|
@@ -172,7 +172,7 @@ export function createBillingFoundationFeature<TTier extends string = string>(
|
|
|
172
172
|
r.defineEvent(PAYMENT_RECEIVED_EVENT_SHORT, paymentEventPayloadSchema, { piiFields: "none" });
|
|
173
173
|
|
|
174
174
|
// Inline projection: materialized current state in `read_subscriptions`.
|
|
175
|
-
// Apply runs in the same TX as ctx.
|
|
175
|
+
// Apply runs in the same TX as ctx.events.unsafeAppend — read-your-own-
|
|
176
176
|
// write without a dispatcher tick.
|
|
177
177
|
r.projection({
|
|
178
178
|
name: "subscription",
|
|
@@ -260,13 +260,18 @@ export function createBillingFoundationFeature<TTier extends string = string>(
|
|
|
260
260
|
perTenant: true,
|
|
261
261
|
runOnBoot: true,
|
|
262
262
|
handler: async (_payload, ctx) => {
|
|
263
|
-
const result = await ctx.write(
|
|
263
|
+
const result = await ctx.dispatch.write(
|
|
264
|
+
SubscriptionFoundationHandlers.syncSubscription,
|
|
265
|
+
{},
|
|
266
|
+
);
|
|
264
267
|
if (!result.isSuccess) {
|
|
265
268
|
throw new Error(
|
|
266
269
|
`billing-foundation:sync-subscriptions: sync-subscription write failed: ${JSON.stringify(result.error)}`,
|
|
267
270
|
);
|
|
268
271
|
}
|
|
269
|
-
ctx.log.info(
|
|
272
|
+
ctx.obs.log.info(
|
|
273
|
+
`[billing-foundation:sync-subscriptions] ${JSON.stringify(result.data)}`,
|
|
274
|
+
);
|
|
270
275
|
},
|
|
271
276
|
});
|
|
272
277
|
|
|
@@ -29,7 +29,7 @@ export type SubscriptionView = {
|
|
|
29
29
|
* aggregate ID), or null if the tenant has never subscribed. The status
|
|
30
30
|
* may be active/canceled/past_due/etc.; the caller decides what to do. */
|
|
31
31
|
export async function getSubscriptionForTenant(
|
|
32
|
-
ctx: HandlerContext,
|
|
32
|
+
ctx: Pick<HandlerContext, "db">,
|
|
33
33
|
tenantId: string,
|
|
34
34
|
): Promise<SubscriptionView | null> {
|
|
35
35
|
const aggId = subscriptionAggregateId(tenantId);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// with no second append.
|
|
10
10
|
// 2. Type mapping: SubscriptionEvent.type (= normalized by the plugin)
|
|
11
11
|
// → one of the 5 ES event types.
|
|
12
|
-
// 3. ctx.
|
|
12
|
+
// 3. ctx.events.unsafeAppend — the inline projection materializes the
|
|
13
13
|
// `read_subscriptions` row in the same TX.
|
|
14
14
|
|
|
15
15
|
import {
|
|
@@ -175,7 +175,7 @@ export async function appendSubscriptionEvent(
|
|
|
175
175
|
// streams, optimize via snapshot or a per-tenant dedup table as the
|
|
176
176
|
// idempotency anchor (like cap-counter).
|
|
177
177
|
// ---------------------------------------------------------------
|
|
178
|
-
const existingEvents = await ctx.
|
|
178
|
+
const existingEvents = await ctx.events.load(aggId);
|
|
179
179
|
const alreadySeen = existingEvents.some((e) => {
|
|
180
180
|
const headers = e.metadata.headers ?? {};
|
|
181
181
|
return (
|
|
@@ -191,7 +191,7 @@ export async function appendSubscriptionEvent(
|
|
|
191
191
|
// late delivery: appending it would roll the row back (a canceled subscription
|
|
192
192
|
// would come back active). Invoice events carry the live state, not a snapshot.
|
|
193
193
|
if (isLateStateEvent(existingEvents, payload)) {
|
|
194
|
-
ctx.log?.warn(
|
|
194
|
+
ctx.obs.log?.warn(
|
|
195
195
|
`[billing-foundation:process-event] dropped late ${payload.type} ${payload.providerEventId}: a newer provider event is already stored`,
|
|
196
196
|
);
|
|
197
197
|
return { duplicate: false, stale: true, subscriptionAggregateId: aggId };
|
|
@@ -260,7 +260,7 @@ export async function appendSubscriptionEvent(
|
|
|
260
260
|
providerEventId: payload.providerEventId,
|
|
261
261
|
providerName: payload.providerName,
|
|
262
262
|
};
|
|
263
|
-
await ctx.
|
|
263
|
+
await ctx.events.unsafeAppend({
|
|
264
264
|
aggregateId: aggId,
|
|
265
265
|
aggregateType: SUBSCRIPTION_AGGREGATE_TYPE,
|
|
266
266
|
type: esEventType,
|
|
@@ -311,7 +311,7 @@ export function createProcessEventHandler(now: () => Temporal.Instant): WriteHan
|
|
|
311
311
|
const payload = event.payload as ProcessEventPayload;
|
|
312
312
|
const current = await getSubscriptionForTenant(ctx, event.user.tenantId);
|
|
313
313
|
if (isStaleSubscriptionEvent(current, payload, now())) {
|
|
314
|
-
ctx.log?.warn(
|
|
314
|
+
ctx.obs.log?.warn(
|
|
315
315
|
`[billing-foundation:process-event] dropped stale ${payload.type} ${payload.providerEventId}: tenant already tracks another subscription`,
|
|
316
316
|
);
|
|
317
317
|
return {
|
package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// 1. Idempotency-check: loads the payment-stream and scans for an
|
|
7
7
|
// already-seen `metadata.providerEventId`. A provider-replay with
|
|
8
8
|
// the same event-id → duplicate=true, no second append.
|
|
9
|
-
// 2. ctx.
|
|
9
|
+
// 2. ctx.events.unsafeAppend — inline-projection materializes a new
|
|
10
10
|
// `read_payments`-row (INSERT-once, not UPSERT — every payment is
|
|
11
11
|
// its own fact, not a state-update).
|
|
12
12
|
|
|
@@ -55,7 +55,7 @@ export const processPaymentEventHandler: WriteHandlerDef = {
|
|
|
55
55
|
// (a tenant with hundreds of purchases scans hundreds of events;
|
|
56
56
|
// optimize via a per-tenant providerEventId-index if that bites).
|
|
57
57
|
// ---------------------------------------------------------------
|
|
58
|
-
const existingEvents = await ctx.
|
|
58
|
+
const existingEvents = await ctx.events.load(aggId);
|
|
59
59
|
const alreadySeen = existingEvents.some((e) => {
|
|
60
60
|
const headers = e.metadata.headers ?? {};
|
|
61
61
|
return (
|
|
@@ -106,7 +106,7 @@ export const processPaymentEventHandler: WriteHandlerDef = {
|
|
|
106
106
|
providerCheckoutId: payload.providerCheckoutId,
|
|
107
107
|
}),
|
|
108
108
|
};
|
|
109
|
-
await ctx.
|
|
109
|
+
await ctx.events.unsafeAppend({
|
|
110
110
|
aggregateId: aggId,
|
|
111
111
|
aggregateType: PAYMENT_AGGREGATE_TYPE,
|
|
112
112
|
type: PAYMENT_RECEIVED_EVENT_QN,
|
|
@@ -77,7 +77,7 @@ export async function resolvePlanPrices(
|
|
|
77
77
|
prices = await plugin.retrievePrices(ctx, allPriceIds);
|
|
78
78
|
} catch (error) {
|
|
79
79
|
const message = error instanceof Error ? error.message : String(error);
|
|
80
|
-
ctx.log?.warn("billing-foundation: retrievePrices threw, all plan prices unavailable", {
|
|
80
|
+
ctx.obs.log?.warn("billing-foundation: retrievePrices threw, all plan prices unavailable", {
|
|
81
81
|
message,
|
|
82
82
|
});
|
|
83
83
|
return result;
|
|
@@ -93,7 +93,7 @@ export async function resolvePlanPrices(
|
|
|
93
93
|
const chosen = active[0];
|
|
94
94
|
if (chosen) result.set(tier, { priceId: chosen.priceId, price: chosen });
|
|
95
95
|
} else if (active.length > 1) {
|
|
96
|
-
ctx.log?.warn(
|
|
96
|
+
ctx.obs.log?.warn(
|
|
97
97
|
`billing-foundation: tier "${tier}" has ${active.length} active flat-amount prices — expected exactly one, price stays unavailable`,
|
|
98
98
|
);
|
|
99
99
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Inline projection for `read_subscriptions`. Materializes the 5
|
|
2
2
|
// subscription events into one row per tenant.
|
|
3
3
|
//
|
|
4
|
-
// Apply runs in the same transaction as ctx.
|
|
4
|
+
// Apply runs in the same transaction as ctx.events.unsafeAppend, so the caller
|
|
5
5
|
// sees its write state immediately (no dispatcher tick required). The PK is
|
|
6
6
|
// event.aggregateId (= deterministic uuidv5 per tenant), so replays collide
|
|
7
7
|
// on the PK instead of creating duplicate rows.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// 2. **Post-tenant-resolution:** `createPortalSession` +
|
|
19
19
|
// `cancelSubscription` are called from regular write handlers with
|
|
20
20
|
// a fully resolved HandlerContext. The plugin can use ctx.config +
|
|
21
|
-
// ctx.secrets for tenant-specific configuration (e.g. tenant-owned
|
|
21
|
+
// ctx.services.secrets for tenant-specific configuration (e.g. tenant-owned
|
|
22
22
|
// customer-id mappings).
|
|
23
23
|
//
|
|
24
24
|
// Foundation uses only the common subset of provider functionality;
|
|
@@ -38,7 +38,7 @@ export function capCounterAggregateId(
|
|
|
38
38
|
* different uuidv5 namespace, different output UUID. This also prevents an
|
|
39
39
|
* accidental calendar increment from landing on the rolling stream.
|
|
40
40
|
*
|
|
41
|
-
* **Caller:** `CapCounterHandlers.incrementRolling` (via `ctx.write`) calls
|
|
41
|
+
* **Caller:** `CapCounterHandlers.incrementRolling` (via `ctx.dispatch.write`) calls
|
|
42
42
|
* this with tenantId + capName and appends increment events to the stream.
|
|
43
43
|
* Race-free because the event store appends with an auto-incrementing version.
|
|
44
44
|
*/
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createEntityExecutor,
|
|
6
6
|
type HandlerContext,
|
|
7
7
|
type JobContext,
|
|
8
|
+
type ReservationContext,
|
|
8
9
|
type SessionUser,
|
|
9
10
|
type TenantId,
|
|
10
11
|
type WriteResult,
|
|
@@ -84,7 +85,7 @@ export type BookCapUsageOptions = {
|
|
|
84
85
|
readonly guardCurrentValue?: (currentValue: number) => void;
|
|
85
86
|
};
|
|
86
87
|
|
|
87
|
-
export type CapCounterContext = HandlerContext | JobContext;
|
|
88
|
+
export type CapCounterContext = HandlerContext | JobContext | ReservationContext;
|
|
88
89
|
|
|
89
90
|
export type CapCounterScope = {
|
|
90
91
|
readonly user: SessionUser;
|
|
@@ -104,7 +105,7 @@ function assertDbServesUser(db: TenantDb, user: SessionUser): TenantDb {
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
// Jobs write in place (their db is not transaction-bound); systemScope handlers reach both dbs via
|
|
107
|
-
// systemDb, because their ctx.db / ctx.
|
|
108
|
+
// systemDb, because their ctx.db / ctx.db.outsideTransaction are fail-closed proxies.
|
|
108
109
|
export function resolveCapCounterScope(
|
|
109
110
|
ctx: CapCounterContext,
|
|
110
111
|
outsideTransaction: boolean,
|
|
@@ -130,11 +131,11 @@ export function resolveCapCounterScope(
|
|
|
130
131
|
: readDb;
|
|
131
132
|
return { user, readDb, writeDb };
|
|
132
133
|
}
|
|
133
|
-
const writeDb = outsideTransaction ? ctx.
|
|
134
|
+
const writeDb = outsideTransaction ? ctx.db.outsideTransaction : ctx.db;
|
|
134
135
|
if (!writeDb) {
|
|
135
136
|
throw new Error(
|
|
136
137
|
outsideTransaction
|
|
137
|
-
? "cap-counter: outsideTransaction requested but ctx.
|
|
138
|
+
? "cap-counter: outsideTransaction requested but ctx.db.outsideTransaction is undefined"
|
|
138
139
|
: "cap-counter: ctx.db missing — run inside a handler context",
|
|
139
140
|
);
|
|
140
141
|
}
|
|
@@ -612,7 +612,7 @@ export async function releaseExpiredCapReservations(
|
|
|
612
612
|
try {
|
|
613
613
|
await releaseCapReservation(ctx, id, outsideTransaction);
|
|
614
614
|
} catch (error) {
|
|
615
|
-
ctx.log?.error("releasing an expired cap reservation failed", { id, capName, error });
|
|
615
|
+
ctx.obs.log?.error("releasing an expired cap reservation failed", { id, capName, error });
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
}
|
|
@@ -13,7 +13,7 @@ export const CAP_COUNTER_ROLLING_AGGREGATE_TYPE = "cap-counter-rolling" as const
|
|
|
13
13
|
// Custom event types for rolling-window counters. The pair is symmetric:
|
|
14
14
|
// _SHORT — matches `r.defineEvent(short, schema)` in the registrar
|
|
15
15
|
// (the framework automatically prefixes it to the QN)
|
|
16
|
-
// _QN — qualified form for `ctx.
|
|
16
|
+
// _QN — qualified form for `ctx.events.unsafeAppend({type})`, the
|
|
17
17
|
// `events.type` column, and `registry.getEvent(qn)` lookups
|
|
18
18
|
// Both MUST stay consistent; the feature test pins against drift.
|
|
19
19
|
export const ROLLING_INCREMENTED_EVENT_SHORT = "rolling-incremented" as const;
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// ai-foundation are BYOK by default and currently have no platform pool
|
|
32
32
|
// to count. cap-counter is generic: an app owner who wants to use the
|
|
33
33
|
// counter calls `bookCapUsage(...)` /
|
|
34
|
-
// `ctx.write(CapCounterHandlers.incrementRolling, ...)` from their own handler.
|
|
34
|
+
// `ctx.dispatch.write(CapCounterHandlers.incrementRolling, ...)` from their own handler.
|
|
35
35
|
// - **No reset cron for the calendar period.** It works without one: the
|
|
36
36
|
// periodStartIso part of the aggregate id rolls over to a fresh counter
|
|
37
37
|
// at the period boundary. Old rows remain for auditing.
|
|
@@ -86,7 +86,7 @@ export function createCapCounterFeature() {
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
// Custom domain event for the rolling counter. r.defineEvent registers the
|
|
89
|
-
// schema with the registry; ctx.
|
|
89
|
+
// schema with the registry; ctx.events.unsafeAppend in the handler reuses the
|
|
90
90
|
// same schema for append-time validation. QN after prefixing:
|
|
91
91
|
// "cap-counter:event:rolling-incremented" (see
|
|
92
92
|
// ROLLING_INCREMENTED_EVENT_QN).
|
|
@@ -71,7 +71,7 @@ export const incrementRollingCapHandler: WriteHandlerDef = {
|
|
|
71
71
|
// unsafeAppendEvent: the strict appendEvent is bound to an app's own event map, which
|
|
72
72
|
// bundled-features cannot see. Schema validation still runs because r.defineEvent
|
|
73
73
|
// registered the schema.
|
|
74
|
-
await ctx.
|
|
74
|
+
await ctx.events.unsafeAppend({
|
|
75
75
|
aggregateId,
|
|
76
76
|
aggregateType: CAP_COUNTER_ROLLING_AGGREGATE_TYPE,
|
|
77
77
|
type: ROLLING_INCREMENTED_EVENT_QN,
|
|
@@ -30,7 +30,7 @@ export function chainReservations(
|
|
|
30
30
|
try {
|
|
31
31
|
await innerHandle.release();
|
|
32
32
|
} catch (releaseError) {
|
|
33
|
-
ctx.log?.error("releasing the inner cap reservation failed", { error: releaseError });
|
|
33
|
+
ctx.obs.log?.error("releasing the inner cap reservation failed", { error: releaseError });
|
|
34
34
|
}
|
|
35
35
|
throw error;
|
|
36
36
|
}
|
|
@@ -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
|
/**
|
|
@@ -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, {
|
|
@@ -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) {
|
|
@@ -127,7 +127,7 @@ export const setWrite = defineWriteHandler({
|
|
|
127
127
|
tenantId,
|
|
128
128
|
event.user.id,
|
|
129
129
|
validateDb,
|
|
130
|
-
ctx.secrets,
|
|
130
|
+
ctx.services.secrets,
|
|
131
131
|
);
|
|
132
132
|
},
|
|
133
133
|
});
|
|
@@ -146,14 +146,14 @@ export const setWrite = defineWriteHandler({
|
|
|
146
146
|
// serialization as a config row so the read path round-trips via
|
|
147
147
|
// deserializeValue. system-scope is guaranteed by the boot-guard.
|
|
148
148
|
if (keyDef.backing === "secrets") {
|
|
149
|
-
if (!ctx.secrets) {
|
|
149
|
+
if (!ctx.services.secrets) {
|
|
150
150
|
throw new InternalError({
|
|
151
151
|
message:
|
|
152
152
|
`[config:write:set] key "${event.payload.key}" declares backing="secrets" but ` +
|
|
153
|
-
`ctx.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
153
|
+
`ctx.services.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
|
-
await ctx.secrets.set(
|
|
156
|
+
await ctx.services.secrets.set(
|
|
157
157
|
SYSTEM_TENANT_ID,
|
|
158
158
|
event.payload.key,
|
|
159
159
|
JSON.stringify(event.payload.value),
|