@cosmicdrift/kumiko-bundled-features 0.385.0 → 0.387.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/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.js +0 -2
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -9,7 +9,7 @@ import { createEntity, createLongTextField, createTextField, } from "@cosmicdrif
|
|
|
9
9
|
// Strictly append-only by design: no update/delete write-handler is
|
|
10
10
|
// registered (see feature.ts). A correction is a new entry, not an edit —
|
|
11
11
|
// that is the whole point of a note *history* instead of the single
|
|
12
|
-
// overwritable textarea this bundle replaces
|
|
12
|
+
// overwritable textarea this bundle replaces.
|
|
13
13
|
//
|
|
14
14
|
// `body` is about the HOST entity (entityType/entityId), not the author — the
|
|
15
15
|
// author is never the data subject of a note's content, so it is deliberately
|
|
@@ -18,7 +18,7 @@ import { createEntity, createLongTextField, createTextField, } from "@cosmicdrif
|
|
|
18
18
|
// employee leaving triggers a forget), garbling unrelated business notes
|
|
19
19
|
// about customers/projects/etc. — data loss, not privacy.
|
|
20
20
|
//
|
|
21
|
-
// `body` is instead `personal: { of: "id" }` (Row-Subject
|
|
21
|
+
// `body` is instead `personal: { of: "id" }` (Row-Subject):
|
|
22
22
|
// the note's OWN row is its content's subject, so `body` is encrypted under a
|
|
23
23
|
// per-note key that nothing else shares. That key gets erased only when the
|
|
24
24
|
// note is reached by a forgotten subject: `note-mention` (below) names the
|
|
@@ -28,7 +28,7 @@ import { createEntity, createLongTextField, createTextField, } from "@cosmicdrif
|
|
|
28
28
|
// shreds `authorName` (`personal: { of: "authorId" }`, the name as stamped at
|
|
29
29
|
// write time); the two erasures are independent.
|
|
30
30
|
//
|
|
31
|
-
// Known gap (
|
|
31
|
+
// Known gap (not fixed by this entity): prose that names a third
|
|
32
32
|
// party without a structured @-mention is not tracked — regex/NLP over
|
|
33
33
|
// free text is unreliable. An operator must erase such a note's own record
|
|
34
34
|
// subject (`forget-subject` kind "record", entity "note-entry") to cover it.
|
|
@@ -76,7 +76,7 @@ export function createNoteEntryEntity(access, parents) {
|
|
|
76
76
|
body: createLongTextField({
|
|
77
77
|
required: true,
|
|
78
78
|
maxLength: 20_000,
|
|
79
|
-
// Row-Subject
|
|
79
|
+
// Row-Subject: the note itself is the subject, so its
|
|
80
80
|
// key is erased per-note via `note-mention` lookups, not tied to any
|
|
81
81
|
// user's own forget.
|
|
82
82
|
personal: { of: "id" },
|
|
@@ -13,8 +13,8 @@ export type NotesHistoryFeatureOptions = {
|
|
|
13
13
|
/** Row-level ownership on the note-entry rows themselves — orthogonal to
|
|
14
14
|
* `access`, which only gates whether a caller may dispatch create/list at
|
|
15
15
|
* all. `ownership.read` is no longer what keeps a caller from reading notes
|
|
16
|
-
* on host entities they can't see: that gate is default-on
|
|
17
|
-
*
|
|
16
|
+
* on host entities they can't see: that gate is default-on and derives from
|
|
17
|
+
* the entity's `parentRef`. Use `ownership.read` for an
|
|
18
18
|
* ADDITIONAL row rule on the note row itself (e.g. author-only visibility);
|
|
19
19
|
* it is AND-ed with the host-visibility gate, never a replacement for it.
|
|
20
20
|
*
|
|
@@ -51,7 +51,7 @@ async function selectNotesReachingSubject(db, subject) {
|
|
|
51
51
|
// (entity.ts), so forgetting the AUTHOR already crypto-shreds that field on
|
|
52
52
|
// its own. `body` is Row-Subject (`personal: { of: "id" }`): its key is per
|
|
53
53
|
// note, so forgetting a subject only reaches a body when the note structurally
|
|
54
|
-
// @-mentions the subject (`note-mention
|
|
54
|
+
// @-mentions the subject (`note-mention`) or hangs on it as host.
|
|
55
55
|
// Free-text mentions are NOT detected — the documented gap in entity.ts.
|
|
56
56
|
//
|
|
57
57
|
// Reached bodies are shredded regardless of the host entity's retention strategy:
|
|
@@ -33,18 +33,18 @@ export function tenantStyleBlock(customCss) {
|
|
|
33
33
|
const sanitized = sanitizeTenantCss(customCss, TENANT_SCOPE);
|
|
34
34
|
if (!sanitized)
|
|
35
35
|
return "";
|
|
36
|
-
// html-ok: sanitizeTenantCss
|
|
36
|
+
// html-ok: sanitizeTenantCss is the escaping boundary (allowlist, strips `<`).
|
|
37
37
|
return `\n<style data-tenant-css>${TENANT_CONTAINMENT}\n${TENANT_CLIP}\n${sanitized}</style>`;
|
|
38
38
|
}
|
|
39
|
-
//
|
|
40
|
-
// server-
|
|
41
|
-
//
|
|
42
|
-
//
|
|
39
|
+
// Minimal HTML5 skeleton with inline CSS — the default `wrapLayout` for
|
|
40
|
+
// server-rendered public pages, so they look clean without an app layout.
|
|
41
|
+
// Apps that want to wrap the body in their own marketing layout
|
|
42
|
+
// (header/footer/theme) pass their own render function.
|
|
43
43
|
//
|
|
44
|
-
// Branding (optional):
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
44
|
+
// Branding (optional): emits a scoped `:root` override after the base
|
|
45
|
+
// `<style>` (accent color, layout preset → max-width) and a logo/title header.
|
|
46
|
+
// All branding values are tenant-supplied and untrusted; branding.ts
|
|
47
|
+
// revalidates/escapes them before they enter the markup.
|
|
48
48
|
export function wrapInLayout(opts) {
|
|
49
49
|
const themeStyleHtml = opts.branding ? brandingStyleBlock(opts.branding) : "";
|
|
50
50
|
const header = opts.branding ? brandingHeaderHtml(opts.branding) : "";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { escapeHtml, isSafeHref } from "@cosmicdrift/kumiko-renderer/headless";
|
|
2
2
|
import { Marked } from "marked";
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Raw
|
|
6
|
-
//
|
|
7
|
-
// (
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// 'none'`). GFM
|
|
11
|
-
//
|
|
3
|
+
// Shared, hardened Markdown→HTML core for server-rendered public
|
|
4
|
+
// pages (legal-pages, managed-pages). Assumption: untrusted tenant authors.
|
|
5
|
+
// Raw HTML tokens are escaped as text (no <script>/<img onerror>-
|
|
6
|
+
// passthrough), and link/image hrefs are restricted to http(s)/mailto/relative
|
|
7
|
+
// (no javascript:/data:). Markdown structure (headings, lists, links,
|
|
8
|
+
// code) remains intact—this neutralizes XSS vectors without a sanitizer
|
|
9
|
+
// dependency. Defense in depth complements `securePageHeaders` (`script-src
|
|
10
|
+
// 'none'`). GFM and breaks are disabled—structured pages do not need
|
|
11
|
+
// tables/strikethrough/task lists.
|
|
12
12
|
const safeRenderer = new Marked({ gfm: false, breaks: false });
|
|
13
13
|
safeRenderer.use({
|
|
14
14
|
walkTokens(token) {
|
|
@@ -23,7 +23,7 @@ safeRenderer.use({
|
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
export function renderSafeMarkdown(markdown) {
|
|
26
|
-
// @cast-boundary third-party-type-gap marked.parse return
|
|
27
|
-
// `{ async: false }`
|
|
26
|
+
// @cast-boundary third-party-type-gap marked.parse return type is `string | Promise<string>`;
|
|
27
|
+
// `{ async: false }` guarantees synchronous output (string)—the cast only fixes the API contract.
|
|
28
28
|
return safeRenderer.parse(markdown, { async: false });
|
|
29
29
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
// Security
|
|
2
|
-
// managed-pages). `script-src 'none'`
|
|
3
|
-
// HTML
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// Security headers for server-rendered public HTML pages (legal-pages,
|
|
2
|
+
// managed-pages). `script-src 'none'` provides defense in depth: even if
|
|
3
|
+
// HTML injection gets through, no script can run. Deliberately omit
|
|
4
|
+
// `default-src` so styles, images, and fonts remain unrestricted for
|
|
5
|
+
// backward compatibility with inline-<style> layouts such as
|
|
6
|
+
// publicstatus' renderLegalLayout.
|
|
7
|
+
// nosniff/SAMEORIGIN/Referrer-Policy are broadly safe defaults.
|
|
7
8
|
const PUBLIC_PAGE_SECURITY_HEADERS = {
|
|
8
9
|
"content-security-policy": "script-src 'none'; object-src 'none'; base-uri 'none'",
|
|
9
10
|
"x-content-type-options": "nosniff",
|
|
@@ -62,10 +62,10 @@ export function createPersonalAccessTokensFeature(options) {
|
|
|
62
62
|
});
|
|
63
63
|
// Direct-write store like store_user_sessions: create/revoke write it, the
|
|
64
64
|
// resolver point-reads it. r.entity would make it a rebuildable projection
|
|
65
|
-
// whose replay (no token events) would wipe every live token
|
|
65
|
+
// whose replay (no token events) would wipe every live token.
|
|
66
66
|
r.storeTable(deriveEntityTableMeta(API_TOKEN_ENTITY_NAME, apiTokenEntity, { source: "unmanaged" }), {
|
|
67
67
|
reason: "read_side.api_tokens_direct_write",
|
|
68
|
-
// create.write encrypts `name` via encryptForDirectWrite
|
|
68
|
+
// create.write encrypts `name` via encryptForDirectWrite.
|
|
69
69
|
piiEncryptedOnWrite: true,
|
|
70
70
|
});
|
|
71
71
|
// Custom domain-event for cross-instance access-invalidation,
|
|
@@ -79,9 +79,9 @@ export function createPersonalAccessTokensFeature(options) {
|
|
|
79
79
|
// Password-change auto-revoke — mirrors sessions' own
|
|
80
80
|
// autoRevokeOnPasswordChange postSave hook, including WHY it's a
|
|
81
81
|
// late-bind callback rather than direct ctx.db use: user:write:user:update
|
|
82
|
-
// is r.systemScope()'d (the user aggregate is a systemStream,
|
|
83
|
-
//
|
|
84
|
-
//
|
|
82
|
+
// is r.systemScope()'d (the user aggregate is a systemStream), so a postSave hook
|
|
83
|
+
// on "user" gets a poisoned ctx.db here. The concrete revoker is bound once
|
|
84
|
+
// run{Prod,Dev}App has a real db handle.
|
|
85
85
|
// Explicit option wins; the runtime binding is replaceable so a second boot of the same
|
|
86
86
|
// feature instance binds its own database.
|
|
87
87
|
let boundAutoRevoke;
|
|
@@ -10,8 +10,8 @@ import { isPrincipalRowBlocked, userTable } from "../user/index.js";
|
|
|
10
10
|
// time would keep a since-revoked admin role for the token's whole (months-long)
|
|
11
11
|
// life. Returns null when the user has no membership in that tenant: removed
|
|
12
12
|
// from the tenant → the PAT stops authenticating there. Also null when the
|
|
13
|
-
// user's lifecycle status blocks them
|
|
14
|
-
//
|
|
13
|
+
// user's lifecycle status blocks them — collapsed onto the same "no roles"
|
|
14
|
+
// outcome as missing-membership so a blocked user's PAT
|
|
15
15
|
// gets an identical 401 to an unknown token (no status oracle).
|
|
16
16
|
export async function resolvePatRoles(db, userId, tenantId) {
|
|
17
17
|
const memberships = await selectMany(db, tenantMembershipsTable, {
|
|
@@ -15,9 +15,9 @@ export const statusQuery = defineQueryHandler({
|
|
|
15
15
|
// One gate for both halves: required keys/secrets of provider-features
|
|
16
16
|
// count only while their provider is the selected one (r.extensionSelector).
|
|
17
17
|
const gate = await buildProviderSelectionGate(ctx, ReadinessQueries.status, query.user, ctx.db);
|
|
18
|
-
// skipAccessFilter:
|
|
19
|
-
// Handler
|
|
20
|
-
//
|
|
18
|
+
// skipAccessFilter: the verdict must count ALL required keys—the
|
|
19
|
+
// Handler itself is TenantAdmin-gated; the per-key filter would falsely
|
|
20
|
+
// report ready:true for SystemAdmin-gated keys.
|
|
21
21
|
const missingConfig = await collectMissingRequiredConfig(ctx, ReadinessQueries.status, query.user, ctx.db, gate, { skipAccessFilter: true });
|
|
22
22
|
// has() is metadata-only: no decryption, no read-audit event — a
|
|
23
23
|
// readiness probe must not pollute the credential-read trail.
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
// RendererFoundationApi —
|
|
2
|
-
// (delivery, mail
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// RendererFoundationApi — cross-feature interface. Consumers
|
|
2
|
+
// (delivery, mail sender, Solon NKA PDF generator) retrieve the appropriate
|
|
3
|
+
// plugin for each render call via `createRendererForTenant`.
|
|
4
|
+
// The pattern mirrors ai-foundation's `createLLMProviderForTenant`.
|
|
5
5
|
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
6
6
|
import { DEFAULT_PLUGIN_BY_KIND } from "./constants.js";
|
|
7
7
|
import { RendererError } from "./types.js";
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// Result in extraContext.
|
|
8
|
+
// The plugin pool is built at boot time from extension usages.
|
|
9
|
+
// The registry provides all registered plugins. The foundation feature builds
|
|
10
|
+
// the pool via `collectRendererPlugins(registry)` and puts it in extraContext.
|
|
12
11
|
export function createRendererFoundationApi(plugins, tenantConfigLookup = () => null) {
|
|
13
12
|
const byKind = indexByKind(plugins);
|
|
14
13
|
return {
|
|
@@ -20,7 +19,7 @@ export function createRendererFoundationApi(plugins, tenantConfigLookup = () =>
|
|
|
20
19
|
const plugin = plugins.find((p) => p.name === tenantPluginName && p.kinds.includes(kind));
|
|
21
20
|
if (plugin)
|
|
22
21
|
return plugin;
|
|
23
|
-
//
|
|
22
|
+
// The tenant configuration points to an unregistered plugin; fall through to the default.
|
|
24
23
|
}
|
|
25
24
|
// 2. Default-Plugin
|
|
26
25
|
const defaultName = DEFAULT_PLUGIN_BY_KIND[kind];
|
|
@@ -29,7 +28,7 @@ export function createRendererFoundationApi(plugins, tenantConfigLookup = () =>
|
|
|
29
28
|
if (plugin)
|
|
30
29
|
return plugin;
|
|
31
30
|
}
|
|
32
|
-
// 3.
|
|
31
|
+
// 3. First plugin in the pool that serves the kind
|
|
33
32
|
const first = byKind.get(kind)?.[0];
|
|
34
33
|
if (first)
|
|
35
34
|
return first;
|
|
@@ -49,11 +48,11 @@ function indexByKind(plugins) {
|
|
|
49
48
|
}
|
|
50
49
|
return map;
|
|
51
50
|
}
|
|
52
|
-
// Single
|
|
53
|
-
//
|
|
51
|
+
// Single source of truth for handlers that require renderer-foundation.
|
|
52
|
+
// The pattern mirrors requireTemplateResolver + requireTextContent.
|
|
54
53
|
export function requireRendererFoundation(ctx, callerName) {
|
|
55
54
|
// @cast-boundary engine-bridge — rendererFoundation kommt per extraContext
|
|
56
|
-
//
|
|
55
|
+
// from the app bootstrap.
|
|
57
56
|
const api = ctx.rendererFoundation;
|
|
58
57
|
if (!api) {
|
|
59
58
|
throw new InternalError({
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Extension-point name for renderer plugins (@cosmicdrift/kumiko-renderer-mail-html, @cosmicdrift/kumiko-renderer-puppeteer-client, ...).
|
|
2
2
|
export const RENDERER_EXTENSION = "renderer";
|
|
3
3
|
export { CONTENT_FORMATS, RENDER_KINDS, } from "../template-resolver/index.js";
|
|
4
|
-
// Standard
|
|
5
|
-
//
|
|
4
|
+
// Standard default plugin for each kind when the tenant has not set explicit configuration.
|
|
5
|
+
// App bootstrap can override this through TenantConfigKey.
|
|
6
6
|
export const DEFAULT_PLUGIN_BY_KIND = {
|
|
7
7
|
mail: "mail-html",
|
|
8
8
|
"document-pdf": "puppeteer",
|
|
@@ -20,19 +20,19 @@ export function createRendererFoundationFeature() {
|
|
|
20
20
|
r.requires({ features: ["template-resolver"] });
|
|
21
21
|
r.extendsRegistrar(RENDERER_EXTENSION, {
|
|
22
22
|
onRegister: () => {
|
|
23
|
-
// Plugin
|
|
24
|
-
// options (kinds, render
|
|
25
|
-
//
|
|
23
|
+
// Plugin conformance check could go here: validate the shape of
|
|
24
|
+
// options (kinds, render function present). No shape check currently —
|
|
25
|
+
// the caller's TypeScript type safety applies.
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
return {};
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
31
|
+
// Build the plugin pool at boot time. App bootstrap calls this after
|
|
32
|
+
// feature registration, builds the pool, and passes it to handlers via
|
|
33
|
+
// extraContext.
|
|
34
34
|
//
|
|
35
|
-
//
|
|
35
|
+
// Symmetric to collectChannels / collectRenderers in delivery-service.
|
|
36
36
|
export function collectRendererPlugins(registry) {
|
|
37
37
|
const usages = registry.getExtensionUsages(RENDERER_EXTENSION);
|
|
38
38
|
return usages.map((usage) => {
|
package/dist/secrets/feature.js
CHANGED
|
@@ -49,15 +49,15 @@ export { tenantSecretsTable } from "./table.js";
|
|
|
49
49
|
// write has to join that transaction so a rejected command rolls it back too.
|
|
50
50
|
export const JOIN_REQUEST_TRANSACTION_REASON = "the secret write runs on the request transaction so a failing batch rolls it back together with the config writes";
|
|
51
51
|
// AppContext carries ctx.secrets via extraContext. requireSecretsContext
|
|
52
|
-
// wraps that raw context so every `.get(...)` call
|
|
53
|
-
// current user
|
|
54
|
-
//
|
|
52
|
+
// wraps that raw context so every `.get(...)` call automatically includes
|
|
53
|
+
// the current user and handler as audit metadata, preventing feature code
|
|
54
|
+
// from silently bypassing read auditing.
|
|
55
55
|
//
|
|
56
|
-
//
|
|
57
|
-
// FileProviderContext
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
56
|
+
// The context shape stays minimal: HandlerContext paths (Set/Delete handlers)
|
|
57
|
+
// and FileProviderContext paths (the S3 plugin in the worker) provide the same
|
|
58
|
+
// two fields, so importing the full HandlerContext is unnecessary.
|
|
59
|
+
// Handler contexts carry the caller as ctx.user; provider contexts set
|
|
60
|
+
// auditUserId, which takes precedence.
|
|
61
61
|
export function requireSecretsContext(ctx, handlerName) {
|
|
62
62
|
if (!ctx.secrets) {
|
|
63
63
|
throw new InternalError({
|
|
@@ -129,7 +129,7 @@ export function createSecretsFeature(opts = {}) {
|
|
|
129
129
|
// Backing table: envelope/metadata/last_rotated_at + the (tenant,key)
|
|
130
130
|
// uniqueIndex are not expressible via the field-DSL (jsonb-without-default,
|
|
131
131
|
// now()-default), so the physical table is the DDL truth. Without this the
|
|
132
|
-
// generated migration omitted those columns → prod-500
|
|
132
|
+
// generated migration omitted those columns → prod-500.
|
|
133
133
|
r.entity({ name: "tenant-secret", ...tenantSecretEntity, backingTable: tenantSecretsTable });
|
|
134
134
|
// Read-audit domain-event. Registered here so ops tools + MSPs can
|
|
135
135
|
// discover the type; secrets-context.get parses payloads against
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// secrets bundle constants — default RBAC for set/delete/list
|
|
1
|
+
// secrets bundle constants — default RBAC for set/delete/list.
|
|
2
2
|
// Default-RBAC of the set/delete/list handlers, hard-wired to ["TenantAdmin"]
|
|
3
|
-
// before
|
|
3
|
+
// before this default was established. Apps with their own role vocabulary override via
|
|
4
4
|
// createSecretsFeature({ roles }) or createSecretsFeature({ access }) — the
|
|
5
5
|
// rotate job stays untouched, it's a manual/ops path across all tenants by
|
|
6
6
|
// design, not a per-tenant RBAC surface.
|
package/dist/seo/feature.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// kumiko-lint-ignore app-feature-structure
|
|
1
|
+
// kumiko-lint-ignore app-feature-structure feature.ts is over 300 lines and not yet split
|
|
2
2
|
import { computeRevisionEtag } from "@cosmicdrift/kumiko-framework/api";
|
|
3
3
|
import { defineFeature, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { RateLimitError } from "@cosmicdrift/kumiko-framework/errors";
|
|
@@ -201,8 +201,8 @@ export function createSeoFeature(opts) {
|
|
|
201
201
|
},
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
|
-
// Boot-
|
|
205
|
-
//
|
|
204
|
+
// Boot-check body extracted as a named function—directly unit-testable,
|
|
205
|
+
// following the same "thin job-shell calls testable function" pattern as
|
|
206
206
|
// legal-pages' runLegalPagesBootCheck.
|
|
207
207
|
r.job("seo-boot-check", { trigger: { manual: true }, runOnBoot: true, runIn: "api" }, async (_payload, ctx) => runSeoBootCheck({
|
|
208
208
|
sitemapEntries: opts.sitemapEntries,
|
|
@@ -5,7 +5,7 @@ export declare const SessionHandlers: {
|
|
|
5
5
|
readonly revoke: "sessions:write:user-session:revoke";
|
|
6
6
|
readonly revokeAllOthers: "sessions:write:user-session:revoke-all-others";
|
|
7
7
|
/** Privileged: System-Caller (cross-feature) revokes ALL live sessions
|
|
8
|
-
*
|
|
8
|
+
* for a user. Used by user-data-rights:restrict-account
|
|
9
9
|
* (DSGVO Art. 18 Account-Freeze). */
|
|
10
10
|
readonly revokeAllForUser: "sessions:write:user-session:revoke-all-for-user";
|
|
11
11
|
};
|
|
@@ -7,7 +7,7 @@ export const SessionHandlers = {
|
|
|
7
7
|
revoke: "sessions:write:user-session:revoke",
|
|
8
8
|
revokeAllOthers: "sessions:write:user-session:revoke-all-others",
|
|
9
9
|
/** Privileged: System-Caller (cross-feature) revokes ALL live sessions
|
|
10
|
-
*
|
|
10
|
+
* for a user. Used by user-data-rights:restrict-account
|
|
11
11
|
* (DSGVO Art. 18 Account-Freeze). */
|
|
12
12
|
revokeAllForUser: "sessions:write:user-session:revoke-all-for-user",
|
|
13
13
|
};
|
package/dist/sessions/feature.js
CHANGED
|
@@ -65,19 +65,19 @@ export function createSessionsFeature(options) {
|
|
|
65
65
|
// events (the row columns ARE the audit trail). Registering it as
|
|
66
66
|
// r.entity would make it a rebuildable implicit projection whose replay
|
|
67
67
|
// finds zero session events and swaps an empty shadow over the live
|
|
68
|
-
// table — wiping every active session on the next projection rebuild
|
|
69
|
-
//
|
|
68
|
+
// table — wiping every active session on the next projection rebuild.
|
|
69
|
+
// r.storeTable keeps the migration DDL but opts the
|
|
70
70
|
// table out of implicit rebuild, like jobs/channel-in-app/feature-toggles
|
|
71
71
|
// which are direct-write stores too.
|
|
72
72
|
r.storeTable(deriveEntityTableMeta(USER_SESSION_ENTITY_NAME, userSessionEntity, { source: "unmanaged" }), {
|
|
73
73
|
reason: "read_side.user_sessions_direct_write",
|
|
74
|
-
// sessionCreator encrypts ip/userAgent via encryptForDirectWrite
|
|
74
|
+
// sessionCreator encrypts ip/userAgent via encryptForDirectWrite.
|
|
75
75
|
piiEncryptedOnWrite: true,
|
|
76
76
|
});
|
|
77
|
-
// Self-registers as auth-foundation's sessionStore provider
|
|
77
|
+
// Self-registers as auth-foundation's sessionStore provider —
|
|
78
78
|
// wraps the same createSessionCallbacks() used by the manual
|
|
79
|
-
// buildServer({ auth: { ... } }) wiring above;
|
|
80
|
-
//
|
|
79
|
+
// buildServer({ auth: { ... } }) wiring above; removes that manual
|
|
80
|
+
// wiring once the middleware resolves generically
|
|
81
81
|
// via resolveSessionStore().
|
|
82
82
|
r.useExtension(EXT_SESSION_STORE, "default", {
|
|
83
83
|
build: (deps) => {
|
|
@@ -94,7 +94,7 @@ export function createSessionsFeature(options) {
|
|
|
94
94
|
};
|
|
95
95
|
},
|
|
96
96
|
});
|
|
97
|
-
// Custom domain-event for cross-instance access-invalidation
|
|
97
|
+
// Custom domain-event for cross-instance access-invalidation.
|
|
98
98
|
// r.defineEvent registers the schema so ctx.unsafeAppendEvent (revoke,
|
|
99
99
|
// revoke-all-others) enforces it at append time. revoke-all-for-user
|
|
100
100
|
// appends via the low-level append() instead (needs to anchor on
|
|
@@ -102,7 +102,7 @@ export function createSessionsFeature(options) {
|
|
|
102
102
|
// consult the registry, so that callsite parses against
|
|
103
103
|
// sessionRevokedSchema explicitly, same guarantee via a different path.
|
|
104
104
|
// No projection: the payload IS the read, consumed directly off the
|
|
105
|
-
// event-store NOTIFY
|
|
105
|
+
// event-store NOTIFY.
|
|
106
106
|
r.defineEvent(SESSION_REVOKED_EVENT_SHORT, sessionRevokedSchema, { piiFields: "none" });
|
|
107
107
|
const handlers = {
|
|
108
108
|
revoke: r.writeHandler(revokeWrite),
|
|
@@ -50,8 +50,8 @@ export const revokeAllForUserWrite = defineWriteHandler({
|
|
|
50
50
|
id: { ne: event.payload.exceptSessionId },
|
|
51
51
|
}),
|
|
52
52
|
});
|
|
53
|
-
// Lightweight append alongside the direct-write above
|
|
54
|
-
//
|
|
53
|
+
// Lightweight append alongside the direct-write above; see revoke.write.ts
|
|
54
|
+
// for why this isn't a lifecycle event on
|
|
55
55
|
// store_user_sessions. Uses the low-level append() (not
|
|
56
56
|
// ctx.unsafeAppendEvent) because this handler is deliberately
|
|
57
57
|
// cross-tenant: the privileged caller's own tenantId (what
|
|
@@ -31,8 +31,8 @@ export const revokeAllOthersWrite = defineWriteHandler({
|
|
|
31
31
|
}));
|
|
32
32
|
}
|
|
33
33
|
const updated = await updateMany(ctx.db, userSessionTable, { revokedAt: Temporal.Now.instant() }, { userId: event.user.id, revokedAt: null, id: { ne: keepSid } });
|
|
34
|
-
// Lightweight append alongside the direct-write above
|
|
35
|
-
//
|
|
34
|
+
// Lightweight append alongside the direct-write above; see revoke.write.ts
|
|
35
|
+
// for why this isn't a lifecycle event on
|
|
36
36
|
// store_user_sessions. Skipped when nothing was revoked (no other
|
|
37
37
|
// live sessions) — a spurious invalidation would be the failure mode.
|
|
38
38
|
if (updated.length > 0) {
|
|
@@ -38,7 +38,7 @@ export const revokeWrite = defineWriteHandler({
|
|
|
38
38
|
handler: async (event, ctx) => {
|
|
39
39
|
const updated = await updateMany(ctx.db, userSessionTable, { revokedAt: Temporal.Now.instant() }, { id: event.payload.id, userId: event.user.id, revokedAt: null });
|
|
40
40
|
if (updated.length > 0) {
|
|
41
|
-
// Lightweight append alongside the direct-write above
|
|
41
|
+
// Lightweight append alongside the direct-write above — NOT a
|
|
42
42
|
// lifecycle event for store_user_sessions (that table stays an
|
|
43
43
|
// unmanaged direct-write store, see feature.ts). Own aggregate id per
|
|
44
44
|
// revoke, no predecessor to satisfy, no version_conflict against a
|
|
@@ -12,9 +12,9 @@ import { USER_SESSION_ENTITY_NAME } from "../constants.js";
|
|
|
12
12
|
// mutate them via ctx.db inside a transaction, but no user request can bypass
|
|
13
13
|
// the revocation flow by poking the column directly.
|
|
14
14
|
export const userSessionEntity = createEntity({
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
15
|
+
// The entity key is "user-session"; snake-casing it would produce
|
|
16
|
+
// "read_user-sessions", which is invalid SQL without quoting. Use an explicit
|
|
17
|
+
// override with a valid read_-prefixed table name.
|
|
18
18
|
table: "store_user_sessions",
|
|
19
19
|
// sid-as-PK: the sessionCreator callback generates the UUID, returns it to
|
|
20
20
|
// the framework; the framework stamps it as `jti`; here the same value is
|
|
@@ -77,7 +77,7 @@ export const userSessionEntity = createEntity({
|
|
|
77
77
|
// Unmanaged direct-write store (r.storeTable in feature.ts, no event stream —
|
|
78
78
|
// revocation is a column write, not an aggregate). Handlers write via ctx.db;
|
|
79
79
|
// source: "unmanaged" makes the meta Writable so those writes compile. See
|
|
80
|
-
// feature.ts for the rebuild-exclusion rationale
|
|
80
|
+
// feature.ts for the rebuild-exclusion rationale.
|
|
81
81
|
export const userSessionTable = deriveEntityTableMeta(USER_SESSION_ENTITY_NAME, userSessionEntity, {
|
|
82
82
|
source: "unmanaged",
|
|
83
83
|
});
|
package/dist/sessions/screens.js
CHANGED
|
@@ -12,7 +12,7 @@ export const createSessionListScreen = (adminRoles = access.admin) => ({
|
|
|
12
12
|
pageSize: MAX_LIST_LIMIT,
|
|
13
13
|
// Mirrors list.query's own fallback (unrecognised/absent sort → createdAt
|
|
14
14
|
// desc) — kept in sync by hand, boot-validator only requires the field
|
|
15
|
-
// be present once the query accepts `sort
|
|
15
|
+
// be present once the query accepts `sort`.
|
|
16
16
|
defaultSort: { field: "createdAt", dir: "desc" },
|
|
17
17
|
columns: [
|
|
18
18
|
{ field: "id", label: i18nKey("sessions.list.col.id") },
|
|
@@ -71,7 +71,7 @@ export const createSessionDetailScreen = (adminRoles = access.admin) => ({
|
|
|
71
71
|
// The shim (projection-detail-shim.ts) stamps every field as
|
|
72
72
|
// type:"text" — field.renderer is the only way this screen
|
|
73
73
|
// type reaches real per-type formatting instead of a raw ISO
|
|
74
|
-
// string
|
|
74
|
+
// string.
|
|
75
75
|
{ field: "createdAt", renderer: { format: "timestamp" } },
|
|
76
76
|
{ field: "expiresAt", renderer: { format: "timestamp" } },
|
|
77
77
|
{ field: "revokedAt", renderer: { format: "timestamp" } },
|
|
@@ -155,11 +155,11 @@ export function createSessionCallbacks(opts) {
|
|
|
155
155
|
return transaction(db, async (tx) => {
|
|
156
156
|
const result = await updateMany(tx, userSessionTable, { revokedAt: Temporal.Now.instant() }, { userId, revokedAt: null });
|
|
157
157
|
// Lightweight append alongside the direct-write above, same pattern
|
|
158
|
-
// as revoke.write.ts
|
|
158
|
+
// as revoke.write.ts — this callback is the password-change
|
|
159
159
|
// auto-revoke path (sessions/feature.ts postSave hook) and has no
|
|
160
160
|
// dispatcher ctx to call unsafeAppendEvent from, so it uses the raw
|
|
161
161
|
// append() like revoke-all-for-user.write.ts does. Without this, the
|
|
162
|
-
// access-invalidation consumer
|
|
162
|
+
// access-invalidation consumer never hears about a password
|
|
163
163
|
// change and an already-open SSE stream survives it — the exact
|
|
164
164
|
// "stale JWT mid-stream" gap this feature exists to close.
|
|
165
165
|
if (result.length > 0) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
// Lightweight custom event appended alongside the direct-write
|
|
3
3
|
// updateMany() in revoke.write.ts / revoke-all-others.write.ts /
|
|
4
|
-
// revoke-all-for-user.write.ts
|
|
4
|
+
// revoke-all-for-user.write.ts. store_user_sessions itself stays
|
|
5
5
|
// an unmanaged direct-write store (see feature.ts) — the row columns are
|
|
6
6
|
// the audit trail, this event is NOT a CRUD/lifecycle event for that
|
|
7
7
|
// table and carries no projection. Its only job is to give cross-instance
|
|
8
|
-
// consumers (access-invalidation
|
|
8
|
+
// consumers (access-invalidation) something to LISTEN for via the
|
|
9
9
|
// existing event-store NOTIFY, keyed by the affected userId.
|
|
10
10
|
//
|
|
11
11
|
// _SHORT/_QN pair mirrors cap-counter's rolling-incremented event:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Boot validation rejects `{ kind: "where" }` in access.write too
|
|
1
|
+
// Boot validation rejects `{ kind: "where" }` in access.write too;
|
|
2
2
|
// failing at factory time names the option instead of an entity scope.
|
|
3
3
|
export function assertNoWhereRuleInOwnershipWrite(factoryName, writeOwnership) {
|
|
4
4
|
// skip: no write ownership declared, nothing to validate
|
|
@@ -4,7 +4,7 @@ import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/ku
|
|
|
4
4
|
// active KMS that is ciphertext (self-describing: it names its own subject,
|
|
5
5
|
// so no entity/field context is needed for key selection). `field` must
|
|
6
6
|
// still match the field name used at encrypt time — it is part of the
|
|
7
|
-
// AAD
|
|
7
|
+
// AAD, so a mismatch fails decrypt loud rather than silently
|
|
8
8
|
// letting ciphertext cut-and-pasted from another field decrypt. An erased
|
|
9
9
|
// subject yields the sentinel, which matches no real value.
|
|
10
10
|
export async function decryptStoredPii(value, field, fallbackRequestId) {
|
|
@@ -4,7 +4,7 @@ import { subjectErasedConflict } from "@cosmicdrift/kumiko-framework/errors";
|
|
|
4
4
|
// Unmanaged direct-write stores (r.unmanagedTable) skip the executor, so its
|
|
5
5
|
// PII encryption never runs — every insert of subject-annotated fields must
|
|
6
6
|
// go through this instead, and the feature declares { piiEncryptedOnWrite:
|
|
7
|
-
// true } at the registration site (enforced by the registry
|
|
7
|
+
// true } at the registration site (enforced by the registry).
|
|
8
8
|
export async function encryptForDirectWrite(entity, entityName, row, fallbackRequestId) {
|
|
9
9
|
const kms = configuredPiiSubjectKms();
|
|
10
10
|
if (!kms)
|
|
@@ -12,19 +12,20 @@
|
|
|
12
12
|
// an unhandled rejection — verified in `mapWithConcurrency.test.ts`).
|
|
13
13
|
export async function mapWithConcurrency(items, limit, fn) {
|
|
14
14
|
const results = new Array(items.length);
|
|
15
|
-
|
|
15
|
+
const unclaimed = items.entries();
|
|
16
16
|
let failed = false;
|
|
17
17
|
async function worker() {
|
|
18
18
|
for (;;) {
|
|
19
19
|
// skip: another worker already failed — stop claiming new items.
|
|
20
20
|
if (failed)
|
|
21
21
|
return;
|
|
22
|
-
const
|
|
22
|
+
const claimed = unclaimed.next();
|
|
23
23
|
// skip: cursor exhausted, normal worker-loop exit
|
|
24
|
-
if (
|
|
24
|
+
if (claimed.done)
|
|
25
25
|
return;
|
|
26
|
+
const [index, item] = claimed.value;
|
|
26
27
|
try {
|
|
27
|
-
results[index] = await fn(
|
|
28
|
+
results[index] = await fn(item, index);
|
|
28
29
|
}
|
|
29
30
|
catch (err) {
|
|
30
31
|
failed = true;
|