@cosmicdrift/kumiko-bundled-features 0.307.0 → 0.309.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 (253) hide show
  1. package/package.json +9 -9
  2. package/src/__tests__/access-invalidation-consumer.integration.test.ts +107 -0
  3. package/src/__tests__/access-invalidation-stream.integration.test.ts +1 -1
  4. package/src/__tests__/credential-scoped-sse-revoke.integration.test.ts +296 -0
  5. package/src/agent-tools/__tests__/agent-doc-lint.test.ts +1 -1
  6. package/src/agent-tools/__tests__/agent-manifest.test.ts +1 -1
  7. package/src/agent-tools/__tests__/agent-optout.test.ts +1 -1
  8. package/src/agent-tools/__tests__/agent-tools.integration.test.ts +1 -1
  9. package/src/agent-tools/__tests__/feature.test.ts +1 -1
  10. package/src/agent-tools/__tests__/tool-catalog.test.ts +1 -1
  11. package/src/agent-tools/agent-manifest.ts +1 -1
  12. package/src/audit/__tests__/escape-hatch-audit.integration.test.ts +1 -1
  13. package/src/audit/escape-hatch-audit-sink.ts +1 -1
  14. package/src/audit/handlers/details.query.ts +1 -1
  15. package/src/audit/handlers/list.query.ts +1 -1
  16. package/src/auth-email-password/__tests__/query-as-member.integration.test.ts +1 -1
  17. package/src/auth-email-password/__tests__/seed-admin-guarded.integration.test.ts +31 -0
  18. package/src/auth-email-password/changes.json +6 -0
  19. package/src/auth-email-password/feature.ts +1 -1
  20. package/src/auth-email-password/handlers/change-password.write.ts +1 -1
  21. package/src/auth-email-password/handlers/confirm-account-unlock.write.ts +1 -1
  22. package/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
  23. package/src/auth-email-password/handlers/invite-accept.write.ts +1 -1
  24. package/src/auth-email-password/handlers/invite-create.write.ts +1 -1
  25. package/src/auth-email-password/handlers/invite-signup-complete.write.ts +1 -1
  26. package/src/auth-email-password/handlers/login.write.ts +1 -1
  27. package/src/auth-email-password/handlers/logout.write.ts +1 -1
  28. package/src/auth-email-password/handlers/reset-password.write.ts +1 -1
  29. package/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
  30. package/src/auth-email-password/handlers/signup-confirm.write.ts +1 -1
  31. package/src/auth-email-password/handlers/signup-request.write.ts +1 -1
  32. package/src/auth-email-password/handlers/token-request-handler.ts +1 -1
  33. package/src/auth-email-password/handlers/verify-email.write.ts +1 -1
  34. package/src/auth-email-password/password-policy.ts +1 -1
  35. package/src/auth-email-password/seeding.ts +16 -3
  36. package/src/auth-mfa/__tests__/session-scoped-sse-revoke.integration.test.ts +1 -1
  37. package/src/auth-mfa/handlers/disable.write.ts +1 -1
  38. package/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
  39. package/src/auth-mfa/handlers/enable-confirm.write.ts +1 -1
  40. package/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  41. package/src/auth-mfa/handlers/enable-start.write.ts +1 -1
  42. package/src/auth-mfa/handlers/regenerate-recovery.write.ts +1 -1
  43. package/src/auth-mfa/handlers/status.query.ts +1 -1
  44. package/src/auth-mfa/handlers/verify.write.ts +1 -1
  45. package/src/billing-foundation/billing-info-query.ts +1 -1
  46. package/src/billing-foundation/events.ts +1 -1
  47. package/src/billing-foundation/handlers/create-checkout-session.write.ts +1 -1
  48. package/src/billing-foundation/handlers/create-portal-session.write.ts +1 -1
  49. package/src/billing-foundation/handlers/list-subscriptions.query.ts +1 -1
  50. package/src/billing-foundation/handlers/process-event.write.ts +1 -1
  51. package/src/billing-foundation/handlers/process-payment-event.write.ts +1 -1
  52. package/src/cap-counter/__tests__/cap-counter.integration.test.ts +1 -1
  53. package/src/cap-counter/__tests__/stock-cap-guard.integration.test.ts +1 -1
  54. package/src/cap-counter/__tests__/with-cap-enforcement.integration.test.ts +1 -1
  55. package/src/cap-counter/book-cap-usage.ts +1 -1
  56. package/src/cap-counter/handlers/get-counter.query.ts +1 -1
  57. package/src/cap-counter/handlers/increment-rolling.write.ts +1 -1
  58. package/src/cap-counter/handlers/increment.write.ts +1 -1
  59. package/src/cap-counter/handlers/mark-soft-warned.write.ts +1 -1
  60. package/src/cap-overview/handlers/caps-usage.query.ts +1 -1
  61. package/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  62. package/src/cap-overview/handlers/tenant-options.query.ts +1 -1
  63. package/src/channel-in-app/handlers/inbox.query.ts +1 -1
  64. package/src/channel-in-app/handlers/mark-all-read.write.ts +1 -1
  65. package/src/channel-in-app/handlers/mark-read.write.ts +1 -1
  66. package/src/channel-in-app/handlers/unread-count.query.ts +1 -1
  67. package/src/compliance-profiles/handlers/for-tenant.query.ts +1 -1
  68. package/src/compliance-profiles/handlers/list-profiles.query.ts +1 -1
  69. package/src/compliance-profiles/handlers/needs-profile.query.ts +1 -1
  70. package/src/compliance-profiles/handlers/set-profile.write.ts +1 -1
  71. package/src/compliance-profiles/handlers/sub-processors.query.ts +1 -1
  72. package/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +1 -1
  73. package/src/config/__tests__/backing-secrets.integration.test.ts +1 -1
  74. package/src/config/__tests__/config.integration.test.ts +1 -1
  75. package/src/config/__tests__/tz-resolution.integration.test.ts +1 -1
  76. package/src/config/handlers/cascade.query.ts +1 -1
  77. package/src/config/handlers/readiness.query.ts +1 -1
  78. package/src/config/handlers/reset.write.ts +1 -1
  79. package/src/config/handlers/schema.query.ts +1 -1
  80. package/src/config/handlers/set.write.ts +1 -1
  81. package/src/config/handlers/values.query.ts +1 -1
  82. package/src/crypto-shredding/handlers/forget-subject.write.ts +1 -1
  83. package/src/custom-fields/__tests__/audit-integration.integration.test.ts +1 -1
  84. package/src/custom-fields/__tests__/cross-tenant-field-delete.integration.test.ts +1 -1
  85. package/src/custom-fields/__tests__/cross-tenant-set-write.integration.test.ts +1 -1
  86. package/src/custom-fields/__tests__/custom-fields.integration.test.ts +1 -1
  87. package/src/custom-fields/__tests__/field-access.integration.test.ts +1 -1
  88. package/src/custom-fields/__tests__/quota.integration.test.ts +1 -1
  89. package/src/custom-fields/__tests__/retention.integration.test.ts +1 -1
  90. package/src/custom-fields/__tests__/user-data-rights.integration.test.ts +1 -1
  91. package/src/custom-fields/events.ts +1 -1
  92. package/src/custom-fields/feature.ts +1 -1
  93. package/src/custom-fields/handlers/clear-custom-field.write.ts +1 -1
  94. package/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
  95. package/src/custom-fields/lib/value-schema.ts +1 -1
  96. package/src/custom-fields/schemas.ts +1 -1
  97. package/src/data-retention/__tests__/retention-cleanup-files.integration.test.ts +454 -0
  98. package/src/data-retention/changes.json +6 -0
  99. package/src/data-retention/feature.ts +1 -0
  100. package/src/data-retention/handlers/policy-for.query.ts +1 -1
  101. package/src/data-retention/override-schema.ts +1 -1
  102. package/src/data-retention/run-retention-cleanup.ts +312 -5
  103. package/src/delivery/__tests__/delivery-pii-kms.integration.test.ts +1 -1
  104. package/src/delivery/__tests__/delivery.integration.test.ts +1 -1
  105. package/src/delivery/events.ts +1 -1
  106. package/src/delivery/feature.ts +1 -1
  107. package/src/delivery/handlers/log.query.ts +1 -1
  108. package/src/delivery/handlers/preferences.query.ts +1 -1
  109. package/src/delivery/handlers/set-preference.write.ts +1 -1
  110. package/src/delivery/jobs.ts +1 -1
  111. package/src/delivery/unsubscribe.ts +1 -1
  112. package/src/derivatives-sharp/__tests__/derivatives-sharp.integration.test.ts +1 -1
  113. package/src/document-ingest-foundation/events.ts +1 -1
  114. package/src/document-ingest-foundation/feature.ts +1 -1
  115. package/src/feature-toggles/__tests__/feature-toggles.integration.test.ts +1 -1
  116. package/src/feature-toggles/events.ts +1 -1
  117. package/src/feature-toggles/handlers/list.query.ts +1 -1
  118. package/src/feature-toggles/handlers/registered.query.ts +1 -1
  119. package/src/feature-toggles/handlers/set.write.ts +1 -1
  120. package/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  121. package/src/file-foundation/__tests__/file-foundation.integration.test.ts +1 -1
  122. package/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +1 -1
  123. package/src/folders/handlers/delete-folder.write.ts +1 -1
  124. package/src/folders/schemas.ts +1 -1
  125. package/src/form-draft/schemas.ts +1 -1
  126. package/src/inbound-mail-foundation/events.ts +1 -1
  127. package/src/inbound-mail-foundation/handlers/connect-account.write.ts +1 -1
  128. package/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +1 -1
  129. package/src/inbound-mail-foundation/handlers/ingest-message.write.ts +1 -1
  130. package/src/inbound-mail-foundation/handlers/list-accounts.query.ts +1 -1
  131. package/src/inbound-mail-foundation/handlers/list-messages.query.ts +1 -1
  132. package/src/inbound-mail-foundation/handlers/update-account.write.ts +1 -1
  133. package/src/inbound-provider-imap/credential-document.ts +1 -1
  134. package/src/jobs/__tests__/jobs-catalog.integration.test.ts +1 -1
  135. package/src/jobs/__tests__/tenant-job-failures.integration.test.ts +1 -1
  136. package/src/jobs/events.ts +1 -1
  137. package/src/jobs/handlers/catalog.query.ts +1 -1
  138. package/src/jobs/handlers/detail.query.ts +1 -1
  139. package/src/jobs/handlers/list.query.ts +1 -1
  140. package/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  141. package/src/jobs/handlers/reindex-entity.job.ts +1 -1
  142. package/src/jobs/handlers/retry.write.ts +1 -1
  143. package/src/jobs/handlers/tenant-failures.query.ts +1 -1
  144. package/src/jobs/handlers/trigger.write.ts +1 -1
  145. package/src/ledger/handlers/reports.query.ts +1 -1
  146. package/src/ledger/schemas.ts +1 -1
  147. package/src/mail-foundation/__tests__/mail-foundation.integration.test.ts +1 -1
  148. package/src/managed-pages/handlers/branding.query.ts +1 -1
  149. package/src/managed-pages/handlers/by-slug.query.ts +1 -1
  150. package/src/managed-pages/handlers/by-tenant-published.query.ts +1 -1
  151. package/src/managed-pages/handlers/set.write.ts +1 -1
  152. package/src/notes-history/changes.json +7 -0
  153. package/src/notes-history/schemas.ts +1 -1
  154. package/src/notes-history/web/notes-section.tsx +37 -36
  155. package/src/personal-access-tokens/feature.ts +10 -0
  156. package/src/personal-access-tokens/handlers/available-scopes.query.ts +1 -1
  157. package/src/personal-access-tokens/handlers/create.write.ts +1 -1
  158. package/src/personal-access-tokens/handlers/list.query.ts +1 -1
  159. package/src/personal-access-tokens/handlers/revoke.write.ts +18 -2
  160. package/src/personal-access-tokens/index.ts +7 -0
  161. package/src/personal-access-tokens/pat-revoked-event.ts +23 -0
  162. package/src/personal-access-tokens/revoke-for-user.ts +31 -0
  163. package/src/rate-limiting/__tests__/rate-limiting.integration.test.ts +1 -1
  164. package/src/rate-limiting/handlers/status.query.ts +1 -1
  165. package/src/readiness/handlers/status.query.ts +1 -1
  166. package/src/secrets/feature.ts +1 -1
  167. package/src/secrets/handlers/delete.write.ts +1 -1
  168. package/src/secrets/handlers/list.query.ts +1 -1
  169. package/src/secrets/handlers/set.write.ts +1 -1
  170. package/src/secrets/secrets-context.ts +1 -1
  171. package/src/seo/handlers/seo-config.query.ts +1 -1
  172. package/src/sessions/handlers/detail.query.ts +1 -1
  173. package/src/sessions/handlers/list.query.ts +1 -1
  174. package/src/sessions/handlers/mine.query.ts +1 -1
  175. package/src/sessions/handlers/revoke-all-for-user.write.ts +1 -1
  176. package/src/sessions/handlers/revoke-all-others.write.ts +1 -1
  177. package/src/sessions/handlers/revoke.write.ts +1 -1
  178. package/src/sessions/session-callbacks.ts +25 -1
  179. package/src/sessions/session-revoked-event.ts +6 -1
  180. package/src/shared/__tests__/row-bound-grant.integration.test.ts +1 -1
  181. package/src/step-dispatcher/mail-runner.ts +1 -1
  182. package/src/step-dispatcher/webhook-runner.ts +1 -1
  183. package/src/subscription-mollie/feature.ts +1 -1
  184. package/src/subscription-stripe/feature.ts +1 -1
  185. package/src/tags/schemas.ts +1 -1
  186. package/src/template-resolver/handlers/by-slug.query.ts +1 -1
  187. package/src/template-resolver/handlers/by-tenant.query.ts +1 -1
  188. package/src/template-resolver/handlers/collection-item.query.ts +1 -1
  189. package/src/template-resolver/handlers/collection-list.query.ts +1 -1
  190. package/src/template-resolver/handlers/collection-set.write.ts +1 -1
  191. package/src/template-resolver/handlers/find-by-id.query.ts +1 -1
  192. package/src/template-resolver/handlers/list.query.ts +1 -1
  193. package/src/template-resolver/handlers/set.write.ts +1 -1
  194. package/src/template-resolver/handlers/shared.ts +1 -1
  195. package/src/template-resolver/handlers/toggle-status.write.ts +1 -1
  196. package/src/template-resolver/handlers/upsert-tenant.write.ts +1 -1
  197. package/src/tenant/__tests__/tenant-timezone-boot.integration.test.ts +1 -1
  198. package/src/tenant/handlers/active-tenant-ids.query.ts +1 -1
  199. package/src/tenant/handlers/add-member.write.ts +1 -1
  200. package/src/tenant/handlers/cancel-invitation.write.ts +1 -1
  201. package/src/tenant/handlers/create.write.ts +1 -1
  202. package/src/tenant/handlers/invitations.query.ts +1 -1
  203. package/src/tenant/handlers/list.query.ts +1 -1
  204. package/src/tenant/handlers/me.query.ts +1 -1
  205. package/src/tenant/handlers/member-directory.query.ts +1 -1
  206. package/src/tenant/handlers/members.query.ts +1 -1
  207. package/src/tenant/handlers/memberships.query.ts +1 -1
  208. package/src/tenant/handlers/remove-member.write.ts +1 -1
  209. package/src/tenant/handlers/resolve-user-ids.query.ts +1 -1
  210. package/src/tenant/handlers/team-list.query.ts +1 -1
  211. package/src/tenant/handlers/tenant-directory.query.ts +1 -1
  212. package/src/tenant/handlers/toggle-enabled.write.ts +1 -1
  213. package/src/tenant/handlers/update-member-roles.write.ts +1 -1
  214. package/src/tenant/handlers/update.write.ts +1 -1
  215. package/src/tenant-handover/events.ts +1 -1
  216. package/src/tenant-handover/handlers/claim.write.ts +1 -1
  217. package/src/tenant-lifecycle/__tests__/tenant-lifecycle.integration.test.ts +8 -24
  218. package/src/tenant-lifecycle/events.ts +1 -1
  219. package/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +1 -1
  220. package/src/tenant-lifecycle/handlers/request-destruction.write.ts +1 -1
  221. package/src/tenant-settings/tenant-defaults.ts +1 -1
  222. package/src/tier-engine/__tests__/tier-resolver.integration.test.ts +1 -1
  223. package/src/tier-engine/feature.ts +1 -1
  224. package/src/tier-engine/handlers/active-tier.query.ts +1 -1
  225. package/src/tier-engine/handlers/get-tenant-tier.query.ts +1 -1
  226. package/src/tier-engine/handlers/set-tenant-tier.write.ts +1 -1
  227. package/src/user/__tests__/user-global-tenancy.integration.test.ts +1 -1
  228. package/src/user/handlers/create.write.ts +1 -1
  229. package/src/user/handlers/find-for-auth.query.ts +1 -1
  230. package/src/user/handlers/me.query.ts +1 -1
  231. package/src/user/handlers/update.write.ts +1 -1
  232. package/src/user/roles-input-schema.ts +1 -1
  233. package/src/user/seeding.ts +29 -20
  234. package/src/user-data-rights/__tests__/boot-checks.test.ts +1 -1
  235. package/src/user-data-rights/changes.json +6 -0
  236. package/src/user-data-rights/feature.ts +1 -0
  237. package/src/user-data-rights/handlers/cancel-deletion.write.ts +1 -1
  238. package/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +1 -1
  239. package/src/user-data-rights/handlers/download-by-job.query.ts +1 -1
  240. package/src/user-data-rights/handlers/download-by-token.query.ts +1 -1
  241. package/src/user-data-rights/handlers/export-status.query.ts +1 -1
  242. package/src/user-data-rights/handlers/lift-restriction.write.ts +1 -1
  243. package/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -1
  244. package/src/user-data-rights/handlers/my-audit-log.query.ts +1 -1
  245. package/src/user-data-rights/handlers/request-deletion-by-email.write.ts +1 -1
  246. package/src/user-data-rights/handlers/request-deletion.write.ts +1 -1
  247. package/src/user-data-rights/handlers/request-export.write.ts +1 -1
  248. package/src/user-data-rights/handlers/restrict-account.write.ts +1 -1
  249. package/src/user-data-rights/handlers/run-forget-cleanup.write.ts +1 -1
  250. package/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +8 -61
  251. package/src/user-profile/handlers/change-email.write.ts +1 -1
  252. package/src/workflow-runner/__tests__/pending-projection.integration.test.ts +1 -1
  253. package/src/workflow-runner/handlers/resume-run.write.ts +1 -1
