@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-samples",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.390.0",
|
|
4
4
|
"description": "Source trees of the Kumiko sample recipes, sample apps and bundled features in repo layout, for tooling such as few-shot corpus builds.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-bundled-features",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.390.0",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
"runtime": "runtime",
|
|
19
19
|
"bunOnlyExports": [
|
|
20
20
|
"./template-resolver/testing",
|
|
21
|
-
"./tenant-lifecycle/testing"
|
|
21
|
+
"./tenant-lifecycle/testing",
|
|
22
|
+
"./tenant/testing",
|
|
23
|
+
"./user/testing"
|
|
22
24
|
]
|
|
23
25
|
},
|
|
24
26
|
"exports": {
|
|
@@ -101,12 +103,14 @@
|
|
|
101
103
|
"./user-profile/web": "./src/user-profile/web/index.ts",
|
|
102
104
|
"./auth-email-password": "./src/auth-email-password/index.ts",
|
|
103
105
|
"./auth-email-password/constants": "./src/auth-email-password/web/constants.ts",
|
|
106
|
+
"./auth-email-password/return-path": "./src/auth-email-password/web/return-path.ts",
|
|
104
107
|
"./auth-email-password/email-templates": "./src/auth-email-password/email-templates.ts",
|
|
105
108
|
"./auth-email-password/seeding": "./src/auth-email-password/seeding.ts",
|
|
106
109
|
"./auth-email-password/testing": "./src/auth-email-password/testing.ts",
|
|
107
110
|
"./auth-email-password/web": "./src/auth-email-password/web/index.ts",
|
|
108
111
|
"./shared/single-use-token-store": "./src/shared/single-use-token-store.ts",
|
|
109
112
|
"./shared/signed-token": "./src/shared/signed-token.ts",
|
|
113
|
+
"./shared/stream-tenant-backfill": "./src/shared/stream-tenant-backfill.ts",
|
|
110
114
|
"./shared/row-bound-grant": "./src/shared/row-bound-grant.ts",
|
|
111
115
|
"./shared/mail-template-body": "./src/shared/mail-template-body.ts",
|
|
112
116
|
"./delivery": "./src/delivery/index.ts",
|
|
@@ -160,19 +164,19 @@
|
|
|
160
164
|
"@cosmicdrift/kumiko-types": "workspace:*",
|
|
161
165
|
"@mollie/api-client": "^4.5.0",
|
|
162
166
|
"@node-rs/argon2": "^2.0.2",
|
|
163
|
-
"@tiptap/core": "3.31.3",
|
|
164
|
-
"@tiptap/extension-link": "3.31.3",
|
|
165
|
-
"@tiptap/extension-list": "3.31.3",
|
|
166
|
-
"@tiptap/extension-table": "3.31.3",
|
|
167
|
-
"@tiptap/html": "3.31.3",
|
|
168
|
-
"@tiptap/extensions": "3.31.3",
|
|
169
|
-
"@tiptap/pm": "3.31.3",
|
|
170
|
-
"@tiptap/react": "3.31.3",
|
|
171
|
-
"@tiptap/starter-kit": "3.31.3",
|
|
167
|
+
"@tiptap/core": "^3.31.3",
|
|
168
|
+
"@tiptap/extension-link": "^3.31.3",
|
|
169
|
+
"@tiptap/extension-list": "^3.31.3",
|
|
170
|
+
"@tiptap/extension-table": "^3.31.3",
|
|
171
|
+
"@tiptap/html": "^3.31.3",
|
|
172
|
+
"@tiptap/extensions": "^3.31.3",
|
|
173
|
+
"@tiptap/pm": "^3.31.3",
|
|
174
|
+
"@tiptap/react": "^3.31.3",
|
|
175
|
+
"@tiptap/starter-kit": "^3.31.3",
|
|
172
176
|
"@types/mailparser": "^3.4.6",
|
|
173
177
|
"@types/qrcode": "^1.5.5",
|
|
174
178
|
"clsx": "^2.1.1",
|
|
175
|
-
"happy-dom": "^
|
|
179
|
+
"happy-dom": "^21.0.4",
|
|
176
180
|
"hono": "^4.13.1",
|
|
177
181
|
"imapflow": "^1.7.8",
|
|
178
182
|
"ioredis": "^5.10.1",
|
|
@@ -180,7 +184,7 @@
|
|
|
180
184
|
"lucide-react": "^1.14.0",
|
|
181
185
|
"mailparser": "^3.9.32",
|
|
182
186
|
"marked": "^18.0.3",
|
|
183
|
-
"nodemailer": "^10.
|
|
187
|
+
"nodemailer": "^10.2.1",
|
|
184
188
|
"pdf-lib": "^1.17.1",
|
|
185
189
|
"qrcode": "^1.5.4",
|
|
186
190
|
"react": "^19.2.6",
|
|
@@ -516,6 +520,10 @@
|
|
|
516
520
|
"types": "./dist/auth-email-password/web/constants.d.ts",
|
|
517
521
|
"default": "./dist/auth-email-password/web/constants.js"
|
|
518
522
|
},
|
|
523
|
+
"./auth-email-password/return-path": {
|
|
524
|
+
"types": "./dist/auth-email-password/web/return-path.d.ts",
|
|
525
|
+
"default": "./dist/auth-email-password/web/return-path.js"
|
|
526
|
+
},
|
|
519
527
|
"./auth-email-password/seeding": {
|
|
520
528
|
"types": "./dist/auth-email-password/seeding.d.ts",
|
|
521
529
|
"default": "./dist/auth-email-password/seeding.js"
|
|
@@ -536,6 +544,10 @@
|
|
|
536
544
|
"types": "./dist/shared/signed-token.d.ts",
|
|
537
545
|
"default": "./dist/shared/signed-token.js"
|
|
538
546
|
},
|
|
547
|
+
"./shared/stream-tenant-backfill": {
|
|
548
|
+
"types": "./dist/shared/stream-tenant-backfill.d.ts",
|
|
549
|
+
"default": "./dist/shared/stream-tenant-backfill.js"
|
|
550
|
+
},
|
|
539
551
|
"./shared/row-bound-grant": {
|
|
540
552
|
"types": "./dist/shared/row-bound-grant.d.ts",
|
|
541
553
|
"default": "./dist/shared/row-bound-grant.js"
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.389.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Local agent tool errors carry a code",
|
|
6
|
+
"detail": "dispatchToolCall returns code invalid_tool_call for validation errors and unknown_tool for an unknown tool name, instead of a result without code. TOOL_CALL_ERROR_CODES names both."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.388.0",
|
|
4
10
|
"type": "fix",
|
|
@@ -9,7 +9,7 @@ export { buildAgentManifest } from "./agent-manifest.ts";
|
|
|
9
9
|
export { AGENT_TOOLS_FEATURE_NAME, createAgentToolsFeature } from "./feature.ts";
|
|
10
10
|
export { buildToolCatalog, OPEN_FORM_TOOL_NAME, toolNameForQn } from "./tool-catalog.ts";
|
|
11
11
|
export type { ToolCallRequest, ToolCallResult, ToolDispatcher } from "./tool-dispatch.ts";
|
|
12
|
-
export { dispatchToolCall } from "./tool-dispatch.ts";
|
|
12
|
+
export { dispatchToolCall, TOOL_CALL_ERROR_CODES } from "./tool-dispatch.ts";
|
|
13
13
|
export type {
|
|
14
14
|
AgentManifest,
|
|
15
15
|
AgentManifestEntity,
|
|
@@ -58,6 +58,21 @@ type ToolFailure = {
|
|
|
58
58
|
|
|
59
59
|
type FailureClassifier = (failure: ToolFailure, cause: unknown) => ToolCallResult;
|
|
60
60
|
|
|
61
|
+
export const TOOL_CALL_ERROR_CODES = {
|
|
62
|
+
invalidToolCall: "invalid_tool_call",
|
|
63
|
+
unknownTool: "unknown_tool",
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
type ToolCallFailure = Extract<ToolCallResult, { readonly ok: false }>;
|
|
67
|
+
|
|
68
|
+
function invalidToolCall(error: string): ToolCallFailure {
|
|
69
|
+
return { ok: false, error, code: TOOL_CALL_ERROR_CODES.invalidToolCall };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function unknownTool(error: string): ToolCallFailure {
|
|
73
|
+
return { ok: false, error, code: TOOL_CALL_ERROR_CODES.unknownTool };
|
|
74
|
+
}
|
|
75
|
+
|
|
61
76
|
const HTTP_TOO_MANY_REQUESTS = 429;
|
|
62
77
|
const HTTP_SERVER_ERROR = 500;
|
|
63
78
|
const UNEXPECTED_FAILURE_MESSAGE = "Tool failed unexpectedly";
|
|
@@ -108,7 +123,7 @@ type FilterOp = (typeof FILTER_OPS)[number];
|
|
|
108
123
|
|
|
109
124
|
type PayloadResult =
|
|
110
125
|
| { readonly ok: true; readonly value: Readonly<Record<string, unknown>> }
|
|
111
|
-
|
|
|
126
|
+
| ToolCallFailure;
|
|
112
127
|
|
|
113
128
|
function isFilterOp(value: unknown): value is FilterOp {
|
|
114
129
|
return isOneOf(FILTER_OPS, value);
|
|
@@ -120,7 +135,7 @@ function buildSearchPayload(
|
|
|
120
135
|
): PayloadResult {
|
|
121
136
|
const query = toolInput["query"];
|
|
122
137
|
if (typeof query !== "string" || query.length === 0) {
|
|
123
|
-
return
|
|
138
|
+
return invalidToolCall(`Tool "${toolName}" requires a non-empty string "query" argument`);
|
|
124
139
|
}
|
|
125
140
|
return { ok: true, value: { search: query, limit: SEARCH_RESULT_LIMIT } };
|
|
126
141
|
}
|
|
@@ -132,7 +147,7 @@ function buildFindByPayload(
|
|
|
132
147
|
): PayloadResult {
|
|
133
148
|
const value = toolInput[fieldName];
|
|
134
149
|
if (value === undefined) {
|
|
135
|
-
return
|
|
150
|
+
return invalidToolCall(`Tool "${toolName}" requires a "${fieldName}" argument`);
|
|
136
151
|
}
|
|
137
152
|
return {
|
|
138
153
|
ok: true,
|
|
@@ -156,10 +171,10 @@ function buildEntityListPayload(
|
|
|
156
171
|
const search = input["search"];
|
|
157
172
|
if (search !== undefined) {
|
|
158
173
|
if (typeof search !== "string") {
|
|
159
|
-
return
|
|
174
|
+
return invalidToolCall(`"search" must be a string`);
|
|
160
175
|
}
|
|
161
176
|
if (list.searchableFields.length === 0) {
|
|
162
|
-
return
|
|
177
|
+
return invalidToolCall("This entity has no searchable fields");
|
|
163
178
|
}
|
|
164
179
|
payload["search"] = search;
|
|
165
180
|
}
|
|
@@ -167,18 +182,18 @@ function buildEntityListPayload(
|
|
|
167
182
|
const filters = input["filters"];
|
|
168
183
|
if (filters !== undefined) {
|
|
169
184
|
if (!Array.isArray(filters)) {
|
|
170
|
-
return
|
|
185
|
+
return invalidToolCall(`"filters" must be an array`);
|
|
171
186
|
}
|
|
172
187
|
const validated: Array<{ field: string; op: FilterOp; value: unknown }> = [];
|
|
173
188
|
for (const entry of filters) {
|
|
174
189
|
if (!isRecord(entry) || typeof entry["field"] !== "string" || !("value" in entry)) {
|
|
175
|
-
return
|
|
190
|
+
return invalidToolCall(`Each filter must be { field, op, value }`);
|
|
176
191
|
}
|
|
177
192
|
if (!list.filterableFields.includes(entry["field"])) {
|
|
178
|
-
return
|
|
193
|
+
return invalidToolCall(`Field "${entry["field"]}" is not filterable on this entity`);
|
|
179
194
|
}
|
|
180
195
|
if (!isFilterOp(entry["op"])) {
|
|
181
|
-
return
|
|
196
|
+
return invalidToolCall(`Unsupported filter operator "${String(entry["op"])}"`);
|
|
182
197
|
}
|
|
183
198
|
validated.push({ field: entry["field"], op: entry["op"], value: entry["value"] });
|
|
184
199
|
}
|
|
@@ -250,7 +265,7 @@ async function dispatchServerQuery(
|
|
|
250
265
|
if (descriptor.detail) {
|
|
251
266
|
const id = input["id"];
|
|
252
267
|
if (typeof id !== "string" || id.length === 0) {
|
|
253
|
-
return
|
|
268
|
+
return invalidToolCall(`This tool requires a non-empty string "id" argument`);
|
|
254
269
|
}
|
|
255
270
|
const data = await dispatcher.query(descriptor.qn, { id }, user);
|
|
256
271
|
return { ok: true, data };
|
|
@@ -285,16 +300,16 @@ async function dispatchServerWrite(
|
|
|
285
300
|
if (descriptor.injectsVersion) {
|
|
286
301
|
const id = input["id"];
|
|
287
302
|
if (typeof id !== "string" || id.length === 0) {
|
|
288
|
-
return
|
|
303
|
+
return invalidToolCall(`This tool requires a non-empty string "id" argument`);
|
|
289
304
|
}
|
|
290
305
|
if (!descriptor.detailQn) {
|
|
291
|
-
return
|
|
306
|
+
return invalidToolCall("Tool is misconfigured: no detail handler to read version from");
|
|
292
307
|
}
|
|
293
308
|
const current = await dispatcher.query(descriptor.detailQn, { id }, user);
|
|
294
309
|
const version =
|
|
295
310
|
isRecord(current) && typeof current["version"] === "number" ? current["version"] : undefined;
|
|
296
311
|
if (version === undefined) {
|
|
297
|
-
return
|
|
312
|
+
return invalidToolCall(`Could not read the current "version" for id "${id}"`);
|
|
298
313
|
}
|
|
299
314
|
payload = { ...input, version };
|
|
300
315
|
}
|
|
@@ -336,10 +351,10 @@ function dispatchClientNavigate(
|
|
|
336
351
|
const entity = input["entity"];
|
|
337
352
|
if (typeof entity === "string") {
|
|
338
353
|
const screenId = descriptor.entityScreens.get(entity);
|
|
339
|
-
if (!screenId) return
|
|
354
|
+
if (!screenId) return invalidToolCall(`Unknown entity "${entity}" for navigation`);
|
|
340
355
|
const id = input["id"];
|
|
341
356
|
if (typeof id !== "string" || id.length === 0) {
|
|
342
|
-
return
|
|
357
|
+
return invalidToolCall(`Navigating to "${entity}" requires a non-empty string "id"`);
|
|
343
358
|
}
|
|
344
359
|
return { ok: true, data: { kind: "navigate", screenId, params: { id } } };
|
|
345
360
|
}
|
|
@@ -347,19 +362,19 @@ function dispatchClientNavigate(
|
|
|
347
362
|
const screenId = input["screenId"];
|
|
348
363
|
if (typeof screenId === "string") {
|
|
349
364
|
if (!descriptor.screenIds.has(screenId)) {
|
|
350
|
-
return
|
|
365
|
+
return invalidToolCall(`Unknown screen "${screenId}"`);
|
|
351
366
|
}
|
|
352
367
|
const params = input["params"];
|
|
353
368
|
if (params !== undefined) {
|
|
354
369
|
if (!isRecord(params) || Object.values(params).some((value) => typeof value !== "string")) {
|
|
355
|
-
return
|
|
370
|
+
return invalidToolCall(`"params" must be an object of string values`);
|
|
356
371
|
}
|
|
357
372
|
return { ok: true, data: { kind: "navigate", screenId, params } };
|
|
358
373
|
}
|
|
359
374
|
return { ok: true, data: { kind: "navigate", screenId, params: {} } };
|
|
360
375
|
}
|
|
361
376
|
|
|
362
|
-
return
|
|
377
|
+
return invalidToolCall(`navigate requires either { entity, id } or { screenId }`);
|
|
363
378
|
}
|
|
364
379
|
|
|
365
380
|
function dispatchClientOpenForm(
|
|
@@ -368,10 +383,10 @@ function dispatchClientOpenForm(
|
|
|
368
383
|
): ToolCallResult {
|
|
369
384
|
const handlerQn = input["handlerQn"];
|
|
370
385
|
if (typeof handlerQn !== "string") {
|
|
371
|
-
return
|
|
386
|
+
return invalidToolCall(`open_form requires a string "handlerQn" argument`);
|
|
372
387
|
}
|
|
373
388
|
const screenId = descriptor.formScreens.get(handlerQn);
|
|
374
|
-
if (!screenId) return
|
|
389
|
+
if (!screenId) return invalidToolCall(`No form screen mounted for handler "${handlerQn}"`);
|
|
375
390
|
return {
|
|
376
391
|
ok: true,
|
|
377
392
|
data: { kind: "open_form", screenId, handlerQn, prefill: input["prefill"] ?? {} },
|
|
@@ -385,14 +400,14 @@ function isStringArray(value: unknown): value is readonly string[] {
|
|
|
385
400
|
function dispatchClientAskUser(input: Readonly<Record<string, unknown>>): ToolCallResult {
|
|
386
401
|
const question = input["question"];
|
|
387
402
|
if (typeof question !== "string" || question.length === 0) {
|
|
388
|
-
return
|
|
403
|
+
return invalidToolCall(`ask_user requires a non-empty string "question" argument`);
|
|
389
404
|
}
|
|
390
405
|
const options = input["options"];
|
|
391
406
|
if (options === undefined) {
|
|
392
407
|
return { ok: true, data: { kind: "ask_user", question } };
|
|
393
408
|
}
|
|
394
409
|
if (!isStringArray(options)) {
|
|
395
|
-
return
|
|
410
|
+
return invalidToolCall(`ask_user "options" argument must be an array of strings`);
|
|
396
411
|
}
|
|
397
412
|
return { ok: true, data: { kind: "ask_user", question, options } };
|
|
398
413
|
}
|
|
@@ -413,9 +428,10 @@ function dispatchClient(
|
|
|
413
428
|
|
|
414
429
|
/** Executes one LLM-issued tool call. Never throws: every failure comes back as `{ ok: false }`
|
|
415
430
|
* so the agent loop can feed the error back to the model instead of crashing.
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
431
|
+
* Every failure carries a `code`: the handler's own code for handler and dispatcher failures
|
|
432
|
+
* (429 adds `retryable`), `invalid_tool_call` for bad arguments and `unknown_tool` for a tool
|
|
433
|
+
* that is not in the table. Client errors (< 500) keep their message, server failures (>= 500,
|
|
434
|
+
* unknown throws) are logged and returned as a generic message.
|
|
419
435
|
* `request.user` must be the caller's real identity: server-kind tools run through the same
|
|
420
436
|
* permission-checked pipeline as an HTTP request. */
|
|
421
437
|
export async function dispatchToolCall(request: ToolCallRequest): Promise<ToolCallResult> {
|
|
@@ -423,7 +439,7 @@ export async function dispatchToolCall(request: ToolCallRequest): Promise<ToolCa
|
|
|
423
439
|
const classifyFailure = createFailureClassifier(toolName, request.log ?? fallbackLog);
|
|
424
440
|
const descriptor = dispatchTable.get(toolName);
|
|
425
441
|
if (!descriptor) {
|
|
426
|
-
return
|
|
442
|
+
return unknownTool(`Unknown tool "${toolName}"`);
|
|
427
443
|
}
|
|
428
444
|
|
|
429
445
|
try {
|
|
@@ -49,6 +49,7 @@ export function createAuditFeature(): FeatureDefinition {
|
|
|
49
49
|
return defineFeature(
|
|
50
50
|
"audit",
|
|
51
51
|
(r) => {
|
|
52
|
+
r.adoptsBundledLists();
|
|
52
53
|
r.describe(
|
|
53
54
|
"Exposes the framework's event store as a paginated, filterable audit log via the `audit:query:list` handler (accessible to `Admin` and `SystemAdmin` roles). No separate table or projection \u2014 the event store is the audit trail by construction: every entity write already records who, when, what entity, and the event payload with PII stripped. A SystemAdmin can pass `scope: \"system\"` to read the app-instance system events such as `app.started`, and reads the events of every tenant (system tenant excluded) through `audit:query:list-all-tenants` and the `audit-log-all-tenants` screen. Filter by `aggregateType`, `aggregateId`, `eventType`, `userId`, or time range. Also records `audit:event:escape-hatch-used` whenever a handler uses one of the framework's escape hatches (unsafeRaw, acknowledgeCrossTenant, db.global() writes, or a granted identity switch).",
|
|
54
55
|
);
|
|
@@ -92,7 +93,7 @@ export function createAuditFeature(): FeatureDefinition {
|
|
|
92
93
|
await runEscapeHatchRetention({
|
|
93
94
|
db: ctx.db.unsafeRaw(),
|
|
94
95
|
registry: ctx.registry,
|
|
95
|
-
configResolver: ctx.configResolver,
|
|
96
|
+
configResolver: ctx.services.configResolver,
|
|
96
97
|
userId: SYSTEM_USER_ID,
|
|
97
98
|
});
|
|
98
99
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Narrow cross-feature query results (ctx.queryAs → Promise<unknown>) into
|
|
1
|
+
// Narrow cross-feature query results (ctx.dispatch.queryAs → Promise<unknown>) into
|
|
2
2
|
// the shape the auth handlers actually read. Replaces a bare
|
|
3
3
|
// `as AuthUserRow | null` at the system boundary — the coding standard
|
|
4
4
|
// requires a TypeGuard in place of unchecked casts from unknown.
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type TenantId,
|
|
20
20
|
type WriteResult,
|
|
21
21
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
22
|
+
import { runInSystemRowLevelSecurityScope } from "@cosmicdrift/kumiko-framework/internal/row-level-security";
|
|
22
23
|
import type { Dispatcher } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
23
24
|
import type { EnvelopeCipher } from "@cosmicdrift/kumiko-framework/secrets";
|
|
24
25
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
@@ -293,7 +294,18 @@ function isMailingOutcome(outcome: BootstrapInviteOutcome): boolean {
|
|
|
293
294
|
return outcome === "invited" || outcome === "resent";
|
|
294
295
|
}
|
|
295
296
|
|
|
296
|
-
|
|
297
|
+
// A one-shot operator process, not a tenant request: it looks up users, memberships and invitations across tenants.
|
|
298
|
+
export function bootstrapTenants(
|
|
299
|
+
deps: BootstrapDeps,
|
|
300
|
+
plan: BootstrapPlan,
|
|
301
|
+
): Promise<BootstrapReport> {
|
|
302
|
+
return runInSystemRowLevelSecurityScope(
|
|
303
|
+
"boot tenant bootstrap creates tenants and memberships before any tenant exists",
|
|
304
|
+
() => bootstrapTenantsInScope(deps, plan),
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function bootstrapTenantsInScope(
|
|
297
309
|
deps: BootstrapDeps,
|
|
298
310
|
plan: BootstrapPlan,
|
|
299
311
|
): Promise<BootstrapReport> {
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.390.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "isSafeReturnPath has its own light subpath",
|
|
6
|
+
"detail": "Importing @cosmicdrift/kumiko-bundled-features/auth-email-password/return-path gives isSafeReturnPath, readReturnToFromSearch, RETURN_TO_QUERY_PARAM and MAX_RETURN_PATH_LENGTH without loading the web barrel, for example in Astro pages that run without the Kumiko runtime."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.389.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "Optional returnTo for password reset and signup",
|
|
12
|
+
"detail": "Password reset and signup accept an optional returnTo path. A safe value (same-origin path, no dot segments) is appended to the mailed link as a query parameter, the reset and signup-complete screens follow it, and the login screen forwards its next to the forgot-password and signup links. Invalid values are dropped silently and never block the mail. isSafeReturnPath and readReturnToFromSearch are exported from the web barrel. isSafeNextPath now uses the same check, so a next with a dot segment such as \"/a/../b\" is no longer followed."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.389.0",
|
|
16
|
+
"type": "improvement",
|
|
17
|
+
"title": "CurrentUser carries tenantId, logout clears remembered list state",
|
|
18
|
+
"detail": "The session CurrentUser has an optional tenantId used to scope remembered list state; logout removes all kumiko.list.* storage entries."
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"version": "0.385.0",
|
|
4
22
|
"type": "improvement",
|
|
@@ -105,7 +105,7 @@ export type EmailVerificationOptions = {
|
|
|
105
105
|
// Brute-force protection on the login handler. Omit for the defaults
|
|
106
106
|
// (5 failures → 15-minute lock). Set the dial knobs to override.
|
|
107
107
|
//
|
|
108
|
-
// Storage: Redis (keyed by userId). Without ctx.redis the handler skips
|
|
108
|
+
// Storage: Redis (keyed by userId). Without ctx.services.redis the handler skips
|
|
109
109
|
// lockout entirely — login still works, but brute-force protection falls
|
|
110
110
|
// back to the IP-rate-limiter. Counter is monotonic: only a successful
|
|
111
111
|
// login resets it, so after a lockout expires the next wrong password
|
|
@@ -149,7 +149,7 @@ export type AuthEmailPasswordOptions = {
|
|
|
149
149
|
};
|
|
150
150
|
|
|
151
151
|
// Auth feature — email+password login. Depends on the user feature for
|
|
152
|
-
// identity lookups (via ctx.queryAs) and on the tenant feature for
|
|
152
|
+
// identity lookups (via ctx.dispatch.queryAs) and on the tenant feature for
|
|
153
153
|
// membership resolution. No direct imports of foreign tables.
|
|
154
154
|
export function createAuthEmailPasswordFeature(
|
|
155
155
|
opts: AuthEmailPasswordOptions = {},
|
|
@@ -10,7 +10,7 @@ import { invalidCredentials } from "../errors.ts";
|
|
|
10
10
|
import { passwordSchema } from "../password-policy.ts";
|
|
11
11
|
|
|
12
12
|
// Change-password — authenticated. The user supplies their current password
|
|
13
|
-
// (re-auth) and the new one. The new hash is written via ctx.writeAs(system)
|
|
13
|
+
// (re-auth) and the new one. The new hash is written via ctx.dispatch.writeAs(system)
|
|
14
14
|
// against the user feature's update handler; field-access on passwordHash
|
|
15
15
|
// (privileged-only) lets the system identity through.
|
|
16
16
|
export const changePasswordWrite = defineWriteHandler({
|
|
@@ -28,8 +28,8 @@ export const changePasswordWrite = defineWriteHandler({
|
|
|
28
28
|
escapeHatch: {
|
|
29
29
|
grants: ["systemIdentity"],
|
|
30
30
|
reason:
|
|
31
|
-
"Reads the caller's own passwordHash (privileged-only field) via ctx.queryAs(SYSTEM, ...) " +
|
|
32
|
-
"and writes the new hash via ctx.writeAs(SYSTEM, user:update) — the caller's own " +
|
|
31
|
+
"Reads the caller's own passwordHash (privileged-only field) via ctx.dispatch.queryAs(SYSTEM, ...) " +
|
|
32
|
+
"and writes the new hash via ctx.dispatch.writeAs(SYSTEM, user:update) — the caller's own " +
|
|
33
33
|
"identity can't reach either, field-access on passwordHash is privileged-only.",
|
|
34
34
|
},
|
|
35
35
|
// Payload carries the old and new password.
|
|
@@ -40,7 +40,7 @@ export const changePasswordWrite = defineWriteHandler({
|
|
|
40
40
|
const systemUser = createSystemUser(event.user.tenantId);
|
|
41
41
|
|
|
42
42
|
// Load self with passwordHash — only visible to the privileged caller.
|
|
43
|
-
const me = (await ctx.queryAs(systemUser, UserQueries.findForAuth, {
|
|
43
|
+
const me = (await ctx.dispatch.queryAs(systemUser, UserQueries.findForAuth, {
|
|
44
44
|
id: event.user.id,
|
|
45
45
|
})) as { id: number; passwordHash: string | null; version: number } | null; // @cast-boundary db-runner
|
|
46
46
|
|
|
@@ -56,14 +56,14 @@ export const changePasswordWrite = defineWriteHandler({
|
|
|
56
56
|
const newHash = await hashPassword(event.payload.newPassword);
|
|
57
57
|
|
|
58
58
|
// The user aggregate is systemStream: its event stream lives on
|
|
59
|
-
// SYSTEM_TENANT_ID deterministically. Previously scattered streams
|
|
60
|
-
//
|
|
59
|
+
// SYSTEM_TENANT_ID deterministically. Previously scattered streams are moved by the
|
|
60
|
+
// boot-time stream-tenant backfill (runStreamTenantBackfillOnBoot).
|
|
61
61
|
const writer = createSystemUser(SYSTEM_TENANT_ID);
|
|
62
62
|
|
|
63
63
|
// Apply via user feature's update handler — writeAs(system) satisfies
|
|
64
64
|
// the privileged-only write rule on passwordHash. Pass the current version
|
|
65
65
|
// through so optimistic locking still applies end-to-end.
|
|
66
|
-
const writeRes = await ctx.writeAs(writer, UserHandlers.update, {
|
|
66
|
+
const writeRes = await ctx.dispatch.writeAs(writer, UserHandlers.update, {
|
|
67
67
|
id: me.id,
|
|
68
68
|
version: me.version,
|
|
69
69
|
changes: { passwordHash: newHash },
|
package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts
CHANGED
|
@@ -40,10 +40,10 @@ export function createConfirmAccountUnlockHandler(opts: ConfirmAccountUnlockOpti
|
|
|
40
40
|
}),
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
|
-
if (!ctx.redis) {
|
|
43
|
+
if (!ctx.services.redis) {
|
|
44
44
|
return writeFailure(
|
|
45
45
|
new InternalError({
|
|
46
|
-
message: "account-unlock requires ctx.redis to clear lockout state",
|
|
46
|
+
message: "account-unlock requires ctx.services.redis to clear lockout state",
|
|
47
47
|
}),
|
|
48
48
|
);
|
|
49
49
|
}
|
|
@@ -54,7 +54,7 @@ export function createConfirmAccountUnlockHandler(opts: ConfirmAccountUnlockOpti
|
|
|
54
54
|
const verify = verifyUnlockToken(event.payload.token, opts.hmacSecret);
|
|
55
55
|
if (!verify.ok) return invalidUnlockToken();
|
|
56
56
|
|
|
57
|
-
await clearLockoutState(ctx.redis, verify.userId);
|
|
57
|
+
await clearLockoutState(ctx.services.redis, verify.userId);
|
|
58
58
|
return { isSuccess: true, data: { kind: "account-unlocked" as const } };
|
|
59
59
|
},
|
|
60
60
|
});
|
|
@@ -42,7 +42,7 @@ export type ConfirmTokenFlowSpec<TSuccessData> = {
|
|
|
42
42
|
// other token flows — "reset" vs "verify" keeps cross-flow replay
|
|
43
43
|
// impossible at both layers (HMAC-purpose AND burn-purpose).
|
|
44
44
|
readonly purpose: string;
|
|
45
|
-
// Used verbatim in the 5xx body when ctx.redis is missing — the feature
|
|
45
|
+
// Used verbatim in the 5xx body when ctx.services.redis is missing — the feature
|
|
46
46
|
// is misconfigured, not the caller's fault.
|
|
47
47
|
readonly redisRequiredMessage: string;
|
|
48
48
|
// Standard failure returned for every "token can't be consumed" path
|
|
@@ -74,10 +74,10 @@ export async function runConfirmTokenFlow<TSuccessData>(
|
|
|
74
74
|
reason:
|
|
75
75
|
"writes the confirming user's row via UserHandlers.update on the caller's handler context, using a SYSTEM_TENANT-scoped identity; the calling handler declares its own escapeHatch",
|
|
76
76
|
});
|
|
77
|
-
if (!ctx.redis) {
|
|
77
|
+
if (!ctx.services.redis) {
|
|
78
78
|
return writeFailure(new InternalError({ message: spec.redisRequiredMessage }));
|
|
79
79
|
}
|
|
80
|
-
const redis: Redis = ctx.redis;
|
|
80
|
+
const redis: Redis = ctx.services.redis;
|
|
81
81
|
|
|
82
82
|
const burn = await burnToken(redis, spec.purpose, userId, expiresAtMs);
|
|
83
83
|
if (burn === "already-used") return spec.invalidToken();
|
|
@@ -99,7 +99,7 @@ export async function runConfirmTokenFlow<TSuccessData>(
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const changes = await spec.buildChanges(me);
|
|
102
|
-
const writeRes = await ctx.writeAs(systemUser, UserHandlers.update, {
|
|
102
|
+
const writeRes = await ctx.dispatch.writeAs(systemUser, UserHandlers.update, {
|
|
103
103
|
id: me.id,
|
|
104
104
|
version: me.version,
|
|
105
105
|
changes,
|
|
@@ -141,7 +141,7 @@ async function loadValidatedUser(
|
|
|
141
141
|
"reads the confirming user's row via UserQueries.findForAuth on the caller's handler context, using a SYSTEM_TENANT-scoped identity; the calling handler declares its own escapeHatch",
|
|
142
142
|
});
|
|
143
143
|
const me = parseAuthUserRow(
|
|
144
|
-
await ctx.queryAs(systemUser, UserQueries.findForAuth, { id: userId }),
|
|
144
|
+
await ctx.dispatch.queryAs(systemUser, UserQueries.findForAuth, { id: userId }),
|
|
145
145
|
);
|
|
146
146
|
if (!me || me.isDeleted || me.version === undefined || me.version < 1) return null;
|
|
147
147
|
return { ...me, version: me.version };
|
package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts
CHANGED
|
@@ -133,16 +133,16 @@ export function createInviteAcceptWithLoginHandler(opts: InviteAcceptWithLoginOp
|
|
|
133
133
|
agent: { expose: false },
|
|
134
134
|
// kumiko-lint-ignore complexity-budget reuses login.write.ts's gate chain (lockout/password/email/status/membership/mfa) plus invite-specific branches (email match, already-member check, invitation update, unburn-on-failure) — splitting would scatter gate order across functions without reducing risk
|
|
135
135
|
handler: async (event, ctx) => {
|
|
136
|
-
if (!ctx.redis) {
|
|
136
|
+
if (!ctx.services.redis) {
|
|
137
137
|
return writeFailure(
|
|
138
|
-
new InternalError({ message: "invite-accept-with-login requires ctx.redis" }),
|
|
138
|
+
new InternalError({ message: "invite-accept-with-login requires ctx.services.redis" }),
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
const invitationId = await getInvitationIdForToken(ctx.redis, event.payload.token);
|
|
142
|
+
const invitationId = await getInvitationIdForToken(ctx.services.redis, event.payload.token);
|
|
143
143
|
if (!invitationId) return invalidInviteToken();
|
|
144
144
|
|
|
145
|
-
const burn = await burnInviteToken(ctx.redis, event.payload.token);
|
|
145
|
+
const burn = await burnInviteToken(ctx.services.redis, event.payload.token);
|
|
146
146
|
if (burn === "already-used") return invalidInviteToken();
|
|
147
147
|
|
|
148
148
|
type InvitationRow = {
|
|
@@ -242,6 +242,8 @@ export function createInviteAcceptWithLoginHandler(opts: InviteAcceptWithLoginOp
|
|
|
242
242
|
db: dbConn,
|
|
243
243
|
tenantId: invitationTenantId,
|
|
244
244
|
mode: "system",
|
|
245
|
+
reason:
|
|
246
|
+
"invitation tenant differs from the caller's tenant, the accept step updates the invitation row there",
|
|
245
247
|
});
|
|
246
248
|
const updateResult = await invitationExecutor.update(
|
|
247
249
|
{
|
|
@@ -254,7 +256,7 @@ export function createInviteAcceptWithLoginHandler(opts: InviteAcceptWithLoginOp
|
|
|
254
256
|
);
|
|
255
257
|
if (!updateResult.isSuccess) return updateResult;
|
|
256
258
|
|
|
257
|
-
await deleteInviteToken(ctx.redis, { invitationId, token: event.payload.token });
|
|
259
|
+
await deleteInviteToken(ctx.services.redis, { invitationId, token: event.payload.token });
|
|
258
260
|
|
|
259
261
|
// buildSessionRoles calls stripForbiddenMembershipRoles internally —
|
|
260
262
|
// a reserved role on an existing membership must never reach the session.
|
|
@@ -296,8 +298,8 @@ export function createInviteAcceptWithLoginHandler(opts: InviteAcceptWithLoginOp
|
|
|
296
298
|
},
|
|
297
299
|
};
|
|
298
300
|
} finally {
|
|
299
|
-
if (!committed && ctx.redis) {
|
|
300
|
-
await unburnInviteToken(ctx.redis, event.payload.token);
|
|
301
|
+
if (!committed && ctx.services.redis) {
|
|
302
|
+
await unburnInviteToken(ctx.services.redis, event.payload.token);
|
|
301
303
|
}
|
|
302
304
|
}
|
|
303
305
|
},
|
|
@@ -94,16 +94,18 @@ export function createInviteAcceptHandler() {
|
|
|
94
94
|
},
|
|
95
95
|
// kumiko-lint-ignore complexity-budget invite branches (auth/anon/burn) stay in one handler
|
|
96
96
|
handler: async (event, ctx) => {
|
|
97
|
-
if (!ctx.redis) {
|
|
97
|
+
if (!ctx.services.redis) {
|
|
98
98
|
return writeFailure(
|
|
99
|
-
new InternalError({
|
|
99
|
+
new InternalError({
|
|
100
|
+
message: "invite-accept requires ctx.services.redis for token consumption",
|
|
101
|
+
}),
|
|
100
102
|
);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
const invitationId = await getInvitationIdForToken(ctx.redis, event.payload.token);
|
|
105
|
+
const invitationId = await getInvitationIdForToken(ctx.services.redis, event.payload.token);
|
|
104
106
|
if (!invitationId) return invalidInviteToken();
|
|
105
107
|
|
|
106
|
-
const burn = await burnInviteToken(ctx.redis, event.payload.token);
|
|
108
|
+
const burn = await burnInviteToken(ctx.services.redis, event.payload.token);
|
|
107
109
|
if (burn === "already-used") return invalidInviteToken();
|
|
108
110
|
|
|
109
111
|
type InvitationRow = {
|
|
@@ -177,6 +179,8 @@ export function createInviteAcceptHandler() {
|
|
|
177
179
|
db: dbConn,
|
|
178
180
|
tenantId: invitationTenantId,
|
|
179
181
|
mode: "system",
|
|
182
|
+
reason:
|
|
183
|
+
"invitation tenant differs from the caller's tenant, the accept step updates the invitation row there",
|
|
180
184
|
});
|
|
181
185
|
const updateResult = await invitationExecutor.update(
|
|
182
186
|
{
|
|
@@ -189,7 +193,7 @@ export function createInviteAcceptHandler() {
|
|
|
189
193
|
);
|
|
190
194
|
if (!updateResult.isSuccess) return updateResult;
|
|
191
195
|
|
|
192
|
-
await deleteInviteToken(ctx.redis, { invitationId, token: event.payload.token });
|
|
196
|
+
await deleteInviteToken(ctx.services.redis, { invitationId, token: event.payload.token });
|
|
193
197
|
|
|
194
198
|
committed = true;
|
|
195
199
|
return {
|
|
@@ -202,8 +206,8 @@ export function createInviteAcceptHandler() {
|
|
|
202
206
|
},
|
|
203
207
|
};
|
|
204
208
|
} finally {
|
|
205
|
-
if (!committed && ctx.redis) {
|
|
206
|
-
await unburnInviteToken(ctx.redis, event.payload.token);
|
|
209
|
+
if (!committed && ctx.services.redis) {
|
|
210
|
+
await unburnInviteToken(ctx.services.redis, event.payload.token);
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
},
|