@cosmicdrift/kumiko-bundled-features 0.352.0 → 0.353.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.
Files changed (105) hide show
  1. package/dist/agent-tools/agent-manifest.js +8 -2
  2. package/dist/agent-tools/manifest-deny-qns.d.ts +3 -0
  3. package/dist/agent-tools/manifest-deny-qns.js +17 -0
  4. package/dist/agent-tools/tool-catalog.d.ts +2 -1
  5. package/dist/agent-tools/tool-catalog.js +4 -1
  6. package/dist/audit/handlers/list.query.js +13 -8
  7. package/dist/auth-email-password/handlers/signup-confirm.write.js +2 -3
  8. package/dist/auth-mfa/schema/user-mfa.d.ts +6 -0
  9. package/dist/auth-mfa/screens.js +2 -2
  10. package/dist/billing-foundation/checkout-core.d.ts +7 -0
  11. package/dist/billing-foundation/checkout-core.js +7 -2
  12. package/dist/billing-foundation/entities.d.ts +8 -0
  13. package/dist/billing-foundation/handlers/start-plan-checkout.write.js +7 -1
  14. package/dist/billing-foundation/projection.d.ts +8 -0
  15. package/dist/cap-counter/entity.d.ts +1 -0
  16. package/dist/cap-overview/access.js +2 -9
  17. package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
  18. package/dist/cap-overview/handlers/tenant-options.query.js +4 -5
  19. package/dist/compliance-profiles/schema/profile-selection.d.ts +8 -8
  20. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +2 -4
  21. package/dist/config/handlers/values.query.d.ts +3 -1
  22. package/dist/config/handlers/values.query.js +7 -2
  23. package/dist/config/table.d.ts +6 -0
  24. package/dist/custom-fields/entity.d.ts +4 -0
  25. package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -0
  26. package/dist/delivery/public-names.js +1 -1
  27. package/dist/delivery/tables.d.ts +6 -0
  28. package/dist/document-ingest-foundation/entity.d.ts +4 -0
  29. package/dist/files-tenant-data/hooks.js +3 -2
  30. package/dist/folders/entity.d.ts +8 -0
  31. package/dist/folders/feature.js +2 -10
  32. package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
  33. package/dist/form-draft/db/queries/cleanup.js +4 -3
  34. package/dist/form-draft/entity.d.ts +2 -0
  35. package/dist/form-draft/handlers/cleanup.job.d.ts +5 -1
  36. package/dist/form-draft/handlers/cleanup.job.js +11 -5
  37. package/dist/inbound-mail-foundation/entities.d.ts +25 -0
  38. package/dist/inbound-mail-foundation/projection.d.ts +20 -0
  39. package/dist/jobs/handlers/list.query.d.ts +2 -1
  40. package/dist/jobs/handlers/list.query.js +39 -14
  41. package/dist/jobs/i18n.js +1 -0
  42. package/dist/jobs/job-run-table.d.ts +6 -0
  43. package/dist/ledger/entity.d.ts +21 -8
  44. package/dist/ledger/entity.js +4 -0
  45. package/dist/ledger/schemas.js +8 -2
  46. package/dist/managed-pages/feature.js +28 -10
  47. package/dist/managed-pages/table.d.ts +12 -0
  48. package/dist/notes-history/entity.d.ts +12 -0
  49. package/dist/notes-history/feature.js +2 -10
  50. package/dist/personal-access-tokens/schema/api-token.d.ts +6 -0
  51. package/dist/personal-access-tokens/screens.js +14 -3
  52. package/dist/secrets/table.d.ts +1 -0
  53. package/dist/seo/feature.js +28 -6
  54. package/dist/sessions/schema/user-session.d.ts +4 -0
  55. package/dist/shared/assert-no-where-rule-in-ownership-write.d.ts +2 -0
  56. package/dist/shared/assert-no-where-rule-in-ownership-write.js +18 -0
  57. package/dist/shared/index.d.ts +2 -1
  58. package/dist/shared/index.js +2 -1
  59. package/dist/shared/rate-limited-text-response.d.ts +2 -0
  60. package/dist/shared/rate-limited-text-response.js +9 -0
  61. package/dist/tags/entity.d.ts +9 -0
  62. package/dist/tags/feature.js +2 -10
  63. package/dist/template-resolver/table.d.ts +40 -30
  64. package/dist/template-resolver/user-content-table.d.ts +30 -20
  65. package/dist/tenant/decrypt-tenant-names.d.ts +3 -0
  66. package/dist/tenant/decrypt-tenant-names.js +10 -0
  67. package/dist/tenant/handlers/me.query.js +5 -1
  68. package/dist/tenant/handlers/memberships.query.js +3 -2
  69. package/dist/tenant/handlers/tenant-directory.query.js +9 -3
  70. package/dist/tenant/index.d.ts +1 -0
  71. package/dist/tenant/index.js +1 -0
  72. package/dist/tenant/invitation-table.d.ts +14 -8
  73. package/dist/tenant/membership-table.d.ts +4 -0
  74. package/dist/tenant/schema/tenant.d.ts +16 -10
  75. package/dist/tenant/schema/tenant.js +4 -6
  76. package/dist/tenant/screens.js +1 -1
  77. package/dist/tenant-handover/move-entity-graph.js +11 -18
  78. package/dist/tenant-lifecycle/feature.js +1 -0
  79. package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +3 -0
  80. package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -0
  81. package/dist/tenant-lifecycle/stages.d.ts +2 -0
  82. package/dist/tenant-lifecycle/stages.js +7 -1
  83. package/dist/tier-engine/entity.d.ts +2 -0
  84. package/dist/tier-engine/tier-resolver.d.ts +2 -0
  85. package/dist/user/handlers/list.query.js +2 -2
  86. package/dist/user/schema/user.d.ts +20 -8
  87. package/dist/user-data-rights/boot-checks.js +5 -0
  88. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +2 -2
  89. package/dist/user-data-rights/schema/download-attempt.d.ts +14 -0
  90. package/dist/user-data-rights/schema/download-token.d.ts +8 -0
  91. package/dist/user-data-rights/schema/export-job.d.ts +14 -8
  92. package/dist/waitlist/entity.d.ts +20 -6
  93. package/dist/workflow-runner/event-trigger.js +6 -3
  94. package/dist/workflow-runner/handlers/resume-run.write.js +3 -0
  95. package/package.json +9 -9
  96. package/src/agent-tools/changes.json +12 -0
  97. package/src/audit/changes.json +6 -0
  98. package/src/form-draft/changes.json +7 -1
  99. package/src/managed-pages/changes.json +6 -0
  100. package/src/seo/changes.json +5 -0
  101. package/src/tenant/changes.json +7 -0
  102. package/src/tenant-handover/changes.json +6 -0
  103. package/src/workflow-runner/changes.json +5 -0
  104. package/dist/shared/has-where-rule.d.ts +0 -2
  105. package/dist/shared/has-where-rule.js +0 -10
