@cosmicdrift/kumiko-bundled-features 0.367.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/dist/audit/handlers/details.query.js +1 -1
- package/dist/audit/handlers/list.query.js +1 -1
- package/dist/audit/run-escape-hatch-retention.js +1 -1
- package/dist/auth-email-password/bootstrap.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +6 -3
- package/dist/auth-email-password/handlers/invite-accept.write.js +6 -3
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +6 -3
- package/dist/auth-email-password/handlers/signup-confirm.write.js +1 -1
- package/dist/auth-email-password/seeding.js +2 -2
- package/dist/auth-foundation/feature.d.ts +4 -0
- package/dist/auth-foundation/feature.js +37 -33
- package/dist/auth-foundation/index.d.ts +1 -1
- package/dist/auth-foundation/index.js +1 -1
- package/dist/auth-mfa/db/queries.js +1 -2
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +2 -3
- package/dist/auth-mfa/handlers/status.query.js +1 -1
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/mfa-code-verifier.js +1 -1
- package/dist/auth-mfa/mfa-status-checker.js +1 -1
- package/dist/auth-mfa-user-data/index.d.ts +4 -0
- package/dist/auth-mfa-user-data/index.js +13 -9
- package/dist/billing-foundation/billing-info-query.js +1 -1
- package/dist/billing-foundation/feature.d.ts +1 -0
- package/dist/billing-foundation/feature.js +5 -6
- package/dist/billing-foundation/handlers/create-portal-session.write.js +1 -1
- package/dist/billing-foundation/projection.js +1 -2
- package/dist/cap-counter/calendar-cap-usage-reservation.d.ts +7 -0
- package/dist/cap-counter/calendar-cap-usage-reservation.js +28 -2
- package/dist/cap-counter/cap-reservation.d.ts +16 -0
- package/dist/cap-counter/cap-reservation.js +144 -14
- package/dist/cap-counter/feature.d.ts +4 -0
- package/dist/cap-counter/feature.js +74 -68
- package/dist/cap-counter/handlers/increment-rolling.write.js +3 -4
- package/dist/cap-counter/index.d.ts +3 -2
- package/dist/cap-counter/index.js +3 -2
- package/dist/cap-counter/tables.js +10 -3
- package/dist/cap-overview/handlers/caps-usage.query.js +1 -2
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +1 -2
- package/dist/cap-overview/handlers/tenant-options.query.js +1 -1
- package/dist/channel-in-app/handlers/inbox.query.js +1 -1
- package/dist/channel-in-app/handlers/mark-all-read.write.js +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.js +1 -1
- package/dist/channel-in-app/handlers/unread-count.query.js +1 -1
- package/dist/channel-in-app/tables.js +1 -2
- package/dist/compliance-profiles/handlers/for-tenant.query.js +1 -1
- package/dist/compliance-profiles/handlers/needs-profile.query.js +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.js +1 -2
- package/dist/compliance-profiles/resolve-for-tenant.js +1 -1
- package/dist/compliance-profiles/seeding.js +3 -5
- package/dist/compliance-profiles-ops/index.d.ts +8 -0
- package/dist/compliance-profiles-ops/index.js +19 -15
- package/dist/config/db/queries/resolver.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +2 -2
- package/dist/config/resolver.js +1 -1
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.js +6 -3
- package/dist/custom-fields/db/queries/field-access.js +1 -1
- package/dist/custom-fields/db/queries/projection.js +1 -1
- package/dist/custom-fields/db/queries/quota.js +1 -1
- package/dist/custom-fields/db/queries/retention.js +1 -2
- package/dist/custom-fields/db/queries/user-data-rights.js +1 -1
- package/dist/custom-fields/feature.d.ts +20 -2
- package/dist/custom-fields/feature.js +9 -13
- package/dist/custom-fields/handlers/clear-custom-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/set-custom-field.write.js +2 -2
- package/dist/custom-fields/wire-for-entity.js +4 -4
- package/dist/data-retention/resolve-for-tenant.js +1 -1
- package/dist/data-retention/run-retention-cleanup.js +17 -13
- package/dist/delivery/address-opt-out.js +1 -2
- package/dist/delivery/attempt-log-retention.js +1 -1
- package/dist/delivery/channel-context.js +1 -1
- package/dist/delivery/db/queries/address-opt-outs.js +1 -1
- package/dist/delivery/db/queries/preferences.js +1 -1
- package/dist/delivery/delivery-service.js +16 -7
- package/dist/delivery/feature.js +1 -1
- package/dist/delivery/handlers/log.query.js +2 -3
- package/dist/delivery/handlers/preferences.query.js +1 -1
- package/dist/delivery/upsert-preference.js +1 -2
- package/dist/derivatives-sharp/feature.d.ts +4 -0
- package/dist/derivatives-sharp/feature.js +15 -11
- package/dist/derivatives-sharp/index.d.ts +1 -1
- package/dist/derivatives-sharp/index.js +1 -1
- package/dist/document-ingest-foundation/feature.d.ts +7 -0
- package/dist/document-ingest-foundation/feature.js +94 -90
- package/dist/document-ingest-foundation/forget-extract-with-file-ref.js +3 -3
- package/dist/document-ingest-foundation/index.d.ts +1 -1
- package/dist/document-ingest-foundation/index.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -2
- package/dist/feature-toggles/handlers/set.write.js +3 -5
- package/dist/feature-toggles/toggle-runtime.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -0
- package/dist/file-derivatives/feature.js +2 -1
- package/dist/file-derivatives/handlers/public-variant-by-file-ref.query.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-foundation/feature.d.ts +6 -0
- package/dist/file-foundation/feature.js +29 -25
- package/dist/file-foundation/index.d.ts +1 -1
- package/dist/file-foundation/index.js +1 -1
- package/dist/file-foundation/read-file-ref-content.js +1 -1
- package/dist/file-provider-inmemory/feature.d.ts +4 -0
- package/dist/file-provider-inmemory/feature.js +24 -20
- package/dist/file-provider-inmemory/index.d.ts +1 -1
- package/dist/file-provider-inmemory/index.js +1 -1
- package/dist/file-provider-s3/env-feature.d.ts +3 -0
- package/dist/file-provider-s3/env-feature.js +46 -0
- package/dist/file-provider-s3/feature.d.ts +26 -0
- package/dist/file-provider-s3/feature.js +84 -72
- package/dist/file-provider-s3/index.d.ts +1 -1
- package/dist/file-provider-s3/index.js +1 -1
- package/dist/file-provider-s3/lib/index.d.ts +3 -0
- package/dist/file-provider-s3/lib/index.js +2 -0
- package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.js +19 -19
- package/dist/file-provider-s3-env/index.d.ts +8 -1
- package/dist/file-provider-s3-env/index.js +7 -2
- package/dist/files-provider-s3/index.d.ts +5 -3
- package/dist/files-provider-s3/index.js +5 -2
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +1 -1
- package/dist/files-tenant-data/hooks.js +1 -2
- package/dist/folders/feature.d.ts +6 -2
- package/dist/folders/feature.js +4 -2
- package/dist/folders-user-data/index.d.ts +4 -0
- package/dist/folders-user-data/index.js +21 -17
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/draft-count.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -2
- package/dist/form-draft/feature.d.ts +4 -0
- package/dist/form-draft/feature.js +5 -1
- package/dist/form-draft/handlers/cleanup.job.js +2 -2
- package/dist/form-draft/index.d.ts +1 -1
- package/dist/form-draft/index.js +1 -1
- package/dist/form-draft/lookup.js +1 -1
- package/dist/form-draft-user-data/index.d.ts +4 -0
- package/dist/form-draft-user-data/index.js +13 -9
- package/dist/inbound-mail-foundation/feature.d.ts +4 -0
- package/dist/inbound-mail-foundation/feature.js +151 -147
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -2
- package/dist/inbound-mail-foundation/index.d.ts +1 -1
- package/dist/inbound-mail-foundation/index.js +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +1 -2
- package/dist/inbound-mail-foundation/projection.js +1 -2
- package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
- package/dist/inbound-provider-imap/feature.d.ts +4 -0
- package/dist/inbound-provider-imap/feature.js +16 -12
- package/dist/inbound-provider-imap/index.d.ts +1 -1
- package/dist/inbound-provider-imap/index.js +1 -1
- package/dist/inbound-provider-inmemory/feature.d.ts +4 -0
- package/dist/inbound-provider-inmemory/feature.js +14 -10
- package/dist/inbound-provider-inmemory/index.d.ts +1 -1
- package/dist/inbound-provider-inmemory/index.js +1 -1
- package/dist/jobs/db/queries/retention.js +1 -1
- package/dist/jobs/db/queries/stale-run-sweep.js +1 -1
- package/dist/jobs/handlers/detail.query.js +1 -1
- package/dist/jobs/handlers/list.query.js +1 -2
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/handlers/tenant-failures.query.js +1 -1
- package/dist/jobs/handlers/tenant-runs.query.js +1 -1
- package/dist/jobs/job-run-logger.js +1 -2
- package/dist/jobs/tenant-job-failure-table.js +1 -2
- package/dist/jobs/tenant-job-run-table.js +1 -2
- package/dist/ledger/feature.d.ts +6 -2
- package/dist/ledger/feature.js +4 -2
- package/dist/mail-foundation/feature.d.ts +7 -0
- package/dist/mail-foundation/feature.js +48 -42
- package/dist/mail-foundation/index.d.ts +1 -1
- package/dist/mail-foundation/index.js +1 -1
- package/dist/mail-transport-inmemory/feature.d.ts +4 -0
- package/dist/mail-transport-inmemory/feature.js +20 -16
- package/dist/mail-transport-inmemory/index.d.ts +1 -1
- package/dist/mail-transport-inmemory/index.js +1 -1
- package/dist/mail-transport-smtp/feature.d.ts +16 -0
- package/dist/mail-transport-smtp/feature.js +85 -79
- package/dist/mail-transport-smtp/index.d.ts +1 -1
- package/dist/mail-transport-smtp/index.js +1 -1
- package/dist/managed-pages/handlers/by-slug.query.js +1 -1
- package/dist/managed-pages/handlers/by-tenant-published.query.js +1 -2
- package/dist/managed-pages/handlers/set.write.js +1 -2
- package/dist/managed-pages/seeding.js +3 -5
- package/dist/metrics/compute.d.ts +1 -1
- package/dist/metrics/filters.d.ts +1 -1
- package/dist/metrics/filters.js +1 -1
- package/dist/metrics/validate.js +1 -1
- package/dist/notes-history/feature.d.ts +7 -2
- package/dist/notes-history/feature.js +4 -2
- package/dist/notes-history/handlers/add-note.write.js +1 -1
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/notes-history-user-data/index.d.ts +4 -0
- package/dist/notes-history-user-data/index.js +21 -17
- package/dist/personal-access-tokens/feature.d.ts +4 -1
- package/dist/personal-access-tokens/feature.js +10 -2
- package/dist/personal-access-tokens/handlers/create.write.js +1 -1
- package/dist/personal-access-tokens/handlers/list.query.js +2 -2
- package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
- package/dist/personal-access-tokens/resolver.js +1 -1
- package/dist/personal-access-tokens/revoke-for-user.js +1 -1
- package/dist/personal-access-tokens/roles.js +3 -5
- package/dist/personal-access-tokens/screens.js +2 -0
- package/dist/readiness/feature.d.ts +8 -0
- package/dist/readiness/feature.js +18 -14
- package/dist/readiness/index.d.ts +1 -1
- package/dist/readiness/index.js +1 -1
- package/dist/secrets/db/queries/read.js +1 -1
- package/dist/secrets/feature.d.ts +3 -0
- package/dist/secrets/feature.js +3 -2
- package/dist/secrets/handlers/rotate.job.js +2 -3
- package/dist/secrets/secrets-context.js +3 -4
- package/dist/sessions/db/queries/cleanup.js +1 -1
- package/dist/sessions/handlers/detail.query.js +1 -1
- package/dist/sessions/handlers/list.query.js +2 -2
- package/dist/sessions/handlers/mine.query.js +1 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/session-callbacks.js +4 -6
- package/dist/sessions/testing.d.ts +1 -1
- package/dist/tags/feature.d.ts +6 -2
- package/dist/tags/feature.js +4 -2
- package/dist/template-resolver/api.js +1 -1
- package/dist/template-resolver/handlers/bundle-import.js +1 -1
- package/dist/template-resolver/handlers/by-slug.query.js +1 -1
- package/dist/template-resolver/handlers/by-tenant.query.js +1 -2
- package/dist/template-resolver/handlers/collection-item.query.js +1 -1
- package/dist/template-resolver/handlers/collection-list.query.js +1 -2
- package/dist/template-resolver/handlers/collection-set.write.js +1 -1
- package/dist/template-resolver/handlers/copy-locale.write.js +1 -1
- package/dist/template-resolver/handlers/diff-to-system.query.js +1 -1
- package/dist/template-resolver/handlers/export-bundle.query.js +1 -1
- package/dist/template-resolver/handlers/find-by-id.query.js +1 -1
- package/dist/template-resolver/handlers/layout-source.query.js +1 -1
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/overview.query.js +1 -1
- package/dist/template-resolver/handlers/reset-to-system.write.js +1 -1
- package/dist/template-resolver/handlers/resource-remove.write.js +1 -1
- package/dist/template-resolver/handlers/set.write.js +1 -1
- package/dist/template-resolver/handlers/template-write.js +1 -1
- package/dist/template-resolver/handlers/tenant-overrides.query.js +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.js +1 -1
- package/dist/template-resolver/handlers/usage.query.js +1 -1
- package/dist/template-resolver/handlers/validate.query.js +1 -1
- package/dist/template-resolver/seeding.js +3 -4
- package/dist/template-resolver/store-template-resource.js +1 -1
- package/dist/template-resolver/template-preview.js +1 -1
- package/dist/template-resolver/template-resources.js +1 -1
- package/dist/template-resolver/testing.js +1 -1
- package/dist/template-resolver-user-data/index.d.ts +4 -0
- package/dist/template-resolver-user-data/index.js +17 -13
- package/dist/tenant/handlers/active-tenant-ids.query.js +1 -1
- package/dist/tenant/handlers/add-member.write.js +1 -2
- package/dist/tenant/handlers/cancel-invitation.write.js +1 -1
- package/dist/tenant/handlers/invitations.query.js +1 -1
- package/dist/tenant/handlers/me.query.js +1 -1
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/memberships.query.js +1 -1
- package/dist/tenant/handlers/remove-member.write.js +1 -2
- package/dist/tenant/handlers/resolve-user-ids.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/handlers/update-member-roles.write.js +1 -2
- package/dist/tenant/invited-membership.js +2 -3
- package/dist/tenant/last-tenant-admin.js +1 -2
- package/dist/tenant/seeding.js +12 -6
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +1 -2
- package/dist/tenant-lifecycle/handlers/request-destruction.write.js +1 -2
- package/dist/tenant-lifecycle/lib/revoke-tenant-sessions.js +1 -1
- package/dist/tenant-lifecycle/lifecycle-gate.js +1 -1
- package/dist/tenant-lifecycle/run-tenant-destroy.js +3 -5
- package/dist/tenant-lifecycle/stages.js +10 -6
- package/dist/tenant-lifecycle/testing.d.ts +1 -1
- package/dist/tenant-lifecycle/testing.js +2 -2
- package/dist/tenant-settings/feature.d.ts +1 -0
- package/dist/tenant-settings/feature.js +2 -1
- package/dist/tier-engine/feature.d.ts +1 -8
- package/dist/tier-engine/feature.js +71 -78
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +2 -3
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -2
- package/dist/user/db/queries/stream-tenant-backfill.js +1 -1
- package/dist/user/handlers/create.write.js +1 -2
- package/dist/user/handlers/find-for-auth.query.js +1 -1
- package/dist/user/handlers/list.query.js +1 -1
- package/dist/user/handlers/update-roles.js +1 -2
- package/dist/user/index.d.ts +1 -1
- package/dist/user/index.js +1 -1
- package/dist/user/invited-global-roles.js +2 -3
- package/dist/user/principal-status.d.ts +4 -0
- package/dist/user/principal-status.js +9 -3
- package/dist/user/resolve-display-names.js +1 -1
- package/dist/user/seeding.js +5 -6
- package/dist/user-data-rights/audit-download.js +2 -2
- package/dist/user-data-rights/db/queries/export-jobs.js +1 -1
- package/dist/user-data-rights/db/queries/forget-cleanup.js +1 -1
- package/dist/user-data-rights/handlers/download-by-job.query.js +1 -1
- package/dist/user-data-rights/handlers/download-by-token.query.js +1 -1
- package/dist/user-data-rights/handlers/export-status.query.js +1 -1
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
- package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
- package/dist/user-data-rights/handlers/request-export.write.js +1 -2
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +3 -3
- package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.d.ts +1 -1
- package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.js +1 -1
- package/dist/user-data-rights/lib/update-user-lifecycle.d.ts +1 -0
- package/dist/user-data-rights/lib/update-user-lifecycle.js +3 -3
- package/dist/user-data-rights/run-export-jobs.js +2 -3
- package/dist/user-data-rights/run-forget-cleanup.js +9 -5
- package/dist/user-data-rights/run-user-export.js +9 -5
- package/dist/waitlist/handlers/invite.write.js +1 -2
- package/dist/waitlist/handlers/reject.write.js +1 -1
- package/dist/waitlist/lib.js +1 -2
- package/dist/workflow-runner/event-subscriber.js +1 -1
- package/dist/workflow-runner/feature.d.ts +4 -0
- package/dist/workflow-runner/feature.js +44 -40
- package/dist/workflow-runner/handlers/resume-run.write.js +1 -1
- package/dist/workflow-runner/index.d.ts +1 -1
- package/dist/workflow-runner/index.js +1 -1
- package/dist/workflow-runner/pending-projection.js +1 -1
- package/package.json +28 -11
- package/src/cap-counter/changes.json +13 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/file-provider-s3/changes.json +10 -1
- package/src/personal-access-tokens/changes.json +6 -0
- package/src/user/changes.json +6 -0
- package/dist/file-provider-s3-env/feature.d.ts +0 -3
- package/dist/file-provider-s3-env/feature.js +0 -46
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.d.ts +0 -0
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.js +0 -0
- /package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.d.ts +0 -0
|
@@ -11,86 +11,98 @@
|
|
|
11
11
|
// { build })`. file-foundation's Factory findet den Plugin via
|
|
12
12
|
// registry.
|
|
13
13
|
// 3. build(ctx, tenantId) liest config + secret, ruft `createS3Provider`
|
|
14
|
-
// aus
|
|
14
|
+
// aus ./lib auf. Der EINZIGE Cross-Feature-Import
|
|
15
15
|
// des Plugins — bewusst lokal gehalten.
|
|
16
16
|
//
|
|
17
17
|
// **Pattern-Vorbild:** mirrors mail-transport-smtp.
|
|
18
18
|
//
|
|
19
19
|
// **Boot-Dependencies:** config + secrets + file-foundation.
|
|
20
|
-
import { createS3Provider } from "@cosmicdrift/kumiko-bundled-features/files-provider-s3";
|
|
21
20
|
import { requireDefined, requireNonEmpty, requireSecretSet, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
22
21
|
import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
|
|
23
22
|
import { access, createTenantConfig, defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
23
|
+
import { createFileProviderS3EnvFeature } from "./env-feature.js";
|
|
24
|
+
import { createS3Provider } from "./lib/s3-provider.js";
|
|
24
25
|
const FEATURE_NAME = "file-provider-s3";
|
|
25
26
|
// =============================================================================
|
|
26
27
|
// Feature-definition
|
|
27
28
|
// =============================================================================
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
29
|
+
function createTenantConfigFileProviderS3Feature() {
|
|
30
|
+
return defineFeature(FEATURE_NAME, (r) => {
|
|
31
|
+
r.describe('Registers itself as the `"s3"` provider for `file-foundation` and owns the per-tenant config keys (`bucket`, `region`, `endpoint`, `forcePathStyle`, `accessKeyId`) and the encrypted `s3.secretAccessKey` secret. Compatible with any S3-compatible object store (AWS S3, Hetzner Object Storage); set credentials via the admin UI or a seed handler before the first file operation.');
|
|
32
|
+
r.uiHints({
|
|
33
|
+
displayLabel: "File Provider · S3",
|
|
34
|
+
category: "storage",
|
|
35
|
+
recommended: false,
|
|
36
|
+
});
|
|
37
|
+
r.requires({ features: ["config"] });
|
|
38
|
+
r.requires({ features: ["secrets"] });
|
|
39
|
+
r.requires({ features: ["file-foundation"] });
|
|
40
|
+
const secretAccessKey = r.secret("s3.secretAccessKey", {
|
|
41
|
+
label: { en: "S3 secret access key" },
|
|
42
|
+
hint: {
|
|
43
|
+
en: "Private half of the S3 key pair. Hetzner calls it 'Secret Key', AWS calls it 'Secret Access Key'.",
|
|
44
|
+
},
|
|
45
|
+
redact: (plaintext) => {
|
|
46
|
+
if (plaintext.length < 8)
|
|
47
|
+
return "•".repeat(plaintext.length);
|
|
48
|
+
return `${plaintext.slice(0, 4)}...${plaintext.slice(-4)}`;
|
|
49
|
+
},
|
|
50
|
+
scope: "tenant",
|
|
51
|
+
// required: true ↔ the missing-secret throw in readSecretAccessKey — keep in sync.
|
|
52
|
+
required: true,
|
|
53
|
+
});
|
|
54
|
+
// required: true ↔ the requireNonEmpty calls in buildS3Provider — keep in sync.
|
|
55
|
+
const configKeys = r.config({
|
|
56
|
+
keys: {
|
|
57
|
+
bucket: createTenantConfig("text", {
|
|
58
|
+
required: true,
|
|
59
|
+
default: "",
|
|
60
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
61
|
+
read: access.roles("TenantAdmin", "SystemAdmin"),
|
|
62
|
+
}),
|
|
63
|
+
region: createTenantConfig("text", {
|
|
64
|
+
required: true,
|
|
65
|
+
default: "",
|
|
66
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
67
|
+
read: access.roles("TenantAdmin", "SystemAdmin"),
|
|
68
|
+
}),
|
|
69
|
+
endpoint: createTenantConfig("text", {
|
|
70
|
+
default: "",
|
|
71
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
72
|
+
read: access.roles("TenantAdmin", "SystemAdmin"),
|
|
73
|
+
}),
|
|
74
|
+
forcePathStyle: createTenantConfig("boolean", {
|
|
75
|
+
default: false,
|
|
76
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
77
|
+
}),
|
|
78
|
+
accessKeyId: createTenantConfig("text", {
|
|
79
|
+
required: true,
|
|
80
|
+
default: "",
|
|
81
|
+
write: access.roles("TenantAdmin", "SystemAdmin"),
|
|
82
|
+
read: access.roles("TenantAdmin", "SystemAdmin"),
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
// Plugin-Registration. entityName "s3" ist was tenants in
|
|
87
|
+
// file-foundation's `provider` config-key setzen.
|
|
88
|
+
const plugin = {
|
|
89
|
+
build: async (ctx, tenantId) => buildS3Provider(ctx, tenantId), // @wrapper-known semantic-alias
|
|
90
|
+
};
|
|
91
|
+
r.useExtension("fileProvider", "s3", plugin);
|
|
92
|
+
return { configKeys, secretAccessKey };
|
|
93
|
+
}, { dedupeOptions: {} });
|
|
94
|
+
}
|
|
95
|
+
export function createFileProviderS3Feature(options = {}) {
|
|
96
|
+
return options.fromEnv === true
|
|
97
|
+
? createFileProviderS3EnvFeature()
|
|
98
|
+
: createTenantConfigFileProviderS3Feature();
|
|
99
|
+
}
|
|
100
|
+
/** @deprecated Use createFileProviderS3Feature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
101
|
+
export const fileProviderS3Feature = createFileProviderS3Feature();
|
|
102
|
+
// Typed config/secret handles are identical across instances, so one module-level instance serves them.
|
|
103
|
+
const tenantConfigFeature = createTenantConfigFileProviderS3Feature();
|
|
92
104
|
/** Typed handle for the S3 secret-access-key. */
|
|
93
|
-
export const S3_SECRET_ACCESS_KEY =
|
|
105
|
+
export const S3_SECRET_ACCESS_KEY = tenantConfigFeature.exports.secretAccessKey;
|
|
94
106
|
// =============================================================================
|
|
95
107
|
// Internal: build the FileStorageProvider from tenant config + secret
|
|
96
108
|
// =============================================================================
|
|
@@ -100,12 +112,12 @@ async function buildS3Provider(ctx, tenantId) {
|
|
|
100
112
|
throw new Error(`${FEATURE_NAME}: ctx.config is missing — feature requires the config-feature mounted in the registry`);
|
|
101
113
|
}
|
|
102
114
|
const FILE_HINT = "Set via tenant-admin UI or seed-handler before reading or writing files.";
|
|
103
|
-
const bucket = requireNonEmpty(await ctxConfig(
|
|
104
|
-
const region = requireNonEmpty(await ctxConfig(
|
|
105
|
-
const endpointRaw = requireDefined(await ctxConfig(
|
|
115
|
+
const bucket = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.bucket), FEATURE_NAME, "bucket", FILE_HINT);
|
|
116
|
+
const region = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.region), FEATURE_NAME, "region", FILE_HINT);
|
|
117
|
+
const endpointRaw = requireDefined(await ctxConfig(tenantConfigFeature.exports.configKeys.endpoint), FEATURE_NAME, "endpoint"); // @cast-boundary engine-payload
|
|
106
118
|
const endpoint = endpointRaw.length > 0 ? endpointRaw : undefined;
|
|
107
|
-
const forcePathStyle = requireDefined(await ctxConfig(
|
|
108
|
-
const accessKeyId = requireNonEmpty(await ctxConfig(
|
|
119
|
+
const forcePathStyle = requireDefined(await ctxConfig(tenantConfigFeature.exports.configKeys.forcePathStyle), FEATURE_NAME, "forcePathStyle"); // @cast-boundary engine-payload
|
|
120
|
+
const accessKeyId = requireNonEmpty(await ctxConfig(tenantConfigFeature.exports.configKeys.accessKeyId), FEATURE_NAME, "accessKeyId", FILE_HINT);
|
|
109
121
|
const secretAccessKey = await readSecretAccessKey(ctx, tenantId);
|
|
110
122
|
return createS3Provider({
|
|
111
123
|
bucket,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { fileProviderS3Feature, S3_SECRET_ACCESS_KEY } from "./feature.js";
|
|
1
|
+
export { createFileProviderS3Feature, type FileProviderS3FeatureOptions, fileProviderS3Feature, S3_SECRET_ACCESS_KEY, } from "./feature.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Public API of the file-provider-s3 bundled-feature.
|
|
2
|
-
export { fileProviderS3Feature, S3_SECRET_ACCESS_KEY } from "./feature.js";
|
|
2
|
+
export { createFileProviderS3Feature, fileProviderS3Feature, S3_SECRET_ACCESS_KEY, } from "./feature.js";
|
|
@@ -3,12 +3,12 @@ import { assertSafeStorageKey, } from "@cosmicdrift/kumiko-framework/files";
|
|
|
3
3
|
// Operator-Pflicht-Setup (Multipart-Upload-Cleanup)
|
|
4
4
|
// =============================================================================
|
|
5
5
|
//
|
|
6
|
-
// `writeStream`
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// in S3
|
|
11
|
-
//
|
|
6
|
+
// `writeStream` uses Bun's S3 writer for real multipart streaming. S3
|
|
7
|
+
// creates a multipart-upload session with an upload ID for it; on normal
|
|
8
|
+
// completion the session is closed. If the export worker is cancelled
|
|
9
|
+
// mid-write (pod restart, K8s OOM kill, process signal), the session stays
|
|
10
|
+
// OPEN in S3 and bills storage for the parts already uploaded — until a
|
|
11
|
+
// lifecycle rule aborts it.
|
|
12
12
|
//
|
|
13
13
|
// **Pflicht-Operator-Setup auf jedem Bucket:**
|
|
14
14
|
//
|
|
@@ -21,9 +21,9 @@ import { assertSafeStorageKey, } from "@cosmicdrift/kumiko-framework/files";
|
|
|
21
21
|
// }]
|
|
22
22
|
// }
|
|
23
23
|
//
|
|
24
|
-
// AWS
|
|
25
|
-
// --lifecycle-configuration file://lifecycle.json`. Hetzner Object Storage
|
|
26
|
-
//
|
|
24
|
+
// AWS CLI: `aws s3api put-bucket-lifecycle-configuration --bucket <name>
|
|
25
|
+
// --lifecycle-configuration file://lifecycle.json`. Hetzner Object Storage,
|
|
26
|
+
// R2 and Minio support the same syntax.
|
|
27
27
|
//
|
|
28
28
|
// =============================================================================
|
|
29
29
|
// Operator-Pflicht-Setup (IAM: list permission)
|
|
@@ -82,11 +82,11 @@ export function createS3Provider(config) {
|
|
|
82
82
|
},
|
|
83
83
|
async writeStream(key, source, options) {
|
|
84
84
|
assertSafeStorageKey(key);
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
85
|
+
// Real multipart streaming via Bun's S3 writer — partSize controls the
|
|
86
|
+
// part boundary internally (AWS/R2 require non-final parts >= 5 MiB,
|
|
87
|
+
// otherwise EntityTooSmall on CompleteMultipartUpload). A manual flush()
|
|
88
|
+
// here would break exactly that guarantee as soon as the source chunks
|
|
89
|
+
// do not line up with partSize.
|
|
90
90
|
const writer = client.file(key).writer({
|
|
91
91
|
...(options?.mimeType !== undefined && { type: options.mimeType }),
|
|
92
92
|
retry: 3,
|
|
@@ -94,8 +94,8 @@ export function createS3Provider(config) {
|
|
|
94
94
|
partSize: STREAM_PART_SIZE,
|
|
95
95
|
});
|
|
96
96
|
for await (const chunk of source) {
|
|
97
|
-
// Await applies
|
|
98
|
-
// queueSize
|
|
97
|
+
// Await applies backpressure and bounds the in-flight queue to
|
|
98
|
+
// queueSize instead of buffering without limit.
|
|
99
99
|
await writer.write(chunk);
|
|
100
100
|
}
|
|
101
101
|
await writer.end();
|
|
@@ -106,9 +106,9 @@ export function createS3Provider(config) {
|
|
|
106
106
|
},
|
|
107
107
|
readStream(key) {
|
|
108
108
|
assertSafeStorageKey(key);
|
|
109
|
-
// Lazy:
|
|
110
|
-
//
|
|
111
|
-
//
|
|
109
|
+
// Lazy: the GET request is only sent on the first chunk pull. If the key
|
|
110
|
+
// does not exist, the error surfaces right there (not on the readStream
|
|
111
|
+
// call) — same lazy behavior as inmemory + local.
|
|
112
112
|
return {
|
|
113
113
|
async *[Symbol.asyncIterator]() {
|
|
114
114
|
for await (const chunk of client.file(key).stream()) {
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Use createFileProviderS3Feature({ fromEnv: true }) from
|
|
3
|
+
* `@cosmicdrift/kumiko-bundled-features/file-provider-s3`. Run `bun kumiko-upgrade --apply`.
|
|
4
|
+
* Removed in the first release after 2026-10-29.
|
|
5
|
+
*/
|
|
6
|
+
export declare const fileProviderS3EnvFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
7
|
+
readonly exports: void;
|
|
8
|
+
};
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { createFileProviderS3Feature } from "../file-provider-s3/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated Use createFileProviderS3Feature({ fromEnv: true }) from
|
|
4
|
+
* `@cosmicdrift/kumiko-bundled-features/file-provider-s3`. Run `bun kumiko-upgrade --apply`.
|
|
5
|
+
* Removed in the first release after 2026-10-29.
|
|
6
|
+
*/
|
|
7
|
+
export const fileProviderS3EnvFeature = createFileProviderS3Feature({ fromEnv: true });
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Moved to `@cosmicdrift/kumiko-bundled-features/file-provider-s3/lib`. Run `bun kumiko-upgrade --apply`
|
|
3
|
+
* to rewrite imports. Removed in the first release after 2026-10-29.
|
|
4
|
+
*/
|
|
5
|
+
export { createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, type S3ProviderConfig, } from "../file-provider-s3/lib/index.js";
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Moved to `@cosmicdrift/kumiko-bundled-features/file-provider-s3/lib`. Run `bun kumiko-upgrade --apply`
|
|
3
|
+
* to rewrite imports. Removed in the first release after 2026-10-29.
|
|
4
|
+
*/
|
|
5
|
+
export { createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, } from "../file-provider-s3/lib/index.js";
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// were a tenant. nextBatch pages tenants internally and buffers their
|
|
18
18
|
// candidates into a flat queue so the shared deadline/circuit-breaker/signal
|
|
19
19
|
// handling still applies per-key.
|
|
20
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
20
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
21
21
|
import { parseDerivativeKey } from "@cosmicdrift/kumiko-framework/derivatives";
|
|
22
22
|
import { assertSafeStorageKey, fileRefsTable, } from "@cosmicdrift/kumiko-framework/files";
|
|
23
23
|
import * as z from "zod";
|
|
@@ -45,8 +45,7 @@
|
|
|
45
45
|
// matches would still delete it out from under the tenant that claimed
|
|
46
46
|
// its original. Batched: one existence query per chunk of listed keys,
|
|
47
47
|
// not one query per key.
|
|
48
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
49
|
-
import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
48
|
+
import { createEventStoreExecutor, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
50
49
|
import { createSystemUser, parseTenantId, } from "@cosmicdrift/kumiko-framework/engine";
|
|
51
50
|
import { assertSafeStorageKey, fileRefEntity, fileRefsTable, storageKeyStemPrefix, tenantStoragePrefixes, } from "@cosmicdrift/kumiko-framework/files";
|
|
52
51
|
import { runChunkedMigration } from "../shared/index.js";
|
|
@@ -2,7 +2,7 @@ import { type AccessRule, type EntityDefinition } from "@cosmicdrift/kumiko-fram
|
|
|
2
2
|
type FoldersToggleable = {
|
|
3
3
|
readonly default: boolean;
|
|
4
4
|
};
|
|
5
|
-
|
|
5
|
+
declare const defaultFoldersFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
6
6
|
readonly exports: void;
|
|
7
7
|
};
|
|
8
8
|
export type FoldersFeatureOptions = {
|
|
@@ -41,5 +41,9 @@ export type FoldersFeatureOptions = {
|
|
|
41
41
|
* otherwise considers every registered entity as a candidate host. */
|
|
42
42
|
readonly parents?: readonly string[];
|
|
43
43
|
};
|
|
44
|
-
export declare function createFoldersFeature(opts?: FoldersFeatureOptions): typeof
|
|
44
|
+
export declare function createFoldersFeature(opts?: FoldersFeatureOptions): typeof defaultFoldersFeature;
|
|
45
|
+
/** @deprecated Use createFoldersFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
46
|
+
export declare const foldersFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
47
|
+
readonly exports: void;
|
|
48
|
+
};
|
|
45
49
|
export {};
|
package/dist/folders/feature.js
CHANGED
|
@@ -62,7 +62,7 @@ function registerFolders(r, access, toggleable, ownership, parents) {
|
|
|
62
62
|
description: "Lists the folder-membership rows of the caller's tenant; filter on entityId to learn which folder one entity sits in, or on folderId to list everything filed into a folder.",
|
|
63
63
|
}));
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
const defaultFoldersFeature = defineFeature(FOLDERS_FEATURE_NAME, (r) => registerFolders(r, DEFAULT_FOLDER_ACCESS, undefined, undefined, undefined));
|
|
66
66
|
function resolveAccess(opts) {
|
|
67
67
|
if (opts.access !== undefined)
|
|
68
68
|
return opts.access;
|
|
@@ -78,7 +78,7 @@ export function createFoldersFeature(opts = {}) {
|
|
|
78
78
|
opts.toggleable === undefined &&
|
|
79
79
|
opts.ownership === undefined &&
|
|
80
80
|
opts.parents === undefined) {
|
|
81
|
-
return
|
|
81
|
+
return defaultFoldersFeature;
|
|
82
82
|
}
|
|
83
83
|
assertNoWhereRuleInOwnershipWrite("createFoldersFeature", opts.ownership?.write);
|
|
84
84
|
if (opts.parents !== undefined && opts.parents.length === 0) {
|
|
@@ -90,3 +90,5 @@ export function createFoldersFeature(opts = {}) {
|
|
|
90
90
|
const access = resolveAccess(opts);
|
|
91
91
|
return defineFeature(FOLDERS_FEATURE_NAME, (r) => registerFolders(r, access, opts.toggleable, opts.ownership, opts.parents));
|
|
92
92
|
}
|
|
93
|
+
/** @deprecated Use createFoldersFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
94
|
+
export const foldersFeature = createFoldersFeature();
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare function createFoldersUserDataFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
|
+
readonly exports: void;
|
|
3
|
+
};
|
|
4
|
+
/** @deprecated Use createFoldersUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
1
5
|
export declare const foldersUserDataFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
6
|
readonly exports: void;
|
|
3
7
|
};
|
|
@@ -5,20 +5,24 @@
|
|
|
5
5
|
// folders stays usable without the user-data-rights stack. Mirrors credit-user-data.
|
|
6
6
|
import { defineFeature, EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
|
|
7
7
|
import { folderAssignmentDeleteHook, folderAssignmentExportHook, folderDeleteHook, folderExportHook, } from "./hooks.js";
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
8
|
+
export function createFoldersUserDataFeature() {
|
|
9
|
+
return defineFeature("folders-user-data", (r) => {
|
|
10
|
+
r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `folders` feature's `folder` + `folder-assignment` entities. Mounts the EXT_USER_DATA export + delete hooks so a tenant's folder tree and its entity-to-folder assignments are included in the user-data export bundle and erased on a tenant-scoped forget (single-user tenants only; multi-user + anonymize are no-ops since folder rows carry no per-user PII). Kept separate from `folders` so folder consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `folders`.");
|
|
11
|
+
// user-data-rights is the hard dependency (EXT_USER_DATA host). `folders` is
|
|
12
|
+
// OPTIONAL: if it's mounted toggleable(default=false) (e.g. per-tenant via
|
|
13
|
+
// tier), a hard r.requires would throw an "effectively disabled" boot
|
|
14
|
+
// warning even though the folder entities exist and the hooks work fine.
|
|
15
|
+
r.requires({ features: ["user-data-rights"] });
|
|
16
|
+
r.optionalRequires("folders");
|
|
17
|
+
r.useExtension(EXT_USER_DATA, "folder", {
|
|
18
|
+
export: folderExportHook,
|
|
19
|
+
delete: folderDeleteHook,
|
|
20
|
+
});
|
|
21
|
+
r.useExtension(EXT_USER_DATA, "folder-assignment", {
|
|
22
|
+
export: folderAssignmentExportHook,
|
|
23
|
+
delete: folderAssignmentDeleteHook,
|
|
24
|
+
});
|
|
25
|
+
}, { dedupeOptions: {} });
|
|
26
|
+
}
|
|
27
|
+
/** @deprecated Use createFoldersUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
28
|
+
export const foldersUserDataFeature = createFoldersUserDataFeature();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
3
|
// COALESCE(modified_at, inserted_at) — a draft's "last touched" timestamp is
|
|
4
4
|
// modified_at once the upsert path (save.write.ts) has updated it at least
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
// COUNT(*), not selectMany(...).length — save.write.ts checks this on every
|
|
3
3
|
// create, and a draft's `values` blob can be up to FORM_DRAFT_VALUES_MAX_BYTES
|
|
4
4
|
// (64KB); loading up to FORM_DRAFT_MAX_PER_OWNER full rows just to count them
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { instantToTimestamptzParam, unsafeReadRetrying, } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { toPostgresArrayLiteral } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { instantToTimestamptzParam, toPostgresArrayLiteral, unsafeReadRetrying, } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
// Narrows a draft blob's raw FileRef-shaped storageKeys (collectDraftFileRefKeys
|
|
4
3
|
// output — extracted from free-form, client-supplied JSON, issue #1889) down to
|
|
5
4
|
// the ones with a real, non-deleted file_refs row owned by this exact
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare function createFormDraftFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
|
+
readonly exports: void;
|
|
3
|
+
};
|
|
4
|
+
/** @deprecated Use createFormDraftFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
1
5
|
export declare const formDraftFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
6
|
readonly exports: void;
|
|
3
7
|
};
|
|
@@ -41,4 +41,8 @@ function registerFormDraft(r) {
|
|
|
41
41
|
handler: (payload, ctx) => cleanupDraftsJob(payload, ctx, ctx.db.unsafeRaw()),
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
export
|
|
44
|
+
export function createFormDraftFeature() {
|
|
45
|
+
return defineFeature(FORM_DRAFT_FEATURE_NAME, registerFormDraft, { dedupeOptions: {} });
|
|
46
|
+
}
|
|
47
|
+
/** @deprecated Use createFormDraftFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
48
|
+
export const formDraftFeature = createFormDraftFeature();
|
|
@@ -37,7 +37,7 @@ async function releaseRowFileRefs(row, db, fileProviderResolver, log) {
|
|
|
37
37
|
const isCreateMode = row.draftKey.includes(":new:");
|
|
38
38
|
const ownedRefs = await filterOwnedFileRefs(db, row.tenantId, row.ownerId, keys, row.insertedAt, isCreateMode);
|
|
39
39
|
const systemUser = createSystemUser(row.tenantId);
|
|
40
|
-
const tenantDb = createTenantDb(db, row.tenantId, "system");
|
|
40
|
+
const tenantDb = createTenantDb({ db, tenantId: row.tenantId, mode: "system" });
|
|
41
41
|
for (const ref of ownedRefs) {
|
|
42
42
|
const forgetResult = await fileRefExecutor.forget({ id: ref.id }, systemUser, tenantDb);
|
|
43
43
|
if (!forgetResult.isSuccess) {
|
|
@@ -78,7 +78,7 @@ export async function deleteStaleDraftsBatch(batch, db, retentionDays, log) {
|
|
|
78
78
|
const byId = new Map(batch.map((row) => [row.id, row]));
|
|
79
79
|
for (const [tenantId, ids] of groupStaleDraftIdsByTenant(batch)) {
|
|
80
80
|
const systemUser = createSystemUser(tenantId);
|
|
81
|
-
const tenantDb = createTenantDb(db, tenantId, "system");
|
|
81
|
+
const tenantDb = createTenantDb({ db, tenantId, mode: "system" });
|
|
82
82
|
for (const id of ids) {
|
|
83
83
|
// Race: user may have saved between select and here — skip if no longer stale.
|
|
84
84
|
if (!(await isDraftStillStale(db, tenantId, id, retentionDays))) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FORM_DRAFT_ACCESS, FORM_DRAFT_FEATURE_NAME, FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT, FormDraftHandlers, FormDraftQueries, } from "./constants.js";
|
|
2
2
|
export { formDraftEntity } from "./entity.js";
|
|
3
3
|
export { formDraftExecutor, formDraftTable } from "./executor.js";
|
|
4
|
-
export { formDraftFeature } from "./feature.js";
|
|
4
|
+
export { createFormDraftFeature, formDraftFeature } from "./feature.js";
|
|
5
5
|
export { discardDraftWrite } from "./handlers/discard.write.js";
|
|
6
6
|
export { type GetDraftResult, getDraftQuery } from "./handlers/get.query.js";
|
|
7
7
|
export { type ListDraftsResult, listDraftsQuery } from "./handlers/list.query.js";
|
package/dist/form-draft/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FORM_DRAFT_ACCESS, FORM_DRAFT_FEATURE_NAME, FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT, FormDraftHandlers, FormDraftQueries, } from "./constants.js";
|
|
2
2
|
export { formDraftEntity } from "./entity.js";
|
|
3
3
|
export { formDraftExecutor, formDraftTable } from "./executor.js";
|
|
4
|
-
export { formDraftFeature } from "./feature.js";
|
|
4
|
+
export { createFormDraftFeature, formDraftFeature } from "./feature.js";
|
|
5
5
|
export { discardDraftWrite } from "./handlers/discard.write.js";
|
|
6
6
|
export { getDraftQuery } from "./handlers/get.query.js";
|
|
7
7
|
export { listDraftsQuery } from "./handlers/list.query.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { formDraftTable } from "./executor.js";
|
|
3
3
|
// Shared by save (upsert lookup + race re-lookup), discard, and get — always
|
|
4
4
|
// scoped by tenantId + ownerId + draftKey, tenantId included explicitly
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare function createFormDraftUserDataFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
|
+
readonly exports: void;
|
|
3
|
+
};
|
|
4
|
+
/** @deprecated Use createFormDraftUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
1
5
|
export declare const formDraftUserDataFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
6
|
readonly exports: void;
|
|
3
7
|
};
|
|
@@ -6,12 +6,16 @@
|
|
|
6
6
|
// pull a hard dependency. Mirrors notes-history-user-data.
|
|
7
7
|
import { defineFeature, EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
|
|
8
8
|
import { formDraftDeleteHook, formDraftExportHook } from "./hooks.js";
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
9
|
+
export function createFormDraftUserDataFeature() {
|
|
10
|
+
return defineFeature("form-draft-user-data", (r) => {
|
|
11
|
+
r.describe("GDPR (Art. 20 export / Art. 17 erasure) coverage for the `form-draft` feature's `form-draft` entity. Mounts the EXT_USER_DATA export hook so a user's saved drafts are included in the user-data export bundle, and a delete hook that physically removes the user's own draft rows on forget. Kept separate from `form-draft` so form-draft consumers without the user-data-rights pipeline don't pull a hard dependency — requires `user-data-rights`, optionalRequires `form-draft`.");
|
|
12
|
+
r.requires({ features: ["user-data-rights"] });
|
|
13
|
+
r.optionalRequires("form-draft");
|
|
14
|
+
r.useExtension(EXT_USER_DATA, "form-draft", {
|
|
15
|
+
export: formDraftExportHook,
|
|
16
|
+
delete: formDraftDeleteHook,
|
|
17
|
+
});
|
|
18
|
+
}, { dedupeOptions: {} });
|
|
19
|
+
}
|
|
20
|
+
/** @deprecated Use createFormDraftUserDataFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
21
|
+
export const formDraftUserDataFeature = createFormDraftUserDataFeature();
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare function createInboundMailFoundationFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
|
+
readonly exports: void;
|
|
3
|
+
};
|
|
4
|
+
/** @deprecated Use createInboundMailFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
1
5
|
export declare const inboundMailFoundationFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
6
|
readonly exports: void;
|
|
3
7
|
};
|