@cosmicdrift/kumiko-framework 0.385.0 → 0.387.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -57
- package/README.md +2 -2
- package/agents/widgets.md +39 -39
- package/dist/api/api-constants.js +2 -2
- package/dist/api/auth-middleware.js +7 -7
- package/dist/api/auth-rate-limiters.js +7 -3
- package/dist/api/auth-routes-mfa.js +1 -1
- package/dist/api/auth-routes-session.js +1 -1
- package/dist/api/auth-routes-shared.js +7 -3
- package/dist/api/auth-routes-signup.js +1 -1
- package/dist/api/client-ip.js +3 -1
- package/dist/api/extra-route.js +1 -1
- package/dist/api/pii-leak-guard.js +4 -2
- package/dist/api/readiness.js +5 -5
- package/dist/api/redis-sse-broker.js +8 -6
- package/dist/api/request-context.d.ts +2 -0
- package/dist/api/request-context.js +16 -7
- package/dist/api/routes.js +2 -2
- package/dist/api/server.js +34 -33
- package/dist/api/sse-broker.js +1 -1
- package/dist/api/sse-route.d.ts +13 -13
- package/dist/api/sse-route.js +15 -15
- package/dist/auth/index.js +4 -4
- package/dist/auth/roles.d.ts +4 -4
- package/dist/auth/roles.js +24 -24
- package/dist/compliance/duration-spec.js +18 -20
- package/dist/compliance/index.js +2 -3
- package/dist/compliance/override-schema.d.ts +4 -4
- package/dist/compliance/override-schema.js +19 -22
- package/dist/compliance/profiles.d.ts +26 -29
- package/dist/compliance/profiles.js +62 -69
- package/dist/compliance/sub-processors.d.ts +28 -30
- package/dist/compliance/sub-processors.js +17 -21
- package/dist/consumer-cli.js +4 -4
- package/dist/crypto/blind-index.js +18 -17
- package/dist/crypto/ciphertext-pattern.js +1 -1
- package/dist/crypto/event-pii.js +3 -3
- package/dist/crypto/kek-source.d.ts +1 -1
- package/dist/crypto/kek-source.js +3 -2
- package/dist/crypto/kms-adapter.d.ts +1 -1
- package/dist/crypto/kms-adapter.js +4 -6
- package/dist/crypto/kms-wiring.d.ts +1 -2
- package/dist/crypto/kms-wiring.js +2 -2
- package/dist/crypto/pg-kms-adapter.js +2 -6
- package/dist/crypto/pii-field-encryption.js +4 -4
- package/dist/crypto/subject-resolver.d.ts +1 -1
- package/dist/crypto/subject-resolver.js +2 -2
- package/dist/db/apply-entity-event.d.ts +6 -6
- package/dist/db/apply-entity-event.js +55 -55
- package/dist/db/blind-index-cleanup.js +7 -7
- package/dist/db/collect-table-metas.js +10 -11
- package/dist/db/compound-types.d.ts +1 -1
- package/dist/db/compound-types.js +12 -12
- package/dist/db/cross-tenant-reads.d.ts +8 -0
- package/dist/db/cross-tenant-reads.js +23 -0
- package/dist/db/cursor.js +3 -4
- package/dist/db/dialect.d.ts +2 -2
- package/dist/db/dialect.js +2 -2
- package/dist/db/eagerload.d.ts +3 -3
- package/dist/db/eagerload.js +21 -12
- package/dist/db/entity-table-meta.d.ts +2 -2
- package/dist/db/entity-table-meta.js +4 -4
- package/dist/db/event-store-executor-context.d.ts +1 -1
- package/dist/db/event-store-executor-context.js +13 -13
- package/dist/db/event-store-executor-read.js +27 -28
- package/dist/db/event-store-executor-write.js +65 -70
- package/dist/db/located-timestamp.d.ts +11 -11
- package/dist/db/located-timestamp.js +29 -30
- package/dist/db/migrate-generator.d.ts +1 -1
- package/dist/db/migrate-generator.js +26 -19
- package/dist/db/migrate-runner.js +25 -25
- package/dist/db/money.d.ts +6 -6
- package/dist/db/money.js +29 -27
- package/dist/db/queries/backfill-pii.js +5 -5
- package/dist/db/queries/ddl.js +1 -1
- package/dist/db/queries/es-ops.d.ts +1 -1
- package/dist/db/queries/es-ops.js +1 -1
- package/dist/db/queries/event-consumer.js +3 -3
- package/dist/db/queries/event-store.js +4 -2
- package/dist/db/queries/projection-rebuild.js +3 -3
- package/dist/db/queries/raw-sql.d.ts +2 -2
- package/dist/db/queries/raw-sql.js +2 -2
- package/dist/db/queries/shadow-swap.js +19 -19
- package/dist/db/queries/test-stack.d.ts +4 -1
- package/dist/db/queries/test-stack.js +15 -2
- package/dist/db/query.d.ts +1 -1
- package/dist/db/query.js +6 -6
- package/dist/db/rebuild-marker.js +20 -21
- package/dist/db/replay-migration-sql.js +2 -2
- package/dist/db/schema-inspection.js +4 -5
- package/dist/db/table-builder.d.ts +1 -2
- package/dist/db/table-builder.js +82 -82
- package/dist/db/tenant-db.d.ts +2 -2
- package/dist/db/tenant-db.js +9 -2
- package/dist/derivatives/delete-stored-file.js +5 -2
- package/dist/derivatives/derivatives-context.js +1 -1
- package/dist/engine/boot-validator/access-roles.js +4 -3
- package/dist/engine/boot-validator/api-ext.js +14 -14
- package/dist/engine/boot-validator/config-deps.js +7 -6
- package/dist/engine/boot-validator/detail-screens.js +3 -3
- package/dist/engine/boot-validator/entity-handler.js +60 -61
- package/dist/engine/boot-validator/gdpr-storage.js +4 -4
- package/dist/engine/boot-validator/i18n-keys.js +1 -1
- package/dist/engine/boot-validator/index.d.ts +2 -2
- package/dist/engine/boot-validator/index.js +20 -20
- package/dist/engine/boot-validator/nav.js +5 -5
- package/dist/engine/boot-validator/ownership.js +12 -9
- package/dist/engine/boot-validator/parent-ref.js +1 -1
- package/dist/engine/boot-validator/pii-retention.js +50 -57
- package/dist/engine/boot-validator/projection-list-screens.js +7 -7
- package/dist/engine/boot-validator/query-refs.js +1 -1
- package/dist/engine/boot-validator/screens-actions.js +15 -16
- package/dist/engine/boot-validator/screens-forms.js +10 -11
- package/dist/engine/boot-validator/screens-lists.js +14 -15
- package/dist/engine/boot-validator/screens.js +34 -40
- package/dist/engine/boot-validator/security-baseline.js +3 -2
- package/dist/engine/boot-validator/transfer-graph.js +2 -2
- package/dist/engine/boot-validator/workspaces.js +3 -3
- package/dist/engine/bridge-stub.js +3 -4
- package/dist/engine/build-app-schema.js +75 -75
- package/dist/engine/build-config-feature-schema.js +50 -50
- package/dist/engine/build-target.js +20 -23
- package/dist/engine/codemod/pipeline-codemod.js +20 -13
- package/dist/engine/config-helpers.js +4 -4
- package/dist/engine/constants.js +2 -2
- package/dist/engine/create-app.js +2 -2
- package/dist/engine/define-feature.js +12 -11
- package/dist/engine/define-handler.js +12 -11
- package/dist/engine/define-step.js +1 -1
- package/dist/engine/define-workflow.d.ts +5 -5
- package/dist/engine/define-workflow.js +6 -6
- package/dist/engine/entity-handlers.js +13 -14
- package/dist/engine/event-def.js +2 -2
- package/dist/engine/extension-names.d.ts +16 -17
- package/dist/engine/extension-names.js +37 -38
- package/dist/engine/extensions/escape-hatch-usage.js +1 -1
- package/dist/engine/extensions/tenant-data.js +2 -2
- package/dist/engine/extensions/user-data.d.ts +23 -24
- package/dist/engine/factories.d.ts +14 -13
- package/dist/engine/factories.js +38 -37
- package/dist/engine/feature-ast/entity-field-types.js +1 -1
- package/dist/engine/feature-ast/extractors/handlers.js +1 -1
- package/dist/engine/feature-ast/extractors/hooks.js +1 -1
- package/dist/engine/feature-ast/extractors/shared.d.ts +2 -3
- package/dist/engine/feature-ast/extractors/shared.js +2 -3
- package/dist/engine/feature-ast/parse.js +13 -13
- package/dist/engine/feature-ast/patch.js +1 -1
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +8 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +1 -1
- package/dist/engine/feature-ast/patterns.d.ts +2 -2
- package/dist/engine/feature-ast/render.js +2 -2
- package/dist/engine/feature-config-events-jobs.js +15 -12
- package/dist/engine/feature-entity-handlers.js +9 -5
- package/dist/engine/feature-manifest.d.ts +9 -9
- package/dist/engine/feature-manifest.js +6 -7
- package/dist/engine/feature-ui-extensions.d.ts +3 -3
- package/dist/engine/feature-ui-extensions.js +30 -22
- package/dist/engine/field-access.js +5 -6
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.js +4 -4
- package/dist/engine/object-form.d.ts +1 -0
- package/dist/engine/object-form.js +14 -4
- package/dist/engine/ownership.js +3 -3
- package/dist/engine/parse-ref-target.js +5 -7
- package/dist/engine/pattern-library/index.js +2 -2
- package/dist/engine/pattern-library/library.js +2 -2
- package/dist/engine/pattern-library/types.js +3 -3
- package/dist/engine/pipeline.js +2 -2
- package/dist/engine/project-app-schema-for-roles.js +1 -1
- package/dist/engine/projection-helpers.js +9 -9
- package/dist/engine/qualified-name.js +2 -2
- package/dist/engine/registry-facade.js +1 -1
- package/dist/engine/registry-ingest.js +12 -12
- package/dist/engine/registry-state.js +17 -19
- package/dist/engine/registry-validate.js +12 -12
- package/dist/engine/run-in.js +2 -2
- package/dist/engine/run-pipeline.js +7 -0
- package/dist/engine/schema-builder.js +40 -38
- package/dist/engine/screen-filter-ops.js +17 -20
- package/dist/engine/screen-helpers.js +4 -3
- package/dist/engine/state-machine.d.ts +12 -12
- package/dist/engine/state-machine.js +7 -7
- package/dist/engine/steps/_resolver-utils.js +4 -3
- package/dist/engine/steps/for-each.js +4 -4
- package/dist/engine/steps/unsafe-projection-delete.js +1 -1
- package/dist/engine/steps/unsafe-projection-upsert.js +4 -4
- package/dist/engine/steps/wait-for-event.js +4 -4
- package/dist/engine/steps/workflow-system-events.js +3 -3
- package/dist/engine/tier-resolver-extension.d.ts +29 -27
- package/dist/engine/tier-resolver-extension.js +26 -26
- package/dist/engine/transfer-adjacency.js +2 -2
- package/dist/engine/validate-projection-allowlist.js +7 -27
- package/dist/engine/walk-step-instances.d.ts +2 -0
- package/dist/engine/walk-step-instances.js +38 -0
- package/dist/engine/where-rule-lint.js +1 -1
- package/dist/engine/write-handler-qn-extract.js +1 -1
- package/dist/entrypoint/index.js +3 -3
- package/dist/env/index.d.ts +7 -6
- package/dist/env/index.js +10 -9
- package/dist/errors/transition-details.js +7 -7
- package/dist/errors/write-error-info.d.ts +6 -6
- package/dist/errors/write-error-info.js +6 -6
- package/dist/es-ops/context.d.ts +9 -9
- package/dist/es-ops/context.js +28 -28
- package/dist/es-ops/index.js +7 -9
- package/dist/es-ops/operations-schema.js +4 -10
- package/dist/es-ops/runner.d.ts +11 -11
- package/dist/es-ops/runner.js +49 -53
- package/dist/es-ops/types.d.ts +55 -55
- package/dist/es-ops/types.js +11 -11
- package/dist/event-store/admin-api.js +6 -7
- package/dist/event-store/errors.js +1 -1
- package/dist/event-store/event-store.js +2 -2
- package/dist/event-store/rebuild-dead-letter.js +1 -1
- package/dist/files/feature.js +9 -10
- package/dist/files/file-handle.js +5 -6
- package/dist/files/file-ref-entity.js +15 -15
- package/dist/files/file-ref-table.js +7 -8
- package/dist/files/file-routes.d.ts +7 -0
- package/dist/files/file-routes.js +11 -5
- package/dist/files/in-memory-provider.js +8 -9
- package/dist/files/local-provider.js +18 -25
- package/dist/files/provider-resolver.d.ts +7 -7
- package/dist/files/storage-tracking.js +2 -2
- package/dist/files/zip-stream.d.ts +12 -19
- package/dist/files/zip-stream.js +44 -63
- package/dist/i18n/required-surface-keys.d.ts +1 -1
- package/dist/i18n/required-surface-keys.js +8 -8
- package/dist/internal/stack-support.d.ts +1 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/jobs/job-runner-helpers.d.ts +1 -2
- package/dist/jobs/job-runner-helpers.js +8 -18
- package/dist/jobs/job-runner-schedulers.d.ts +1 -1
- package/dist/jobs/job-runner-schedulers.js +3 -4
- package/dist/jobs/job-runner.js +17 -18
- package/dist/lifecycle/lifecycle.js +3 -5
- package/dist/lifecycle/signal-handlers.js +5 -4
- package/dist/logging/utils.d.ts +2 -1
- package/dist/logging/utils.js +38 -10
- package/dist/migrations/index.js +1 -1
- package/dist/migrations/kumiko-drift.js +14 -13
- package/dist/migrations/pending-rebuilds.d.ts +21 -20
- package/dist/migrations/pending-rebuilds.js +27 -27
- package/dist/migrations/projection-table-index.d.ts +3 -3
- package/dist/migrations/projection-table-index.js +8 -8
- package/dist/observability/metric-validator.js +1 -1
- package/dist/observability/metrics-handle.js +3 -3
- package/dist/pipeline/append-event-core.js +11 -2
- package/dist/pipeline/cascade-handler.d.ts +1 -1
- package/dist/pipeline/dispatch-batch.js +2 -2
- package/dist/pipeline/dispatch-query.js +10 -10
- package/dist/pipeline/dispatch-shared.d.ts +1 -0
- package/dist/pipeline/dispatch-shared.js +42 -19
- package/dist/pipeline/dispatch-stream.js +1 -1
- package/dist/pipeline/dispatch-write.js +3 -3
- package/dist/pipeline/dispatcher-utils.d.ts +1 -1
- package/dist/pipeline/dispatcher-utils.js +1 -1
- package/dist/pipeline/event-consumer-state.js +2 -2
- package/dist/pipeline/event-dispatcher-delivery.js +1 -1
- package/dist/pipeline/event-dispatcher.js +17 -28
- package/dist/pipeline/irreversible-operation-gate.js +1 -1
- package/dist/pipeline/lifecycle-pipeline.js +9 -9
- package/dist/pipeline/member-read-only-transaction.js +1 -3
- package/dist/pipeline/msp-rebuild.js +1 -1
- package/dist/pipeline/projection-rebuild.js +13 -12
- package/dist/pipeline/system-hooks.js +39 -41
- package/dist/pipeline/system-identity-switch.js +1 -3
- package/dist/pipeline/tenant-timezone-cache.js +1 -1
- package/dist/random/generate.d.ts +29 -29
- package/dist/random/generate.js +30 -30
- package/dist/random/words.js +20 -20
- package/dist/rate-limit/middleware.js +9 -5
- package/dist/redis/client.js +2 -2
- package/dist/redis/pubsub-signal.js +14 -17
- package/dist/schema-cli.js +116 -22
- package/dist/search/index.js +4 -4
- package/dist/search/purge-subject.js +4 -5
- package/dist/search/reindex-entity.js +6 -9
- package/dist/time/boot-tz-warning.d.ts +2 -2
- package/dist/time/boot-tz-warning.js +8 -8
- package/dist/time/iana.js +10 -10
- package/dist/time/index.js +9 -9
- package/dist/time/legacy-date.d.ts +2 -2
- package/dist/time/legacy-date.js +6 -8
- package/dist/time/polyfill.js +1 -1
- package/dist/time/tz-context.d.ts +1 -1
- package/dist/time/tz-context.js +1 -1
- package/dist/ui-types/app-schema.js +7 -7
- package/dist/ui-types/list-row-meta.js +4 -4
- package/dist/upgrade-cli.js +10 -9
- package/dist/utils/compare.js +1 -1
- package/package.json +4 -4
- package/src/changes.json +54 -0
- package/src/scripts/codemod/crypto-shredding-testing-move.ts +2 -2
- package/src/scripts/codemod/migrate-cross-tenant.ts +1 -1
- package/src/scripts/codemod/migrate-open-to-all.ts +1 -1
- package/src/scripts/codemod/pii-personal-migration.ts +17 -8
- package/src/scripts/codemod/unprocessable-error-details-reason.ts +2 -2
|
@@ -64,27 +64,25 @@ export interface ComplianceProfile {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* Profile
|
|
68
|
-
* `minimal-no-region`
|
|
69
|
-
*
|
|
70
|
-
*
|
|
67
|
+
* Profile keys that the tenant admin may select during onboarding.
|
|
68
|
+
* `minimal-no-region` is intentionally excluded: it is the default fallback
|
|
69
|
+
* for "no choice made yet" and produces a visible warning. Production
|
|
70
|
+
* tenants must select an actual profile.
|
|
71
71
|
*/
|
|
72
72
|
export declare const SELECTABLE_PROFILE_KEYS: readonly ["eu-dsgvo", "swiss-dsg", "de-hr-dsgvo-hgb"];
|
|
73
73
|
/**
|
|
74
|
-
* Top-
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* würde die Profile-Identität zerstoeren.
|
|
74
|
+
* Top-level `ComplianceProfile` properties that a tenant override may modify.
|
|
75
|
+
* Identity fields (key, region, label, extends) are excluded because
|
|
76
|
+
* overriding them would destroy the profile's identity.
|
|
78
77
|
*
|
|
79
|
-
*
|
|
80
|
-
* - set-profile
|
|
81
|
-
* -
|
|
78
|
+
* This is the single source of truth for:
|
|
79
|
+
* - the set-profile handler whitelist, which rejects typos
|
|
80
|
+
* - the snapshot test that guards against drift from the profile's top level
|
|
82
81
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* Richtungen.
|
|
82
|
+
* When a new top-level property is added to `ComplianceProfile` (for example,
|
|
83
|
+
* `dataSubjectRights` or `crossBorderTransferRules`), it must be added here;
|
|
84
|
+
* otherwise set-profile rejects valid overrides. The snapshot test in
|
|
85
|
+
* profiles.test.ts detects drift in either direction.
|
|
88
86
|
*/
|
|
89
87
|
export declare const OVERRIDABLE_PROFILE_KEYS: ReadonlySet<string>;
|
|
90
88
|
type DeepReadonly<T> = T extends object ? {
|
|
@@ -95,9 +93,9 @@ type DeepPartial<T> = T extends object ? {
|
|
|
95
93
|
[K in keyof T]?: DeepPartial<T[K]>;
|
|
96
94
|
} : T;
|
|
97
95
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
96
|
+
* Precomputed profile list with `extends` already resolved. It is computed
|
|
97
|
+
* once when the module loads, so definition errors (cycles or missing
|
|
98
|
+
* targets) are thrown immediately rather than on the first resolver call.
|
|
101
99
|
*/
|
|
102
100
|
export declare const COMPLIANCE_PROFILES: Readonly<Record<ComplianceProfileKey, ComplianceProfile>>;
|
|
103
101
|
export interface EffectiveComplianceProfile {
|
|
@@ -105,19 +103,18 @@ export interface EffectiveComplianceProfile {
|
|
|
105
103
|
readonly warning?: "no-profile-selected";
|
|
106
104
|
}
|
|
107
105
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
106
|
+
* Returns the effective compliance profile for a tenant, including its
|
|
107
|
+
* tenant override.
|
|
110
108
|
*
|
|
111
|
-
* Edge-
|
|
109
|
+
* Edge-case behavior:
|
|
112
110
|
* - selection=undefined → minimal-no-region + warning="no-profile-selected"
|
|
113
|
-
* - selection=valid + override=undefined → effective profile,
|
|
114
|
-
* - selection=valid + override → deep-merged effective,
|
|
111
|
+
* - selection=valid + override=undefined → effective profile, no warning
|
|
112
|
+
* - selection=valid + override → deep-merged effective profile, no warning
|
|
115
113
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* bei Bedarf.
|
|
114
|
+
* The former "minimal-in-production" warning was removed because
|
|
115
|
+
* set-profile no longer accepts minimal-no-region as a tenant selection.
|
|
116
|
+
* Production-specific behavior, such as blocking the default, can be added
|
|
117
|
+
* later if needed.
|
|
121
118
|
*/
|
|
122
119
|
export declare function resolveComplianceProfile(args: {
|
|
123
120
|
readonly selection?: ComplianceProfileKey;
|
|
@@ -1,37 +1,34 @@
|
|
|
1
|
-
// Compliance
|
|
1
|
+
// Compliance profiles — GDPR + sector-specific regulations.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// The tenant admin must select a profile during onboarding. A profile
|
|
4
|
+
// bundles user rights (forget grace period, restriction, access-request
|
|
5
|
+
// deadline), notification languages, breach disclosure, audit-log retention,
|
|
6
|
+
// subprocessor requirements, and the tenant-destruction grace period.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// Current set: three profiles plus one default fallback. Extending via
|
|
9
|
+
// `extends` is straightforward; additional jurisdictions (uk-gdpr,
|
|
10
|
+
// ca-pipeda, us-ccpa, hipaa-healthcare) can be added when needed.
|
|
11
11
|
//
|
|
12
|
-
// Edge-
|
|
12
|
+
// Edge-case decisions:
|
|
13
13
|
//
|
|
14
|
-
// 1. Default
|
|
15
|
-
// `minimal-no-region`
|
|
16
|
-
//
|
|
17
|
-
//
|
|
14
|
+
// 1. Default fallback: `resolveComplianceProfile(undefined)` returns
|
|
15
|
+
// `minimal-no-region` with `warning: "no-profile-selected"`. The caller
|
|
16
|
+
// can use this to trigger an onboarding banner; resolution is never
|
|
17
|
+
// silent.
|
|
18
18
|
//
|
|
19
|
-
// 2.
|
|
20
|
-
// eu-dsgvo,
|
|
21
|
-
//
|
|
19
|
+
// 2. Extends-chain depth: only one level is allowed. de-hr-dsgvo-hgb
|
|
20
|
+
// extends eu-dsgvo, but eu-dsgvo must not extend another profile. The
|
|
21
|
+
// boot validator checks this.
|
|
22
22
|
//
|
|
23
|
-
// 3.
|
|
24
|
-
// `{ userRights: { gracePeriod: { days: 60 } } }`
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
// treffen.
|
|
23
|
+
// 3. Override deep-merge semantics: merging is recursive. An override such
|
|
24
|
+
// as `{ userRights: { gracePeriod: { days: 60 } } }` on eu-dsgvo leaves
|
|
25
|
+
// the other userRights fields unchanged. Top-level replacement is not
|
|
26
|
+
// supported; the override must target the corresponding property path.
|
|
28
27
|
//
|
|
29
|
-
// 4. Required-
|
|
30
|
-
// TypeScript
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
// Siehe docs/plans/datenschutz/compliance-profiles.md.
|
|
28
|
+
// 4. Required-field overrides: the override type is `DeepPartial<...>`.
|
|
29
|
+
// TypeScript prevents null drops at compile time. Runtime casts from
|
|
30
|
+
// the tenant-admin override endpoint pass through a Zod schema with
|
|
31
|
+
// all properties optional, but not nullable.
|
|
35
32
|
import { isPlainObject } from "../utils/is-plain-object.js";
|
|
36
33
|
// --- Profile-Definitions (raw, before extends-Resolution) ---
|
|
37
34
|
const RAW_PROFILES = {
|
|
@@ -155,12 +152,12 @@ const RAW_PROFILES = {
|
|
|
155
152
|
tenantDestroyGracePeriod: { days: 30 },
|
|
156
153
|
},
|
|
157
154
|
};
|
|
158
|
-
// --- Tenant-
|
|
155
|
+
// --- Tenant-selectable list (excluding minimal-no-region) ---
|
|
159
156
|
/**
|
|
160
|
-
* Profile
|
|
161
|
-
* `minimal-no-region`
|
|
162
|
-
*
|
|
163
|
-
*
|
|
157
|
+
* Profile keys that the tenant admin may select during onboarding.
|
|
158
|
+
* `minimal-no-region` is intentionally excluded: it is the default fallback
|
|
159
|
+
* for "no choice made yet" and produces a visible warning. Production
|
|
160
|
+
* tenants must select an actual profile.
|
|
164
161
|
*/
|
|
165
162
|
export const SELECTABLE_PROFILE_KEYS = [
|
|
166
163
|
"eu-dsgvo",
|
|
@@ -168,20 +165,18 @@ export const SELECTABLE_PROFILE_KEYS = [
|
|
|
168
165
|
"de-hr-dsgvo-hgb",
|
|
169
166
|
];
|
|
170
167
|
/**
|
|
171
|
-
* Top-
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* würde die Profile-Identität zerstoeren.
|
|
168
|
+
* Top-level `ComplianceProfile` properties that a tenant override may modify.
|
|
169
|
+
* Identity fields (key, region, label, extends) are excluded because
|
|
170
|
+
* overriding them would destroy the profile's identity.
|
|
175
171
|
*
|
|
176
|
-
*
|
|
177
|
-
* - set-profile
|
|
178
|
-
* -
|
|
172
|
+
* This is the single source of truth for:
|
|
173
|
+
* - the set-profile handler whitelist, which rejects typos
|
|
174
|
+
* - the snapshot test that guards against drift from the profile's top level
|
|
179
175
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* Richtungen.
|
|
176
|
+
* When a new top-level property is added to `ComplianceProfile` (for example,
|
|
177
|
+
* `dataSubjectRights` or `crossBorderTransferRules`), it must be added here;
|
|
178
|
+
* otherwise set-profile rejects valid overrides. The snapshot test in
|
|
179
|
+
* profiles.test.ts detects drift in either direction.
|
|
185
180
|
*/
|
|
186
181
|
export const OVERRIDABLE_PROFILE_KEYS = new Set([
|
|
187
182
|
"userRights",
|
|
@@ -192,11 +187,11 @@ export const OVERRIDABLE_PROFILE_KEYS = new Set([
|
|
|
192
187
|
"tenantDestroyGracePeriod",
|
|
193
188
|
"forgetDiscovery",
|
|
194
189
|
]);
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
// { months: 24 }
|
|
199
|
-
//
|
|
190
|
+
// These paths are replaced as atomic values rather than merged recursively.
|
|
191
|
+
// This is required for discriminated unions, where a patch may provide a
|
|
192
|
+
// sibling property instead of an override; for example, changing retention
|
|
193
|
+
// from { months: 24 } to { years: 10 } would otherwise produce
|
|
194
|
+
// { months: 24, years: 10 }, which is semantically invalid.
|
|
200
195
|
const ATOMIC_PATHS = new Set([
|
|
201
196
|
"userRights.gracePeriod",
|
|
202
197
|
"userRights.auskunftFrist",
|
|
@@ -213,7 +208,7 @@ function deepMerge(base, patch, path = "") {
|
|
|
213
208
|
const fullPath = path ? `${path}.${k}` : k;
|
|
214
209
|
const existing = out[k];
|
|
215
210
|
if (ATOMIC_PATHS.has(fullPath)) {
|
|
216
|
-
// Atomic — replace
|
|
211
|
+
// Atomic — replace completely instead of merging recursively.
|
|
217
212
|
out[k] = v;
|
|
218
213
|
}
|
|
219
214
|
else if (isPlainObject(existing) && isPlainObject(v)) {
|
|
@@ -226,13 +221,12 @@ function deepMerge(base, patch, path = "") {
|
|
|
226
221
|
return out; // @cast-boundary generic-record
|
|
227
222
|
}
|
|
228
223
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* Boot-Validation einfach).
|
|
224
|
+
* Resolves a profile, including its `extends` chain. Throws when the chain
|
|
225
|
+
* is deeper than one level to prevent cycles and keep boot validation simple.
|
|
232
226
|
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
227
|
+
* The `extends` target itself must not extend another profile. A required
|
|
228
|
+
* multi-level hierarchy must instead be defined explicitly (for example,
|
|
229
|
+
* `de-hr-strict extends eu-dsgvo` rather than
|
|
236
230
|
* `de-hr-strict extends de-hr-dsgvo-hgb extends eu-dsgvo`).
|
|
237
231
|
*/
|
|
238
232
|
function resolveExtends(key) {
|
|
@@ -248,25 +242,24 @@ function resolveExtends(key) {
|
|
|
248
242
|
raw);
|
|
249
243
|
}
|
|
250
244
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
245
|
+
* Precomputed profile list with `extends` already resolved. It is computed
|
|
246
|
+
* once when the module loads, so definition errors (cycles or missing
|
|
247
|
+
* targets) are thrown immediately rather than on the first resolver call.
|
|
254
248
|
*/
|
|
255
249
|
export const COMPLIANCE_PROFILES = Object.fromEntries(Object.keys(RAW_PROFILES).map((k) => [k, resolveExtends(k)])); // @cast-boundary dynamic-key
|
|
256
250
|
/**
|
|
257
|
-
*
|
|
258
|
-
*
|
|
251
|
+
* Returns the effective compliance profile for a tenant, including its
|
|
252
|
+
* tenant override.
|
|
259
253
|
*
|
|
260
|
-
* Edge-
|
|
254
|
+
* Edge-case behavior:
|
|
261
255
|
* - selection=undefined → minimal-no-region + warning="no-profile-selected"
|
|
262
|
-
* - selection=valid + override=undefined → effective profile,
|
|
263
|
-
* - selection=valid + override → deep-merged effective,
|
|
256
|
+
* - selection=valid + override=undefined → effective profile, no warning
|
|
257
|
+
* - selection=valid + override → deep-merged effective profile, no warning
|
|
264
258
|
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
* bei Bedarf.
|
|
259
|
+
* The former "minimal-in-production" warning was removed because
|
|
260
|
+
* set-profile no longer accepts minimal-no-region as a tenant selection.
|
|
261
|
+
* Production-specific behavior, such as blocking the default, can be added
|
|
262
|
+
* later if needed.
|
|
270
263
|
*/
|
|
271
264
|
export function resolveComplianceProfile(args) {
|
|
272
265
|
if (!args.selection) {
|
|
@@ -1,69 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Bundle
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Bundle tier marker for SubProcessor.appliesTo. "all-tiers" matches
|
|
3
|
+
* regardless of the tenant's specific bundle (for example, Hetzner as a
|
|
4
|
+
* hosting provider). Specific tier names can be filtered per tenant.
|
|
5
5
|
*/
|
|
6
6
|
export type BundleTier = "all-tiers" | "standard" | "business" | "enterprise";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Describes a processor within the meaning of GDPR Article 28 that Kumiko
|
|
9
|
+
* uses for platform operations.
|
|
10
10
|
*/
|
|
11
11
|
export interface SubProcessor {
|
|
12
12
|
/** Voller juristischer Name. */
|
|
13
13
|
readonly name: string;
|
|
14
|
-
/**
|
|
14
|
+
/** What the sub-processor does for us. */
|
|
15
15
|
readonly purpose: string;
|
|
16
16
|
/** Sitz / Datenverarbeitungs-Region. */
|
|
17
17
|
readonly region: string;
|
|
18
|
-
/** Link
|
|
18
|
+
/** Link to the data processing agreement (DPA/AVV). */
|
|
19
19
|
readonly dpa: string;
|
|
20
|
-
/**
|
|
20
|
+
/** Date when the sub-processor was added to the platform. */
|
|
21
21
|
readonly addedAt: string;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
* Tenants
|
|
25
|
-
* Aenderungen.
|
|
23
|
+
* Bundle tiers that use this sub-processor.
|
|
24
|
+
* Tenants in unaffected tiers do not need notifications about changes.
|
|
26
25
|
*/
|
|
27
26
|
readonly appliesTo: readonly BundleTier[];
|
|
28
27
|
/**
|
|
29
|
-
* Standard Contractual Clauses (SCC)
|
|
30
|
-
*
|
|
31
|
-
* EU/
|
|
28
|
+
* Whether Standard Contractual Clauses (SCC) for transfers to third
|
|
29
|
+
* countries have been concluded. Required for all sub-processors based
|
|
30
|
+
* outside the EU/EEA.
|
|
32
31
|
*/
|
|
33
32
|
readonly sccRequired?: boolean;
|
|
34
33
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* The tenant must explicitly activate this sub-processor (for example,
|
|
35
|
+
* for an AI feature). No data is sent to it without opt-in.
|
|
37
36
|
*/
|
|
38
37
|
readonly optInOnly?: boolean;
|
|
39
38
|
/**
|
|
40
|
-
* Business Associate Agreement
|
|
41
|
-
* Relevant
|
|
39
|
+
* Whether a Business Associate Agreement is available for HIPAA customers.
|
|
40
|
+
* Relevant only for hipaa-healthcare compliance profiles.
|
|
42
41
|
*/
|
|
43
42
|
readonly hipaaBaaAvailable?: boolean;
|
|
44
43
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
44
|
+
* Planned but not yet active.
|
|
45
|
+
* The sub-processor endpoint outputs it in a separate "planned" section
|
|
46
|
+
* so tenants receive lead time for configuration.
|
|
48
47
|
*/
|
|
49
48
|
readonly status?: "active" | "planned";
|
|
50
49
|
}
|
|
51
50
|
/**
|
|
52
|
-
*
|
|
51
|
+
* Platform-wide sub-processor list.
|
|
53
52
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* stille Aenderungen.
|
|
53
|
+
* Ordered by addedAt (oldest first). Update the snapshot test explicitly
|
|
54
|
+
* when changing this list; it detects silent changes.
|
|
57
55
|
*/
|
|
58
56
|
export declare const KUMIKO_SUB_PROCESSORS: readonly SubProcessor[];
|
|
59
57
|
/**
|
|
60
|
-
* Filter helper —
|
|
61
|
-
*
|
|
58
|
+
* Filter helper — active sub-processors only (excluding status="planned").
|
|
59
|
+
* Used by the public JSON endpoint.
|
|
62
60
|
*/
|
|
63
61
|
export declare function getActiveSubProcessors(): readonly SubProcessor[];
|
|
64
62
|
/**
|
|
65
|
-
* Filter helper —
|
|
66
|
-
*
|
|
67
|
-
*
|
|
63
|
+
* Filter helper — planned sub-processors only (status="planned"). They are
|
|
64
|
+
* output separately in a "coming soon" section so tenant admins receive
|
|
65
|
+
* lead time for compliance profile configuration.
|
|
68
66
|
*/
|
|
69
67
|
export declare function getPlannedSubProcessors(): readonly SubProcessor[];
|
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Kumiko platform sub-processors.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// /api/compliance/sub-processors (JSON
|
|
6
|
-
// /api/compliance/sub-processors.rss (RSS
|
|
3
|
+
// Processors within the meaning of GDPR Article 28 that Kumiko uses for
|
|
4
|
+
// platform operations. Publicly exposed at:
|
|
5
|
+
// /api/compliance/sub-processors (JSON)
|
|
6
|
+
// /api/compliance/sub-processors.rss (RSS)
|
|
7
7
|
//
|
|
8
8
|
// Separate from the public marketing overview (kumiko.rocks/subprocessors),
|
|
9
9
|
// which is compiled independently from templates/legal/_shared/subprocessors/
|
|
10
10
|
// catalog.*.md. The two lists are not synced.
|
|
11
11
|
//
|
|
12
|
-
// Tenant
|
|
13
|
-
//
|
|
14
|
-
//
|
|
12
|
+
// Tenant admins must be informed of additions, changes, and removals with
|
|
13
|
+
// the lead time from the compliance profile (typically 30d). The notification
|
|
14
|
+
// cron is not available yet.
|
|
15
15
|
//
|
|
16
16
|
// SubProcessor has no "removed" state yet: a removed entry is deleted from
|
|
17
17
|
// the array, so until the notification cron exists a removal is documented
|
|
18
18
|
// only in the changelog. Removed so far: Mailbox.org (mailbox hosting),
|
|
19
|
-
// replaced by ALL-INKL.COM
|
|
20
|
-
//
|
|
21
|
-
// Quelle: docs/plans/datenschutz/compliance-profiles.md "Sub-Processor-
|
|
22
|
-
// Management" + docs/plans/datenschutz/legal-artifacts.md.
|
|
19
|
+
// replaced by ALL-INKL.COM.
|
|
23
20
|
/**
|
|
24
|
-
*
|
|
21
|
+
* Platform-wide sub-processor list.
|
|
25
22
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* stille Aenderungen.
|
|
23
|
+
* Ordered by addedAt (oldest first). Update the snapshot test explicitly
|
|
24
|
+
* when changing this list; it detects silent changes.
|
|
29
25
|
*/
|
|
30
26
|
export const KUMIKO_SUB_PROCESSORS = [
|
|
31
27
|
{
|
|
@@ -107,16 +103,16 @@ export const KUMIKO_SUB_PROCESSORS = [
|
|
|
107
103
|
},
|
|
108
104
|
];
|
|
109
105
|
/**
|
|
110
|
-
* Filter helper —
|
|
111
|
-
*
|
|
106
|
+
* Filter helper — active sub-processors only (excluding status="planned").
|
|
107
|
+
* Used by the public JSON endpoint.
|
|
112
108
|
*/
|
|
113
109
|
export function getActiveSubProcessors() {
|
|
114
110
|
return KUMIKO_SUB_PROCESSORS.filter((sp) => sp.status !== "planned");
|
|
115
111
|
}
|
|
116
112
|
/**
|
|
117
|
-
* Filter helper —
|
|
118
|
-
*
|
|
119
|
-
*
|
|
113
|
+
* Filter helper — planned sub-processors only (status="planned"). They are
|
|
114
|
+
* output separately in a "coming soon" section so tenant admins receive
|
|
115
|
+
* lead time for compliance profile configuration.
|
|
120
116
|
*/
|
|
121
117
|
export function getPlannedSubProcessors() {
|
|
122
118
|
return KUMIKO_SUB_PROCESSORS.filter((sp) => sp.status === "planned");
|
package/dist/consumer-cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import { ensureTemporalPolyfill } from "./time/index.js";
|
|
|
12
12
|
// "--instance-id=<id>") out of argv regardless of position, leaving the
|
|
13
13
|
// remaining positionals for sub/name — instead of two independent
|
|
14
14
|
// positional/flag reads that silently misparse "--instance-id" with no
|
|
15
|
-
// value, the "=" form, or a flag placed before the positionals
|
|
15
|
+
// value, the "=" form, or a flag placed before the positionals.
|
|
16
16
|
function parseConsumerCliArgs(argv) {
|
|
17
17
|
const positionals = [];
|
|
18
18
|
let instanceId;
|
|
@@ -57,9 +57,9 @@ export async function runConsumerCli(argv, out) {
|
|
|
57
57
|
if (sub !== "status" && sub !== "restart") {
|
|
58
58
|
// Unknown subcommand must be visible on stderr, not just a bare exit 1 —
|
|
59
59
|
// ops invocations piping `2>&1 >/dev/null` or log pipelines that only
|
|
60
|
-
// watch stderr would otherwise see a failure with zero explanation
|
|
61
|
-
//
|
|
62
|
-
//
|
|
60
|
+
// watch stderr would otherwise see a failure with zero explanation.
|
|
61
|
+
// A bare help call (no subcommand at all) is not an error, so it keeps
|
|
62
|
+
// exit 0 + stdout.
|
|
63
63
|
const write = sub === undefined ? out.log : out.err;
|
|
64
64
|
if (sub !== undefined)
|
|
65
65
|
out.err(` Unknown subcommand: ${sub}`);
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
// Blind
|
|
2
|
-
// `lookupable: true`
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// Blind index for PII equality lookups.
|
|
2
|
+
// `lookupable: true` on a Subject-annotated text field generates a
|
|
3
|
+
// `<snake>_bidx` column containing a deterministic HMAC of the
|
|
4
|
+
// PLAINTEXT value. Equality queries match `(col = $1 OR col_bidx = $2)`
|
|
5
|
+
// and therefore work for both plaintext legacy rows and encrypted rows.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
7
|
+
// Value format: kumiko-bidx:v1:<base64url(HMAC-SHA256(key, value))>
|
|
8
8
|
//
|
|
9
|
-
// HMAC
|
|
10
|
-
// case-sensitive
|
|
9
|
+
// HMAC computation is byte-exact and performs no normalization, preserving
|
|
10
|
+
// the existing case-sensitive equality semantics (lowercasing would change
|
|
11
|
+
// the behavior).
|
|
11
12
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// BYOK
|
|
15
|
-
//
|
|
13
|
+
// The key is deliberately a SEPARATE 32-byte key (env:
|
|
14
|
+
// KUMIKO_BLIND_INDEX_KEY), not derived from PLATFORM_KEK and not part of the
|
|
15
|
+
// KmsAdapter contract, so BYOK adapters must never see it. Rotation requires
|
|
16
|
+
// recomputing all bidx columns.
|
|
16
17
|
//
|
|
17
|
-
// bidx
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// bidx values exist ONLY in the projection, never in event payloads: a
|
|
19
|
+
// deterministic HMAC in an immutable event would create permanent linkage
|
|
20
|
+
// and break erasure. applyEntityEvent computes them during Apply (live and
|
|
21
|
+
// rebuild); after key erasure, the rebuild recomputes them as NULL.
|
|
21
22
|
import { createHmac } from "node:crypto";
|
|
22
23
|
import { requestContext } from "../api/request-context.js";
|
|
23
24
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, isPiiCiphertext, PII_ERASED_SENTINEL, } from "./pii-field-encryption.js";
|
|
@@ -38,7 +39,7 @@ export function decodeBlindIndexKey(base64Key) {
|
|
|
38
39
|
// Boot-injected app-wide key, mirroring configurePiiSubjectKms: run{Prod,Dev}App
|
|
39
40
|
// call configureBlindIndexKey once; query compilers + applyEntityEvent resolve
|
|
40
41
|
// lazily. Absent key = blind-indexing off (bidx columns stay NULL, equality
|
|
41
|
-
// lookups match plaintext rows only
|
|
42
|
+
// lookups match plaintext rows only).
|
|
42
43
|
let injectedKey;
|
|
43
44
|
export function configureBlindIndexKey(base64Key) {
|
|
44
45
|
injectedKey = base64Key === undefined ? undefined : decodeBlindIndexKey(base64Key);
|
|
@@ -9,7 +9,7 @@ export function quoteIdent(name) {
|
|
|
9
9
|
export function escapeLikePattern(value) {
|
|
10
10
|
return value.replace(/[\\%_]/g, (m) => `\\${m}`);
|
|
11
11
|
}
|
|
12
|
-
// "v%" matches any format version (v1 no-AAD, v2 AAD-bound
|
|
12
|
+
// "v%" matches any format version (v1 no-AAD, v2 AAD-bound) — the
|
|
13
13
|
// subject key placement is stable across versions.
|
|
14
14
|
export function subjectCiphertextLikePattern(subjectKey) {
|
|
15
15
|
return `kumiko-pii:v%:${escapeLikePattern(subjectKey)}:%`;
|
package/dist/crypto/event-pii.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// PII on custom-event payloads
|
|
1
|
+
// PII on custom-event payloads. Entity CRUD events get their PII
|
|
2
2
|
// encrypted by the executor; events written via ctx.appendEvent / MSP-apply /
|
|
3
3
|
// low-level append() (delivery attempt-log, jobs run-logger) had no encrypt
|
|
4
4
|
// path at all. `r.defineEvent(name, schema, { piiFields })` declares which
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// events skip the registry and take their stance from system-event-pii.ts
|
|
9
9
|
// instead (fail-closed when missing).
|
|
10
10
|
//
|
|
11
|
-
// `piiFields` is a mandatory, explicit stance
|
|
11
|
+
// `piiFields` is a mandatory, explicit stance: a payload can only
|
|
12
12
|
// go uncatalogued through a declared `piiFields: "none"`, never by omission —
|
|
13
13
|
// defineEvent refuses to register an event without one. What used to be a
|
|
14
14
|
// silent no-op (forgetting the option) is now either an explicit "none" or a
|
|
@@ -48,7 +48,7 @@ function isStructuredJsonValue(value) {
|
|
|
48
48
|
return typeof value === "object" && value !== null;
|
|
49
49
|
}
|
|
50
50
|
// Encrypts catalogued payload fields under the declared subject's DEK
|
|
51
|
-
// (user/tenant/self — resolveEventSubject
|
|
51
|
+
// (user/tenant/self — resolveEventSubject). No-op when the event
|
|
52
52
|
// type is uncatalogued or no subject KMS is configured (plaintext rollout
|
|
53
53
|
// mode — the hard boot gate governs whether that is acceptable). A
|
|
54
54
|
// user-subject field with an empty owner follows its declared `whenAbsent`
|
|
@@ -14,7 +14,7 @@ export type KekSourceEnv = {
|
|
|
14
14
|
export type KekSourceOptions = {
|
|
15
15
|
readonly fetch?: typeof globalThis.fetch;
|
|
16
16
|
readonly logPrefix?: string;
|
|
17
|
-
/** Where the boot line naming the KEK source goes. Defaults to `console.info
|
|
17
|
+
/** Where the boot line naming the KEK source goes. Defaults to the process logger, or `console.info` before one is wired. */
|
|
18
18
|
readonly log?: (message: string) => void;
|
|
19
19
|
/** Env names to resolve, e.g. `kmsSlotsOf(schema)`. */
|
|
20
20
|
readonly slots: readonly string[];
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
// made at all. Any `*_CIPHERTEXT` in the env that names no requested slot is
|
|
5
5
|
// ignored — a foreign ciphertext must never fail boot.
|
|
6
6
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
7
|
+
import { createFallbackLogger } from "../logging/utils.js";
|
|
8
|
+
const kekLog = createFallbackLogger("kumiko:kek");
|
|
7
9
|
const SCALEWAY_KEY_MANAGER_API_VERSION = "v1alpha1";
|
|
8
10
|
const DEFAULT_REGION = "fr-par";
|
|
9
11
|
const DECRYPT_TIMEOUT_MS = 5_000;
|
|
@@ -107,8 +109,7 @@ export async function resolvePlatformKeks(env, options) {
|
|
|
107
109
|
throw new Error(`${prefix}PLATFORM_KEK_PREVIOUS_VERSION must be set when PLATFORM_KEK_PREVIOUS is set.`);
|
|
108
110
|
}
|
|
109
111
|
const results = await Promise.all(slots.map((name) => resolveSlot(name, env, options, fetchImpl)));
|
|
110
|
-
|
|
111
|
-
const log = options.log ?? console.info;
|
|
112
|
+
const log = options.log ?? ((message) => kekLog.info(message));
|
|
112
113
|
const resolved = {};
|
|
113
114
|
slots.forEach((name, index) => {
|
|
114
115
|
const result = results[index];
|
|
@@ -6,7 +6,7 @@ export declare const subjectIdSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
6
6
|
userId: z.ZodUUID;
|
|
7
7
|
}, z.core.$strip>, z.ZodObject<{
|
|
8
8
|
kind: z.ZodLiteral<"tenant">;
|
|
9
|
-
tenantId: z.
|
|
9
|
+
tenantId: z.ZodUUID;
|
|
10
10
|
}, z.core.$strip>, z.ZodObject<{
|
|
11
11
|
kind: z.ZodLiteral<"record">;
|
|
12
12
|
entity: z.ZodString;
|