@@ -17,6 +17,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
17
17
  readonly type: "text";
18
18
  readonly description?: string;
19
19
  readonly maxLength?: number;
20
+ readonly minLength?: number;
20
21
  readonly required?: boolean;
21
22
  readonly searchable?: boolean;
22
23
  readonly sortable?: boolean;
@@ -38,6 +39,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
38
39
  readonly type: "text";
39
40
  readonly description?: string;
40
41
  readonly maxLength?: number;
42
+ readonly minLength?: number;
41
43
  readonly required?: boolean;
42
44
  readonly searchable?: boolean;
43
45
  readonly sortable?: boolean;
@@ -67,10 +69,10 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
67
69
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
68
70
  readonly display?: "radio" | "dropdown";
69
71
  readonly optionTones?: {
70
- readonly done?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
71
- readonly failed?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
72
- readonly pending?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
73
- readonly running?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
72
+ readonly done?: "bad" | "neutral" | "ok" | "warn" | undefined;
73
+ readonly failed?: "bad" | "neutral" | "ok" | "warn" | undefined;
74
+ readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
75
+ readonly running?: "bad" | "neutral" | "ok" | "warn" | undefined;
74
76
  } | undefined;
75
77
  readonly optionsQuery?: string;
76
78
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
@@ -127,6 +129,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
127
129
  readonly type: "text";
128
130
  readonly description?: string;
129
131
  readonly maxLength?: number;
