@cosmicdrift/kumiko-samples 0.362.0 → 0.363.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 +17 -6
- package/packages/bundled-features/src/admin-shell/changes.json +6 -0
- package/packages/bundled-features/src/admin-shell/feature.ts +8 -1
- package/packages/bundled-features/src/agent-tools/agent-manifest.ts +3 -4
- package/packages/bundled-features/src/agent-tools/filter-ops.ts +1 -3
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -3
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +2 -1
- package/packages/bundled-features/src/auth-email-password/changes.json +14 -0
- package/packages/bundled-features/src/auth-email-password/email-templates.ts +12 -138
- package/packages/bundled-features/src/auth-email-password/feature.ts +30 -9
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +4 -5
- package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +3 -4
- package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +3 -12
- package/packages/bundled-features/src/auth-email-password/index.ts +2 -17
- package/packages/bundled-features/src/auth-email-password/magic-link-mail.ts +30 -22
- package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +158 -0
- package/packages/bundled-features/src/auth-email-password/signup-activation.ts +2 -3
- package/packages/bundled-features/src/auth-foundation/types.ts +8 -18
- package/packages/bundled-features/src/auth-mfa/feature.ts +8 -10
- package/packages/bundled-features/src/auth-mfa/hmac-token-codec.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/mfa-challenge-token.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/mfa-preauth-setup-token.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/mfa-setup-token.ts +8 -8
- package/packages/bundled-features/src/billing-foundation/changes.json +7 -0
- package/packages/bundled-features/src/billing-foundation/constants.ts +5 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +38 -44
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +115 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +30 -30
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-notify.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +1 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +4 -9
- package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -6
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -1
- package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +6 -4
- package/packages/bundled-features/src/channel-email/changes.json +19 -0
- package/packages/bundled-features/src/channel-email/email-channel.ts +122 -29
- package/packages/bundled-features/src/channel-email/feature.ts +6 -3
- package/packages/bundled-features/src/channel-email/index.ts +7 -1
- package/packages/bundled-features/src/channel-email/pii-guard.ts +13 -0
- package/packages/bundled-features/src/channel-email/smtp-transport.ts +15 -1
- package/packages/bundled-features/src/channel-email/types.ts +23 -0
- package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +2 -2
- package/packages/bundled-features/src/config/handlers/set.write.ts +1 -5
- package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +2 -2
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -11
- package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +7 -6
- package/packages/bundled-features/src/data-retention/changes.json +6 -0
- package/packages/bundled-features/src/data-retention/index.ts +1 -0
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +8 -6
- package/packages/bundled-features/src/delivery/attachment-ref.ts +84 -0
- package/packages/bundled-features/src/delivery/changes.json +48 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +129 -4
- package/packages/bundled-features/src/delivery/constants.ts +2 -0
- package/packages/bundled-features/src/delivery/delivery-service.ts +104 -26
- package/packages/bundled-features/src/delivery/feature.ts +1 -1
- package/packages/bundled-features/src/delivery/index.ts +17 -2
- package/packages/bundled-features/src/delivery/jobs.ts +48 -5
- package/packages/bundled-features/src/delivery/notify-factory.ts +14 -9
- package/packages/bundled-features/src/delivery/testing.ts +9 -1
- package/packages/bundled-features/src/delivery/types.ts +28 -18
- package/packages/bundled-features/src/delivery/unsubscribe.ts +5 -2
- package/packages/bundled-features/src/derivatives-sharp/render.ts +1 -22
- package/packages/bundled-features/src/document-ingest-foundation/pages.ts +6 -3
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +4 -4
- package/packages/bundled-features/src/file-foundation/index.ts +7 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +86 -0
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +5 -2
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +11 -11
- package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +2 -2
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +2 -2
- package/packages/bundled-features/src/form-draft/release-file-refs.ts +3 -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/ingest-message.write.ts +6 -6
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +2 -2
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +7 -7
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +2 -6
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +5 -13
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +4 -6
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +40 -25
- package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +4 -3
- package/packages/bundled-features/src/jobs/handlers/catalog.query.ts +1 -1
- package/packages/bundled-features/src/ledger/recurring.ts +1 -3
- package/packages/bundled-features/src/managed-pages/branding.ts +33 -9
- package/packages/bundled-features/src/managed-pages/changes.json +6 -0
- package/packages/bundled-features/src/managed-pages/feature.ts +1 -0
- package/packages/bundled-features/src/managed-pages/i18n.ts +1 -0
- package/packages/bundled-features/src/managed-pages/screens/branding-screen.ts +8 -0
- package/packages/bundled-features/src/page-render/branding.ts +3 -0
- package/packages/bundled-features/src/page-render/markdown.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +2 -4
- package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -1
- package/packages/bundled-features/src/personal-access-tokens/index.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -1
- package/packages/bundled-features/src/renderer-foundation/README.md +11 -10
- package/packages/bundled-features/src/renderer-foundation/api.ts +14 -14
- package/packages/bundled-features/src/renderer-foundation/changes.json +39 -0
- package/packages/bundled-features/src/renderer-foundation/constants.ts +6 -8
- package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
- package/packages/bundled-features/src/renderer-foundation/index.ts +13 -2
- package/packages/bundled-features/src/renderer-foundation/types.ts +132 -35
- package/packages/bundled-features/src/renderer-pdf/feature.ts +7 -1
- package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +2 -2
- package/packages/bundled-features/src/sessions/feature.ts +2 -4
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -1
- package/packages/bundled-features/src/shared/attachment-file-name.ts +39 -0
- package/packages/bundled-features/src/shared/index.ts +6 -0
- package/packages/bundled-features/src/shared/is-tenant-db.ts +1 -1
- package/packages/bundled-features/src/shared/mail-template-body.ts +25 -0
- package/packages/bundled-features/src/shared/sharp-input-limits.ts +26 -0
- package/packages/bundled-features/src/shared/signup-handover.ts +4 -4
- package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +5 -1
- package/packages/bundled-features/src/tags/web/tag-chip.tsx +2 -1
- package/packages/bundled-features/src/template-resolver/README.md +63 -7
- package/packages/bundled-features/src/template-resolver/api.ts +83 -8
- package/packages/bundled-features/src/template-resolver/changes.json +118 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +214 -0
- package/packages/bundled-features/src/template-resolver/constants.ts +39 -11
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +335 -0
- package/packages/bundled-features/src/template-resolver/document-schema.ts +323 -0
- package/packages/bundled-features/src/template-resolver/feature.ts +56 -6
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +188 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +30 -2
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +142 -0
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +72 -0
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +83 -0
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +3 -3
- package/packages/bundled-features/src/template-resolver/handlers/import-bundle-system.write.ts +42 -0
- package/packages/bundled-features/src/template-resolver/handlers/import-bundle.write.ts +22 -0
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +108 -0
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +5 -7
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +250 -0
- package/packages/bundled-features/src/template-resolver/handlers/preview.query.ts +25 -0
- package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +58 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-link-pdf.write.ts +34 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +50 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +24 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +135 -0
- package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +106 -0
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +32 -3
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +7 -2
- package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +184 -0
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +183 -0
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +55 -0
- package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +57 -10
- package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +19 -71
- package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +15 -76
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +17 -0
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +116 -0
- package/packages/bundled-features/src/template-resolver/index.ts +100 -0
- package/packages/bundled-features/src/template-resolver/layout-regions.ts +206 -0
- package/packages/bundled-features/src/template-resolver/linked-resources.ts +102 -0
- package/packages/bundled-features/src/template-resolver/preview-display-html.ts +36 -0
- package/packages/bundled-features/src/template-resolver/print-document.ts +58 -0
- package/packages/bundled-features/src/template-resolver/qualified-names.ts +30 -0
- package/packages/bundled-features/src/template-resolver/record-mapping.ts +26 -0
- package/packages/bundled-features/src/template-resolver/resource-image.ts +47 -0
- package/packages/bundled-features/src/template-resolver/seeding.ts +147 -17
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +416 -0
- package/packages/bundled-features/src/template-resolver/table.ts +14 -0
- package/packages/bundled-features/src/template-resolver/template-bundle.ts +79 -0
- package/packages/bundled-features/src/template-resolver/template-diff.ts +78 -0
- package/packages/bundled-features/src/template-resolver/template-meta.ts +129 -0
- package/packages/bundled-features/src/template-resolver/template-preview.ts +573 -0
- package/packages/bundled-features/src/template-resolver/template-resources.ts +74 -0
- package/packages/bundled-features/src/template-resolver/template-usage.ts +48 -0
- package/packages/bundled-features/src/template-resolver/template-validation.ts +229 -0
- package/packages/bundled-features/src/template-resolver/testing.ts +5 -5
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +9 -6
- package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +162 -0
- package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +28 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +850 -0
- package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +61 -0
- package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +26 -0
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +100 -0
- package/packages/bundled-features/src/template-resolver/web/index.ts +19 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +36 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +169 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-text.ts +37 -0
- package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +14 -0
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +3 -2
- package/packages/bundled-features/src/tenant/seeding.ts +41 -7
- package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +2 -1
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +4 -4
- package/packages/bundled-features/src/user/handlers/detail.query.ts +3 -5
- package/packages/bundled-features/src/user/roles-input-schema.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/changes.json +7 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/email-templates.ts +5 -149
- package/packages/bundled-features/src/user-data-rights/feature.ts +72 -35
- package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +2 -1
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +5 -11
- package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +134 -53
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +157 -0
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +2 -1
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -1
- package/packages/bundled-features/src/waitlist/changes.json +7 -0
- package/packages/bundled-features/src/waitlist/feature.ts +17 -0
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +4 -5
- package/packages/bundled-features/src/waitlist/mail.ts +69 -18
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +1 -2
- package/samples/apps/ui-walkthrough/package.json +2 -0
- package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +9 -0
- package/samples/apps/ui-walkthrough/src/app/client.tsx +6 -0
- package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +154 -0
- package/samples/apps/ui-walkthrough/src/app/server.ts +5 -1
- package/samples/apps/ui-walkthrough/src/app/shell.tsx +12 -1
- package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +354 -0
- package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +68 -0
- package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +18 -0
- package/samples/apps/ui-walkthrough/src/features/billing/index.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/billing/web/index.ts +7 -0
- package/samples/apps/ui-walkthrough/src/run-config.ts +37 -1
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +0 -2
- package/samples/apps/use-all-bundled/feature-manifest.json +115 -20
- package/samples/apps/use-all-bundled/kumiko/migrations/0045_template-resource-meta.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0046_pdf-rendered.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/package.json +2 -0
- package/samples/apps/use-all-bundled/playwright.config.ts +38 -3
- package/samples/apps/use-all-bundled/schema/generate.ts +13 -3
- package/samples/apps/use-all-bundled/schema/schema.generated.ts +3 -0
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +3 -0
- package/samples/apps/use-all-bundled/src/app/auth-constants.ts +3 -0
- package/samples/apps/use-all-bundled/src/app/client.tsx +4 -0
- package/samples/apps/use-all-bundled/src/app/seed-documents.ts +128 -0
- package/samples/apps/use-all-bundled/src/app/seed.ts +4 -0
- package/samples/apps/use-all-bundled/src/run-config.ts +11 -11
- package/samples/recipes/delivery-notifications/README.md +26 -25
- package/samples/recipes/delivery-notifications/package.json +2 -1
- package/samples/recipes/delivery-notifications/src/feature.ts +64 -58
- package/samples/recipes/seed-migration/README.md +1 -1
- package/packages/bundled-features/src/renderer-simple/changes.json +0 -27
- package/packages/bundled-features/src/renderer-simple/feature.ts +0 -66
- package/packages/bundled-features/src/renderer-simple/index.ts +0 -8
- package/packages/bundled-features/src/renderer-simple/mail-blocks.ts +0 -138
- package/packages/bundled-features/src/renderer-simple/resolve-variables.ts +0 -57
- package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +0 -304
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-samples",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.363.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": "BUSL-1.1",
|
|
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.363.0",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -115,7 +115,6 @@
|
|
|
115
115
|
"./channel-discord": "./src/channel-discord/index.ts",
|
|
116
116
|
"./channel-teams": "./src/channel-teams/index.ts",
|
|
117
117
|
"./channel-telegram": "./src/channel-telegram/index.ts",
|
|
118
|
-
"./renderer-simple": "./src/renderer-simple/index.ts",
|
|
119
118
|
"./renderer-pdf": "./src/renderer-pdf/index.ts",
|
|
120
119
|
"./files-provider-s3": "./src/files-provider-s3/index.ts",
|
|
121
120
|
"./rate-limiting": "./src/rate-limiting/index.ts",
|
|
@@ -131,6 +130,7 @@
|
|
|
131
130
|
"./feature-toggles": "./src/feature-toggles/index.ts",
|
|
132
131
|
"./feature-toggles/web": "./src/feature-toggles/web/index.ts",
|
|
133
132
|
"./template-resolver": "./src/template-resolver/index.ts",
|
|
133
|
+
"./template-resolver/document-schema": "./src/template-resolver/document-schema.ts",
|
|
134
134
|
"./template-resolver/seeding": "./src/template-resolver/seeding.ts",
|
|
135
135
|
"./template-resolver/testing": "./src/template-resolver/testing.ts",
|
|
136
136
|
"./template-resolver/web": "./src/template-resolver/web/index.ts",
|
|
@@ -156,9 +156,19 @@
|
|
|
156
156
|
"@cosmicdrift/kumiko-types": "workspace:*",
|
|
157
157
|
"@mollie/api-client": "^4.5.0",
|
|
158
158
|
"@node-rs/argon2": "^2.0.2",
|
|
159
|
+
"@tiptap/core": "3.31.3",
|
|
160
|
+
"@tiptap/extension-link": "3.31.3",
|
|
161
|
+
"@tiptap/extension-list": "3.31.3",
|
|
162
|
+
"@tiptap/extension-table": "3.31.3",
|
|
163
|
+
"@tiptap/html": "3.31.3",
|
|
164
|
+
"@tiptap/extensions": "3.31.3",
|
|
165
|
+
"@tiptap/pm": "3.31.3",
|
|
166
|
+
"@tiptap/react": "3.31.3",
|
|
167
|
+
"@tiptap/starter-kit": "3.31.3",
|
|
159
168
|
"@types/mailparser": "^3.4.6",
|
|
160
169
|
"@types/qrcode": "^1.5.5",
|
|
161
170
|
"clsx": "^2.1.1",
|
|
171
|
+
"happy-dom": "^20.11.2",
|
|
162
172
|
"hono": "^4.13.1",
|
|
163
173
|
"imapflow": "^1.7.8",
|
|
164
174
|
"ioredis": "^5.10.1",
|
|
@@ -553,10 +563,6 @@
|
|
|
553
563
|
"types": "./dist/channel-telegram/index.d.ts",
|
|
554
564
|
"default": "./dist/channel-telegram/index.js"
|
|
555
565
|
},
|
|
556
|
-
"./renderer-simple": {
|
|
557
|
-
"types": "./dist/renderer-simple/index.d.ts",
|
|
558
|
-
"default": "./dist/renderer-simple/index.js"
|
|
559
|
-
},
|
|
560
566
|
"./renderer-pdf": {
|
|
561
567
|
"types": "./dist/renderer-pdf/index.d.ts",
|
|
562
568
|
"default": "./dist/renderer-pdf/index.js"
|
|
@@ -617,6 +623,10 @@
|
|
|
617
623
|
"types": "./dist/template-resolver/index.d.ts",
|
|
618
624
|
"default": "./dist/template-resolver/index.js"
|
|
619
625
|
},
|
|
626
|
+
"./template-resolver/document-schema": {
|
|
627
|
+
"types": "./dist/template-resolver/document-schema.d.ts",
|
|
628
|
+
"default": "./dist/template-resolver/document-schema.js"
|
|
629
|
+
},
|
|
620
630
|
"./template-resolver/seeding": {
|
|
621
631
|
"types": "./dist/template-resolver/seeding.d.ts",
|
|
622
632
|
"default": "./dist/template-resolver/seeding.js"
|
|
@@ -689,6 +699,7 @@
|
|
|
689
699
|
"@testing-library/user-event": "^14.6.1",
|
|
690
700
|
"@cosmicdrift/kumiko-locale-de": "workspace:*",
|
|
691
701
|
"@cosmicdrift/kumiko-locale-es": "workspace:*",
|
|
702
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "workspace:*",
|
|
692
703
|
"jsqr": "^1.4.0",
|
|
693
704
|
"unpdf": "^1.8.1"
|
|
694
705
|
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.363.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "includeDocumentDesigner lists the template navs in the admin workspaces",
|
|
6
|
+
"detail": "With includeDocumentDesigner, the tenant workspace shows document-designer:nav:templates and the platform workspace document-designer:nav:platform-templates. The option requires the document-designer feature and defaults to false."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.330.0",
|
|
4
10
|
"type": "breaking",
|
|
@@ -36,6 +36,9 @@ export type CreateAdminShellOptions = {
|
|
|
36
36
|
* Requires cap-overview mounted. Default false — apps that don't mount cap-overview
|
|
37
37
|
* must not get a nav entry pointing at a screen that doesn't exist. */
|
|
38
38
|
readonly includeCapOverview?: boolean;
|
|
39
|
+
/** Tenant nav → document-designer:nav:templates, platform nav → document-designer:nav:platform-templates.
|
|
40
|
+
* Requires document-designer mounted (a separate package, so no import here). Default false. */
|
|
41
|
+
readonly includeDocumentDesigner?: boolean;
|
|
39
42
|
/** When false, only overview screens + nav are registered — app owns r.workspace(). Default true. */
|
|
40
43
|
readonly registerWorkspaces?: boolean;
|
|
41
44
|
/** Metric list the overview panels are built from — pass the SAME list to
|
|
@@ -49,12 +52,13 @@ export function createAdminShellFeature(options: CreateAdminShellOptions = {}):
|
|
|
49
52
|
const platformWsId = options.workspaceIds?.platform ?? DEFAULT_PLATFORM_WORKSPACE_ID;
|
|
50
53
|
const includeTierAdmin = options.includeTierAdmin ?? true;
|
|
51
54
|
const includeCapOverview = options.includeCapOverview ?? false;
|
|
55
|
+
const includeDocumentDesigner = options.includeDocumentDesigner ?? false;
|
|
52
56
|
const registerWorkspaces = options.registerWorkspaces ?? true;
|
|
53
57
|
const metrics = options.metrics ?? DEFAULT_METRICS;
|
|
54
58
|
|
|
55
59
|
return defineFeature(ADMIN_SHELL_FEATURE, (r) => {
|
|
56
60
|
r.describe(
|
|
57
|
-
"Registers tenant-admin and platform-admin workspaces with provider nav into owner-feature screens (`tenant:screen:members`, `audit:screen:audit-log`, `tenant:screen:tenant-list`, `jobs:screen:job-runs`, optional `tier-engine:screen:tier-admin`, optional `cap-overview:screen:my-caps`/`cap-overview:screen:tenant-cap-list`) and the two overview dashboards, built from the metrics list (`metrics` option, default DEFAULT_METRICS). Mount after user, tenant, audit, jobs, metrics and metrics-system; pass `workspaceIds` to match app URL conventions (e.g. Studio `d`/`s`, PublicStatus `admin`/`sysadmin`). Client: `adminShellClient()`, `tenantClient()`, `auditClient()`, `jobsClient()`, optional `tierEngineClient()`.",
|
|
61
|
+
"Registers tenant-admin and platform-admin workspaces with provider nav into owner-feature screens (`tenant:screen:members`, `audit:screen:audit-log`, `tenant:screen:tenant-list`, `jobs:screen:job-runs`, optional `tier-engine:screen:tier-admin`, optional `cap-overview:screen:my-caps`/`cap-overview:screen:tenant-cap-list`, optional `document-designer` template navs) and the two overview dashboards, built from the metrics list (`metrics` option, default DEFAULT_METRICS). Mount after user, tenant, audit, jobs, metrics and metrics-system; pass `workspaceIds` to match app URL conventions (e.g. Studio `d`/`s`, PublicStatus `admin`/`sysadmin`). Client: `adminShellClient()`, `tenantClient()`, `auditClient()`, `jobsClient()`, optional `tierEngineClient()`.",
|
|
58
62
|
);
|
|
59
63
|
r.uiHints({
|
|
60
64
|
displayLabel: "Admin Shell",
|
|
@@ -69,6 +73,7 @@ export function createAdminShellFeature(options: CreateAdminShellOptions = {}):
|
|
|
69
73
|
r.requires("metrics-system");
|
|
70
74
|
if (includeTierAdmin) r.requires("tier-engine");
|
|
71
75
|
if (includeCapOverview) r.requires("cap-overview");
|
|
76
|
+
if (includeDocumentDesigner) r.requires("document-designer");
|
|
72
77
|
|
|
73
78
|
r.translations({ keys: ADMIN_SHELL_I18N });
|
|
74
79
|
|
|
@@ -77,12 +82,14 @@ export function createAdminShellFeature(options: CreateAdminShellOptions = {}):
|
|
|
77
82
|
"tenant:nav:members",
|
|
78
83
|
"audit:nav:audit-log",
|
|
79
84
|
...(includeCapOverview ? (["admin-shell:nav:my-caps"] as const) : []),
|
|
85
|
+
...(includeDocumentDesigner ? (["document-designer:nav:templates"] as const) : []),
|
|
80
86
|
];
|
|
81
87
|
const platformNav: string[] = [
|
|
82
88
|
"admin-shell:nav:platform-overview",
|
|
83
89
|
"admin-shell:nav:tenants",
|
|
84
90
|
...(includeCapOverview ? (["admin-shell:nav:tenant-caps"] as const) : []),
|
|
85
91
|
"jobs:nav:job-runs",
|
|
92
|
+
...(includeDocumentDesigner ? (["document-designer:nav:platform-templates"] as const) : []),
|
|
86
93
|
...(includeTierAdmin ? (["admin-shell:nav:tier-admin"] as const) : []),
|
|
87
94
|
];
|
|
88
95
|
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
SYSTEM_ONLY_JSON_SCHEMA_KEY,
|
|
19
19
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
20
20
|
import { translationValueOtherText } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
21
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
21
22
|
import * as z from "zod";
|
|
22
23
|
import { recordManifestDenyQns } from "./manifest-deny-qns.js";
|
|
23
24
|
import type {
|
|
@@ -199,7 +200,7 @@ export function systemOnlyPropertyNames(jsonSchema: Record<string, unknown>): re
|
|
|
199
200
|
if (typeof properties !== "object" || properties === null) return [];
|
|
200
201
|
return Object.entries(properties)
|
|
201
202
|
.filter(
|
|
202
|
-
([, property]) => (property
|
|
203
|
+
([, property]) => isPlainObject(property) && property[SYSTEM_ONLY_JSON_SCHEMA_KEY] === true,
|
|
203
204
|
)
|
|
204
205
|
.map(([name]) => name);
|
|
205
206
|
}
|
|
@@ -243,9 +244,7 @@ function buildHandlerEntry(
|
|
|
243
244
|
// A handler whose schema can't be expressed as JSON Schema (transforms,
|
|
244
245
|
// z.instanceof, ...) is unusable for an agent tool call — leave it out
|
|
245
246
|
// rather than ship a broken tool.
|
|
246
|
-
inputSchema = withoutSystemOnlyProperties(
|
|
247
|
-
z.toJSONSchema(def.schema, { io: "input" }) as Record<string, unknown>,
|
|
248
|
-
);
|
|
247
|
+
inputSchema = withoutSystemOnlyProperties(z.toJSONSchema(def.schema, { io: "input" }));
|
|
249
248
|
} catch {
|
|
250
249
|
return undefined;
|
|
251
250
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
export const FILTER_OPS = ["eq", "ne", "lt", "gt", "lte", "gte", "in"] as const;
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
-
}
|
|
3
|
+
export { isPlainObject as isRecord } from "@cosmicdrift/kumiko-types/type-guards";
|
|
@@ -137,9 +137,7 @@ function addToolsForListHandler(
|
|
|
137
137
|
addTool(sink, tool, { kind: "search", entityName, qn });
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
for (const [fieldName, field] of Object.entries(
|
|
141
|
-
entity.fields as Record<string, FieldDefinition>,
|
|
142
|
-
)) {
|
|
140
|
+
for (const [fieldName, field] of Object.entries(entity.fields)) {
|
|
143
141
|
if (!isFilterable(field) || !isReadableWithoutRowCondition(field, roles)) continue;
|
|
144
142
|
const fieldSchema = jsonSchemaTypeForField(field);
|
|
145
143
|
if (!fieldSchema) continue;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SessionUser, WriteResult } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { runAsDirectCallEntry } from "@cosmicdrift/kumiko-framework/internal/request-context";
|
|
3
|
+
import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
3
4
|
import { FILTER_OPS, isRecord } from "./filter-ops.js";
|
|
4
5
|
import type { ToolDispatchDescriptor } from "./types.js";
|
|
5
6
|
|
|
@@ -48,7 +49,7 @@ type PayloadResult =
|
|
|
48
49
|
| { readonly ok: false; readonly error: string };
|
|
49
50
|
|
|
50
51
|
function isFilterOp(value: unknown): value is FilterOp {
|
|
51
|
-
return
|
|
52
|
+
return isOneOf(FILTER_OPS, value);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
function buildSearchPayload(
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.363.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "AuthMailContent is removed",
|
|
6
|
+
"detail": "The sections-based content type only fed the retired renderer-simple. Auth mails are template notifications with variables, so nothing builds or consumes AuthMailContent anymore.",
|
|
7
|
+
"migration": "Drop AuthMailContent imports; the auth mail text lives in the seeded templates and is overridden per tenant in the template editor."
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"version": "0.363.0",
|
|
11
|
+
"type": "breaking",
|
|
12
|
+
"title": "Auth mails are notifications with seeded templates, render*Email is gone",
|
|
13
|
+
"detail": "password-reset, account-unlock, email-verification, signup-activation and invite are declared as r.notification with a localized template and variables, seeded as system templates at boot and rendered by renderer-mail-html, so a tenant can override the text in the template editor. A locale without its own subject key falls back to en, because the renderer has no locale fallback. AuthMailNotificationTypes is exported for the qualified names.",
|
|
14
|
+
"migration": "The notification types are now `auth-email-password:notify:<name>` (before: the plain names). Update delivery preferences, preference rows and tests that reference the old names. renderResetPasswordEmail, renderUnlockAccountEmail, renderVerifyEmail, renderActivationEmail, renderInviteEmail, AuthMailSection, RenderTokenContentArgs and RenderInviteEmailArgs are removed; AuthMailContent stays. An app that mounts auth-email-password now needs template-resolver, renderer-foundation and @cosmicdrift/kumiko-renderer-mail-html (composeRendererStack() from dev-server mounts all of them; with includeBundled, composeFeatures adds whichever is missing). Boot fails with a clear error otherwise, and apps without the template tables need a schema migration (`kumiko schema generate`). kumiko-schema-check counts the three as implicit features of every HAS_AUTH app, so its check fails until that migration exists. Tests that read the token from a mail use the text part (`mail.text`); the html part encodes `=` as `=`."
|
|
15
|
+
},
|
|
2
16
|
{
|
|
3
17
|
"version": "0.354.0",
|
|
4
18
|
"type": "breaking",
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// renderer-simple turns it into HTML. Apps wanting their own branding swap the
|
|
5
|
-
// renderer; these templates are deliberately plain so the renderer (and the
|
|
6
|
-
// operator reading the mailer log) can rely on them.
|
|
1
|
+
// English texts and expiry formatting for the transactional auth mails. The
|
|
2
|
+
// mail bodies are built from these keys into stored templates (see
|
|
3
|
+
// mail-notifications.ts).
|
|
7
4
|
//
|
|
8
5
|
// English ships here. Other languages register via @cosmicdrift/kumiko-locale-*
|
|
9
6
|
// (localeDe() / localeEs() call registerMailTranslations).
|
|
10
7
|
|
|
11
|
-
import {
|
|
8
|
+
import { registerMailTranslations } from "@cosmicdrift/kumiko-framework/i18n";
|
|
12
9
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
13
10
|
|
|
14
11
|
export type AuthMailLocale = string;
|
|
@@ -56,138 +53,14 @@ export const AUTH_MAIL_EN: Readonly<Record<string, string>> = {
|
|
|
56
53
|
|
|
57
54
|
registerMailTranslations("en", AUTH_MAIL_EN);
|
|
58
55
|
|
|
59
|
-
export type
|
|
60
|
-
readonly url: string;
|
|
56
|
+
export type TokenMailTiming = {
|
|
61
57
|
readonly expiresAt: string;
|
|
62
|
-
readonly locale?: AuthMailLocale;
|
|
63
|
-
/** Optional app name for subject + intro. Default from auth.mail.appNameDefault. */
|
|
64
|
-
readonly appName?: string;
|
|
65
58
|
/** ISO instant the token was issued; the validity duration is measured from it. Default: now. */
|
|
66
59
|
readonly issuedAt?: string;
|
|
67
60
|
/** IANA zone the expiry time is shown in. Default "UTC"; an invalid zone falls back to "UTC". */
|
|
68
61
|
readonly timeZone?: string;
|
|
69
62
|
};
|
|
70
63
|
|
|
71
|
-
export type RenderInviteEmailArgs = RenderTokenContentArgs & { readonly role: string };
|
|
72
|
-
|
|
73
|
-
export type AuthMailSection =
|
|
74
|
-
| { readonly text: string }
|
|
75
|
-
| { readonly button: { readonly label: string; readonly url: string } };
|
|
76
|
-
|
|
77
|
-
export type AuthMailContent = {
|
|
78
|
-
readonly subject: string;
|
|
79
|
-
readonly header: string;
|
|
80
|
-
readonly sections: readonly AuthMailSection[];
|
|
81
|
-
readonly footer: string;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
function tokenMailContent(spec: {
|
|
85
|
-
readonly subject: string;
|
|
86
|
-
readonly header: string;
|
|
87
|
-
readonly greeting: string;
|
|
88
|
-
readonly intro: string;
|
|
89
|
-
readonly buttonLabel: string;
|
|
90
|
-
readonly buttonUrl: string;
|
|
91
|
-
readonly expiry: string;
|
|
92
|
-
readonly ignore: string;
|
|
93
|
-
}): AuthMailContent {
|
|
94
|
-
return {
|
|
95
|
-
subject: spec.subject,
|
|
96
|
-
header: spec.header,
|
|
97
|
-
sections: [
|
|
98
|
-
{ text: spec.greeting },
|
|
99
|
-
{ text: spec.intro },
|
|
100
|
-
{ button: { label: spec.buttonLabel, url: spec.buttonUrl } },
|
|
101
|
-
{ text: spec.expiry },
|
|
102
|
-
],
|
|
103
|
-
footer: spec.ignore,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function t(locale: string, key: string, params?: Readonly<Record<string, string>>): string {
|
|
108
|
-
return mailT(locale, key, params);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function appNameFor(args: RenderTokenContentArgs): string {
|
|
112
|
-
const locale = args.locale ?? "en";
|
|
113
|
-
return args.appName ?? t(locale, "auth.mail.appNameDefault");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function renderResetPasswordEmail(args: RenderTokenContentArgs): AuthMailContent {
|
|
117
|
-
const locale = args.locale ?? "en";
|
|
118
|
-
const app = appNameFor(args);
|
|
119
|
-
return tokenMailContent({
|
|
120
|
-
subject: t(locale, "auth.mail.reset.subject", { app }),
|
|
121
|
-
header: t(locale, "auth.mail.reset.button"),
|
|
122
|
-
greeting: t(locale, "auth.mail.reset.greeting"),
|
|
123
|
-
intro: t(locale, "auth.mail.reset.intro", { app }),
|
|
124
|
-
buttonLabel: t(locale, "auth.mail.reset.button"),
|
|
125
|
-
buttonUrl: args.url,
|
|
126
|
-
expiry: t(locale, "auth.mail.reset.expiry", expiryParams(args, locale)),
|
|
127
|
-
ignore: t(locale, "auth.mail.reset.ignore"),
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function renderUnlockAccountEmail(args: RenderTokenContentArgs): AuthMailContent {
|
|
132
|
-
const locale = args.locale ?? "en";
|
|
133
|
-
const app = appNameFor(args);
|
|
134
|
-
return tokenMailContent({
|
|
135
|
-
subject: t(locale, "auth.mail.unlock.subject", { app }),
|
|
136
|
-
header: t(locale, "auth.mail.unlock.button"),
|
|
137
|
-
greeting: t(locale, "auth.mail.unlock.greeting"),
|
|
138
|
-
intro: t(locale, "auth.mail.unlock.intro", { app }),
|
|
139
|
-
buttonLabel: t(locale, "auth.mail.unlock.button"),
|
|
140
|
-
buttonUrl: args.url,
|
|
141
|
-
expiry: t(locale, "auth.mail.unlock.expiry", expiryParams(args, locale)),
|
|
142
|
-
ignore: t(locale, "auth.mail.unlock.ignore"),
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export function renderVerifyEmail(args: RenderTokenContentArgs): AuthMailContent {
|
|
147
|
-
const locale = args.locale ?? "en";
|
|
148
|
-
const app = appNameFor(args);
|
|
149
|
-
return tokenMailContent({
|
|
150
|
-
subject: t(locale, "auth.mail.verify.subject", { app }),
|
|
151
|
-
header: t(locale, "auth.mail.verify.button"),
|
|
152
|
-
greeting: t(locale, "auth.mail.verify.greeting"),
|
|
153
|
-
intro: t(locale, "auth.mail.verify.intro", { app }),
|
|
154
|
-
buttonLabel: t(locale, "auth.mail.verify.button"),
|
|
155
|
-
buttonUrl: args.url,
|
|
156
|
-
expiry: t(locale, "auth.mail.verify.expiry", expiryParams(args, locale)),
|
|
157
|
-
ignore: t(locale, "auth.mail.verify.ignore"),
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function renderActivationEmail(args: RenderTokenContentArgs): AuthMailContent {
|
|
162
|
-
const locale = args.locale ?? "en";
|
|
163
|
-
const app = appNameFor(args);
|
|
164
|
-
return tokenMailContent({
|
|
165
|
-
subject: t(locale, "auth.mail.activation.subject", { app }),
|
|
166
|
-
header: t(locale, "auth.mail.activation.button"),
|
|
167
|
-
greeting: t(locale, "auth.mail.activation.greeting"),
|
|
168
|
-
intro: t(locale, "auth.mail.activation.intro", { app }),
|
|
169
|
-
buttonLabel: t(locale, "auth.mail.activation.button"),
|
|
170
|
-
buttonUrl: args.url,
|
|
171
|
-
expiry: t(locale, "auth.mail.activation.expiry", expiryParams(args, locale)),
|
|
172
|
-
ignore: t(locale, "auth.mail.activation.ignore"),
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export function renderInviteEmail(args: RenderInviteEmailArgs): AuthMailContent {
|
|
177
|
-
const locale = args.locale ?? "en";
|
|
178
|
-
const app = args.appName ?? "Workspace";
|
|
179
|
-
return tokenMailContent({
|
|
180
|
-
subject: t(locale, "auth.mail.invite.subject", { app }),
|
|
181
|
-
header: t(locale, "auth.mail.invite.button"),
|
|
182
|
-
greeting: t(locale, "auth.mail.invite.greeting"),
|
|
183
|
-
intro: t(locale, "auth.mail.invite.intro", { app, role: args.role }),
|
|
184
|
-
buttonLabel: t(locale, "auth.mail.invite.button"),
|
|
185
|
-
buttonUrl: args.url,
|
|
186
|
-
expiry: t(locale, "auth.mail.invite.expiry", expiryParams(args, locale)),
|
|
187
|
-
ignore: t(locale, "auth.mail.invite.ignore"),
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
64
|
const MS_PER_MINUTE = 60_000;
|
|
192
65
|
const MS_PER_HOUR = 60 * MS_PER_MINUTE;
|
|
193
66
|
const MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
@@ -241,18 +114,19 @@ function formatWhen(expiresAt: Temporal.Instant, locale: string, timeZone: strin
|
|
|
241
114
|
}
|
|
242
115
|
}
|
|
243
116
|
|
|
244
|
-
|
|
245
|
-
|
|
117
|
+
// Formatted as text here because the stored template only knows plain variables.
|
|
118
|
+
export function tokenMailExpiry(
|
|
119
|
+
args: TokenMailTiming,
|
|
246
120
|
locale: string,
|
|
247
|
-
): { readonly
|
|
121
|
+
): { readonly validFor: string; readonly validUntil: string } {
|
|
248
122
|
try {
|
|
249
123
|
const expiresAt = Temporal.Instant.from(args.expiresAt);
|
|
250
124
|
const issuedAt = args.issuedAt ? Temporal.Instant.from(args.issuedAt) : Temporal.Now.instant();
|
|
251
125
|
return {
|
|
252
|
-
|
|
253
|
-
|
|
126
|
+
validFor: formatDuration(expiresAt.epochMilliseconds - issuedAt.epochMilliseconds, locale),
|
|
127
|
+
validUntil: formatWhen(expiresAt, locale, args.timeZone ?? "UTC"),
|
|
254
128
|
};
|
|
255
129
|
} catch {
|
|
256
|
-
return {
|
|
130
|
+
return { validFor: args.expiresAt, validUntil: args.expiresAt };
|
|
257
131
|
}
|
|
258
132
|
}
|
|
@@ -30,6 +30,12 @@ import {
|
|
|
30
30
|
} from "./handlers/signup-request.write.js";
|
|
31
31
|
import { createSwitchTenantMfaGateHandler } from "./handlers/switch-tenant-mfa-gate.write.js";
|
|
32
32
|
import { createVerifyEmailHandler } from "./handlers/verify-email.write.js";
|
|
33
|
+
import {
|
|
34
|
+
AUTH_MAIL_VARIABLES,
|
|
35
|
+
authMailLocalizedTemplate,
|
|
36
|
+
INVITE_MAIL_VARIABLES,
|
|
37
|
+
sendsMagicLinkMail,
|
|
38
|
+
} from "./mail-notifications.js";
|
|
33
39
|
|
|
34
40
|
/**
|
|
35
41
|
* Env-vars contract for the `auth-email-password` feature.
|
|
@@ -199,17 +205,32 @@ export function createAuthEmailPasswordFeature(
|
|
|
199
205
|
// All five magic-link flows (reset/verify/signup/invite/unlock) dispatch
|
|
200
206
|
// via ctx.notify → delivery must be mounted. Fail closed at boot instead
|
|
201
207
|
// of silently dropping the mail.
|
|
202
|
-
if (
|
|
203
|
-
opts.passwordReset ||
|
|
204
|
-
opts.emailVerification ||
|
|
205
|
-
opts.signup ||
|
|
206
|
-
opts.invite ||
|
|
207
|
-
opts.accountUnlock
|
|
208
|
-
) {
|
|
209
|
-
r.requires("delivery");
|
|
210
|
-
}
|
|
208
|
+
if (sendsMagicLinkMail(opts)) r.requires("delivery");
|
|
211
209
|
r.envSchema(authEmailPasswordEnvSchema);
|
|
212
210
|
|
|
211
|
+
// Declared unconditionally: apps also issue the activation link from their
|
|
212
|
+
// own flows (issueSignupActivation) without enabling the signup option.
|
|
213
|
+
r.notification("password-reset", {
|
|
214
|
+
variables: AUTH_MAIL_VARIABLES,
|
|
215
|
+
localizedTemplate: authMailLocalizedTemplate("passwordReset"),
|
|
216
|
+
});
|
|
217
|
+
r.notification("account-unlock", {
|
|
218
|
+
variables: AUTH_MAIL_VARIABLES,
|
|
219
|
+
localizedTemplate: authMailLocalizedTemplate("accountUnlock"),
|
|
220
|
+
});
|
|
221
|
+
r.notification("email-verification", {
|
|
222
|
+
variables: AUTH_MAIL_VARIABLES,
|
|
223
|
+
localizedTemplate: authMailLocalizedTemplate("emailVerification"),
|
|
224
|
+
});
|
|
225
|
+
r.notification("signup-activation", {
|
|
226
|
+
variables: AUTH_MAIL_VARIABLES,
|
|
227
|
+
localizedTemplate: authMailLocalizedTemplate("signupActivation"),
|
|
228
|
+
});
|
|
229
|
+
r.notification("invite", {
|
|
230
|
+
variables: INVITE_MAIL_VARIABLES,
|
|
231
|
+
localizedTemplate: authMailLocalizedTemplate("invite"),
|
|
232
|
+
});
|
|
233
|
+
|
|
213
234
|
const handlers = {
|
|
214
235
|
login: r.writeHandler(
|
|
215
236
|
createLoginHandler({
|
|
@@ -55,12 +55,10 @@ import { GLOBAL_ROLE_OPTIONS } from "../../user/constants.js";
|
|
|
55
55
|
import { userTable } from "../../user/schema/user.js";
|
|
56
56
|
import { AUTH_INVITE_DEFAULT_TTL_MINUTES } from "../constants.js";
|
|
57
57
|
import type { AuthMailLocale } from "../email-templates.js";
|
|
58
|
-
import { renderInviteEmail } from "../email-templates.js";
|
|
59
58
|
import { inviteAlreadyAccepted } from "../errors.js";
|
|
60
59
|
import { invalidateExistingInviteToken, storeInviteToken } from "../invite-token-store.js";
|
|
61
60
|
import { dispatchMagicLinkMail, resolveHandlerMailLocale } from "../magic-link-mail.js";
|
|
62
|
-
|
|
63
|
-
const INVITE_NOTIFICATION_TYPE = "auth-email-password:invite";
|
|
61
|
+
import { AuthMailNotificationTypes } from "../mail-notifications.js";
|
|
64
62
|
|
|
65
63
|
type GlobalRole = (typeof GLOBAL_ROLE_OPTIONS)[number];
|
|
66
64
|
|
|
@@ -247,8 +245,8 @@ async function issueInvitation(
|
|
|
247
245
|
ctx.notify,
|
|
248
246
|
{
|
|
249
247
|
handlerName: "invite-create",
|
|
250
|
-
notificationType:
|
|
251
|
-
|
|
248
|
+
notificationType: AuthMailNotificationTypes.invite,
|
|
249
|
+
fallbackAppName: "Workspace",
|
|
252
250
|
},
|
|
253
251
|
{
|
|
254
252
|
email,
|
|
@@ -257,6 +255,7 @@ async function issueInvitation(
|
|
|
257
255
|
expiresAt: expiresAt.toString(),
|
|
258
256
|
issuedAt: issuedAt.toString(),
|
|
259
257
|
timeZone: ctx.tz.user,
|
|
258
|
+
role: request.role,
|
|
260
259
|
...(opts.appName !== undefined && { appName: opts.appName }),
|
|
261
260
|
locale,
|
|
262
261
|
},
|
package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AUTH_UNLOCK_DEFAULT_TTL_MINUTES, AuthErrors } from "../constants.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AuthMailNotificationTypes } from "../mail-notifications.js";
|
|
3
3
|
import { signUnlockToken } from "../unlock-token.js";
|
|
4
4
|
import {
|
|
5
5
|
createTokenRequestHandler,
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
type TokenRequestOptions,
|
|
8
8
|
} from "./token-request-handler.js";
|
|
9
9
|
|
|
10
|
-
const UNLOCK_NOTIFICATION_TYPE = "auth-email-password:account-unlock";
|
|
11
|
-
|
|
12
10
|
export type RequestAccountUnlockOptions = TokenRequestOptions;
|
|
13
11
|
|
|
14
12
|
// Public shape re-exported for callers that build custom routes on top of
|
|
@@ -32,8 +30,7 @@ export function createRequestAccountUnlockHandler(opts: RequestAccountUnlockOpti
|
|
|
32
30
|
// locked right now. Confirming just clears the (possibly already
|
|
33
31
|
// empty) lockout state — harmless no-op if they weren't locked.
|
|
34
32
|
extraSilentSkip: () => false,
|
|
35
|
-
notificationType:
|
|
36
|
-
renderContent: renderUnlockAccountEmail,
|
|
33
|
+
notificationType: AuthMailNotificationTypes.accountUnlock,
|
|
37
34
|
},
|
|
38
35
|
opts,
|
|
39
36
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AUTH_VERIFY_DEFAULT_TTL_MINUTES, AuthErrors } from "../constants.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AuthMailNotificationTypes } from "../mail-notifications.js";
|
|
3
3
|
import { signVerificationToken } from "../verification-token.js";
|
|
4
4
|
import {
|
|
5
5
|
createTokenRequestHandler,
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
type TokenRequestOptions,
|
|
8
8
|
} from "./token-request-handler.js";
|
|
9
9
|
|
|
10
|
-
const VERIFY_NOTIFICATION_TYPE = "auth-email-password:email-verification";
|
|
11
|
-
|
|
12
10
|
export type RequestEmailVerificationOptions = TokenRequestOptions;
|
|
13
11
|
|
|
14
12
|
export type RequestVerificationData = TokenRequestData<"verification-requested">;
|
|
@@ -29,8 +27,7 @@ export function createRequestEmailVerificationHandler(opts: RequestEmailVerifica
|
|
|
29
27
|
// unknown/deleted to keep the enumeration surface symmetric — the
|
|
30
28
|
// caller sees the same 200 regardless of whether a token was minted.
|
|
31
29
|
extraSilentSkip: (user) => user.emailVerified === true,
|
|
32
|
-
notificationType:
|
|
33
|
-
renderContent: renderVerifyEmail,
|
|
30
|
+
notificationType: AuthMailNotificationTypes.emailVerification,
|
|
34
31
|
},
|
|
35
32
|
opts,
|
|
36
33
|
);
|
package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AUTH_RESET_DEFAULT_TTL_MINUTES, AuthErrors } from "../constants.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AuthMailNotificationTypes } from "../mail-notifications.js";
|
|
3
3
|
import { signResetToken } from "../reset-token.js";
|
|
4
4
|
import {
|
|
5
5
|
createTokenRequestHandler,
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
type TokenRequestOptions,
|
|
8
8
|
} from "./token-request-handler.js";
|
|
9
9
|
|
|
10
|
-
const RESET_NOTIFICATION_TYPE = "auth-email-password:password-reset";
|
|
11
|
-
|
|
12
10
|
export type RequestPasswordResetOptions = TokenRequestOptions;
|
|
13
11
|
|
|
14
12
|
// Public shape re-exported for callers that build custom routes on top of
|
|
@@ -31,8 +29,7 @@ export function createRequestPasswordResetHandler(opts: RequestPasswordResetOpti
|
|
|
31
29
|
// non-deleted user can initiate a reset regardless of verification
|
|
32
30
|
// state. The sessions feature handles the post-change revocation.
|
|
33
31
|
extraSilentSkip: () => false,
|
|
34
|
-
notificationType:
|
|
35
|
-
renderContent: renderResetPasswordEmail,
|
|
32
|
+
notificationType: AuthMailNotificationTypes.passwordReset,
|
|
36
33
|
},
|
|
37
34
|
opts,
|
|
38
35
|
);
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
37
37
|
import { generateUniqueName } from "@cosmicdrift/kumiko-framework/random";
|
|
38
38
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
39
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
39
40
|
import * as z from "zod";
|
|
40
41
|
import {
|
|
41
42
|
findSignupHandoverProvider,
|
|
@@ -100,10 +101,8 @@ const SIGNUP_CONFIRM_PROVISION_REASON =
|
|
|
100
101
|
// match; this reads the same field the framework itself uses.
|
|
101
102
|
function isBenignClaimRejection(error: WriteErrorInfo): boolean {
|
|
102
103
|
return (
|
|
103
|
-
|
|
104
|
-
error.details
|
|
105
|
-
(error.details as Record<string, unknown>)["reason"] ===
|
|
106
|
-
SIGNUP_HANDOVER_BENIGN_CLAIM_REJECTION_CODE
|
|
104
|
+
isPlainObject(error.details) &&
|
|
105
|
+
error.details["reason"] === SIGNUP_HANDOVER_BENIGN_CLAIM_REJECTION_CODE
|
|
107
106
|
);
|
|
108
107
|
}
|
|
109
108
|
|
|
@@ -19,11 +19,7 @@ import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
|
19
19
|
import * as z from "zod";
|
|
20
20
|
import { UserQueries } from "../../user/index.js";
|
|
21
21
|
import { type AuthUserRow, parseAuthUserRow } from "../auth-user-row.js";
|
|
22
|
-
import type {
|
|
23
|
-
AuthMailContent,
|
|
24
|
-
AuthMailLocale,
|
|
25
|
-
RenderTokenContentArgs,
|
|
26
|
-
} from "../email-templates.js";
|
|
22
|
+
import type { AuthMailLocale } from "../email-templates.js";
|
|
27
23
|
import { dispatchMagicLinkMail, resolveHandlerMailLocale } from "../magic-link-mail.js";
|
|
28
24
|
|
|
29
25
|
const RequestTokenSchema = z.object({
|
|
@@ -67,13 +63,9 @@ export type TokenRequestSpec<TName extends string, TSuccessKind extends string>
|
|
|
67
63
|
// soft-deleted". Verification skips when emailVerified is already true;
|
|
68
64
|
// password-reset has no extra condition (returns false).
|
|
69
65
|
readonly extraSilentSkip: (user: AuthUserRow) => boolean;
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
// route:{email} path delivers directly and buildMessage falls back to data.
|
|
66
|
+
// Trigger-less r.notification dispatched via ctx.notify on success; the
|
|
67
|
+
// recipient is an anonymous email, so route:{email} delivers directly.
|
|
73
68
|
readonly notificationType: string;
|
|
74
|
-
// Builds the structured mail body from the magic-link + expiry. Per-flow
|
|
75
|
-
// (renderResetPasswordEmail / renderVerifyEmail).
|
|
76
|
-
readonly renderContent: (args: RenderTokenContentArgs) => AuthMailContent;
|
|
77
69
|
};
|
|
78
70
|
|
|
79
71
|
export type TokenRequestOptions = {
|
|
@@ -154,7 +146,6 @@ export function createTokenRequestHandler<TName extends string, TSuccessKind ext
|
|
|
154
146
|
{
|
|
155
147
|
handlerName: spec.handlerName,
|
|
156
148
|
notificationType: spec.notificationType,
|
|
157
|
-
renderContent: spec.renderContent,
|
|
158
149
|
},
|
|
159
150
|
{
|
|
160
151
|
// Row value is ciphertext with an active KMS; the byte-exact
|