@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
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// existing resume-due-runs job picks the row up on its next
|
|
24
24
|
// cron tick — the resume path remains unchanged.
|
|
25
25
|
|
|
26
|
-
import { selectMany, updateMany } from "@cosmicdrift/kumiko-framework/db";
|
|
26
|
+
import { selectMany, sql, updateMany } from "@cosmicdrift/kumiko-framework/db";
|
|
27
27
|
import type {
|
|
28
28
|
FeatureRegistrar,
|
|
29
29
|
MultiStreamApplyFn,
|
|
@@ -32,7 +32,6 @@ import type {
|
|
|
32
32
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
33
33
|
import { evaluateEventMatch } from "@cosmicdrift/kumiko-framework/engine";
|
|
34
34
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
35
|
-
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
36
35
|
import type { TriggerEventRef } from "./runner.ts";
|
|
37
36
|
import { workflowRunPendingTable } from "./tables.ts";
|
|
38
37
|
|
|
@@ -92,7 +91,9 @@ const wakeupApply: MultiStreamApplyFn = async (event, tx) => {
|
|
|
92
91
|
aggregateId: event.aggregateId,
|
|
93
92
|
version: event.version,
|
|
94
93
|
} satisfies TriggerEventRef,
|
|
95
|
-
|
|
94
|
+
// DB clock, like the due comparison in due-runs.ts: an app-clock stamp ahead of the
|
|
95
|
+
// database clock would leave the row not-yet-due for the next resume tick.
|
|
96
|
+
wakeAt: sql`now()`,
|
|
96
97
|
},
|
|
97
98
|
{ tenantId: row.tenantId, runId: row.runId, stepIndex: row.stepIndex },
|
|
98
99
|
);
|
|
@@ -144,7 +144,8 @@ export function registerEventTrigger(r: FeatureRegistrar, workflow: WorkflowDefi
|
|
|
144
144
|
version: event.version,
|
|
145
145
|
},
|
|
146
146
|
...(idempotencyKey && { idempotencyKey }),
|
|
147
|
-
|
|
147
|
+
// The MSP context is still flat; the runner reads the namespaced shape.
|
|
148
|
+
handlerCtx: { events: { unsafeAppend: ctx.unsafeAppendEvent } },
|
|
148
149
|
});
|
|
149
150
|
} catch (error) {
|
|
150
151
|
// Failures outside the step loop (run-started append) have no step yet, so 0.
|
|
@@ -76,7 +76,7 @@ export function createWorkflowRunnerFeature() {
|
|
|
76
76
|
|
|
77
77
|
for (const row of dueRows) {
|
|
78
78
|
try {
|
|
79
|
-
await ctx.write("workflow-runner:write:resume-run", {
|
|
79
|
+
await ctx.dispatch.write("workflow-runner:write:resume-run", {
|
|
80
80
|
runId: row.runId,
|
|
81
81
|
stepIndex: row.stepIndex,
|
|
82
82
|
});
|
|
@@ -84,7 +84,7 @@ export function createWorkflowRunnerFeature() {
|
|
|
84
84
|
// skip: one row's dispatch failing (infra hiccup, not a business
|
|
85
85
|
// outcome — resume-run itself never throws for expected cases)
|
|
86
86
|
// must not stop the rest of this tenant's due rows from resuming.
|
|
87
|
-
ctx.log.warn(
|
|
87
|
+
ctx.obs.log.warn(
|
|
88
88
|
`[workflow-runner:resume-due-runs] runId=${row.runId} stepIndex=${row.stepIndex} dispatch failed: ${String(error)}`,
|
|
89
89
|
);
|
|
90
90
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// 1. Fingerprint check FIRST — before claiming, before any pipeline
|
|
8
8
|
// work. A changed workflow definition fails loud (WORKFLOW_RUN_FAILED,
|
|
9
9
|
// reason "workflow_definition_changed"), never a silent skip.
|
|
10
|
-
// 2. Claim via a savepoint-scoped WORKFLOW_RESUMED append (ctx.
|
|
10
|
+
// 2. Claim via a savepoint-scoped WORKFLOW_RESUMED append (ctx.events.tryAppend,
|
|
11
11
|
// not unsafeAppendEvent — a losing VersionConflict must not poison this
|
|
12
12
|
// handler's own transaction). A losing claim means another worker beat
|
|
13
13
|
// us to this row; silent no-op.
|
|
@@ -78,7 +78,7 @@ async function appendRunFailed(
|
|
|
78
78
|
runId: string,
|
|
79
79
|
failedPayload: WorkflowRunFailedPayload,
|
|
80
80
|
): Promise<void> {
|
|
81
|
-
await ctx.
|
|
81
|
+
await ctx.events.unsafeAppend({
|
|
82
82
|
aggregateId: runId,
|
|
83
83
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
84
84
|
type: WORKFLOW_RUN_FAILED_TYPE,
|
|
@@ -176,7 +176,7 @@ function readResumedPayload(payload: unknown): {
|
|
|
176
176
|
// mistake attempt 1's WORKFLOW_RESUMED for attempt 2's and skip the second
|
|
177
177
|
// retry entirely.
|
|
178
178
|
function isRunAlreadySettled(
|
|
179
|
-
runEvents: Awaited<ReturnType<HandlerContext["
|
|
179
|
+
runEvents: Awaited<ReturnType<HandlerContext["events"]["load"]>>,
|
|
180
180
|
stepIndex: number,
|
|
181
181
|
expectedRetryAttempt: number | undefined,
|
|
182
182
|
): boolean {
|
|
@@ -192,7 +192,7 @@ function isRunAlreadySettled(
|
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
type LoadedEvents = Awaited<ReturnType<HandlerContext["
|
|
195
|
+
type LoadedEvents = Awaited<ReturnType<HandlerContext["events"]["load"]>>;
|
|
196
196
|
|
|
197
197
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
198
198
|
return typeof value === "object" && value !== null;
|
|
@@ -229,7 +229,7 @@ function readTriggerSource(startedPayload: unknown): TriggerSource | null {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
async function loadReferencedEvent(ctx: HandlerContext, ref: TriggerEventRef) {
|
|
232
|
-
const events = await ctx.
|
|
232
|
+
const events = await ctx.events.load(ref.aggregateId, { atVersion: ref.version });
|
|
233
233
|
return events.find((e) => e.id === ref.eventId);
|
|
234
234
|
}
|
|
235
235
|
|
|
@@ -385,7 +385,7 @@ async function runResumedPipeline(ctx: HandlerContext, input: ResumedPipelineInp
|
|
|
385
385
|
workflowName,
|
|
386
386
|
stepIndex: steps.length,
|
|
387
387
|
};
|
|
388
|
-
await ctx.
|
|
388
|
+
await ctx.events.unsafeAppend({
|
|
389
389
|
aggregateId: runId,
|
|
390
390
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
391
391
|
type: WORKFLOW_RUN_COMPLETED_TYPE,
|
|
@@ -448,7 +448,7 @@ export const resumeRunHandler: WriteHandlerDef = {
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
const { workflowName } = pending;
|
|
451
|
-
const runEvents = await ctx.
|
|
451
|
+
const runEvents = await ctx.events.load(runId);
|
|
452
452
|
|
|
453
453
|
// Before the workflow resolution: a racing tick on an already-settled run
|
|
454
454
|
// must not append run-failed after run-completed when the definition has
|
|
@@ -469,7 +469,7 @@ export const resumeRunHandler: WriteHandlerDef = {
|
|
|
469
469
|
}
|
|
470
470
|
const workflow = resolved.workflow;
|
|
471
471
|
|
|
472
|
-
const claim = await ctx.
|
|
472
|
+
const claim = await ctx.events.tryAppend({
|
|
473
473
|
aggregateId: runId,
|
|
474
474
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
475
475
|
type: WORKFLOW_RESUMED_TYPE,
|
|
@@ -75,7 +75,9 @@ export type WorkflowRunFailedPayload = {
|
|
|
75
75
|
readonly reason?: string;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
export type WorkflowRunContext =
|
|
78
|
+
export type WorkflowRunContext = {
|
|
79
|
+
readonly events: Pick<HandlerContext["events"], "unsafeAppend">;
|
|
80
|
+
};
|
|
79
81
|
|
|
80
82
|
export class WorkflowSuspensionUnsupportedError extends Error {
|
|
81
83
|
constructor(
|
|
@@ -116,7 +118,7 @@ export async function startAndRunWorkflow(args: {
|
|
|
116
118
|
...(args.idempotencyKey && { idempotencyKey: args.idempotencyKey }),
|
|
117
119
|
};
|
|
118
120
|
|
|
119
|
-
await args.handlerCtx.
|
|
121
|
+
await args.handlerCtx.events.unsafeAppend({
|
|
120
122
|
aggregateId: args.runId,
|
|
121
123
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
122
124
|
type: WORKFLOW_RUN_STARTED_TYPE,
|
|
@@ -127,7 +129,7 @@ export async function startAndRunWorkflow(args: {
|
|
|
127
129
|
|
|
128
130
|
// @cast-boundary msp-to-handler-ctx — event-trigger hands over the narrower
|
|
129
131
|
// MultiStreamApplyContext (no query/write/writeAs). The step vocabulary this
|
|
130
|
-
// runner drives (wait, compute, return) only ever calls
|
|
132
|
+
// runner drives (wait, compute, return) only ever calls events.unsafeAppend.
|
|
131
133
|
const stepCtx = args.handlerCtx as unknown as HandlerContext;
|
|
132
134
|
const outcome = await runStepList(
|
|
133
135
|
steps,
|
|
@@ -158,7 +160,7 @@ export async function startAndRunWorkflow(args: {
|
|
|
158
160
|
stepIndex: steps.length,
|
|
159
161
|
};
|
|
160
162
|
|
|
161
|
-
await args.handlerCtx.
|
|
163
|
+
await args.handlerCtx.events.unsafeAppend({
|
|
162
164
|
aggregateId: args.runId,
|
|
163
165
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
164
166
|
type: WORKFLOW_RUN_COMPLETED_TYPE,
|
|
@@ -40,18 +40,32 @@ import type { EmailMessage } from "@cosmicdrift/kumiko-bundled-features/channel-
|
|
|
40
40
|
import {
|
|
41
41
|
createMailFoundationFeature,
|
|
42
42
|
createTransportForTenant,
|
|
43
|
+
type MailTransportContext,
|
|
43
44
|
} from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
|
|
44
45
|
import {
|
|
45
46
|
access,
|
|
46
47
|
createTenantConfig,
|
|
47
48
|
defineFeature,
|
|
48
|
-
type
|
|
49
|
+
type ReservationContext,
|
|
49
50
|
type WriteHandlerDef,
|
|
50
51
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
51
52
|
import { z } from "zod";
|
|
52
53
|
import { DEMO_TIER_MAP, TIER_NAMES, type TierName } from "./tier-map";
|
|
53
54
|
|
|
54
55
|
const FEATURE_NAME = "newsletter";
|
|
56
|
+
|
|
57
|
+
// The transport factory takes a narrow context (it also runs in the worker), so the handler's
|
|
58
|
+
// secrets live under services and are handed over explicitly.
|
|
59
|
+
function mailContextOf(
|
|
60
|
+
ctx: Pick<ReservationContext, "config" | "registry" | "services" | "user">,
|
|
61
|
+
): MailTransportContext {
|
|
62
|
+
return {
|
|
63
|
+
config: ctx.config,
|
|
64
|
+
registry: ctx.registry,
|
|
65
|
+
secrets: ctx.services.secrets,
|
|
66
|
+
auditUserId: ctx.user.id,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
55
69
|
const NEWSLETTER_CAP = "newsletters-per-month";
|
|
56
70
|
|
|
57
71
|
// =============================================================================
|
|
@@ -71,7 +85,7 @@ const innerSendHandler: WriteHandlerDef = {
|
|
|
71
85
|
handler: async (event, ctx) => {
|
|
72
86
|
const payload = event.payload as z.infer<typeof sendSchema>;
|
|
73
87
|
const transport = await createTransportForTenant(
|
|
74
|
-
ctx,
|
|
88
|
+
mailContextOf(ctx),
|
|
75
89
|
event.user.tenantId,
|
|
76
90
|
"newsletter:write:send",
|
|
77
91
|
);
|
|
@@ -108,7 +122,7 @@ function isValidTierName(value: string): value is TierName {
|
|
|
108
122
|
return (TIER_NAMES as readonly string[]).includes(value);
|
|
109
123
|
}
|
|
110
124
|
|
|
111
|
-
async function resolveTier(ctx:
|
|
125
|
+
async function resolveTier(ctx: ReservationContext): Promise<TierName> {
|
|
112
126
|
const tenantId = ctx.user?.tenantId;
|
|
113
127
|
if (tenantId) {
|
|
114
128
|
const sub = await getSubscriptionForTenant(ctx, tenantId);
|
|
@@ -131,10 +145,10 @@ async function resolveTier(ctx: HandlerContext): Promise<TierName> {
|
|
|
131
145
|
|
|
132
146
|
/** Notifier-Factory: bauen einen SoftHitNotifier der die Warnung über
|
|
133
147
|
* dieselbe mail-foundation an den Tenant-Admin schickt. */
|
|
134
|
-
function buildSoftHitNotifier(ctx:
|
|
148
|
+
function buildSoftHitNotifier(ctx: ReservationContext): SoftHitNotifier {
|
|
135
149
|
return async (info) => {
|
|
136
150
|
const transport = await createTransportForTenant(
|
|
137
|
-
ctx,
|
|
151
|
+
mailContextOf(ctx),
|
|
138
152
|
info.tenantId,
|
|
139
153
|
"newsletter:soft-hit-notifier",
|
|
140
154
|
);
|
|
@@ -26,6 +26,6 @@ await runDevApp({
|
|
|
26
26
|
watchDirs: ["./src", "../../../packages/*/src"],
|
|
27
27
|
extraContext: ({ registry }) => ({
|
|
28
28
|
configResolver: resolver,
|
|
29
|
-
|
|
29
|
+
configAccessorFactory: createConfigAccessorFactory(registry, resolver),
|
|
30
30
|
}),
|
|
31
31
|
});
|
|
@@ -7,6 +7,7 @@ import { styleguideClient } from "../features/demo/web";
|
|
|
7
7
|
import { examplesClient } from "../features/examples/web";
|
|
8
8
|
import { galleryClient } from "../features/gallery/web";
|
|
9
9
|
import { widgetsClient } from "../features/widgets/web";
|
|
10
|
+
import { workboardClient } from "../features/workboard/web";
|
|
10
11
|
import { AppShell } from "./shell";
|
|
11
12
|
|
|
12
13
|
// createKumikoApp fetches the schema itself from the authenticated
|
|
@@ -24,5 +25,6 @@ createKumikoApp({
|
|
|
24
25
|
widgetsClient,
|
|
25
26
|
examplesClient,
|
|
26
27
|
contentClient(),
|
|
28
|
+
workboardClient,
|
|
27
29
|
],
|
|
28
30
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
|
|
2
|
-
import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import { buildEntityTable, createTenantDb, fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { createEntityExecutor } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
|
|
5
5
|
|
|
@@ -8,9 +8,6 @@ import { demoEntity } from "../features/demo/feature";
|
|
|
8
8
|
// Gibt der List-View echte Rows mit Status-/Flag-Vielfalt. price (money)
|
|
9
9
|
// bleibt leer — der Money-Input zeigt sich im Edit-Screen, im Seed lassen wir
|
|
10
10
|
// ihn weg um nicht von der money-Payload-Form abzuhängen.
|
|
11
|
-
// ponytail: kein Idempotenz-Check — die Screenshot-DB ist ephemer (frisch pro
|
|
12
|
-
// Boot). Beim `bun run dev` gegen die persistente Dev-DB dupliziert ein
|
|
13
|
-
// Neustart die Rows; das ist hier nur eine Demo, daher egal.
|
|
14
11
|
const STATUSES = ["draft", "review", "published", "archived"] as const;
|
|
15
12
|
|
|
16
13
|
// Fixed across boots (unlike the framework-minted ids for every other seed
|
|
@@ -19,7 +16,12 @@ const STATUSES = ["draft", "review", "published", "archived"] as const;
|
|
|
19
16
|
// otherwise change every run.
|
|
20
17
|
export const FIRST_STYLEGUIDE_ITEM_ID = "00000000-0000-4000-8000-0000000000f1";
|
|
21
18
|
|
|
19
|
+
const demoItemTable = buildEntityTable("item", demoEntity);
|
|
20
|
+
|
|
22
21
|
export const seedStyleguideItems: SeedFn = async (stack) => {
|
|
22
|
+
// The first row has a fixed id, so its presence means a persistent dev DB was seeded already.
|
|
23
|
+
if (await fetchOne(stack.db, demoItemTable, { id: FIRST_STYLEGUIDE_ITEM_ID })) return;
|
|
24
|
+
|
|
23
25
|
// Bypass the write-handler HTTP path for the first row — its schema has
|
|
24
26
|
// no `id` field (buildInsertSchema only exposes entity fields), so an
|
|
25
27
|
// explicit id would be silently stripped before reaching the executor.
|
|
@@ -20,6 +20,8 @@ import { examplesFeature } from "../features/examples/feature";
|
|
|
20
20
|
import { galleryFeature } from "../features/gallery/feature";
|
|
21
21
|
import { aiTextDemoFeature } from "../features/widgets/ai-text-demo";
|
|
22
22
|
import { widgetsFeature } from "../features/widgets/feature";
|
|
23
|
+
import { workboardFeature } from "../features/workboard/feature";
|
|
24
|
+
import { seedWorkboardTasks } from "../features/workboard/seed";
|
|
23
25
|
import { seedStyleguideItems } from "./seed";
|
|
24
26
|
|
|
25
27
|
const configResolver = createConfigResolver();
|
|
@@ -35,17 +37,18 @@ await runDevApp({
|
|
|
35
37
|
contentFeature,
|
|
36
38
|
aiTextDemoFeature,
|
|
37
39
|
aiSettingsFeature,
|
|
40
|
+
workboardFeature,
|
|
38
41
|
],
|
|
39
|
-
// Aktiviert die Upload-Routes (/api/files) + ctx.files für den Avatar-
|
|
42
|
+
// Aktiviert die Upload-Routes (/api/files) + ctx.services.files für den Avatar-
|
|
40
43
|
// Stresstest. In-Memory reicht für die Demo (nicht-persistent).
|
|
41
44
|
files: { storageProvider: createInMemoryFileProvider() },
|
|
42
45
|
port: Number.parseInt(process.env["PORT"] ?? "4180", 10),
|
|
43
46
|
clientEntry: "./src/app/client.tsx",
|
|
44
47
|
htmlPath: "./public/index.html",
|
|
45
48
|
watchDirs: ["./src", "../../../packages/*/src"],
|
|
46
|
-
seeds: [seedStyleguideItems, seedAiConnections],
|
|
49
|
+
seeds: [seedStyleguideItems, seedAiConnections, seedWorkboardTasks],
|
|
47
50
|
extraContext: ({ registry }) => ({
|
|
48
51
|
configResolver,
|
|
49
|
-
|
|
52
|
+
configAccessorFactory: createConfigAccessorFactory(registry, configResolver),
|
|
50
53
|
}),
|
|
51
54
|
});
|
|
@@ -28,13 +28,21 @@ const loanMonthMs = (monthIndex: number): number => Date.UTC(2020, monthIndex, 1
|
|
|
28
28
|
// screenshots stay stable.
|
|
29
29
|
const growth = (1 + LOAN_MONTHLY_RATE) ** LOAN_MONTHS;
|
|
30
30
|
const annuityMinor = (LOAN_PRINCIPAL_MINOR * LOAN_MONTHLY_RATE * growth) / (growth - 1);
|
|
31
|
+
// Month index -> extra repayment, which shortens the term below LOAN_MONTHS.
|
|
32
|
+
const EXTRA_REPAYMENTS_MINOR: ReadonlyMap<number, number> = new Map([
|
|
33
|
+
[84, 3_000_000],
|
|
34
|
+
[150, 2_000_000],
|
|
35
|
+
]);
|
|
31
36
|
let balanceMinor: number = LOAN_PRINCIPAL_MINOR;
|
|
32
37
|
let interestPaidMinor = 0;
|
|
38
|
+
let payoffMonth: number | undefined;
|
|
33
39
|
const LOAN_REMAINING_POINTS = [{ atMs: loanMonthMs(0), value: LOAN_PRINCIPAL_MINOR }];
|
|
34
40
|
const LOAN_INTEREST_POINTS = [{ atMs: loanMonthMs(0), value: 0 }];
|
|
35
41
|
for (let i = 1; i <= LOAN_MONTHS; i++) {
|
|
36
42
|
const interest = balanceMinor * LOAN_MONTHLY_RATE;
|
|
37
|
-
|
|
43
|
+
const extraRepayment = EXTRA_REPAYMENTS_MINOR.get(i) ?? 0;
|
|
44
|
+
balanceMinor = Math.max(0, balanceMinor - (annuityMinor - interest) - extraRepayment);
|
|
45
|
+
if (balanceMinor === 0) payoffMonth ??= i;
|
|
38
46
|
interestPaidMinor += interest;
|
|
39
47
|
LOAN_REMAINING_POINTS.push({ atMs: loanMonthMs(i), value: Math.round(balanceMinor) });
|
|
40
48
|
LOAN_INTEREST_POINTS.push({ atMs: loanMonthMs(i), value: Math.round(interestPaidMinor) });
|
|
@@ -44,10 +52,13 @@ const LOAN_SERIES = [
|
|
|
44
52
|
{ key: "interest", label: "widgets:dashboard:loan-interest", points: LOAN_INTEREST_POINTS },
|
|
45
53
|
];
|
|
46
54
|
const LOAN_MARKERS = [
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
...[...EXTRA_REPAYMENTS_MINOR.keys()].map((monthIndex, i) => ({
|
|
56
|
+
atMs: loanMonthMs(monthIndex),
|
|
57
|
+
label: { i18nKey: `widgets:dashboard:marker-extra-${i + 1}` },
|
|
58
|
+
kind: "extra",
|
|
59
|
+
})),
|
|
49
60
|
{
|
|
50
|
-
atMs: loanMonthMs(LOAN_MONTHS),
|
|
61
|
+
atMs: loanMonthMs(payoffMonth ?? LOAN_MONTHS),
|
|
51
62
|
label: { i18nKey: "widgets:dashboard:marker-payoff" },
|
|
52
63
|
kind: "payoff",
|
|
53
64
|
},
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createDateField,
|
|
3
|
+
createEntity,
|
|
4
|
+
createNumberField,
|
|
5
|
+
createSelectField,
|
|
6
|
+
createTextField,
|
|
7
|
+
defineFeature,
|
|
8
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
9
|
+
|
|
10
|
+
import { WORKBOARD_I18N } from "./i18n";
|
|
11
|
+
|
|
12
|
+
export const taskEntity = createEntity({
|
|
13
|
+
table: "read_workboard_tasks",
|
|
14
|
+
fields: {
|
|
15
|
+
title: createTextField({
|
|
16
|
+
personal: false,
|
|
17
|
+
reason: "is_business_data",
|
|
18
|
+
required: true,
|
|
19
|
+
searchable: true,
|
|
20
|
+
sortable: true,
|
|
21
|
+
}),
|
|
22
|
+
status: createSelectField({
|
|
23
|
+
options: ["open", "inProgress", "blocked", "done"] as const,
|
|
24
|
+
default: "open",
|
|
25
|
+
sortable: true,
|
|
26
|
+
filterable: true,
|
|
27
|
+
}),
|
|
28
|
+
priority: createSelectField({
|
|
29
|
+
options: ["low", "medium", "high"] as const,
|
|
30
|
+
default: "medium",
|
|
31
|
+
sortable: true,
|
|
32
|
+
filterable: true,
|
|
33
|
+
}),
|
|
34
|
+
dueDate: createDateField({ sortable: true }),
|
|
35
|
+
assignee: createTextField({ personal: false, reason: "is_business_data", sortable: true }),
|
|
36
|
+
estimateHours: createNumberField({ sortable: true, filterable: true }),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const open = {
|
|
41
|
+
access: {
|
|
42
|
+
openToAll: {
|
|
43
|
+
reason: "demo app: any signed-in user manages every task; there is no per-user ownership",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
// All of this round's list options on one screen: remembered state, one reset
|
|
49
|
+
// button, the column picker (estimateHours starts hidden) and the density choice.
|
|
50
|
+
export const workboardFeature = defineFeature("workboard", (r) => {
|
|
51
|
+
r.translations({ keys: WORKBOARD_I18N });
|
|
52
|
+
r.crud("task", taskEntity, { write: open, read: open });
|
|
53
|
+
|
|
54
|
+
r.screen({
|
|
55
|
+
id: "task-list",
|
|
56
|
+
type: "entityList",
|
|
57
|
+
entity: "task",
|
|
58
|
+
columns: [
|
|
59
|
+
"title",
|
|
60
|
+
"status",
|
|
61
|
+
"priority",
|
|
62
|
+
{ field: "dueDate", hideOnNarrow: true },
|
|
63
|
+
{ field: "assignee", hideOnNarrow: true },
|
|
64
|
+
{ field: "estimateHours", hidden: true, hideOnNarrow: true },
|
|
65
|
+
],
|
|
66
|
+
pagination: "pages",
|
|
67
|
+
pageSize: 25,
|
|
68
|
+
defaultSort: { field: "dueDate", dir: "asc" },
|
|
69
|
+
searchable: true,
|
|
70
|
+
facets: { status: { display: "chips" }, priority: {} },
|
|
71
|
+
table: {
|
|
72
|
+
rememberState: true,
|
|
73
|
+
resetAll: true,
|
|
74
|
+
columnPicker: true,
|
|
75
|
+
density: { default: "comfortable", userChoice: true },
|
|
76
|
+
export: { xlsx: true },
|
|
77
|
+
},
|
|
78
|
+
rowActions: [
|
|
79
|
+
{ kind: "navigate", id: "edit", label: "Edit", screen: "task-edit", rowClick: true },
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// The same tasks as a spreadsheet-like board: fixed column widths, a pinned title,
|
|
84
|
+
// keyboard navigation between rows, row checkboxes with a bulk delete.
|
|
85
|
+
r.screen({
|
|
86
|
+
id: "task-board",
|
|
87
|
+
type: "entityList",
|
|
88
|
+
entity: "task",
|
|
89
|
+
columns: [
|
|
90
|
+
{ field: "title", pinned: "left", width: 260, minWidth: 140 },
|
|
91
|
+
{ field: "status", width: 180, minWidth: 100 },
|
|
92
|
+
{ field: "priority", width: 180, minWidth: 100 },
|
|
93
|
+
{ field: "dueDate", width: 180, minWidth: 100, hideOnNarrow: true },
|
|
94
|
+
{ field: "assignee", width: 220, minWidth: 100, hideOnNarrow: true },
|
|
95
|
+
{ field: "estimateHours", width: 180, minWidth: 100, hideOnNarrow: true },
|
|
96
|
+
],
|
|
97
|
+
pagination: "pages",
|
|
98
|
+
pageSize: 25,
|
|
99
|
+
defaultSort: { field: "dueDate", dir: "asc" },
|
|
100
|
+
searchable: true,
|
|
101
|
+
table: {
|
|
102
|
+
rememberState: true,
|
|
103
|
+
columnPicker: true,
|
|
104
|
+
pinning: true,
|
|
105
|
+
resizing: true,
|
|
106
|
+
keyboardNavigation: true,
|
|
107
|
+
density: { default: "comfortable", userChoice: true },
|
|
108
|
+
},
|
|
109
|
+
rowActions: [
|
|
110
|
+
{ kind: "navigate", id: "edit", label: "Edit", screen: "task-edit", rowClick: true },
|
|
111
|
+
{
|
|
112
|
+
kind: "writeHandler",
|
|
113
|
+
id: "delete",
|
|
114
|
+
label: "Delete",
|
|
115
|
+
handler: "workboard:write:task:delete",
|
|
116
|
+
style: "danger",
|
|
117
|
+
visible: { field: "status", ne: "done" },
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
bulkActions: [{ id: "delete", rowAction: "delete" }],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// The same tasks grouped by status on the server: each header carries the
|
|
124
|
+
// group's count and estimate sum, a footer row the sum over all filtered tasks.
|
|
125
|
+
r.screen({
|
|
126
|
+
id: "task-estimates",
|
|
127
|
+
type: "entityList",
|
|
128
|
+
entity: "task",
|
|
129
|
+
columns: ["title", "status", "priority", "assignee", "estimateHours"],
|
|
130
|
+
pagination: "pages",
|
|
131
|
+
pageSize: 3,
|
|
132
|
+
defaultSort: { field: "title", dir: "asc" },
|
|
133
|
+
searchable: true,
|
|
134
|
+
facets: { estimateHours: { display: "range" } },
|
|
135
|
+
table: {
|
|
136
|
+
grouping: { field: "status", collapsedWhen: "done", userChoice: true, fields: ["priority"] },
|
|
137
|
+
totals: [{ field: "estimateHours", kind: "sum" }],
|
|
138
|
+
},
|
|
139
|
+
rowActions: [
|
|
140
|
+
{ kind: "navigate", id: "edit", label: "Edit", screen: "task-edit", rowClick: true },
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
r.screen({
|
|
145
|
+
id: "task-edit",
|
|
146
|
+
type: "entityEdit",
|
|
147
|
+
entity: "task",
|
|
148
|
+
dormant: true,
|
|
149
|
+
listScreenId: "task-list",
|
|
150
|
+
layout: {
|
|
151
|
+
sections: [
|
|
152
|
+
{
|
|
153
|
+
columns: 2,
|
|
154
|
+
fields: ["title", "assignee", "status", "priority", "dueDate", "estimateHours"],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
r.nav({ id: "workboard", label: "workboard:nav.workboard", icon: "list", order: 40 });
|
|
161
|
+
r.nav({
|
|
162
|
+
id: "task-list",
|
|
163
|
+
label: "workboard:nav.tasks",
|
|
164
|
+
parent: "workboard:nav:workboard",
|
|
165
|
+
screen: "workboard:screen:task-list",
|
|
166
|
+
icon: "table",
|
|
167
|
+
order: 10,
|
|
168
|
+
});
|
|
169
|
+
r.nav({
|
|
170
|
+
id: "task-board",
|
|
171
|
+
label: "workboard:nav.board",
|
|
172
|
+
parent: "workboard:nav:workboard",
|
|
173
|
+
screen: "workboard:screen:task-board",
|
|
174
|
+
icon: "table",
|
|
175
|
+
order: 20,
|
|
176
|
+
});
|
|
177
|
+
r.nav({
|
|
178
|
+
id: "task-estimates",
|
|
179
|
+
label: "workboard:nav.estimates",
|
|
180
|
+
parent: "workboard:nav:workboard",
|
|
181
|
+
screen: "workboard:screen:task-estimates",
|
|
182
|
+
icon: "table",
|
|
183
|
+
order: 30,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { LocalizedString } from "../shared-i18n";
|
|
2
|
+
|
|
3
|
+
export const WORKBOARD_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
4
|
+
"workboard:nav.workboard": { de: "Aufgaben", en: "Workboard" },
|
|
5
|
+
"workboard:nav.tasks": { de: "Alle Aufgaben", en: "All tasks" },
|
|
6
|
+
"workboard:nav.board": { de: "Aufgaben-Board", en: "Task board" },
|
|
7
|
+
"workboard:nav.estimates": { de: "Aufwand je Status", en: "Estimates by status" },
|
|
8
|
+
"screen:task-board.title": { de: "Aufgaben-Board", en: "Task board" },
|
|
9
|
+
"screen:task-estimates.title": { de: "Aufwand je Status", en: "Estimates by status" },
|
|
10
|
+
"screen:task-list.title": { de: "Aufgaben", en: "Tasks" },
|
|
11
|
+
"screen:task-edit.title": { de: "Aufgabe bearbeiten", en: "Edit task" },
|
|
12
|
+
"screen:task-edit.create.title": { de: "Aufgabe anlegen", en: "Create task" },
|
|
13
|
+
"screen:task-edit.edit.title": { de: "Aufgabe bearbeiten", en: "Edit task" },
|
|
14
|
+
"workboard:entity:task:field:title": { de: "Titel", en: "Title" },
|
|
15
|
+
"workboard:entity:task:field:status": { de: "Status", en: "Status" },
|
|
16
|
+
"workboard:entity:task:field:status:option:open": { de: "Offen", en: "Open" },
|
|
17
|
+
"workboard:entity:task:field:status:option:inProgress": { de: "In Arbeit", en: "In progress" },
|
|
18
|
+
"workboard:entity:task:field:status:option:blocked": { de: "Blockiert", en: "Blocked" },
|
|
19
|
+
"workboard:entity:task:field:status:option:done": { de: "Erledigt", en: "Done" },
|
|
20
|
+
"workboard:entity:task:field:priority": { de: "Priorität", en: "Priority" },
|
|
21
|
+
"workboard:entity:task:field:priority:option:low": { de: "Niedrig", en: "Low" },
|
|
22
|
+
"workboard:entity:task:field:priority:option:medium": { de: "Mittel", en: "Medium" },
|
|
23
|
+
"workboard:entity:task:field:priority:option:high": { de: "Hoch", en: "High" },
|
|
24
|
+
"workboard:entity:task:field:dueDate": { de: "Fällig am", en: "Due date" },
|
|
25
|
+
"workboard:entity:task:field:assignee": { de: "Zuständig", en: "Assignee" },
|
|
26
|
+
"workboard:entity:task:field:estimateHours": { de: "Aufwand (Std.)", en: "Estimate (h)" },
|
|
27
|
+
};
|