132
+ readonly minLength?: number;
130
133
  readonly required?: boolean;
131
134
  readonly searchable?: boolean;
132
135
  readonly sortable?: boolean;
@@ -193,6 +196,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
193
196
  readonly type: "text";
194
197
  readonly description?: string;
195
198
  readonly maxLength?: number;
199
+ readonly minLength?: number;
196
200
  readonly required?: boolean;
197
201
  readonly searchable?: boolean;
198
202
  readonly sortable?: boolean;
@@ -214,6 +218,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
214
218
  readonly type: "text";
215
219
  readonly description?: string;
216
220
  readonly maxLength?: number;
221
+ readonly minLength?: number;
217
222
  readonly required?: boolean;
218
223
  readonly searchable?: boolean;
219
224
  readonly sortable?: boolean;
@@ -243,10 +248,10 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
243
248
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
244
249
  readonly display?: "radio" | "dropdown";
245
250
  readonly optionTones?: {
246
- readonly done?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
247
- readonly failed?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
248
- readonly pending?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
249
- readonly running?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
251
+ readonly done?: "bad" | "neutral" | "ok" | "warn" | undefined;
252
+ readonly failed?: "bad" | "neutral" | "ok" | "warn" | undefined;
253
+ readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
254
+ readonly running?: "bad" | "neutral" | "ok" | "warn" | undefined;
250
255
  } | undefined;
251
256
  readonly optionsQuery?: string;
252
257
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
@@ -303,6 +308,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
303
308
  readonly type: "text";
304
309
  readonly description?: string;
305
310
  readonly maxLength?: number;
311
+ readonly minLength?: number;
306
312
  readonly required?: boolean;
307
313
  readonly searchable?: boolean;
308
314
  readonly sortable?: boolean;
@@ -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,9 +138,9 @@ 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?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
137
- readonly pending?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
138
- readonly rejected?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
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;
@@ -177,6 +182,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
177
182
  readonly type: "text";
178
183
  readonly description?: string;
179
184
  readonly maxLength?: number;
185
+ readonly minLength?: number;
180
186
  readonly required?: boolean;
181
187
  readonly searchable?: boolean;
182
188
  readonly sortable?: boolean;