@@ -13,7 +13,7 @@ import {
13
13
  TestUsers,
14
14
  unsafeCreateEntityTable,
15
15
  } from "@cosmicdrift/kumiko-framework/stack";
16
- import { z } from "zod";
16
+ import * as z from "zod";
17
17
  import { UserHandlers } from "../constants";
18
18
  import { createUserFeature } from "../feature";
19
19
  import { userEntity, userTable } from "../schema/user";
@@ -14,7 +14,7 @@ import {
14
14
  import { isValidLocaleTag } from "@cosmicdrift/kumiko-framework/i18n";
15
15
  import { isValidIanaTimeZone } from "@cosmicdrift/kumiko-framework/time";
16
16
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
17
- import { z } from "zod";
17
+ import * as z from "zod";
18
18
  import { UserErrors } from "../constants";
19
19
  import { rolesInputSchema } from "../roles-input-schema";
20
20
  import { userEntity, userTable } from "../schema/user";
@@ -1,7 +1,7 @@
1
1
  import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
- import { z } from "zod";
4
+ import * as z from "zod";
5
5
  import { userTable } from "../schema/user";
6
6
 
7
7
  // Privileged auth lookup: returns the full user row — including passwordHash —
@@ -1,7 +1,7 @@
1
1
  import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
- import { z } from "zod";
4
+ import * as z from "zod";
5
5
  import { userEntity, userTable } from "../schema/user";
6
6
 
7
7
  const crud = createEventStoreExecutor(userTable, userEntity, { entityName: "user" });
@@ -7,7 +7,7 @@ import {
7
7
  } from "@cosmicdrift/kumiko-framework/errors";
8
8
  import { isValidLocaleTag } from "@cosmicdrift/kumiko-framework/i18n";
9
9
  import { isValidIanaTimeZone } from "@cosmicdrift/kumiko-framework/time";
10
- import { z } from "zod";
10
+ import * as z from "zod";
11
11
  import { UserErrors } from "../constants";
12
12
  import { rolesInputSchema } from "../roles-input-schema";
13
13
  import { userEntity, userTable } from "../schema/user";
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import * as z from "zod";
2
2
 
3
3
  /** Accept string[] or a JSON-encoded string[]; reject bare non-JSON strings. */
4
4
  export const rolesInputSchema = z.union([
@@ -71,26 +71,8 @@ export async function seedUser(
71
71
  // liefert die Projection-Row als Record<string, unknown>.
72
72
  if (existing) {
73
73
  const id = existing["id"] as string;
74
- // Reconcile emailVerified on an already-seeded row: a persistent dev DB
75
- // (or a re-run bootstrap) can carry a User seeded before this flag
76
- // existed or before it flipped to true — without this, "seed with
77
- // emailVerified: true" only ever takes effect on the very first insert
78
- // and the flag silently does nothing on every re-run after (#1687).
79
- // Goes through the executor (a real `.updated` event), never a direct
80
- // write.
81
- if (options.emailVerified === true && existing["emailVerified"] !== true) {
82
- const result = await userExecutor.update(
83
- { id, version: existing["version"] as number, changes: { emailVerified: true } },
84
- by,
85
- tdb,
86
- );
87
- // version_conflict = a concurrent write already changed the row —
88
- // fine for a seed helper, don't fail the whole seed run over it.
89
- if (!result.isSuccess && result.error.code !== "version_conflict") {
90
- throw new Error(
91
- `seedUser emailVerified reconcile failed: ${result.error.code} — ${JSON.stringify(result.error.details ?? {})}`,
92
- );
93
- }
74
+ if (options.emailVerified === true) {
75
+ await reconcileSeededUserEmailVerified(db, existing, by);
94
76
  }
95
77
  return { id };
96
78
  }
@@ -116,6 +98,33 @@ export async function seedUser(
116
98
  return { id: extractId(result.data, "seedUser") };
117
99
  }
118
100
 
101
+ // A re-run seed onto a row created before emailVerified flipped to true must
102
+ // still set it (#1687) — via the executor, so it lands as a real `.updated` event.
103
+ export async function reconcileSeededUserEmailVerified(
104
+ db: DbConnection,
105
+ existingRow: Record<string, unknown>,
106
+ by: SessionUser,
107
+ ): Promise<void> {
108
+ // skip: already verified, nothing to reconcile
109
+ if (existingRow["emailVerified"] === true) return;
110
+ // @cast-boundary db-row: users.id ist uuid-Spalte (string), fetchOne
111
+ // liefert die Projection-Row als Record<string, unknown>.
112
+ const id = existingRow["id"] as string;
113
+ const tdb = createTenantDb(db, by.tenantId, "system");
114
+ const result = await userExecutor.update(
115
+ { id, version: existingRow["version"] as number, changes: { emailVerified: true } },
116
+ by,
117
+ tdb,
118
+ );
119
+ // version_conflict = a concurrent write already changed the row —
120
+ // fine for a seed helper, don't fail the whole seed run over it.
121
+ if (!result.isSuccess && result.error.code !== "version_conflict") {
122
+ throw new Error(
123
+ `reconcileSeededUserEmailVerified failed: ${result.error.code} — ${JSON.stringify(result.error.details ?? {})}`,
124
+ );
125
+ }
126
+ }
127
+
119
128
  // Extrahiert die `id`-Spalte aus dem executor.create-Result. Der
120
129
  // Executor liefert ein Record<string, unknown> (die Projection-Row), in
121
130
  // das die DB die Aggregat-id reinschreibt — wir prüfen runtime statt
@@ -9,7 +9,7 @@ import {
9
9
  validateBoot,
10
10
  } from "@cosmicdrift/kumiko-framework/engine";
11
11
  import { createFilesFeature } from "@cosmicdrift/kumiko-framework/files";
12
- import { z } from "zod";
12
+ import * as z from "zod";
13
13
  import { authFoundationFeature } from "../../auth-foundation";
14
14
  import { createComplianceProfilesFeature } from "../../compliance-profiles/feature";
15
15
  import { createConfigFeature } from "../../config/feature";
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.308.0",
4
+ "type": "fix",
5
+ "title": "The privacy-center screen's \"restrict\" action declares an explicit icon",
6
+ "detail": "The boot validator now requires every projectionDetail action to resolve an icon (fw#3234); \"restrict\" resolved none from the shared id-derived map, so it now declares `icon: \"lock\"` explicitly. \"request-deletion\" needed no change — it now resolves via the shared map's new `deletion: \"trash\"` entry (@cosmicdrift/kumiko-types)."
7
+ },
2
8
  {
3
9
  "version": "0.289.0",
4
10
  "type": "improvement",
@@ -406,6 +406,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
406
406
  actions: [
407
407
  {
408
408
  id: "restrict",
409
+ icon: "lock",
409
410
  label: i18nKey("userDataRights.privacyCenter.restriction.restrict"),
410
411
  handler: UserDataRightsHandlers.restrictAccount,
411
412
  confirm: i18nKey("userDataRights.privacyCenter.restriction.dialogDescription"),
@@ -1,6 +1,6 @@
1
1
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
3
- import { z } from "zod";
3
+ import * as z from "zod";
4
4
  import { isWithinGracePeriod } from "../../shared";
5
5
  import { USER_STATUS, userTable } from "../../user";
6
6
  import { updateUserLifecycle } from "../lib/update-user-lifecycle";
@@ -5,7 +5,7 @@ import {
5
5
  type HandlerContext,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
8
- import { z } from "zod";
8
+ import * as z from "zod";
9
9
  import { USER_STATUS, userTable } from "../../user";
10
10
  import { redeemDeletionToken } from "../deletion-token";
11
11
  import { startDeletionGracePeriod } from "./deletion-grace-period";
@@ -32,7 +32,7 @@ import {
32
32
  } from "@cosmicdrift/kumiko-framework/engine";
33
33
  import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
34
34
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
35
- import { z } from "zod";
35
+ import * as z from "zod";
36
36
  import { recordDownloadUse, recordInvalidAttempt } from "../audit-download";
37
37
  import { makeTenantStorageProviderResolver } from "../lib/storage-provider-resolver";
38
38
  import { exportDownloadTokensTable } from "../schema/download-token";
@@ -34,7 +34,7 @@ import {
34
34
  } from "@cosmicdrift/kumiko-framework/engine";
35
35
  import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
36
36
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
37
- import { z } from "zod";
37
+ import * as z from "zod";
38
38
  import { recordDownloadUse, recordInvalidAttempt } from "../audit-download";
39
39
  import { makeTenantStorageProviderResolver } from "../lib/storage-provider-resolver";
40
40
  import { exportDownloadTokensTable } from "../schema/download-token";
@@ -14,7 +14,7 @@
14
14
  import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
15
15
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
16
16
  import type { getTemporal } from "@cosmicdrift/kumiko-framework/time";
17
- import { z } from "zod";
17
+ import * as z from "zod";
18
18
  import { exportJobsTable } from "../schema/export-job";
19
19
 
20
20
  type Instant = InstanceType<ReturnType<typeof getTemporal>["Instant"]>;
@@ -1,6 +1,6 @@
1
1
  import { access, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
3
- import { z } from "zod";
3
+ import * as z from "zod";
4
4
  import { USER_STATUS, userTable } from "../../user";
5
5
  import { denyIfTargetOutsideAdminTenant } from "../lib/deny-if-target-outside-admin-tenant";
6
6
  import { updateUserLifecycle } from "../lib/update-user-lifecycle";
@@ -1,7 +1,7 @@
1
1
  import { selectMany, type WhereObject } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { Temporal } from "temporal-polyfill";
4
- import { z } from "zod";
4
+ import * as z from "zod";
5
5
  import { downloadAttemptsTable } from "../schema/download-attempt";
6
6
 
7
7
  // Operator-Query: invalid Download-Attempts (S2.U7).
@@ -2,7 +2,7 @@ import { selectMany, type WhereObject } from "@cosmicdrift/kumiko-framework/bun-
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
4
4
  import { Temporal } from "temporal-polyfill";
5
- import { z } from "zod";
5
+ import * as z from "zod";
6
6
 
7
7
  // DSGVO Art. 15 Selbstauskunft — User reads HIS OWN audit-log.
8
8
  // WHERE createdBy = ctx.user.id ist hard-coded (kein userId-Param,
@@ -1,5 +1,5 @@
1
1
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { USER_STATUS, userTable } from "../../user";
4
4
  import { signDeletionToken } from "../deletion-token";
5
5
  import { updateUserLifecycle } from "../lib/update-user-lifecycle";
@@ -2,7 +2,7 @@ import { createTransportForTenant } from "@cosmicdrift/kumiko-bundled-features/m
2
2
  import type { DurationSpec } from "@cosmicdrift/kumiko-framework/compliance";
3
3
  import { createSystemUser, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { writeFailure } from "@cosmicdrift/kumiko-framework/errors";
5
- import { z } from "zod";
5
+ import * as z from "zod";
6
6
  import { USER_STATUS } from "../../user";
7
7
  import {
8
8
  type GdprMailDefaults,
@@ -25,7 +25,7 @@ import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
25
25
  import { defineWriteHandler, type SaveContext } from "@cosmicdrift/kumiko-framework/engine";
26
26
  import type { WriteFailure } from "@cosmicdrift/kumiko-framework/errors";
27
27
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
28
- import { z } from "zod";
28
+ import * as z from "zod";
29
29
  import {
30
30
  ACTIVE_JOB_CONSTRAINT,
31
31
  EXPORT_JOB_STATUS,
@@ -4,7 +4,7 @@ import {
4
4
  UnprocessableError,
5
5
  writeFailure,
6
6
  } from "@cosmicdrift/kumiko-framework/errors";
7
- import { z } from "zod";
7
+ import * as z from "zod";
8
8
  import { USER_STATUS, userTable } from "../../user";
9
9
  import { denyIfTargetOutsideAdminTenant } from "../lib/deny-if-target-outside-admin-tenant";
10
10
  import { isAdminActor } from "../lib/is-admin-actor";
@@ -14,7 +14,7 @@ import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
14
14
  import { access, defineWriteHandler, SYSTEM_USER_ID } from "@cosmicdrift/kumiko-framework/engine";
15
15
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
16
16
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
17
- import { z } from "zod";
17
+ import * as z from "zod";
18
18
  import { resolveAppTenantModel } from "../lib/resolve-tenant-model";
19
19
  import { makeTenantStorageProviderResolver } from "../lib/storage-provider-resolver";
20
20
  import { runForgetCleanup, type SendDeletionExecutedEmailFn } from "../run-forget-cleanup";
@@ -1,5 +1,5 @@
1
1
  import { createEventStoreExecutor, type TenantDb } from "@cosmicdrift/kumiko-framework/db";
2
- import { derivativeListPrefix, isDerivativeKeyOf } from "@cosmicdrift/kumiko-framework/derivatives";
2
+ import { deleteStoredFileAndDerivatives } from "@cosmicdrift/kumiko-framework/derivatives";
3
3
  import {
4
4
  createSystemUser,
5
5
  type FieldDefinition,
@@ -10,13 +10,11 @@ import {
10
10
  type UserDataHookCtx,
11
11
  type UserDataStorageProvider,
12
12
  } from "@cosmicdrift/kumiko-framework/engine";
13
- import {
14
- assertSafeStorageKey,
15
- fileRefEntity,
16
- fileRefsTable,
17
- } from "@cosmicdrift/kumiko-framework/files";
13
+ import { fileRefEntity, fileRefsTable } from "@cosmicdrift/kumiko-framework/files";
18
14
  import { assertErased } from "../../shared";
19
15
 
16
+ const ERROR_CONTEXT = "user-data-rights-defaults:fileRef";
17
+
20
18
  // Forget writes go through the executor (events), not deleteMany/updateMany:
21
19
  // a projection rebuild replays the events, so the erasure survives. Eventless
22
20
  // writes are wiped/resurrected on rebuild — the Art.17 hole this fixes. Bounded:
@@ -174,52 +172,12 @@ function isPersonalFileRow(registry: Registry, row: Record<string, unknown>): bo
174
172
  return isPersonalPiiField(fieldDef);
175
173
  }
176
174
 
177
- // Derivatives (thumbnails/resized variants — see derivatives-context.ts) are
178
- // never tracked anywhere but the storage layer: they're rendered under a
179
- // deterministic key (deriveKey + variantSuffix) computed from the original's
180
- // key + a render spec, on demand, and nothing writes that key back onto the
181
- // FileRef row. List the original's key-prefix and keep only candidates whose
182
- // suffix matches the derivative grammar, anchored to the original's own
183
- // basename AND extension — a same-directory sibling original (a different
184
- // file, possibly another user's) shares the same list prefix but fails the
185
- // extension/suffix check and is never touched.
186
- async function listDerivativeKeys(
187
- originalKey: string,
188
- provider: UserDataStorageProvider,
189
- ): Promise<readonly string[]> {
190
- let candidates: readonly string[];
191
- try {
192
- candidates = await provider.list(derivativeListPrefix(originalKey));
193
- } catch (err) {
194
- // Wrap rather than let a raw provider error (e.g. S3 AccessDenied) surface
195
- // unexplained — list() is a NEW requirement this hook added on top of
196
- // delete(); a bucket policy granting only s3:DeleteObject now fails forget
197
- // every run instead of just leaving derivatives behind. Name the likely
198
- // cause so an operator doesn't have to guess.
199
- throw new Error(
200
- `[user-data-rights-defaults:fileRef] provider.list() failed while looking up derivatives of key=${originalKey} — forget/erasure requires list permission on the storage bucket (e.g. s3:ListBucket), not just delete. Original error: ${err instanceof Error ? err.message : String(err)}`,
201
- );
202
- }
203
- const derivativeKeys: string[] = [];
204
- for (const candidate of candidates) {
205
- if (!isDerivativeKeyOf(originalKey, candidate)) continue;
206
- try {
207
- assertSafeStorageKey(candidate);
208
- } catch {
209
- // ponytail: a listing hit that fails the storage-key grammar can't be
210
- // a real derivative (every derivative is written via a validated
211
- // write()) — skip rather than pass a malformed key to delete().
212
- continue;
213
- }
214
- derivativeKeys.push(candidate);
215
- }
216
- return derivativeKeys;
217
- }
218
-
219
175
  // Delete every row's binary (original + any derivatives) via the provider.
220
176
  // Returns the keys whose delete threw — the caller fails closed on a
221
177
  // non-empty list so the sub-tx rolls back and the next forget run retries
222
- // (delete is idempotent → converges).
178
+ // (delete is idempotent → converges). Derivative-listing + per-key delete
179
+ // lives in the shared derivatives helper (also used by data-retention's
180
+ // hardDelete cleanup) so this hook no longer carries its own copy.
223
181
  async function deleteBinaries(
224
182
  rows: readonly Record<string, unknown>[],
225
183
  provider: UserDataStorageProvider,
@@ -228,18 +186,7 @@ async function deleteBinaries(
228
186
  for (const row of rows) {
229
187
  const key = row["storageKey"]; // @cast-boundary db-row
230
188
  if (typeof key !== "string" || key.length === 0) continue;
231
- const keysToDelete = [key, ...(await listDerivativeKeys(key, provider))];
232
- for (const k of keysToDelete) {
233
- try {
234
- await provider.delete(k);
235
- } catch (err) {
236
- // biome-ignore lint/suspicious/noConsole: operator-visibility for binary-cleanup-failure
237
- console.warn(
238
- `[user-data-rights-defaults:fileRef] storage delete failed key=${k} err=${err instanceof Error ? err.message : String(err)}`,
239
- );
240
- failedKeys.push(k);
241
- }
242
- }
189
+ failedKeys.push(...(await deleteStoredFileAndDerivatives(key, provider, ERROR_CONTEXT)));
243
190
  }
244
191
  return failedKeys;
245
192
  }
@@ -5,7 +5,7 @@ import {
5
5
  SYSTEM_TENANT_ID,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
8
- import { z } from "zod";
8
+ import * as z from "zod";
9
9
  import { AuthErrors } from "../../auth-email-password";
10
10
  import { decryptStoredPii, verifyPassword } from "../../shared";
11
11
  import { UserErrors, UserHandlers, UserQueries } from "../../user";
@@ -21,7 +21,7 @@ import {
21
21
  WORKFLOW_WAITING_TYPE,
22
22
  } from "@cosmicdrift/kumiko-framework/engine";
23
23
  import { setupTestStack, type TestStack, TestUsers } from "@cosmicdrift/kumiko-framework/stack";
24
- import { z } from "zod";
24
+ import * as z from "zod";
25
25
  import { workflowRunAggregateId } from "../aggregate-id";
26
26
  import { workflowRunnerFeature } from "../feature";
27
27
  import { workflowRunPendingTable } from "../tables";
@@ -48,7 +48,7 @@ import {
48
48
  type WriteHandlerDef,
49
49
  } from "@cosmicdrift/kumiko-framework/engine";
50
50
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
51
- import { z } from "zod";
51
+ import * as z from "zod";
52
52
  import {
53
53
  isResumableSuspension,
54
54
  type WorkflowRunCompletedPayload,