@cosmicdrift/kumiko-bundled-features 0.352.0 → 0.354.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/agent-tools/agent-doc-lint.d.ts +2 -0
- package/dist/agent-tools/agent-doc-lint.js +61 -1
- package/dist/agent-tools/agent-manifest.d.ts +1 -0
- package/dist/agent-tools/agent-manifest.js +17 -5
- package/dist/agent-tools/feature.js +7 -2
- package/dist/agent-tools/index.d.ts +1 -1
- package/dist/agent-tools/index.js +1 -1
- package/dist/agent-tools/manifest-deny-qns.d.ts +3 -0
- package/dist/agent-tools/manifest-deny-qns.js +17 -0
- package/dist/agent-tools/tool-catalog.d.ts +2 -1
- package/dist/agent-tools/tool-catalog.js +4 -1
- package/dist/agent-tools/tool-dispatch.js +1 -1
- package/dist/audit/handlers/list.query.js +13 -8
- package/dist/auth-email-password/handlers/change-password.write.js +1 -0
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +2 -2
- package/dist/auth-email-password/handlers/invite-accept.write.js +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +17 -0
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +4 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -0
- package/dist/auth-email-password/handlers/reset-password.write.js +1 -0
- package/dist/auth-email-password/handlers/signup-confirm.write.js +6 -4
- package/dist/auth-email-password/handlers/signup-request.write.js +51 -77
- package/dist/auth-email-password/handlers/token-request-handler.js +1 -0
- package/dist/auth-email-password/handlers/verify-email.write.js +1 -0
- package/dist/auth-email-password/index.d.ts +2 -0
- package/dist/auth-email-password/index.js +2 -0
- package/dist/auth-email-password/seeding.d.ts +2 -0
- package/dist/auth-email-password/seeding.js +30 -8
- package/dist/auth-email-password/signup-activation.d.ts +24 -0
- package/dist/auth-email-password/signup-activation.js +41 -0
- package/dist/auth-email-password/signup-token-store.d.ts +5 -0
- package/dist/auth-email-password/signup-token-store.js +8 -3
- package/dist/auth-email-password/web/auth-gate.d.ts +2 -2
- package/dist/auth-email-password/web/auth-gate.js +5 -5
- package/dist/auth-email-password/web/auth-redirect.d.ts +1 -0
- package/dist/auth-email-password/web/auth-redirect.js +14 -0
- package/dist/auth-email-password/web/login-screen.js +2 -2
- package/dist/auth-email-password/web/user-menu.js +1 -1
- package/dist/auth-mfa/feature.js +5 -0
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -0
- package/dist/auth-mfa/handlers/verify.write.js +1 -0
- package/dist/auth-mfa/schema/user-mfa.d.ts +6 -0
- package/dist/auth-mfa/screens.js +2 -2
- package/dist/auth-mfa/web/mfa-recovery-codes-reveal.js +1 -1
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +3 -3
- package/dist/auth-mfa/web/mfa-verify-screen.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-verify-screen.js +1 -1
- package/dist/billing-foundation/billing-info-query.d.ts +5 -2
- package/dist/billing-foundation/checkout-core.d.ts +7 -0
- package/dist/billing-foundation/checkout-core.js +7 -2
- package/dist/billing-foundation/entities.d.ts +8 -0
- package/dist/billing-foundation/handlers/start-plan-checkout.write.js +7 -1
- package/dist/billing-foundation/projection.d.ts +8 -0
- package/dist/cap-counter/entity.d.ts +1 -0
- package/dist/cap-overview/access.js +2 -9
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
- package/dist/cap-overview/handlers/tenant-options.query.js +4 -5
- package/dist/channel-in-app/in-app-channel.js +1 -1
- package/dist/channel-in-app/tables.js +4 -2
- package/dist/compliance-profiles/schema/profile-selection.d.ts +10 -8
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +2 -4
- package/dist/config/handlers/values.query.d.ts +3 -1
- package/dist/config/handlers/values.query.js +7 -2
- package/dist/config/table.d.ts +6 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.js +110 -61
- package/dist/custom-fields/entity.d.ts +4 -0
- package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -0
- package/dist/delivery/db/queries/address-opt-outs.d.ts +3 -1
- package/dist/delivery/db/queries/address-opt-outs.js +12 -7
- package/dist/delivery/delivery-service.js +60 -12
- package/dist/delivery/public-names.js +1 -1
- package/dist/delivery/tables.d.ts +6 -0
- package/dist/delivery/unsubscribe.js +66 -14
- package/dist/document-ingest-foundation/entity.d.ts +4 -0
- package/dist/feature-toggles/feature.js +2 -3
- package/dist/feature-toggles/toggle-runtime.d.ts +5 -1
- package/dist/feature-toggles/toggle-runtime.js +30 -6
- package/dist/feature-toggles/toggle-sync-signal.d.ts +3 -2
- package/dist/feature-toggles/toggle-sync-signal.js +29 -10
- package/dist/file-derivatives/handlers/public-variant.query.d.ts +1 -0
- package/dist/file-derivatives/handlers/public-variant.query.js +7 -1
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +5 -0
- package/dist/files-tenant-data/hooks.js +61 -24
- package/dist/folders/entity.d.ts +8 -0
- package/dist/folders/feature.js +2 -10
- package/dist/folders/handlers/delete-folder.write.js +31 -4
- package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
- package/dist/form-draft/db/queries/cleanup.js +4 -3
- package/dist/form-draft/entity.d.ts +2 -0
- package/dist/form-draft/handlers/cleanup.job.d.ts +5 -1
- package/dist/form-draft/handlers/cleanup.job.js +11 -5
- package/dist/foundation-shared/index.d.ts +1 -1
- package/dist/foundation-shared/index.js +1 -1
- package/dist/foundation-shared/mail-host-policy.d.ts +4 -0
- package/dist/foundation-shared/mail-host-policy.js +13 -4
- package/dist/inbound-mail-foundation/entities.d.ts +25 -0
- package/dist/inbound-mail-foundation/projection.d.ts +20 -0
- package/dist/inbound-provider-imap/feature.js +2 -0
- package/dist/inbound-provider-imap/imap-client.js +3 -4
- package/dist/jobs/constants.d.ts +1 -0
- package/dist/jobs/constants.js +1 -0
- package/dist/jobs/db/queries/retention.d.ts +1 -0
- package/dist/jobs/db/queries/retention.js +5 -0
- package/dist/jobs/db/queries/stale-run-sweep.d.ts +2 -0
- package/dist/jobs/db/queries/stale-run-sweep.js +13 -2
- package/dist/jobs/feature.js +7 -1
- package/dist/jobs/handlers/list.query.d.ts +2 -1
- package/dist/jobs/handlers/list.query.js +40 -15
- package/dist/jobs/handlers/tenant-failures.query.js +1 -1
- package/dist/jobs/handlers/tenant-runs.query.d.ts +17 -0
- package/dist/jobs/handlers/tenant-runs.query.js +72 -0
- package/dist/jobs/i18n.js +1 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.js +1 -0
- package/dist/jobs/job-run-logger.d.ts +2 -2
- package/dist/jobs/job-run-logger.js +98 -9
- package/dist/jobs/job-run-table.d.ts +6 -0
- package/dist/jobs/tenant-job-failure-table.js +15 -2
- package/dist/jobs/tenant-job-run-table.d.ts +4 -0
- package/dist/jobs/tenant-job-run-table.js +34 -0
- package/dist/ledger/entity.d.ts +24 -8
- package/dist/ledger/entity.js +17 -5
- package/dist/ledger/feature.js +3 -0
- package/dist/ledger/handlers/confirm-schedule-period.write.js +9 -3
- package/dist/ledger/handlers/create-transaction.write.js +1 -0
- package/dist/ledger/handlers/reverse-transaction.write.js +1 -0
- package/dist/ledger/schedule-subject-pair.d.ts +2 -0
- package/dist/ledger/schedule-subject-pair.js +24 -0
- package/dist/ledger/schemas.js +8 -2
- package/dist/mail-transport-smtp/feature.d.ts +3 -4
- package/dist/mail-transport-smtp/feature.js +4 -13
- package/dist/managed-pages/feature.js +28 -10
- package/dist/managed-pages/table.d.ts +12 -0
- package/dist/notes-history/entity.d.ts +12 -0
- package/dist/notes-history/entity.js +4 -0
- package/dist/notes-history/feature.js +2 -10
- package/dist/personal-access-tokens/handlers/create.write.js +1 -0
- package/dist/personal-access-tokens/schema/api-token.d.ts +6 -0
- package/dist/personal-access-tokens/screens.js +14 -3
- package/dist/secrets/table.d.ts +1 -0
- package/dist/seo/feature.js +28 -6
- package/dist/sessions/feature.d.ts +1 -0
- package/dist/sessions/feature.js +9 -8
- package/dist/sessions/handlers/detail.query.d.ts +1 -1
- package/dist/sessions/handlers/detail.query.js +2 -2
- package/dist/sessions/handlers/list.query.d.ts +1 -1
- package/dist/sessions/handlers/list.query.js +5 -3
- package/dist/sessions/schema/user-session.d.ts +4 -0
- package/dist/sessions/screens.d.ts +2 -2
- package/dist/sessions/screens.js +6 -7
- package/dist/shared/assert-no-where-rule-in-ownership-write.d.ts +2 -0
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +18 -0
- package/dist/shared/encrypt-for-direct-write.js +10 -2
- package/dist/shared/index.d.ts +4 -3
- package/dist/shared/index.js +4 -3
- package/dist/shared/parent-visibility.d.ts +2 -1
- package/dist/shared/parent-visibility.js +21 -0
- package/dist/shared/rate-limited-text-response.d.ts +2 -0
- package/dist/shared/rate-limited-text-response.js +9 -0
- package/dist/shared/row-bound-grant.js +16 -2
- package/dist/shared/session-locale-field.d.ts +1 -0
- package/dist/shared/session-locale-field.js +6 -0
- package/dist/tags/entity.d.ts +9 -0
- package/dist/tags/feature.js +2 -10
- package/dist/template-resolver/api.d.ts +2 -2
- package/dist/template-resolver/handlers/list.query.d.ts +2 -0
- package/dist/template-resolver/handlers/list.query.js +2 -2
- package/dist/template-resolver/table.d.ts +48 -30
- package/dist/template-resolver/user-content-table.d.ts +34 -20
- package/dist/tenant/decrypt-tenant-names.d.ts +3 -0
- package/dist/tenant/decrypt-tenant-names.js +10 -0
- package/dist/tenant/feature.js +7 -1
- package/dist/tenant/handlers/me.query.js +5 -1
- package/dist/tenant/handlers/memberships.query.js +3 -2
- package/dist/tenant/handlers/tenant-directory.query.js +9 -3
- package/dist/tenant/handlers/toggle-enabled.write.js +2 -0
- package/dist/tenant/handlers/update-member-roles.write.js +1 -0
- package/dist/tenant/index.d.ts +1 -0
- package/dist/tenant/index.js +1 -0
- package/dist/tenant/invitation-table.d.ts +54 -8
- package/dist/tenant/invitation-table.js +6 -1
- package/dist/tenant/invited-membership.d.ts +8 -6
- package/dist/tenant/invited-membership.js +28 -7
- package/dist/tenant/membership-table.d.ts +4 -0
- package/dist/tenant/schema/tenant.d.ts +18 -10
- package/dist/tenant/schema/tenant.js +4 -6
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +11 -18
- package/dist/tenant-handover/transfer-graph.d.ts +2 -21
- package/dist/tenant-handover/transfer-graph.js +8 -75
- package/dist/tenant-lifecycle/boot-checks.d.ts +1 -0
- package/dist/tenant-lifecycle/boot-checks.js +13 -0
- package/dist/tenant-lifecycle/constants.d.ts +3 -0
- package/dist/tenant-lifecycle/constants.js +5 -0
- package/dist/tenant-lifecycle/events.d.ts +5 -0
- package/dist/tenant-lifecycle/events.js +5 -0
- package/dist/tenant-lifecycle/feature.js +6 -3
- package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +10 -5
- package/dist/tenant-lifecycle/run-tenant-destroy.js +59 -17
- package/dist/tenant-lifecycle/stages.d.ts +8 -1
- package/dist/tenant-lifecycle/stages.js +33 -4
- package/dist/tenant-lifecycle/testing.d.ts +8 -0
- package/dist/tenant-lifecycle/testing.js +42 -0
- package/dist/tier-engine/entity.d.ts +2 -0
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -0
- package/dist/tier-engine/tier-resolver.d.ts +2 -0
- package/dist/user/handlers/detail.query.js +2 -0
- package/dist/user/handlers/list.query.js +6 -2
- package/dist/user/handlers/update.write.js +1 -0
- package/dist/user/schema/user.d.ts +22 -8
- package/dist/user/seeding.d.ts +1 -0
- package/dist/user/seeding.js +20 -0
- package/dist/user-data-rights/boot-checks.js +5 -0
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +1 -0
- package/dist/user-data-rights/index.d.ts +1 -0
- package/dist/user-data-rights/index.js +1 -0
- package/dist/user-data-rights/schema/download-attempt.d.ts +14 -0
- package/dist/user-data-rights/schema/download-attempt.js +17 -9
- package/dist/user-data-rights/schema/download-token.d.ts +8 -0
- package/dist/user-data-rights/schema/export-job.d.ts +16 -8
- package/dist/user-profile/handlers/change-email.write.js +8 -2
- package/dist/waitlist/entity.d.ts +22 -6
- package/dist/workflow-runner/event-trigger.d.ts +1 -0
- package/dist/workflow-runner/event-trigger.js +63 -15
- package/dist/workflow-runner/handlers/resume-run.write.js +8 -2
- package/dist/workflow-runner/runner.d.ts +2 -1
- package/dist/workflow-runner/runner.js +5 -1
- package/package.json +35 -10
- package/src/agent-tools/changes.json +12 -0
- package/src/audit/changes.json +6 -0
- package/src/auth-email-password/changes.json +24 -0
- package/src/auth-mfa/changes.json +7 -0
- package/src/billing-foundation/changes.json +6 -0
- package/src/channel-in-app/changes.json +8 -1
- package/src/crypto-shredding/changes.json +12 -0
- package/src/delivery/changes.json +6 -0
- package/src/files/changes.json +24 -0
- package/src/files-tenant-data/changes.json +5 -0
- package/src/folders/changes.json +6 -0
- package/src/form-draft/changes.json +7 -1
- package/src/inbound-provider-imap/changes.json +6 -0
- package/src/jobs/changes.json +30 -0
- package/src/ledger/changes.json +23 -0
- package/src/managed-pages/changes.json +6 -0
- package/src/notes-history/changes.json +13 -0
- package/src/seo/changes.json +5 -0
- package/src/template-resolver/changes.json +5 -0
- package/src/tenant/changes.json +19 -0
- package/src/tenant-handover/changes.json +12 -0
- package/src/tenant-lifecycle/changes.json +22 -0
- package/src/tier-engine/changes.json +5 -0
- package/src/user/changes.json +15 -0
- package/src/user-data-rights/changes.json +6 -0
- package/src/workflow-runner/changes.json +5 -0
- package/dist/shared/has-where-rule.d.ts +0 -2
- package/dist/shared/has-where-rule.js +0 -10
|
@@ -4,6 +4,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
4
4
|
readonly type: "text";
|
|
5
5
|
readonly description?: string;
|
|
6
6
|
readonly maxLength?: number;
|
|
7
|
+
readonly minLength?: number;
|
|
7
8
|
readonly required?: boolean;
|
|
8
9
|
readonly searchable?: boolean;
|
|
9
10
|
readonly sortable?: boolean;
|
|
@@ -25,6 +26,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
25
26
|
readonly type: "text";
|
|
26
27
|
readonly description?: string;
|
|
27
28
|
readonly maxLength?: number;
|
|
29
|
+
readonly minLength?: number;
|
|
28
30
|
readonly required?: boolean;
|
|
29
31
|
readonly searchable?: boolean;
|
|
30
32
|
readonly sortable?: boolean;
|
|
@@ -46,6 +48,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
46
48
|
readonly type: "text";
|
|
47
49
|
readonly description?: string;
|
|
48
50
|
readonly maxLength?: number;
|
|
51
|
+
readonly minLength?: number;
|
|
49
52
|
readonly required?: boolean;
|
|
50
53
|
readonly searchable?: boolean;
|
|
51
54
|
readonly sortable?: boolean;
|
|
@@ -67,6 +70,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
67
70
|
readonly type: "text";
|
|
68
71
|
readonly description?: string;
|
|
69
72
|
readonly maxLength?: number;
|
|
73
|
+
readonly minLength?: number;
|
|
70
74
|
readonly required?: boolean;
|
|
71
75
|
readonly searchable?: boolean;
|
|
72
76
|
readonly sortable?: boolean;
|
|
@@ -104,6 +108,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
104
108
|
readonly type: "text";
|
|
105
109
|
readonly description?: string;
|
|
106
110
|
readonly maxLength?: number;
|
|
111
|
+
readonly minLength?: number;
|
|
107
112
|
readonly required?: boolean;
|
|
108
113
|
readonly searchable?: boolean;
|
|
109
114
|
readonly sortable?: boolean;
|
|
@@ -133,13 +138,14 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
133
138
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
134
139
|
readonly display?: "radio" | "dropdown";
|
|
135
140
|
readonly optionTones?: {
|
|
136
|
-
readonly invited?:
|
|
137
|
-
readonly pending?:
|
|
138
|
-
readonly rejected?:
|
|
141
|
+
readonly invited?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
142
|
+
readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
143
|
+
readonly rejected?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
139
144
|
} | undefined;
|
|
140
145
|
readonly optionsQuery?: string;
|
|
141
146
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
142
147
|
readonly optionsAvailabilityQuery?: string;
|
|
148
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"invited" | "pending" | "rejected">[] | undefined;
|
|
143
149
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
144
150
|
required: true;
|
|
145
151
|
};
|
|
@@ -177,6 +183,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
177
183
|
readonly type: "text";
|
|
178
184
|
readonly description?: string;
|
|
179
185
|
readonly maxLength?: number;
|
|
186
|
+
readonly minLength?: number;
|
|
180
187
|
readonly required?: boolean;
|
|
181
188
|
readonly searchable?: boolean;
|
|
182
189
|
readonly sortable?: boolean;
|
|
@@ -198,6 +205,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
|
|
|
198
205
|
readonly type: "text";
|
|
199
206
|
readonly description?: string;
|
|
200
207
|
readonly maxLength?: number;
|
|
208
|
+
readonly minLength?: number;
|
|
201
209
|
readonly required?: boolean;
|
|
202
210
|
readonly searchable?: boolean;
|
|
203
211
|
readonly sortable?: boolean;
|
|
@@ -221,6 +229,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
221
229
|
readonly type: "text";
|
|
222
230
|
readonly description?: string;
|
|
223
231
|
readonly maxLength?: number;
|
|
232
|
+
readonly minLength?: number;
|
|
224
233
|
readonly required?: boolean;
|
|
225
234
|
readonly searchable?: boolean;
|
|
226
235
|
readonly sortable?: boolean;
|
|
@@ -242,6 +251,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
242
251
|
readonly type: "text";
|
|
243
252
|
readonly description?: string;
|
|
244
253
|
readonly maxLength?: number;
|
|
254
|
+
readonly minLength?: number;
|
|
245
255
|
readonly required?: boolean;
|
|
246
256
|
readonly searchable?: boolean;
|
|
247
257
|
readonly sortable?: boolean;
|
|
@@ -263,6 +273,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
263
273
|
readonly type: "text";
|
|
264
274
|
readonly description?: string;
|
|
265
275
|
readonly maxLength?: number;
|
|
276
|
+
readonly minLength?: number;
|
|
266
277
|
readonly required?: boolean;
|
|
267
278
|
readonly searchable?: boolean;
|
|
268
279
|
readonly sortable?: boolean;
|
|
@@ -284,6 +295,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
284
295
|
readonly type: "text";
|
|
285
296
|
readonly description?: string;
|
|
286
297
|
readonly maxLength?: number;
|
|
298
|
+
readonly minLength?: number;
|
|
287
299
|
readonly required?: boolean;
|
|
288
300
|
readonly searchable?: boolean;
|
|
289
301
|
readonly sortable?: boolean;
|
|
@@ -321,6 +333,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
321
333
|
readonly type: "text";
|
|
322
334
|
readonly description?: string;
|
|
323
335
|
readonly maxLength?: number;
|
|
336
|
+
readonly minLength?: number;
|
|
324
337
|
readonly required?: boolean;
|
|
325
338
|
readonly searchable?: boolean;
|
|
326
339
|
readonly sortable?: boolean;
|
|
@@ -350,13 +363,14 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
350
363
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
351
364
|
readonly display?: "radio" | "dropdown";
|
|
352
365
|
readonly optionTones?: {
|
|
353
|
-
readonly invited?:
|
|
354
|
-
readonly pending?:
|
|
355
|
-
readonly rejected?:
|
|
366
|
+
readonly invited?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
367
|
+
readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
368
|
+
readonly rejected?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
356
369
|
} | undefined;
|
|
357
370
|
readonly optionsQuery?: string;
|
|
358
371
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
359
372
|
readonly optionsAvailabilityQuery?: string;
|
|
373
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"invited" | "pending" | "rejected">[] | undefined;
|
|
360
374
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
361
375
|
required: true;
|
|
362
376
|
};
|
|
@@ -394,6 +408,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
394
408
|
readonly type: "text";
|
|
395
409
|
readonly description?: string;
|
|
396
410
|
readonly maxLength?: number;
|
|
411
|
+
readonly minLength?: number;
|
|
397
412
|
readonly required?: boolean;
|
|
398
413
|
readonly searchable?: boolean;
|
|
399
414
|
readonly sortable?: boolean;
|
|
@@ -415,6 +430,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
|
|
|
415
430
|
readonly type: "text";
|
|
416
431
|
readonly description?: string;
|
|
417
432
|
readonly maxLength?: number;
|
|
433
|
+
readonly minLength?: number;
|
|
418
434
|
readonly required?: boolean;
|
|
419
435
|
readonly searchable?: boolean;
|
|
420
436
|
readonly sortable?: boolean;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { FeatureRegistrar, WorkflowDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
export declare function assertEventTriggerStepsSupported(workflow: WorkflowDefinition): void;
|
|
2
3
|
export declare function registerEventTrigger(r: FeatureRegistrar, workflow: WorkflowDefinition): void;
|
|
@@ -8,13 +8,62 @@
|
|
|
8
8
|
// wiring uses the unbound pool), so `workflow.run-started` and the rest of
|
|
9
9
|
// the pipeline are not atomic. A throw from startAndRunWorkflow is recorded
|
|
10
10
|
// as `workflow.run-failed` and swallowed, so the dispatcher moves on.
|
|
11
|
-
import { describeWorkflowStepError, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RUN_FAILED_TYPE, } from "@cosmicdrift/kumiko-framework/engine";
|
|
11
|
+
import { buildPipelineSteps, createSystemUser, describeWorkflowStepError, getStep, SYSTEM_TENANT_ID, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RUN_FAILED_TYPE, WorkflowStepError, } from "@cosmicdrift/kumiko-framework/engine";
|
|
12
12
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
13
13
|
import { workflowRunAggregateId } from "./aggregate-id.js";
|
|
14
14
|
import { registerEventWakeup } from "./event-subscriber.js";
|
|
15
|
-
import { startAndRunWorkflow } from "./runner.js";
|
|
15
|
+
import { startAndRunWorkflow, WorkflowSuspensionUnsupportedError, } from "./runner.js";
|
|
16
16
|
import { registerWorkflow } from "./workflow-registry.js";
|
|
17
17
|
const log = createFallbackLogger("workflow-runner");
|
|
18
|
+
// The MSP apply context only offers unsafeAppendEvent/loadAggregate; these steps reach for
|
|
19
|
+
// ctx.db/write/writeAs and would crash on the first run instead of at registration.
|
|
20
|
+
const STEP_KINDS_NEEDING_HANDLER_CONTEXT = new Set([
|
|
21
|
+
"aggregate.create",
|
|
22
|
+
"aggregate.update",
|
|
23
|
+
"callFeature",
|
|
24
|
+
"read.findOne",
|
|
25
|
+
"read.findMany",
|
|
26
|
+
"unsafeProjectionUpsert",
|
|
27
|
+
"unsafeProjectionDelete",
|
|
28
|
+
]);
|
|
29
|
+
function* walkStepInstances(steps) {
|
|
30
|
+
for (const step of steps) {
|
|
31
|
+
yield step;
|
|
32
|
+
const { args } = step;
|
|
33
|
+
if (typeof args !== "object" || args === null)
|
|
34
|
+
continue;
|
|
35
|
+
for (const path of getStep(step.kind)?.subPaths ?? []) {
|
|
36
|
+
const nested = path in args ? Reflect.get(args, path) : undefined;
|
|
37
|
+
if (Array.isArray(nested))
|
|
38
|
+
yield* walkStepInstances(nested);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function assertEventTriggerStepsSupported(workflow) {
|
|
43
|
+
let steps;
|
|
44
|
+
try {
|
|
45
|
+
// Same contract as the boot validator for handler pipelines: the closure must build its
|
|
46
|
+
// step list from the step builder alone, so an empty event is enough to enumerate kinds.
|
|
47
|
+
steps = buildPipelineSteps(workflow.pipelineDef, {
|
|
48
|
+
type: "workflow-registration-probe",
|
|
49
|
+
payload: {},
|
|
50
|
+
user: createSystemUser(SYSTEM_TENANT_ID),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new Error(`Workflow "${workflow.name}" pipeline closure threw at registration: ${String(error)}. ` +
|
|
55
|
+
"Build the step list without reading event payload fields; read them inside step resolvers.", { cause: error });
|
|
56
|
+
}
|
|
57
|
+
for (const step of walkStepInstances(steps)) {
|
|
58
|
+
if (getStep(step.kind) === undefined) {
|
|
59
|
+
throw new Error(`Workflow "${workflow.name}" uses unknown step kind "${step.kind}"`);
|
|
60
|
+
}
|
|
61
|
+
if (STEP_KINDS_NEEDING_HANDLER_CONTEXT.has(step.kind)) {
|
|
62
|
+
throw new Error(`Workflow "${workflow.name}" is event-triggered but uses step "${step.kind}", which needs a ` +
|
|
63
|
+
"handler context (db/write) the event-trigger projection does not provide.");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
18
67
|
export function registerEventTrigger(r, workflow) {
|
|
19
68
|
// Populate the workflow-registry unconditionally, before the event-trigger
|
|
20
69
|
// guard below — resume-run (framework#2513 Phase 2) looks workflows up by
|
|
@@ -28,6 +77,7 @@ export function registerEventTrigger(r, workflow) {
|
|
|
28
77
|
// need a scheduler, not an MSP, so there is nothing to register here.
|
|
29
78
|
if (workflow.trigger.kind !== "event")
|
|
30
79
|
return;
|
|
80
|
+
assertEventTriggerStepsSupported(workflow);
|
|
31
81
|
const eventType = workflow.trigger.eventType;
|
|
32
82
|
r.multiStreamProjection({
|
|
33
83
|
name: `workflow-${workflow.name}`,
|
|
@@ -41,19 +91,16 @@ export function registerEventTrigger(r, workflow) {
|
|
|
41
91
|
// `trigger.filter` below typed without a cast.
|
|
42
92
|
if (workflow.trigger.kind !== "event")
|
|
43
93
|
return;
|
|
44
|
-
if (workflow.trigger.filter) {
|
|
45
|
-
const matches = workflow.trigger.filter(event);
|
|
46
|
-
// skip: the workflow's own trigger filter rejected this event — not
|
|
47
|
-
// this run's concern, so no run is started and nothing is recorded.
|
|
48
|
-
if (!matches)
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
94
|
// @cast-boundary msp-to-write-event — the MSP delivers a StoredEvent
|
|
52
95
|
// (event-store shape); the workflow runner expects a WriteEvent
|
|
53
96
|
// (handler shape). The fields workflow steps read (type, payload)
|
|
54
97
|
// overlap exactly — the missing `.user` field is acceptable because
|
|
55
98
|
// workflow triggers run system-level, not user-scoped.
|
|
56
99
|
const triggerEvent = event;
|
|
100
|
+
// skip: the workflow's own trigger filter rejected this event — not this run's
|
|
101
|
+
// concern, so no run is started and nothing is recorded.
|
|
102
|
+
if (workflow.trigger.filter && !workflow.trigger.filter(triggerEvent))
|
|
103
|
+
return;
|
|
57
104
|
let idempotencyKey;
|
|
58
105
|
if (typeof workflow.idempotencyKey === "function") {
|
|
59
106
|
idempotencyKey = workflow.idempotencyKey(triggerEvent);
|
|
@@ -75,23 +122,24 @@ export function registerEventTrigger(r, workflow) {
|
|
|
75
122
|
version: event.version,
|
|
76
123
|
},
|
|
77
124
|
...(idempotencyKey && { idempotencyKey }),
|
|
78
|
-
// @cast-boundary msp-to-handler-ctx — MultiStreamApplyContext only
|
|
79
|
-
// exposes unsafeAppendEvent/loadAggregate, a subset of
|
|
80
|
-
// HandlerContext. The step vocabulary this runner drives (wait,
|
|
81
|
-
// compute, return) only ever calls unsafeAppendEvent on it.
|
|
82
125
|
handlerCtx: ctx,
|
|
83
126
|
});
|
|
84
127
|
}
|
|
85
128
|
catch (error) {
|
|
129
|
+
// Failures outside the step loop (run-started append) have no step yet, so 0.
|
|
130
|
+
const stepIndex = error instanceof WorkflowStepError ||
|
|
131
|
+
error instanceof WorkflowSuspensionUnsupportedError
|
|
132
|
+
? error.stepIndex
|
|
133
|
+
: 0;
|
|
86
134
|
log.warn("workflow run failed", {
|
|
87
135
|
runId,
|
|
88
136
|
workflowName: workflow.name,
|
|
89
|
-
stepIndex
|
|
137
|
+
stepIndex,
|
|
90
138
|
error: String(error),
|
|
91
139
|
});
|
|
92
140
|
const failedPayload = {
|
|
93
141
|
workflowName: workflow.name,
|
|
94
|
-
stepIndex
|
|
142
|
+
stepIndex,
|
|
95
143
|
error: describeWorkflowStepError(error),
|
|
96
144
|
};
|
|
97
145
|
await ctx.unsafeAppendEvent({
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// resultKey on steps/wait-for-event.ts) — pre-seeded into stepsAcc below so
|
|
31
31
|
// a subsequent step's resolver can read `ctx.steps[awaits.someKey]`.
|
|
32
32
|
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
33
|
-
import { buildPipelineSteps, computeDefinitionFingerprint, describeWorkflowStepError, getStep, runStepList, SYSTEM_ROLE, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RESUMED_TYPE, WORKFLOW_RETRY_SCHEDULED_TYPE, WORKFLOW_RUN_COMPLETED_TYPE, WORKFLOW_RUN_FAILED_TYPE, WORKFLOW_RUN_STARTED_TYPE, WORKFLOW_WAITING_FOR_EVENT_TYPE, } from "@cosmicdrift/kumiko-framework/engine";
|
|
33
|
+
import { buildPipelineSteps, computeDefinitionFingerprint, describeWorkflowStepError, getStep, runStepList, SYSTEM_ROLE, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RESUMED_TYPE, WORKFLOW_RETRY_SCHEDULED_TYPE, WORKFLOW_RUN_COMPLETED_TYPE, WORKFLOW_RUN_FAILED_TYPE, WORKFLOW_RUN_STARTED_TYPE, WORKFLOW_WAITING_FOR_EVENT_TYPE, WorkflowStepError, } from "@cosmicdrift/kumiko-framework/engine";
|
|
34
34
|
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
35
35
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
36
36
|
import * as z from "zod";
|
|
@@ -52,6 +52,9 @@ async function appendRunFailed(ctx, runId, failedPayload) {
|
|
|
52
52
|
}
|
|
53
53
|
function checkQ7Fingerprint(workflow, workflowName, runId, stepIndex, storedFingerprint) {
|
|
54
54
|
const currentFingerprint = computeDefinitionFingerprint(workflow);
|
|
55
|
+
if (storedFingerprint === null) {
|
|
56
|
+
log.warn(`Run ${runId} of workflow "${workflowName}" has no stored definition fingerprint — resuming against the current definition unchecked.`);
|
|
57
|
+
}
|
|
55
58
|
const fingerprintChanged = storedFingerprint !== null && currentFingerprint !== storedFingerprint;
|
|
56
59
|
if (!fingerprintChanged) {
|
|
57
60
|
return null;
|
|
@@ -235,9 +238,12 @@ async function runResumedPipeline(ctx, input) {
|
|
|
235
238
|
}
|
|
236
239
|
catch (error) {
|
|
237
240
|
log.warn("workflow run failed", { runId, workflowName, stepIndex, error: String(error) });
|
|
241
|
+
// The input stepIndex is the suspended step; the failure happened at the step the resumed pass reached.
|
|
238
242
|
const failedPayload = {
|
|
239
243
|
workflowName,
|
|
240
|
-
stepIndex
|
|
244
|
+
stepIndex: error instanceof WorkflowStepError || error instanceof WorkflowSuspensionUnsupportedError
|
|
245
|
+
? error.stepIndex
|
|
246
|
+
: stepIndex,
|
|
241
247
|
error: describeWorkflowStepError(error),
|
|
242
248
|
};
|
|
243
249
|
await appendRunFailed(ctx, runId, failedPayload);
|
|
@@ -22,6 +22,7 @@ export type WorkflowRunFailedPayload = {
|
|
|
22
22
|
readonly error: string;
|
|
23
23
|
readonly reason?: string;
|
|
24
24
|
};
|
|
25
|
+
export type WorkflowRunContext = Pick<HandlerContext, "unsafeAppendEvent">;
|
|
25
26
|
export declare class WorkflowSuspensionUnsupportedError extends Error {
|
|
26
27
|
readonly workflowName: string;
|
|
27
28
|
readonly stepIndex: number;
|
|
@@ -42,7 +43,7 @@ export declare function startAndRunWorkflow(args: {
|
|
|
42
43
|
readonly triggerEvent: WriteEvent;
|
|
43
44
|
readonly triggerEventRef: TriggerEventRef;
|
|
44
45
|
readonly idempotencyKey?: string;
|
|
45
|
-
readonly handlerCtx:
|
|
46
|
+
readonly handlerCtx: WorkflowRunContext;
|
|
46
47
|
}): Promise<{
|
|
47
48
|
readonly outcome: "completed" | "suspended";
|
|
48
49
|
}>;
|
|
@@ -53,7 +53,11 @@ export async function startAndRunWorkflow(args) {
|
|
|
53
53
|
payload: startedPayload,
|
|
54
54
|
});
|
|
55
55
|
const steps = buildPipelineSteps(args.workflow.pipelineDef, args.triggerEvent);
|
|
56
|
-
|
|
56
|
+
// @cast-boundary msp-to-handler-ctx — event-trigger hands over the narrower
|
|
57
|
+
// MultiStreamApplyContext (no query/write/writeAs). The step vocabulary this
|
|
58
|
+
// runner drives (wait, compute, return) only ever calls unsafeAppendEvent.
|
|
59
|
+
const stepCtx = args.handlerCtx;
|
|
60
|
+
const outcome = await runStepList(steps, args.triggerEvent, stepCtx, {}, {}, {
|
|
57
61
|
runId: args.runId,
|
|
58
62
|
workflowName: args.workflow.name,
|
|
59
63
|
stepIndex: 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-bundled-features",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.354.0",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"kumiko": {
|
|
18
18
|
"runtime": "runtime",
|
|
19
19
|
"bunOnlyExports": [
|
|
20
|
-
"./template-resolver/testing"
|
|
20
|
+
"./template-resolver/testing",
|
|
21
|
+
"./tenant-lifecycle/testing"
|
|
21
22
|
]
|
|
22
23
|
},
|
|
23
24
|
"exports": {
|
|
@@ -257,6 +258,10 @@
|
|
|
257
258
|
"types": "./dist/user-data-rights/index.d.ts",
|
|
258
259
|
"default": "./dist/user-data-rights/index.js"
|
|
259
260
|
},
|
|
261
|
+
"./user-data-rights/email-templates": {
|
|
262
|
+
"types": "./dist/user-data-rights/email-templates.d.ts",
|
|
263
|
+
"default": "./dist/user-data-rights/email-templates.js"
|
|
264
|
+
},
|
|
260
265
|
"./user-data-rights/web": {
|
|
261
266
|
"types": "./dist/user-data-rights/web/index.d.ts",
|
|
262
267
|
"default": "./dist/user-data-rights/web/index.js"
|
|
@@ -285,6 +290,10 @@
|
|
|
285
290
|
"types": "./dist/tenant-lifecycle/index.d.ts",
|
|
286
291
|
"default": "./dist/tenant-lifecycle/index.js"
|
|
287
292
|
},
|
|
293
|
+
"./tenant-lifecycle/testing": {
|
|
294
|
+
"types": "./dist/tenant-lifecycle/testing.d.ts",
|
|
295
|
+
"default": "./dist/tenant-lifecycle/testing.js"
|
|
296
|
+
},
|
|
288
297
|
"./tenant-handover": {
|
|
289
298
|
"types": "./dist/tenant-handover/index.d.ts",
|
|
290
299
|
"default": "./dist/tenant-handover/index.js"
|
|
@@ -317,6 +326,10 @@
|
|
|
317
326
|
"types": "./dist/auth-email-password/index.d.ts",
|
|
318
327
|
"default": "./dist/auth-email-password/index.js"
|
|
319
328
|
},
|
|
329
|
+
"./auth-email-password/email-templates": {
|
|
330
|
+
"types": "./dist/auth-email-password/email-templates.d.ts",
|
|
331
|
+
"default": "./dist/auth-email-password/email-templates.js"
|
|
332
|
+
},
|
|
320
333
|
"./auth-email-password/constants": {
|
|
321
334
|
"types": "./dist/auth-email-password/constants.d.ts",
|
|
322
335
|
"default": "./dist/auth-email-password/constants.js"
|
|
@@ -503,12 +516,12 @@
|
|
|
503
516
|
}
|
|
504
517
|
},
|
|
505
518
|
"dependencies": {
|
|
506
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
507
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
508
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
509
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
510
|
-
"@cosmicdrift/kumiko-renderer-web": "0.
|
|
511
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
519
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.354.0",
|
|
520
|
+
"@cosmicdrift/kumiko-framework": "0.354.0",
|
|
521
|
+
"@cosmicdrift/kumiko-headless": "0.354.0",
|
|
522
|
+
"@cosmicdrift/kumiko-renderer": "0.354.0",
|
|
523
|
+
"@cosmicdrift/kumiko-renderer-web": "0.354.0",
|
|
524
|
+
"@cosmicdrift/kumiko-types": "0.354.0",
|
|
512
525
|
"@mollie/api-client": "^4.5.0",
|
|
513
526
|
"@node-rs/argon2": "^2.0.2",
|
|
514
527
|
"@types/mailparser": "^3.4.6",
|
|
@@ -771,6 +784,10 @@
|
|
|
771
784
|
"types": "./dist/user-data-rights/index.d.ts",
|
|
772
785
|
"default": "./dist/user-data-rights/index.js"
|
|
773
786
|
},
|
|
787
|
+
"./user-data-rights/email-templates": {
|
|
788
|
+
"types": "./dist/user-data-rights/email-templates.d.ts",
|
|
789
|
+
"default": "./dist/user-data-rights/email-templates.js"
|
|
790
|
+
},
|
|
774
791
|
"./user-data-rights/web": {
|
|
775
792
|
"types": "./dist/user-data-rights/web/index.d.ts",
|
|
776
793
|
"default": "./dist/user-data-rights/web/index.js"
|
|
@@ -799,6 +816,10 @@
|
|
|
799
816
|
"types": "./dist/tenant-lifecycle/index.d.ts",
|
|
800
817
|
"default": "./dist/tenant-lifecycle/index.js"
|
|
801
818
|
},
|
|
819
|
+
"./tenant-lifecycle/testing": {
|
|
820
|
+
"types": "./dist/tenant-lifecycle/testing.d.ts",
|
|
821
|
+
"default": "./dist/tenant-lifecycle/testing.js"
|
|
822
|
+
},
|
|
802
823
|
"./tenant-handover": {
|
|
803
824
|
"types": "./dist/tenant-handover/index.d.ts",
|
|
804
825
|
"default": "./dist/tenant-handover/index.js"
|
|
@@ -831,6 +852,10 @@
|
|
|
831
852
|
"types": "./dist/auth-email-password/index.d.ts",
|
|
832
853
|
"default": "./dist/auth-email-password/index.js"
|
|
833
854
|
},
|
|
855
|
+
"./auth-email-password/email-templates": {
|
|
856
|
+
"types": "./dist/auth-email-password/email-templates.d.ts",
|
|
857
|
+
"default": "./dist/auth-email-password/email-templates.js"
|
|
858
|
+
},
|
|
834
859
|
"./auth-email-password/constants": {
|
|
835
860
|
"types": "./dist/auth-email-password/constants.d.ts",
|
|
836
861
|
"default": "./dist/auth-email-password/constants.js"
|
|
@@ -1025,8 +1050,8 @@
|
|
|
1025
1050
|
],
|
|
1026
1051
|
"devDependencies": {
|
|
1027
1052
|
"@testing-library/user-event": "^14.6.1",
|
|
1028
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
1029
|
-
"@cosmicdrift/kumiko-locale-es": "0.
|
|
1053
|
+
"@cosmicdrift/kumiko-locale-de": "0.354.0",
|
|
1054
|
+
"@cosmicdrift/kumiko-locale-es": "0.354.0",
|
|
1030
1055
|
"jsqr": "^1.4.0"
|
|
1031
1056
|
}
|
|
1032
1057
|
}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.353.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "buildToolCatalog throws when the manifest was built with denyQns the catalog options lack",
|
|
6
|
+
"migration": "Pass the same denyQns list to buildAgentManifest and buildToolCatalog."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.353.0",
|
|
10
|
+
"type": "fix",
|
|
11
|
+
"title": "Agent manifest screen titles resolve per feature instead of by mount order",
|
|
12
|
+
"detail": "Agent manifest screen titles no longer depend on feature mount order\nTwo features with a screen of the same short id used to get the title of whichever feature was mounted first. The manifest now looks up the screen's own feature-prefixed title key first and falls back to the unprefixed key."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.338.0",
|
|
4
16
|
"type": "improvement",
|
package/src/audit/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.353.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Audit list paging no longer repeats rows with ascending sort",
|
|
6
|
+
"detail": "Audit list pages forward without repeats when sorted ascending\n`audit:query:list` with `sortDirection: \"asc\"` returned the same rows again on the next page because the cursor always meant \"older than\". The cursor now follows the sort direction, and ties are broken by event id. Sorting by `type` returns a single page without `nextCursor`, since an event id cannot resume a type-ordered listing."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.346.0",
|
|
4
10
|
"type": "improvement",
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "Invitations pin the invitee's membership version; superseded accept no longer relies on timestamps",
|
|
6
|
+
"migration": "New nullable column read_tenant_invitations.membership_version: run `kumiko schema generate` and apply the migration before deploying. Invitations issued before the migration keep the timestamp comparison."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.354.0",
|
|
10
|
+
"type": "fix",
|
|
11
|
+
"title": "Login, MFA verify and MFA preauth setup follow the server landingPath when no valid next parameter is present",
|
|
12
|
+
"detail": "AuthGate onSuccess receives the landing path. A validated next parameter still wins; a landing path equal to the current path is not followed, so the screen does not reload itself."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.354.0",
|
|
16
|
+
"type": "fix",
|
|
17
|
+
"title": "Signup-confirm and invite-signup-complete store the request locale on the new user and in the session"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"version": "0.354.0",
|
|
21
|
+
"type": "fix",
|
|
22
|
+
"title": "INITIAL_SIGNUP_ROLES stays [\"TenantAdmin\", \"Admin\"] as a transition",
|
|
23
|
+
"detail": "New self-signup owners hold TenantAdmin plus the legacy Admin literal, because handlers that gate on the Admin literal would otherwise lock them out. Both roles show in Team, Members until those handlers gate on access.admin. This supersedes the earlier note that the owner role is only TenantAdmin.",
|
|
24
|
+
"migration": "Move your own handlers that gate on the Admin literal to access.admin; after that the Admin entry can be dropped from the constant."
|
|
25
|
+
},
|
|
2
26
|
{
|
|
3
27
|
"version": "0.348.0",
|
|
4
28
|
"type": "fix",
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "auth-mfa declares the master-key env slots, so composeEnvSchema requires KUMIKO_SECRETS_MASTER_KEY_V1 when auth-mfa is mounted",
|
|
6
|
+
"detail": "Review batch H1: framework parts of consumer-app findings.\n- `auth-email-password` exports `issueSignupActivation` (invalidate, mint, store and mail an activation link; the signup-request handler now runs on it), `SIGNUP_ACTIVATION_NOTIFICATION_TYPE`, `storeSignupToken`, `invalidateExistingSignupToken`, `normalizeEmail` and `SIGNUP_TOKEN_KEY_PREFIXES`.\n- `auth-mfa` declares the master-key env slots (`KUMIKO_SECRETS_MASTER_KEY_V1`, `_CURRENT_VERSION`, the `_CIPHERTEXT` twin) as a shared fragment with `secrets`, so a rotated `V<n>` slot is unpacked even without `secrets` mounted.\n- `user-data-rights` exports `TENANT_MODEL_CONFIG_KEY`; `createTemplateResolverApi` takes a `DbRunner`.\n- The user menu's logout item carries `data-testid=\"user-menu-logout\"`.\n- renderer-web: a `Field` description is linked to its text input via `aria-describedby`; the facet filter dropdown is capped to the available viewport height and scrolls; `createBrowserLocaleResolver` takes `normalizeLocale` and the default storage key is exported as `BROWSER_LOCALE_STORAGE_KEY`.\n- testing: `loginViaApi(request, credentials, { bucketKey })`, `CLIENT_IP_HEADER` from `@cosmicdrift/kumiko-testing/e2e`, and a Playwright-free `@cosmicdrift/kumiko-testing/e2e/constants` subpath (`KUMIKO_SECRETS_MASTER_KEY_V1`).",
|
|
7
|
+
"migration": "Apps that bring their own masterKey provider instead of the env KEK add \"auth-mfa\" to composeEnvSchema's optionalFeatures, like they already do for \"secrets\". Required wins as soon as auth-mfa is not in optionalFeatures, even when `secrets` is listed there."
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"version": "0.341.0",
|
|
4
11
|
"type": "breaking",
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "BillingInfo.prices and getBillingPrices are keyed by the tier union",
|
|
6
|
+
"migration": "A getBillingPrices that returns keys outside your tier union no longer compiles; remove or rename those keys."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.346.0",
|
|
4
10
|
"type": "fix",
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "forget-subject: the SUBJECT_FORGOTTEN audit now commits before the handler tx does and records cleanupError when a derived-data sweep fails",
|
|
6
|
+
"detail": "The SUBJECT_FORGOTTEN audit event is appended through the outside-transaction db, so it commits before the handler transaction does and survives a later rollback. If the blind-index sweep or search purge fails, the event carries cleanupError (error code or name, never the message) and the handler then fails; retry to finish the cleanup. The user-lifecycle step runs in a savepoint and no longer aborts the handler transaction."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.354.0",
|
|
10
|
+
"type": "fix",
|
|
11
|
+
"title": "Writing a personal field of an erased data subject answers 409 subject_erased instead of 500",
|
|
12
|
+
"detail": "Writing PII to an erased data subject answers 409 `subject_erased`, rebinding a hook's unsafeRaw grant no longer inherits db.global() writes, jobs wait for boot gates before consuming\nA write that has to encrypt a personal field for a subject whose key was erased (crypto-shredding) now fails with a `ConflictError` (409, reason `subject_erased`, i18n in en and de) instead of a 500, on the executor write path and in `encryptForDirectWrite`. A hook's own `unsafeRaw` grant (`withUnsafeRawGrant`) no longer carries the handler's `globalWrites` grant. The job runner starts its BullMQ worker only after the boot gates passed, so a job queued by a previous run cannot execute against an unmet boot precondition. `buildServer` warns at boot when `r.systemScope()` features exist but no RateLimitResolver is configured. The auth, MFA, PAT, change-email and request-deletion handlers declare only the escape-hatch grants they use."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.338.0",
|
|
4
16
|
"type": "improvement",
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "POST /resubscribe requires the undo token from the POST /unsubscribe response",
|
|
6
|
+
"migration": "Clients that called the resubscribe route with the unsubscribe token must send the undo token instead: read it from the hidden token field of the page POST /unsubscribe returns (aud kumiko:resubscribe, valid for 1 hour). The unsubscribe token is rejected on /resubscribe with 400, and the undo token is rejected on /unsubscribe."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.352.0",
|
|
4
10
|
"type": "breaking",
|
package/src/files/changes.json
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "breaking",
|
|
5
|
+
"title": "FileHandle.derive throws for suffixes outside <name>-<16 hex>",
|
|
6
|
+
"detail": "Final review batch D.\n- `FileHandle.derive(suffix)` now throws unless the suffix is `<name>-<16 hex>` (build it with `variantSuffix(name, spec)`). Free-form suffixes such as `derive(\"thumb\")` wrote keys the forget/tenant-destroy sweep could not recognize, so those binaries survived erasure. Callers passing a bare name must switch to `variantSuffix`.\n- `resolveKmsWiring` / `requireKmsWiring` throw when a `*_CIPHERTEXT` slot is set without its plaintext, pointing at the async entry points, instead of a misleading \"trio required\" error or a silent plaintext-PII fallback.\n- Event-PII owner/`whenAbsent` resolution now also runs without a configured KMS, so a missing owner fails in dev like in prod.\n- PII event backfill queues rebuilds under a per-run migration id, so a peer replica's re-queue is no longer cleared by another run.\n- `seedAdminGuarded` re-writes the canonical admin's email so the blind index is repaired, and skips undecryptable foreign user rows instead of aborting the boot seed.\n- A tenant-bound `FileContext.list` refuses prefixes outside the tenant's key space.\n- An entityList whose create screen was dropped for the caller's roles now carries `createUnavailable`, so the renderer no longer falls back to a generic create form.\n- Boot validation rejects an object-form `redirect` with `idFrom` whose same-feature target screen carries no id.\n- `defineFeature` throws when `dedupeOptions` holds a nested object (it can never compare equal across two mounts).\n- `FileContext.ref` and `list` (tenant-bound) refuse keys outside `${tenantId}/`; list columns accept `virtual: true`; `httpRoute` session-only routes now pass the global IP rate limit; tenant timezone cache TTL is 30 s; text fields without a personal stance warn at boot; the orphan-derivative sweep keeps derivatives whose original still exists; `piiFields` owner fields that can never yield a string throw unless `whenAbsent` is set.",
|
|
7
|
+
"migration": "Build the suffix with variantSuffix(name, spec) instead of passing a free-form string."
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"version": "0.354.0",
|
|
11
|
+
"type": "breaking",
|
|
12
|
+
"title": "A tenant-bound FileContext.list throws for prefixes outside the tenant's key space",
|
|
13
|
+
"migration": "Pass a prefix that starts with `${tenantId}/`."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"version": "0.354.0",
|
|
17
|
+
"type": "breaking",
|
|
18
|
+
"title": "A tenant-bound FileContext.ref throws for keys outside the tenant's key space",
|
|
19
|
+
"migration": "Use keys that start with `${tenantId}/`."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"version": "0.354.0",
|
|
23
|
+
"type": "fix",
|
|
24
|
+
"title": "The signed download URL carries a neutral file name instead of the personal fileName"
|
|
25
|
+
},
|
|
2
26
|
{
|
|
3
27
|
"version": "0.341.0",
|
|
4
28
|
"type": "improvement",
|
package/src/folders/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.354.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "folder:delete removes assignments whose host entity is gone instead of refusing forever",
|
|
6
|
+
"detail": "An assignment pointing at a hard-deleted, soft-deleted or unregistered host blocked folder:delete permanently with folder_has_assignments, because clear-folder needs a visible host and could not remove it. folder:delete now removes such assignments through the event-store executor (normal delete events) before the check, without the caller's read gate. Assignments of live hosts, including ones the caller cannot see, still block with folder_has_assignments. A refused delete removes nothing. The cleanup runs lazily at folder:delete, not in a host-delete hook, so restoring a soft-deleted host before then keeps its folder."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.246.0",
|
|
4
10
|
"type": "improvement",
|