@@ -198,6 +204,7 @@ export declare const waitlistEntryEntity: import("@cosmicdrift/kumiko-types/fiel
198
204
  readonly type: "text";
199
205
  readonly description?: string;
200
206
  readonly maxLength?: number;
207
+ readonly minLength?: number;
201
208
  readonly required?: boolean;
202
209
  readonly searchable?: boolean;
203
210
  readonly sortable?: boolean;
@@ -221,6 +228,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
221
228
  readonly type: "text";
222
229
  readonly description?: string;
223
230
  readonly maxLength?: number;
231
+ readonly minLength?: number;
224
232
  readonly required?: boolean;
225
233
  readonly searchable?: boolean;
226
234
  readonly sortable?: boolean;
@@ -242,6 +250,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
242
250
  readonly type: "text";
243
251
  readonly description?: string;
244
252
  readonly maxLength?: number;
253
+ readonly minLength?: number;
245
254
  readonly required?: boolean;
246
255
  readonly searchable?: boolean;
247
256
  readonly sortable?: boolean;
@@ -263,6 +272,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
263
272
  readonly type: "text";
264
273
  readonly description?: string;
265
274
  readonly maxLength?: number;
275
+ readonly minLength?: number;
266
276
  readonly required?: boolean;
267
277
  readonly searchable?: boolean;
268
278
  readonly sortable?: boolean;
@@ -284,6 +294,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
284
294
  readonly type: "text";
285
295
  readonly description?: string;
286
296
  readonly maxLength?: number;
297
+ readonly minLength?: number;
287
298
  readonly required?: boolean;
288
299
  readonly searchable?: boolean;
289
300
  readonly sortable?: boolean;
@@ -321,6 +332,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
321
332
  readonly type: "text";
322
333
  readonly description?: string;
323
334
  readonly maxLength?: number;
335
+ readonly minLength?: number;
324
336
  readonly required?: boolean;
325
337
  readonly searchable?: boolean;
326
338
  readonly sortable?: boolean;
@@ -350,9 +362,9 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
350
362
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
351
363
  readonly display?: "radio" | "dropdown";
352
364
  readonly optionTones?: {
353
- readonly invited?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
354
- readonly pending?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
355
- readonly rejected?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
365
+ readonly invited?: "bad" | "neutral" | "ok" | "warn" | undefined;
366
+ readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
367
+ readonly rejected?: "bad" | "neutral" | "ok" | "warn" | undefined;
356
368
  } | undefined;
357
369
  readonly optionsQuery?: string;
358
370
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
@@ -394,6 +406,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
394
406
  readonly type: "text";
395
407
  readonly description?: string;
396
408
  readonly maxLength?: number;
409
+ readonly minLength?: number;
397
410
  readonly required?: boolean;
398
411
  readonly searchable?: boolean;
399
412
  readonly sortable?: boolean;
@@ -415,6 +428,7 @@ export declare const waitlistEntryTable: import("@cosmicdrift/kumiko-framework/d
415
428
  readonly type: "text";
416
429
  readonly description?: string;
417
430
  readonly maxLength?: number;
431
+ readonly minLength?: number;
418
432
  readonly required?: boolean;
419
433
  readonly searchable?: boolean;
420
434
  readonly sortable?: boolean;
@@ -12,7 +12,7 @@ import { describeWorkflowStepError, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RUN_FAILED
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
18
  export function registerEventTrigger(r, workflow) {
@@ -83,15 +83,18 @@ export function registerEventTrigger(r, workflow) {
83
83
  });
84
84
  }
85
85
  catch (error) {
86
+ // Only the suspension error knows its step; a throw inside a step
87
+ // carries no index, so it still reports 0.
88
+ const stepIndex = error instanceof WorkflowSuspensionUnsupportedError ? error.stepIndex : 0;
86
89
  log.warn("workflow run failed", {
87
90
  runId,
88
91
  workflowName: workflow.name,
89
- stepIndex: 0,
92
+ stepIndex,
90
93
  error: String(error),
91
94
  });
92
95
  const failedPayload = {
93
96
  workflowName: workflow.name,
94
- stepIndex: 0,
97
+ stepIndex,
95
98
  error: describeWorkflowStepError(error),
96
99
  };
97
100
  await ctx.unsafeAppendEvent({
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-bundled-features",
3
- "version": "0.352.0",
3
+ "version": "0.353.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>",
@@ -503,12 +503,12 @@
503
503
  }
504
504
  },
505
505
  "dependencies": {
506
- "@cosmicdrift/kumiko-dispatcher-live": "0.352.0",
507
- "@cosmicdrift/kumiko-framework": "0.352.0",
508
- "@cosmicdrift/kumiko-headless": "0.352.0",
509
- "@cosmicdrift/kumiko-renderer": "0.352.0",
510
- "@cosmicdrift/kumiko-renderer-web": "0.352.0",
511
- "@cosmicdrift/kumiko-types": "0.352.0",
506
+ "@cosmicdrift/kumiko-dispatcher-live": "0.353.0",
507
+ "@cosmicdrift/kumiko-framework": "0.353.0",
508
+ "@cosmicdrift/kumiko-headless": "0.353.0",
509
+ "@cosmicdrift/kumiko-renderer": "0.353.0",
510
+ "@cosmicdrift/kumiko-renderer-web": "0.353.0",
511
+ "@cosmicdrift/kumiko-types": "0.353.0",
512
512
  "@mollie/api-client": "^4.5.0",
513
513
  "@node-rs/argon2": "^2.0.2",
514
514
  "@types/mailparser": "^3.4.6",
@@ -1025,8 +1025,8 @@
1025
1025
  ],
1026
1026
  "devDependencies": {
1027
1027
  "@testing-library/user-event": "^14.6.1",
1028
- "@cosmicdrift/kumiko-locale-de": "0.352.0",
1029
- "@cosmicdrift/kumiko-locale-es": "0.352.0",
1028
+ "@cosmicdrift/kumiko-locale-de": "0.353.0",
1029
+ "@cosmicdrift/kumiko-locale-es": "0.353.0",
1030
1030
  "jsqr": "^1.4.0"
1031
1031
  }
1032
1032
  }
@@ -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",
@@ -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 +1,7 @@
1
- []
1
+ [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "fix",
5
+ "title": "The stale-draft cleanup keeps sweeping when a whole batch was re-saved in the meantime"
6
+ }
7
+ ]
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "fix",
5
+ "title": "A rate-limited page request answers 429 with Retry-After instead of 503 or an unbranded page",
6
+ "detail": "Managed pages and sitemap answer 429 when rate limited, agent catalog checks the deny list, draft cleanup continues past skipped rows\nA rate-limited managed-page request now answers 429 with `Retry-After` instead of 503 or an unbranded page, and `sitemap.xml` and `llms.txt` answer 429 instead of silently dropping the managed-page entries. `buildToolCatalog` throws when its manifest was built with `denyQns` that the catalog options lack. The form-draft cleanup no longer stops when a whole batch was re-saved by users in the meantime."
7
+ },
2
8
  {
3
9
  "version": "0.335.0",
4
10
  "type": "fix",
@@ -1,4 +1,9 @@
1
1
  [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "fix",
5
+ "title": "sitemap.xml and llms.txt answer 429 when the managed-pages read is rate limited instead of omitting the pages"
6
+ },
2
7
  {
3
8
  "version": "0.147.3",
4
9
  "type": "fix",
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "breaking",
5
+ "title": "Tenant names are encrypted under the tenant record and crypto-shredded when the tenant is destroyed",
6
+ "detail": "Tenant names are PII encrypted under the tenant record and crypto-shredded on tenant destroy\n`tenant.name` is now `personal: { of: \"id\" }`, so it is stored as `kumiko-pii:` ciphertext in events and in `read_tenants`. Signup no longer writes the email into the tenant name; it uses the generated tenant key. The tenant destroy job erases the tenant record key and purges the tenant's search documents. The tenant queries (`me`, memberships, tenant-directory, user list, cap-overview, tenants-missing-profile) decrypt the name, and the tenant list sorts by `key` because encrypted names are not sortable.",
7
+ "migration": "After the bump run the PII backfill (backfillEventPiiEncryption), then rebuild the read_tenants projection; the backfill only encrypts event payloads. Raw reads of read_tenants.name in apps now return ciphertext and must go through decryptStoredPii or the tenant query handlers. Tenants that were already destroyed (read_tenants.destroyed_at set) get the erased sentinel instead of a fresh record key."
8
+ },
2
9
  {
3
10
  "version": "0.341.0",
4
11
  "type": "improvement",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "fix",
5
+ "title": "Tenant handover claims fail with transfer_graph_too_deep only when rows exist beyond the last allowed hop",
6
+ "detail": "Tenant handover only fails with `transfer_graph_too_deep` when rows really hang below the fifth hop, and failed workflow runs report the suspended step\nA claim used to fail whenever the last round's entity type had outgoing edges, even with no rows behind them, so a chain of exactly five hops with an unrestricted `parentRef` entity registered was rejected. `workflow.run-failed` carries the real `stepIndex` for the unsupported-suspension case instead of always 0."
7
+ },
2
8
  {
3
9
  "version": "0.321.0",
4
10
  "type": "improvement",
@@ -1,4 +1,9 @@
1
1
  [
2
+ {
3
+ "version": "0.353.0",
4
+ "type": "fix",
5
+ "title": "workflow.run-failed carries the real stepIndex when a run suspends in an unsupported step"
6
+ },
2
7
  {
3
8
  "version": "0.340.0",
4
9
  "type": "improvement",
@@ -1,2 +0,0 @@
1
- import type { OwnershipMap } from "@cosmicdrift/kumiko-framework/engine";
2
- export declare function hasWhereRule(map: OwnershipMap | undefined): boolean;
@@ -1,10 +0,0 @@
1
- // `where`-rules are read-path only (buildOwnershipClause). The write path
2
- // decides in memory against the concrete row, so a where-rule there can only
3
- // ever deny — boot validation rejects the shape (fw#2626). Feature factories
4
- // that accept an `ownership` option reject it earlier, at build time, so the
5
- // author gets the option name in the message instead of an entity scope.
6
- export function hasWhereRule(map) {
7
- if (!map)
8
- return false;
9
- return Object.values(map).some((rule) => rule !== "all" && rule.kind === "where");
10
- }