@cosmicdrift/kumiko-samples 0.366.0 → 0.368.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 +16 -2
- package/packages/bundled-features/src/audit/handlers/details.query.ts +1 -1
- package/packages/bundled-features/src/audit/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/bootstrap.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +10 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +10 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +6 -2
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/seeding.ts +2 -2
- package/packages/bundled-features/src/auth-foundation/feature.ts +43 -34
- package/packages/bundled-features/src/auth-foundation/index.ts +1 -0
- package/packages/bundled-features/src/auth-mfa/db/queries.ts +5 -2
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/status.query.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +1 -1
- package/packages/bundled-features/src/auth-mfa-user-data/index.ts +19 -10
- package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/feature.ts +138 -135
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/projection.ts +3 -2
- package/packages/bundled-features/src/cap-counter/calendar-cap-usage-reservation.ts +52 -1
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +203 -15
- package/packages/bundled-features/src/cap-counter/changes.json +13 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +84 -73
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +3 -4
- package/packages/bundled-features/src/cap-counter/index.ts +9 -1
- package/packages/bundled-features/src/cap-counter/tables.ts +10 -3
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -2
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +6 -2
- package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +1 -1
- package/packages/bundled-features/src/channel-email/changes.json +6 -0
- package/packages/bundled-features/src/channel-email/email-channel.ts +12 -2
- package/packages/bundled-features/src/channel-email/feature.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/mark-all-read.write.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/tables.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +1 -2
- package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +8 -4
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +26 -17
- package/packages/bundled-features/src/config/db/queries/resolver.ts +1 -1
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +2 -2
- package/packages/bundled-features/src/config/resolver.ts +1 -1
- package/packages/bundled-features/src/config/write-helpers.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +9 -7
- package/packages/bundled-features/src/custom-fields/db/queries/field-access.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/projection.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/quota.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/retention.ts +6 -2
- package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +1 -1
- package/packages/bundled-features/src/custom-fields/feature.ts +11 -14
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +4 -4
- package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +16 -10
- package/packages/bundled-features/src/delivery/address-opt-out.ts +5 -2
- package/packages/bundled-features/src/delivery/attempt-log-retention.ts +1 -1
- package/packages/bundled-features/src/delivery/changes.json +12 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +2 -1
- package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +1 -1
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +1 -1
- package/packages/bundled-features/src/delivery/delivery-service.ts +70 -8
- package/packages/bundled-features/src/delivery/feature.ts +2 -2
- package/packages/bundled-features/src/delivery/handlers/log.query.ts +3 -2
- package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +1 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-address.write.ts +10 -5
- package/packages/bundled-features/src/delivery/index.ts +6 -0
- package/packages/bundled-features/src/delivery/testing.ts +2 -0
- package/packages/bundled-features/src/delivery/types.ts +4 -0
- package/packages/bundled-features/src/delivery/unsubscribe-link.ts +73 -0
- package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +17 -0
- package/packages/bundled-features/src/delivery/unsubscribe.ts +94 -31
- package/packages/bundled-features/src/delivery/upsert-preference.ts +5 -2
- package/packages/bundled-features/src/derivatives-sharp/feature.ts +21 -12
- package/packages/bundled-features/src/derivatives-sharp/index.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +112 -103
- package/packages/bundled-features/src/document-ingest-foundation/forget-extract-with-file-ref.ts +3 -3
- package/packages/bundled-features/src/document-ingest-foundation/index.ts +4 -1
- package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -5
- package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/feature.ts +134 -129
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
- package/packages/bundled-features/src/file-foundation/feature.ts +38 -29
- package/packages/bundled-features/src/file-foundation/index.ts +1 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +1 -1
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +32 -21
- package/packages/bundled-features/src/file-provider-inmemory/index.ts +6 -1
- package/packages/bundled-features/src/file-provider-s3/changes.json +10 -1
- package/packages/bundled-features/src/file-provider-s3/env-feature.ts +62 -0
- package/packages/bundled-features/src/file-provider-s3/feature.ts +107 -73
- package/packages/bundled-features/src/file-provider-s3/index.ts +6 -1
- package/packages/bundled-features/src/file-provider-s3/lib/index.ts +3 -0
- package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/s3-provider.ts +19 -19
- package/packages/bundled-features/src/file-provider-s3-env/index.ts +7 -2
- package/packages/bundled-features/src/files-provider-s3/index.ts +11 -3
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +1 -1
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +1 -2
- package/packages/bundled-features/src/folders/feature.ts +8 -3
- package/packages/bundled-features/src/folders-user-data/index.ts +27 -18
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +3 -2
- package/packages/bundled-features/src/form-draft/feature.ts +6 -1
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +2 -2
- package/packages/bundled-features/src/form-draft/index.ts +1 -1
- package/packages/bundled-features/src/form-draft/lookup.ts +1 -1
- package/packages/bundled-features/src/form-draft-user-data/index.ts +19 -10
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +165 -154
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +1 -2
- package/packages/bundled-features/src/inbound-mail-foundation/index.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-access-token.ts +5 -2
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +3 -2
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +22 -13
- package/packages/bundled-features/src/inbound-provider-imap/index.ts +6 -1
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +20 -12
- package/packages/bundled-features/src/inbound-provider-inmemory/index.ts +1 -0
- package/packages/bundled-features/src/jobs/db/queries/retention.ts +1 -1
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/detail.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +7 -2
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +11 -10
- package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
- package/packages/bundled-features/src/ledger/feature.ts +6 -3
- package/packages/bundled-features/src/mail-foundation/feature.ts +107 -55
- package/packages/bundled-features/src/mail-foundation/index.ts +4 -0
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +25 -17
- package/packages/bundled-features/src/mail-transport-inmemory/index.ts +6 -1
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +91 -79
- package/packages/bundled-features/src/mail-transport-smtp/index.ts +1 -0
- package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +1 -1
- package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +1 -2
- package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +1 -2
- package/packages/bundled-features/src/managed-pages/seeding.ts +8 -4
- package/packages/bundled-features/src/metrics/compute.ts +1 -1
- package/packages/bundled-features/src/metrics/filters.ts +1 -1
- package/packages/bundled-features/src/metrics/validate.ts +1 -1
- package/packages/bundled-features/src/notes-history/feature.ts +6 -3
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
- package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
- package/packages/bundled-features/src/notes-history-user-data/index.ts +27 -18
- package/packages/bundled-features/src/personal-access-tokens/changes.json +6 -0
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +17 -2
- package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/roles.ts +8 -6
- package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -0
- package/packages/bundled-features/src/readiness/feature.ts +25 -16
- package/packages/bundled-features/src/readiness/index.ts +1 -1
- package/packages/bundled-features/src/secrets/db/queries/read.ts +1 -1
- package/packages/bundled-features/src/secrets/feature.ts +8 -3
- package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +2 -2
- package/packages/bundled-features/src/secrets/secrets-context.ts +4 -3
- package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/detail.query.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/mine.query.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/sessions/session-callbacks.ts +14 -7
- package/packages/bundled-features/src/sessions/testing.ts +1 -1
- package/packages/bundled-features/src/tags/feature.ts +6 -3
- package/packages/bundled-features/src/template-resolver/api.ts +1 -1
- package/packages/bundled-features/src/template-resolver/changes.json +25 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +61 -9
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +19 -0
- package/packages/bundled-features/src/template-resolver/document-schema.ts +33 -0
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +10 -2
- package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +1 -2
- package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -2
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +9 -3
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +9 -2
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +7 -2
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +8 -3
- package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +22 -2
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/index.ts +4 -0
- package/packages/bundled-features/src/template-resolver/qualified-names.ts +1 -0
- package/packages/bundled-features/src/template-resolver/seeding.ts +57 -10
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-preview.ts +3 -1
- package/packages/bundled-features/src/template-resolver/template-resources.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-system-only.ts +21 -0
- package/packages/bundled-features/src/template-resolver/template-validation.ts +48 -24
- package/packages/bundled-features/src/template-resolver/testing.ts +1 -1
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +2 -0
- package/packages/bundled-features/src/template-resolver-user-data/index.ts +23 -14
- package/packages/bundled-features/src/tenant/handlers/active-tenant-ids.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -2
- package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/invitations.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/me.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -1
- package/packages/bundled-features/src/tenant/handlers/resolve-user-ids.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -2
- package/packages/bundled-features/src/tenant/invited-membership.ts +2 -2
- package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -2
- package/packages/bundled-features/src/tenant/seeding.ts +12 -12
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +1 -2
- package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +1 -2
- package/packages/bundled-features/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/lifecycle-gate.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +3 -3
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +10 -5
- package/packages/bundled-features/src/tenant-lifecycle/testing.ts +3 -3
- package/packages/bundled-features/src/tenant-settings/feature.ts +34 -29
- package/packages/bundled-features/src/tier-engine/feature.ts +426 -428
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +2 -3
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +5 -2
- package/packages/bundled-features/src/user/changes.json +6 -0
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +1 -1
- package/packages/bundled-features/src/user/handlers/create.write.ts +1 -2
- package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +1 -1
- package/packages/bundled-features/src/user/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -1
- package/packages/bundled-features/src/user/index.ts +5 -1
- package/packages/bundled-features/src/user/invited-global-roles.ts +2 -2
- package/packages/bundled-features/src/user/principal-status.ts +13 -3
- package/packages/bundled-features/src/user/resolve-display-names.ts +1 -1
- package/packages/bundled-features/src/user/seeding.ts +5 -5
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/changes.json +6 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/export-jobs.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +1 -2
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/lib/deny-if-target-outside-admin-tenant.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +7 -2
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +7 -3
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +11 -5
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +10 -5
- package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +1 -2
- package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
- package/packages/bundled-features/src/waitlist/lib.ts +5 -2
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/feature.ts +58 -47
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/index.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/pending-projection.ts +1 -1
- package/samples/apps/admin-console/src/run-config.ts +2 -2
- package/samples/apps/cap-billing-demo/package.json +3 -0
- package/samples/apps/cap-billing-demo/src/feature.ts +2 -2
- package/samples/apps/cap-billing-demo/src/run-config.ts +8 -8
- package/samples/apps/marketing-demo/src/app/seed.ts +1 -1
- package/samples/apps/marketing-demo/src/db/queries/seed-counts.ts +1 -1
- package/samples/apps/showcase/package.json +3 -0
- package/samples/apps/showcase/src/app/seed-items.ts +1 -1
- package/samples/apps/styleguide/src/app/seed.ts +2 -2
- package/samples/apps/styleguide/src/features/ai-settings/seed.ts +2 -2
- package/samples/apps/ui-walkthrough/scripts/emit-e2e-data.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +2 -2
- package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +2 -0
- package/samples/apps/ui-walkthrough/src/app/seed-vehicles.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/seed.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +12 -0
- package/samples/apps/ui-walkthrough/src/db/queries/row-counts.ts +1 -1
- package/samples/apps/ui-walkthrough/src/db/queries/task-counts.ts +1 -1
- package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +7 -0
- package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +2 -0
- package/samples/apps/use-all-bundled/feature-manifest.json +4 -4
- package/samples/apps/use-all-bundled/package.json +4 -0
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +2 -2
- package/samples/apps/use-all-bundled/src/app/auth-constants.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/cap-overview-caps.ts +2 -2
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/seed-documents.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/seed.ts +11 -5
- package/samples/apps/use-all-bundled/src/run-config.ts +55 -56
- package/samples/apps/user-data-rights-demo/README.md +2 -2
- package/samples/apps/user-data-rights-demo/package.json +3 -0
- package/samples/apps/user-data-rights-demo/src/run-config.ts +7 -7
- package/samples/apps/workspaces/package.json +3 -0
- package/samples/recipes/access-control/package.json +3 -0
- package/samples/recipes/anonymous-access/package.json +3 -0
- package/samples/recipes/anonymous-access-multitenant/package.json +3 -0
- package/samples/recipes/apex-landing/package.json +1 -0
- package/samples/recipes/apex-surface-auth/package.json +3 -0
- package/samples/recipes/apex-surface-auth/src/feature.ts +2 -2
- package/samples/recipes/api-worker-split/package.json +3 -0
- package/samples/recipes/api-worker-split/src/feature.ts +1 -2
- package/samples/recipes/auth-claims/package.json +3 -0
- package/samples/recipes/auth-foundation-providers/src/feature.ts +1 -1
- package/samples/recipes/auth-mfa/package.json +3 -0
- package/samples/recipes/basic-entity/package.json +3 -0
- package/samples/recipes/chat-channels/package.json +3 -0
- package/samples/recipes/compliance-profiles-demo/package.json +3 -0
- package/samples/recipes/cross-feature-events/package.json +3 -1
- package/samples/recipes/cross-feature-events/src/feature.ts +1 -1
- package/samples/recipes/crypto-shredding-hr/package.json +3 -0
- package/samples/recipes/currencies-global/package.json +3 -0
- package/samples/recipes/currencies-per-tenant/package.json +3 -0
- package/samples/recipes/custom-fields-basic/package.json +3 -0
- package/samples/recipes/custom-handlers/package.json +3 -0
- package/samples/recipes/dashboard-stats/package.json +3 -0
- package/samples/recipes/delivery-notifications/package.json +3 -0
- package/samples/recipes/e2e-generator/package.json +3 -0
- package/samples/recipes/embedded/package.json +3 -0
- package/samples/recipes/embedded-entity-form/package.json +1 -0
- package/samples/recipes/encrypted-tenant-config/README.md +1 -1
- package/samples/recipes/encrypted-tenant-config/package.json +3 -0
- package/samples/recipes/error-contract/package.json +3 -0
- package/samples/recipes/event-sourcing/package.json +3 -1
- package/samples/recipes/event-sourcing/src/feature.ts +16 -20
- package/samples/recipes/event-sourcing/tsconfig.json +2 -6
- package/samples/recipes/feature-toggles/package.json +3 -0
- package/samples/recipes/field-access/package.json +3 -0
- package/samples/recipes/files-post-processing/package.json +1 -0
- package/samples/recipes/golden-path/README.md +30 -0
- package/samples/recipes/golden-path/package.json +11 -0
- package/samples/recipes/golden-path/src/feature.ts +70 -0
- package/samples/recipes/idempotency/package.json +3 -0
- package/samples/recipes/inbound-mail-triage/package.json +3 -0
- package/samples/recipes/lane-routing/package.json +3 -0
- package/samples/recipes/ledger-banking/package.json +3 -0
- package/samples/recipes/ledger-invoicing/package.json +3 -0
- package/samples/recipes/legal-pages/package.json +3 -0
- package/samples/recipes/lifecycle-hooks/package.json +3 -0
- package/samples/recipes/managed-config/package.json +3 -0
- package/samples/recipes/managed-pages/package.json +3 -0
- package/samples/recipes/notes-history-basic/package.json +3 -0
- package/samples/recipes/ownership/package.json +3 -0
- package/samples/recipes/pdf-audit-export/package.json +1 -0
- package/samples/recipes/pipeline-basics/package.json +3 -0
- package/samples/recipes/public-share-token/package.json +3 -0
- package/samples/recipes/public-share-token/src/feature.ts +1 -1
- package/samples/recipes/rate-limiting/package.json +3 -0
- package/samples/recipes/realtime-sse/package.json +3 -0
- package/samples/recipes/record-detail-layout/package.json +1 -0
- package/samples/recipes/reference-data/package.json +3 -0
- package/samples/recipes/relations/package.json +3 -0
- package/samples/recipes/screens-nav/package.json +3 -0
- package/samples/recipes/search/package.json +3 -0
- package/samples/recipes/secrets-demo/package.json +3 -0
- package/samples/recipes/security-baseline/src/feature.ts +2 -2
- package/samples/recipes/session-revocation/README.md +1 -1
- package/samples/recipes/session-revocation/package.json +3 -0
- package/samples/recipes/session-revocation/src/feature.ts +1 -1
- package/samples/recipes/state-machine/package.json +3 -1
- package/samples/recipes/state-machine/src/entities/invoice.ts +2 -2
- package/samples/recipes/state-machine/src/events.ts +19 -0
- package/samples/recipes/state-machine/src/feature.ts +25 -30
- package/samples/recipes/state-machine/src/handlers/_helpers.ts +13 -14
- package/samples/recipes/state-machine/src/handlers/create.ts +1 -1
- package/samples/recipes/state-machine/src/handlers/transitions.ts +129 -122
- package/samples/recipes/state-machine/src/reducer.ts +1 -1
- package/samples/recipes/state-machine/tsconfig.json +2 -6
- package/samples/recipes/tags-basic/package.json +3 -0
- package/samples/recipes/tenant-isolation/package.json +3 -0
- package/samples/recipes/tenant-settings/package.json +3 -0
- package/samples/recipes/tier-admin/package.json +3 -0
- package/samples/recipes/timezones/package.json +3 -0
- package/samples/recipes/tsconfig.base.json +1 -1
- package/samples/recipes/user-data-rights/package.json +3 -0
- package/samples/recipes/user-data-rights/src/feature.ts +6 -2
- package/samples/recipes/user-profile/package.json +3 -0
- package/samples/recipes/user-profile/src/feature.ts +2 -2
- package/samples/recipes/webhook-step/package.json +3 -0
- package/samples/recipes/wizard-form/package.json +1 -0
- package/samples/recipes/workflow-engine/package.json +3 -0
- package/samples/recipes/workflow-engine/src/db/queries/suspended-runs.ts +5 -2
- package/samples/recipes/writeform-section/package.json +1 -0
- package/packages/bundled-features/src/file-provider-s3-env/feature.ts +0 -58
- /package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/env-helper.ts +0 -0
|
@@ -100,137 +100,142 @@ export function createFileDerivativesFeature(opts: FileDerivativesOptions = {}):
|
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
return defineFeature(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
r.extendsRegistrar(EXT_DERIVATIVE_OVERLAY_RESOLVER, {
|
|
136
|
-
onRegister: () => {
|
|
137
|
-
// No side-effects at register-time — resolution happens in
|
|
138
|
-
// variant(), keyed by the FileRef's entityType, before the spec
|
|
139
|
-
// hash is computed.
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Registered ONLY when resolveApexTenant is supplied — r.queryHandler
|
|
144
|
-
// registers publicVariantQuery into the feature's dispatch table as a
|
|
145
|
-
// side effect of being called, independent of what's done with its
|
|
146
|
-
// return value. Calling it unconditionally would make `publicVariant`
|
|
147
|
-
// (access: ["anonymous", ...]) reachable via the generic `/api` query
|
|
148
|
-
// dispatch even when the httpRoute below isn't mounted, bypassing the
|
|
149
|
-
// "tenantId comes from the host, never the payload" invariant that only
|
|
150
|
-
// `resolveApexTenant` enforces.
|
|
151
|
-
if (opts.resolveApexTenant) {
|
|
152
|
-
const resolveApexTenant = opts.resolveApexTenant;
|
|
153
|
-
const byFileRef = opts.publicTenantResolution === "fileRef";
|
|
154
|
-
const routeQn = byFileRef ? PUBLIC_VARIANT_BY_FILE_REF_QN : PUBLIC_VARIANT_QN;
|
|
155
|
-
|
|
156
|
-
r.queryHandler(publicVariantQuery);
|
|
157
|
-
// publicVariantByFileRefQuery is the ONLY way "fileRef" mode is
|
|
158
|
-
// reachable — registered ONLY in that mode for the same reason
|
|
159
|
-
// publicVariantQuery is gated above: registering it unconditionally
|
|
160
|
-
// would expose its unsafeRaw, cross-tenant FileRef lookup via the
|
|
161
|
-
// generic `/api` query dispatch even in default "host" mode.
|
|
162
|
-
if (byFileRef) {
|
|
163
|
-
// The handler reads the FileRef-tenant's row to keep a blocked
|
|
164
|
-
// tenant's public variants from staying reachable — require the
|
|
165
|
-
// dependency so a missing mount fails boot, not the tenant check
|
|
166
|
-
// silently no-op-ing at request time.
|
|
167
|
-
r.requires({ features: ["tenant"] });
|
|
168
|
-
r.queryHandler(publicVariantByFileRefQuery);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
r.httpRoute({
|
|
172
|
-
method: "GET",
|
|
173
|
-
path: `${basePath}/:fileRefId/:variant`,
|
|
174
|
-
anonymous: true,
|
|
175
|
-
handler: async (c, { systemQuery }) => {
|
|
176
|
-
// `param(...)` is string|undefined here — `path` is a computed
|
|
177
|
-
// template, so Hono can't infer the param type from a literal.
|
|
178
|
-
const fileRefId = c.req.param("fileRefId");
|
|
179
|
-
const variant = c.req.param("variant");
|
|
180
|
-
// 404, not 400 — a syntactically bad name and "doesn't exist" must
|
|
181
|
-
// answer identically, no name-oracle. fileRefsTable.id is a UUID
|
|
182
|
-
// column — a malformed id must fail here, not at the DB. Without
|
|
183
|
-
// this, an anonymous, internet-facing caller can throw a Postgres
|
|
184
|
-
// 22P02 on every request (Bun.SQL pools the failed connection), a
|
|
185
|
-
// DoS primitive with no auth required.
|
|
186
|
-
if (!fileRefId || !variant || !VARIANT_NAME_RE.test(variant) || !isUuid(fileRefId)) {
|
|
187
|
-
return c.text("not found", 404);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const host = c.req.header("host") ?? new URL(c.req.url).host;
|
|
191
|
-
const tenantId = await resolveApexTenant(host);
|
|
192
|
-
if (!tenantId) return c.text("not found", 404);
|
|
193
|
-
|
|
194
|
-
let result: PublicVariantQueryResult;
|
|
195
|
-
try {
|
|
196
|
-
// @cast-boundary engine-payload — shape comes from
|
|
197
|
-
// publicVariantQuery's return type (publicVariantByFileRefQuery
|
|
198
|
-
// returns exactly that, or null, never its own shape).
|
|
199
|
-
result = (await systemQuery(
|
|
200
|
-
routeQn,
|
|
201
|
-
{ fileRefId, variant },
|
|
202
|
-
tenantId,
|
|
203
|
-
)) as PublicVariantQueryResult;
|
|
204
|
-
} catch (err) {
|
|
205
|
-
if (err instanceof RateLimitError) {
|
|
206
|
-
return c.text("rate limited", 429);
|
|
207
|
-
}
|
|
208
|
-
// biome-ignore lint/suspicious/noConsole: ops-visible fallback, no logger wired into HttpRouteHandlerDeps
|
|
209
|
-
console.error(
|
|
210
|
-
`file-derivatives: public-variant query failed for fileRefId="${fileRefId}" variant="${variant}"`,
|
|
211
|
-
err,
|
|
212
|
-
);
|
|
213
|
-
return c.text("variant unavailable", 503);
|
|
214
|
-
}
|
|
215
|
-
if (!result) return c.text("not found", 404);
|
|
216
|
-
|
|
217
|
-
const bytes = Buffer.from(result.dataBase64, "base64");
|
|
218
|
-
const etag = computeRevisionEtag([tenantId, fileRefId, variant, result.revision]);
|
|
219
|
-
return cachedResponse(c.req.raw, {
|
|
220
|
-
body: bytes,
|
|
221
|
-
etag,
|
|
222
|
-
cache: { kind: "revalidate", maxAgeSeconds: 60 },
|
|
223
|
-
// Explicit here, not left to the app-wide security-headers default, so the route stays safe standalone.
|
|
224
|
-
headers: {
|
|
225
|
-
"content-type": result.mimeType,
|
|
226
|
-
vary: "Host",
|
|
227
|
-
"x-content-type-options": "nosniff",
|
|
228
|
-
},
|
|
229
|
-
});
|
|
103
|
+
return defineFeature(
|
|
104
|
+
FEATURE_NAME,
|
|
105
|
+
(r) => {
|
|
106
|
+
r.describe(
|
|
107
|
+
"Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: \"ip\"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: \"fileRef\"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.",
|
|
108
|
+
);
|
|
109
|
+
r.uiHints({
|
|
110
|
+
displayLabel: "File Derivatives",
|
|
111
|
+
category: "storage",
|
|
112
|
+
recommended: false,
|
|
113
|
+
});
|
|
114
|
+
// Needs a storage provider to read the original + write the variant —
|
|
115
|
+
// without file-foundation there's nothing to derive from or write to.
|
|
116
|
+
r.requires({ features: ["file-foundation"] });
|
|
117
|
+
// variant() reads fileRefsTable, which "files" (not file-foundation)
|
|
118
|
+
// owns — without this, mounting file-derivatives + file-foundation
|
|
119
|
+
// alone boots fine but fails at request-time with a SQL error the first
|
|
120
|
+
// time variant() runs.
|
|
121
|
+
r.requires({ features: ["files"] });
|
|
122
|
+
|
|
123
|
+
r.extendsRegistrar(EXT_DERIVATIVE_RENDERER, {
|
|
124
|
+
onRegister: () => {
|
|
125
|
+
// No side-effects at register-time — resolution (exact MIME match,
|
|
126
|
+
// then `<type>/*` wildcard) happens at request-time in
|
|
127
|
+
// resolveRenderer, mirrors file-foundation's fileProvider point.
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
r.extendsRegistrar(EXT_DERIVATIVE_PUBLIC_PREDICATE, {
|
|
131
|
+
onRegister: () => {
|
|
132
|
+
// No side-effects at register-time — resolution happens at
|
|
133
|
+
// request-time in publicVariantQuery, keyed by the FileRef's
|
|
134
|
+
// entityType.
|
|
230
135
|
},
|
|
231
136
|
});
|
|
232
|
-
|
|
233
|
-
|
|
137
|
+
r.extendsRegistrar(EXT_DERIVATIVE_OVERLAY_RESOLVER, {
|
|
138
|
+
onRegister: () => {
|
|
139
|
+
// No side-effects at register-time — resolution happens in
|
|
140
|
+
// variant(), keyed by the FileRef's entityType, before the spec
|
|
141
|
+
// hash is computed.
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Registered ONLY when resolveApexTenant is supplied — r.queryHandler
|
|
146
|
+
// registers publicVariantQuery into the feature's dispatch table as a
|
|
147
|
+
// side effect of being called, independent of what's done with its
|
|
148
|
+
// return value. Calling it unconditionally would make `publicVariant`
|
|
149
|
+
// (access: ["anonymous", ...]) reachable via the generic `/api` query
|
|
150
|
+
// dispatch even when the httpRoute below isn't mounted, bypassing the
|
|
151
|
+
// "tenantId comes from the host, never the payload" invariant that only
|
|
152
|
+
// `resolveApexTenant` enforces.
|
|
153
|
+
if (opts.resolveApexTenant) {
|
|
154
|
+
const resolveApexTenant = opts.resolveApexTenant;
|
|
155
|
+
const byFileRef = opts.publicTenantResolution === "fileRef";
|
|
156
|
+
const routeQn = byFileRef ? PUBLIC_VARIANT_BY_FILE_REF_QN : PUBLIC_VARIANT_QN;
|
|
157
|
+
|
|
158
|
+
r.queryHandler(publicVariantQuery);
|
|
159
|
+
// publicVariantByFileRefQuery is the ONLY way "fileRef" mode is
|
|
160
|
+
// reachable — registered ONLY in that mode for the same reason
|
|
161
|
+
// publicVariantQuery is gated above: registering it unconditionally
|
|
162
|
+
// would expose its unsafeRaw, cross-tenant FileRef lookup via the
|
|
163
|
+
// generic `/api` query dispatch even in default "host" mode.
|
|
164
|
+
if (byFileRef) {
|
|
165
|
+
// The handler reads the FileRef-tenant's row to keep a blocked
|
|
166
|
+
// tenant's public variants from staying reachable — require the
|
|
167
|
+
// dependency so a missing mount fails boot, not the tenant check
|
|
168
|
+
// silently no-op-ing at request time.
|
|
169
|
+
r.requires({ features: ["tenant"] });
|
|
170
|
+
r.queryHandler(publicVariantByFileRefQuery);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
r.httpRoute({
|
|
174
|
+
method: "GET",
|
|
175
|
+
path: `${basePath}/:fileRefId/:variant`,
|
|
176
|
+
anonymous: true,
|
|
177
|
+
handler: async (c, { systemQuery }) => {
|
|
178
|
+
// `param(...)` is string|undefined here — `path` is a computed
|
|
179
|
+
// template, so Hono can't infer the param type from a literal.
|
|
180
|
+
const fileRefId = c.req.param("fileRefId");
|
|
181
|
+
const variant = c.req.param("variant");
|
|
182
|
+
// 404, not 400 — a syntactically bad name and "doesn't exist" must
|
|
183
|
+
// answer identically, no name-oracle. fileRefsTable.id is a UUID
|
|
184
|
+
// column — a malformed id must fail here, not at the DB. Without
|
|
185
|
+
// this, an anonymous, internet-facing caller can throw a Postgres
|
|
186
|
+
// 22P02 on every request (Bun.SQL pools the failed connection), a
|
|
187
|
+
// DoS primitive with no auth required.
|
|
188
|
+
if (!fileRefId || !variant || !VARIANT_NAME_RE.test(variant) || !isUuid(fileRefId)) {
|
|
189
|
+
return c.text("not found", 404);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const host = c.req.header("host") ?? new URL(c.req.url).host;
|
|
193
|
+
const tenantId = await resolveApexTenant(host);
|
|
194
|
+
if (!tenantId) return c.text("not found", 404);
|
|
195
|
+
|
|
196
|
+
let result: PublicVariantQueryResult;
|
|
197
|
+
try {
|
|
198
|
+
// @cast-boundary engine-payload — shape comes from
|
|
199
|
+
// publicVariantQuery's return type (publicVariantByFileRefQuery
|
|
200
|
+
// returns exactly that, or null, never its own shape).
|
|
201
|
+
result = (await systemQuery(
|
|
202
|
+
routeQn,
|
|
203
|
+
{ fileRefId, variant },
|
|
204
|
+
tenantId,
|
|
205
|
+
)) as PublicVariantQueryResult;
|
|
206
|
+
} catch (err) {
|
|
207
|
+
if (err instanceof RateLimitError) {
|
|
208
|
+
return c.text("rate limited", 429);
|
|
209
|
+
}
|
|
210
|
+
// biome-ignore lint/suspicious/noConsole: ops-visible fallback, no logger wired into HttpRouteHandlerDeps
|
|
211
|
+
console.error(
|
|
212
|
+
`file-derivatives: public-variant query failed for fileRefId="${fileRefId}" variant="${variant}"`,
|
|
213
|
+
err,
|
|
214
|
+
);
|
|
215
|
+
return c.text("variant unavailable", 503);
|
|
216
|
+
}
|
|
217
|
+
if (!result) return c.text("not found", 404);
|
|
218
|
+
|
|
219
|
+
const bytes = Buffer.from(result.dataBase64, "base64");
|
|
220
|
+
const etag = computeRevisionEtag([tenantId, fileRefId, variant, result.revision]);
|
|
221
|
+
return cachedResponse(c.req.raw, {
|
|
222
|
+
body: bytes,
|
|
223
|
+
etag,
|
|
224
|
+
cache: { kind: "revalidate", maxAgeSeconds: 60 },
|
|
225
|
+
// Explicit here, not left to the app-wide security-headers default, so the route stays safe standalone.
|
|
226
|
+
headers: {
|
|
227
|
+
"content-type": result.mimeType,
|
|
228
|
+
vary: "Host",
|
|
229
|
+
"x-content-type-options": "nosniff",
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
Object.keys(opts).length === 0 ? { dedupeOptions: {} } : undefined,
|
|
237
|
+
);
|
|
234
238
|
}
|
|
235
239
|
|
|
240
|
+
/** @deprecated Use createFileDerivativesFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
236
241
|
export const fileDerivativesFeature = createFileDerivativesFeature();
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// but this handler's own isPublic gate runs exactly the same either way.
|
|
24
24
|
|
|
25
25
|
import { computeRevisionEtag } from "@cosmicdrift/kumiko-framework/api";
|
|
26
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
26
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
27
27
|
import { resolveFieldVariant } from "@cosmicdrift/kumiko-framework/derivatives";
|
|
28
28
|
import {
|
|
29
29
|
defineQueryHandler,
|
|
@@ -37,36 +37,45 @@ export {
|
|
|
37
37
|
|
|
38
38
|
const FEATURE_NAME = "file-foundation";
|
|
39
39
|
|
|
40
|
-
export
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
export function createFileFoundationFeature() {
|
|
41
|
+
return defineFeature(
|
|
42
|
+
FEATURE_NAME,
|
|
43
|
+
(r) => {
|
|
44
|
+
r.describe(
|
|
45
|
+
"Defines the `fileProvider` extension point and a per-tenant `provider` config key that selects which registered storage plugin to use at runtime. Call `createFileProviderForTenant(ctx, tenantId)` to get a `FileStorageProvider` — use this feature together with at least one `file-provider-*` feature; the `files` feature builds on top of it for tracked `FileRef` entities with GDPR hooks.",
|
|
46
|
+
);
|
|
47
|
+
r.uiHints({
|
|
48
|
+
displayLabel: "File Provider Foundation",
|
|
49
|
+
category: "storage",
|
|
50
|
+
recommended: false,
|
|
51
|
+
});
|
|
52
|
+
r.requires({ features: ["config"] });
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
r.extendsRegistrar(EXT_FILE_PROVIDER, {
|
|
55
|
+
onRegister: () => {
|
|
56
|
+
// No side-effects at register-time — registry stores the usage,
|
|
57
|
+
// factory looks it up at request-time.
|
|
58
|
+
},
|
|
59
|
+
});
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
const providerConfigKey = r.config(
|
|
62
|
+
"provider",
|
|
63
|
+
createTenantConfig("text", {
|
|
64
|
+
default: "",
|
|
65
|
+
env: FILE_STORAGE_PROVIDER_ENV,
|
|
66
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
67
|
+
read: access.roles("TenantAdmin", "SystemAdmin", "User"),
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
// Readiness gating: provider-plugins' required keys/secrets count only
|
|
71
|
+
// while their plugin is the one this key selects.
|
|
72
|
+
r.extensionSelector(EXT_FILE_PROVIDER, providerConfigKey);
|
|
73
|
+
|
|
74
|
+
return { providerConfigKey };
|
|
75
|
+
},
|
|
76
|
+
{ dedupeOptions: {} },
|
|
66
77
|
);
|
|
67
|
-
|
|
68
|
-
// while their plugin is the one this key selects.
|
|
69
|
-
r.extensionSelector(EXT_FILE_PROVIDER, providerConfigKey);
|
|
78
|
+
}
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
/** @deprecated Use createFileFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
81
|
+
export const fileFoundationFeature = createFileFoundationFeature();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
1
|
import type { DbRunner, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { isUuid, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import {
|
|
5
5
|
createFileContext,
|
|
@@ -58,27 +58,38 @@ export function clearStorage(tenantId: string): void {
|
|
|
58
58
|
// =============================================================================
|
|
59
59
|
// Feature-definition
|
|
60
60
|
// =============================================================================
|
|
61
|
+
export function createFileProviderInMemoryFeature() {
|
|
62
|
+
return defineFeature(
|
|
63
|
+
FEATURE_NAME,
|
|
64
|
+
(r) => {
|
|
65
|
+
r.describe(
|
|
66
|
+
'Registers an in-process `"inmemory"` provider for `file-foundation` that stores file bytes per tenant in a module-level Map. Use `listKeys(tenantId)` and `clearStorage(tenantId)` in demo apps and tests; not for production (data is lost on restart and grows without bound).',
|
|
67
|
+
);
|
|
68
|
+
r.uiHints({
|
|
69
|
+
displayLabel: "File Provider · In-Memory",
|
|
70
|
+
category: "storage",
|
|
71
|
+
recommended: false,
|
|
72
|
+
});
|
|
73
|
+
// Kein requires auf "config" oder "secrets" — der
|
|
74
|
+
// In-Memory-Provider hat keine Config + kein Secret. Nur die
|
|
75
|
+
// file-foundation muss da sein (Plugin-extension-point).
|
|
76
|
+
r.requires({ features: ["file-foundation"] });
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
const plugin: FileProviderPlugin = {
|
|
79
|
+
build: async (
|
|
80
|
+
_ctx: FileProviderContext,
|
|
81
|
+
tenantId: string,
|
|
82
|
+
): Promise<FileStorageProvider> => {
|
|
83
|
+
// Returns the per-tenant storage. Identity-stable across calls so
|
|
84
|
+
// accumulated state is kept.
|
|
85
|
+
return getOrCreateProviderForTenant(tenantId);
|
|
86
|
+
}, // @wrapper-known semantic-alias
|
|
87
|
+
};
|
|
88
|
+
r.useExtension("fileProvider", "inmemory", plugin);
|
|
89
|
+
},
|
|
90
|
+
{ dedupeOptions: {} },
|
|
65
91
|
);
|
|
66
|
-
|
|
67
|
-
displayLabel: "File Provider · In-Memory",
|
|
68
|
-
category: "storage",
|
|
69
|
-
recommended: false,
|
|
70
|
-
});
|
|
71
|
-
// Kein requires auf "config" oder "secrets" — der
|
|
72
|
-
// In-Memory-Provider hat keine Config + kein Secret. Nur die
|
|
73
|
-
// file-foundation muss da sein (Plugin-extension-point).
|
|
74
|
-
r.requires({ features: ["file-foundation"] });
|
|
92
|
+
}
|
|
75
93
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Returnt den per-tenant Storage. Identitätsstabil zwischen calls
|
|
79
|
-
// damit accumulated state erhalten bleibt.
|
|
80
|
-
return getOrCreateProviderForTenant(tenantId);
|
|
81
|
-
}, // @wrapper-known semantic-alias
|
|
82
|
-
};
|
|
83
|
-
r.useExtension("fileProvider", "inmemory", plugin);
|
|
84
|
-
});
|
|
94
|
+
/** @deprecated Use createFileProviderInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
95
|
+
export const fileProviderInMemoryFeature = createFileProviderInMemoryFeature();
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
// Public API of the file-provider-inmemory bundled-feature.
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
clearStorage,
|
|
5
|
+
createFileProviderInMemoryFeature,
|
|
6
|
+
fileProviderInMemoryFeature,
|
|
7
|
+
listKeys,
|
|
8
|
+
} from "./feature.js";
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
[
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.368.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "The S3 file providers merge into createFileProviderS3Feature({ fromEnv })",
|
|
6
|
+
"detail": "createFileProviderS3Feature() mounts the per-tenant config provider as before. createFileProviderS3Feature({ fromEnv: true }) mounts the env-configured provider (feature name, provider key \"s3-env\" and requires unchanged). The S3 client helpers (createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, S3ProviderConfig) move to the new subpath @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib.\n\nThe subpaths file-provider-s3-env and files-provider-s3 keep working as deprecated re-exports and are removed in the first release after 2026-10-29.\n\nold -> new:\n fileProviderS3EnvFeature from .../file-provider-s3-env -> createFileProviderS3Feature({ fromEnv: true }) from .../file-provider-s3\n fileProviderS3Feature -> createFileProviderS3Feature()\n @cosmicdrift/kumiko-bundled-features/files-provider-s3 -> @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib",
|
|
7
|
+
"migration": "Run `bun kumiko-upgrade --apply`. It rewrites the imports and the env feature mount, and reports `typeof fileProviderS3EnvFeature` and re-exports of it with file and line.",
|
|
8
|
+
"codemod": "scripts/codemod/s3-imports.ts"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// file-provider-s3-env — S3 file provider configured entirely from
|
|
2
|
+
// process.env. ONE shared bucket for ALL tenants: wire it by setting the
|
|
3
|
+
// `S3_*` env vars + mounting — no per-tenant admin seeding and no
|
|
4
|
+
// `secrets`-feature dependency.
|
|
5
|
+
//
|
|
6
|
+
// **vs the default file-provider-s3:** the config-based `"s3"` provider owns per-tenant
|
|
7
|
+
// config keys + an encrypted `s3.secretAccessKey` secret (per-tenant
|
|
8
|
+
// buckets, admin-seeded). This `"s3-env"` provider reads one credential set
|
|
9
|
+
// from env and serves every tenant from one bucket — the
|
|
10
|
+
// Hetzner-Object-Storage / single-bucket deploy case. Tenant isolation
|
|
11
|
+
// still holds: file keys carry the tenant (export ZIPs:
|
|
12
|
+
// `exports/<tenantId>/<jobId>.zip`) or are globally-unique UUIDs (fileRefs).
|
|
13
|
+
//
|
|
14
|
+
// **Pattern-Vorbild:** mirrors file-provider-inmemory (zero admin seeding,
|
|
15
|
+
// only the file-foundation plugin-point required).
|
|
16
|
+
//
|
|
17
|
+
// **Env vars** (read by createS3ProviderFromEnv, prefix `S3_`):
|
|
18
|
+
// required — S3_BUCKET, S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY
|
|
19
|
+
// optional — S3_ENDPOINT (S3-compat stores incl. Hetzner Object Storage),
|
|
20
|
+
// S3_FORCE_PATH_STYLE
|
|
21
|
+
// Missing required vars throw on the FIRST file op (inside the export cron).
|
|
22
|
+
// The user-data-rights boot guard surfaces that at boot instead.
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
FileProviderContext,
|
|
26
|
+
FileProviderPlugin,
|
|
27
|
+
} from "@cosmicdrift/kumiko-bundled-features/file-foundation";
|
|
28
|
+
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
29
|
+
import type { FileStorageProvider } from "@cosmicdrift/kumiko-framework/files";
|
|
30
|
+
import { createS3ProviderFromEnv } from "./lib/env-helper.js";
|
|
31
|
+
|
|
32
|
+
const FEATURE_NAME = "file-provider-s3-env";
|
|
33
|
+
|
|
34
|
+
export function createFileProviderS3EnvFeature() {
|
|
35
|
+
return defineFeature(
|
|
36
|
+
FEATURE_NAME,
|
|
37
|
+
(r) => {
|
|
38
|
+
r.describe(
|
|
39
|
+
'Registers an `"s3-env"` provider for `file-foundation` that reads one S3 credential set from `process.env` (`S3_BUCKET`/`S3_REGION`/`S3_ACCESS_KEY`/`S3_SECRET_KEY`, optional `S3_ENDPOINT`/`S3_FORCE_PATH_STYLE`) and serves every tenant from one shared bucket — no per-tenant config or secret seeding. Use this for single-bucket S3-compatible deploys (e.g. Hetzner Object Storage); use `file-provider-s3` instead when each tenant needs its own bucket/credentials.',
|
|
40
|
+
);
|
|
41
|
+
r.uiHints({
|
|
42
|
+
displayLabel: "File Provider · S3 (env)",
|
|
43
|
+
category: "storage",
|
|
44
|
+
recommended: false,
|
|
45
|
+
});
|
|
46
|
+
// No requires on "config" or "secrets" — credentials come from
|
|
47
|
+
// env, not the per-tenant config + secrets store. Only the file-foundation
|
|
48
|
+
// plugin-extension-point must be mounted.
|
|
49
|
+
r.requires({ features: ["file-foundation"] });
|
|
50
|
+
|
|
51
|
+
const plugin: FileProviderPlugin = {
|
|
52
|
+
// tenantId ignored: one shared bucket serves all tenants (isolation via
|
|
53
|
+
// tenant-prefixed / UUID keys). Built fresh per call like file-provider-s3;
|
|
54
|
+
// the S3 client opens no connection at construction.
|
|
55
|
+
build: async (_ctx: FileProviderContext, _tenantId: string): Promise<FileStorageProvider> =>
|
|
56
|
+
createS3ProviderFromEnv(), // @wrapper-known semantic-alias
|
|
57
|
+
};
|
|
58
|
+
r.useExtension("fileProvider", "s3-env", plugin);
|
|
59
|
+
},
|
|
60
|
+
{ dedupeOptions: {} },
|
|
61
|
+
);
|
|
62
|
+
}
|