@cosmicdrift/kumiko-framework 0.257.0 → 0.258.1

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 (138) hide show
  1. package/package.json +3 -3
  2. package/src/__tests__/anonymous-access.integration.test.ts +3 -3
  3. package/src/__tests__/derived-fields.integration.test.ts +1 -1
  4. package/src/__tests__/entity-list-limits.integration.test.ts +1 -1
  5. package/src/__tests__/error-contract.integration.test.ts +1 -1
  6. package/src/__tests__/ownership-where-write-path.integration.test.ts +1 -1
  7. package/src/__tests__/ownership.integration.test.ts +7 -3
  8. package/src/__tests__/schema-cli-rebuild.integration.test.ts +2 -2
  9. package/src/__tests__/transition-guard.integration.test.ts +3 -3
  10. package/src/api/__tests__/api.test.ts +21 -3
  11. package/src/api/__tests__/batch.integration.test.ts +3 -3
  12. package/src/api/__tests__/body-limit.test.ts +7 -1
  13. package/src/api/__tests__/dispatcher-live.integration.test.ts +1 -1
  14. package/src/api/__tests__/http-route-rate-limit.integration.test.ts +7 -1
  15. package/src/api/__tests__/metrics-endpoint.test.ts +7 -1
  16. package/src/api/__tests__/nested-write.integration.test.ts +3 -3
  17. package/src/api/__tests__/server-boot-guards.test.ts +11 -4
  18. package/src/bun-db/__tests__/write-brand.test.ts +4 -1
  19. package/src/db/__tests__/apply-entity-event-tenant.integration.test.ts +1 -1
  20. package/src/db/__tests__/assert-exists-in.integration.test.ts +1 -1
  21. package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +2 -2
  22. package/src/db/__tests__/collect-table-metas.test.ts +9 -5
  23. package/src/db/__tests__/compound-types.test.ts +1 -1
  24. package/src/db/__tests__/config-seed.integration.test.ts +3 -3
  25. package/src/db/__tests__/eagerload.integration.test.ts +7 -7
  26. package/src/db/__tests__/entity-table-from-registry.test.ts +8 -2
  27. package/src/db/__tests__/entity-table-meta-source.test.ts +7 -3
  28. package/src/db/__tests__/entity-table-types.test.ts +4 -4
  29. package/src/db/__tests__/event-store-executor-list.integration.test.ts +9 -2
  30. package/src/db/__tests__/event-store-executor-reference-search.integration.test.ts +4 -4
  31. package/src/db/__tests__/event-store-executor-reference-sort.integration.test.ts +3 -3
  32. package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +4 -4
  33. package/src/db/__tests__/event-store-executor.integration.test.ts +11 -6
  34. package/src/db/__tests__/event-store-system-stream.integration.test.ts +2 -2
  35. package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +6 -4
  36. package/src/db/__tests__/located-timestamp.test.ts +1 -1
  37. package/src/db/__tests__/money.test.ts +1 -1
  38. package/src/db/__tests__/multi-row-insert.integration.test.ts +3 -3
  39. package/src/db/__tests__/parent-ref-clause.test.ts +213 -0
  40. package/src/db/__tests__/schema-migration.integration.test.ts +30 -14
  41. package/src/db/__tests__/source-shadow-create.integration.test.ts +1 -1
  42. package/src/db/__tests__/table-builder-indexes.test.ts +14 -12
  43. package/src/db/__tests__/table-builder-required.test.ts +2 -2
  44. package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
  45. package/src/db/__tests__/tenant-db-where-merge.test.ts +5 -2
  46. package/src/db/__tests__/tenant-db.integration.test.ts +2 -2
  47. package/src/db/__tests__/unique-violation-mapping.integration.test.ts +2 -2
  48. package/src/db/event-store-executor-read.ts +97 -19
  49. package/src/db/parent-ref-clause.ts +182 -0
  50. package/src/db/table-builder.ts +7 -0
  51. package/src/engine/__tests__/boot-validator-action-wiring.test.ts +50 -8
  52. package/src/engine/__tests__/boot-validator-detail-for.test.ts +28 -4
  53. package/src/engine/__tests__/boot-validator-entity-list.test.ts +20 -4
  54. package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +9 -3
  55. package/src/engine/__tests__/boot-validator.test.ts +716 -91
  56. package/src/engine/__tests__/define-feature-entity-mapping.test.ts +2 -2
  57. package/src/engine/__tests__/engine.test.ts +128 -37
  58. package/src/engine/__tests__/entity-handlers.test.ts +3 -3
  59. package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +4 -4
  60. package/src/engine/__tests__/entity-restore-tenant-isolation.integration.test.ts +1 -1
  61. package/src/engine/__tests__/entity-write-crosstenant.integration.test.ts +1 -1
  62. package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
  63. package/src/engine/__tests__/extends-registrar.test.ts +13 -3
  64. package/src/engine/__tests__/factories-long-text.test.ts +10 -6
  65. package/src/engine/__tests__/feature-crud-shorthand.test.ts +1 -1
  66. package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +1 -1
  67. package/src/engine/__tests__/multiselect-filter.integration.test.ts +1 -1
  68. package/src/engine/__tests__/nav.test.ts +1 -1
  69. package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
  70. package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
  71. package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
  72. package/src/engine/__tests__/projection-detail-actions.test.ts +6 -1
  73. package/src/engine/__tests__/projection-detail-singleton.test.ts +6 -1
  74. package/src/engine/__tests__/projection-detail-tabs.test.ts +6 -1
  75. package/src/engine/__tests__/projection-list-filter.integration.test.ts +7 -2
  76. package/src/engine/__tests__/projection.test.ts +1 -1
  77. package/src/engine/__tests__/registry.test.ts +13 -3
  78. package/src/engine/__tests__/schema-builder.test.ts +39 -11
  79. package/src/engine/__tests__/screen.test.ts +21 -15
  80. package/src/engine/__tests__/search-payload-extension.test.ts +15 -3
  81. package/src/engine/__tests__/store-table.test.ts +6 -3
  82. package/src/engine/__tests__/validate-projection-allowlist.test.ts +12 -4
  83. package/src/engine/__tests__/validation-hooks.test.ts +7 -1
  84. package/src/engine/boot-validator/__tests__/ownership.test.ts +2 -2
  85. package/src/engine/boot-validator/__tests__/parent-ref.test.ts +149 -0
  86. package/src/engine/boot-validator/action-wiring.ts +7 -7
  87. package/src/engine/boot-validator/index.ts +2 -0
  88. package/src/engine/boot-validator/parent-ref.ts +96 -0
  89. package/src/engine/boot-validator/projection-list-screens.ts +36 -23
  90. package/src/engine/boot-validator/query-output-columns.ts +2 -1
  91. package/src/engine/boot-validator/query-refs.ts +2 -1
  92. package/src/engine/boot-validator/screens.ts +322 -131
  93. package/src/engine/build-config-feature-schema.ts +2 -2
  94. package/src/engine/define-handler.ts +6 -0
  95. package/src/engine/entity-handlers.ts +6 -1
  96. package/src/engine/factories.ts +2 -0
  97. package/src/engine/feature-entity-handlers.ts +5 -0
  98. package/src/engine/index.ts +6 -0
  99. package/src/engine/ownership.ts +15 -0
  100. package/src/engine/pattern-library/mixed-schemas.ts +1 -0
  101. package/src/engine/screen-helpers.ts +25 -0
  102. package/src/engine/types/index.ts +5 -0
  103. package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
  104. package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
  105. package/src/files/__tests__/file-field-pipeline.integration.test.ts +1 -1
  106. package/src/files/__tests__/files.integration.test.ts +1 -1
  107. package/src/files/file-ref-entity.ts +9 -9
  108. package/src/i18n/__tests__/i18n.test.ts +7 -1
  109. package/src/i18n/required-surface-keys.ts +48 -0
  110. package/src/migrations/__tests__/kumiko-drift.integration.test.ts +3 -1
  111. package/src/migrations/__tests__/pending-rebuilds.integration.test.ts +2 -2
  112. package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
  113. package/src/pipeline/__tests__/cascade-handler.integration.test.ts +23 -8
  114. package/src/pipeline/__tests__/cascade-handler.test.ts +18 -3
  115. package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
  116. package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +5 -3
  117. package/src/pipeline/__tests__/dispatcher.test.ts +42 -6
  118. package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +2 -2
  119. package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
  120. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +42 -6
  121. package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +2 -2
  122. package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
  123. package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +6 -2
  124. package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +6 -2
  125. package/src/pipeline/__tests__/perf-rebuild.integration.test.ts +1 -1
  126. package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
  127. package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +3 -3
  128. package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
  129. package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +2 -2
  130. package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +13 -2
  131. package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
  132. package/src/search/__tests__/reindex-entity.integration.test.ts +6 -1
  133. package/src/search/__tests__/search-pii-derived-index.integration.test.ts +7 -1
  134. package/src/stack/__tests__/ownership-boot-guard.integration.test.ts +1 -1
  135. package/src/testing/__tests__/e2e-generator.test.ts +15 -5
  136. package/src/testing/e2e-generator.ts +2 -0
  137. package/src/testing/shared-entities.ts +4 -2
  138. package/src/ui-types/index.ts +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-framework",
3
- "version": "0.257.0",
3
+ "version": "0.258.1",
4
4
  "description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -198,7 +198,7 @@
198
198
  "./package.json": "./package.json"
199
199
  },
200
200
  "dependencies": {
201
- "@cosmicdrift/kumiko-types": "0.257.0",
201
+ "@cosmicdrift/kumiko-types": "0.258.1",
202
202
  "bullmq": "^5.76.7",
203
203
  "bun-types": "^1.3.13",
204
204
  "hono": "^4.13.1",
@@ -214,7 +214,7 @@
214
214
  "zod": "^4.4.3"
215
215
  },
216
216
  "devDependencies": {
217
- "@cosmicdrift/kumiko-dispatcher-live": "0.257.0",
217
+ "@cosmicdrift/kumiko-dispatcher-live": "0.258.1",
218
218
  "bun-types": "^1.3.13",
219
219
  "pino-pretty": "^13.1.3"
220
220
  },
@@ -29,7 +29,7 @@ const OTHER_TENANT_ID = "00000000-0000-4000-8000-000000000002" as TenantId;
29
29
  const productEntity = createEntity({
30
30
  table: "anon_products",
31
31
  fields: {
32
- name: createTextField({ required: true }),
32
+ name: createTextField({ personal: false, reason: "test_fixture", required: true }),
33
33
  },
34
34
  });
35
35
  const productTable = buildEntityTable("product", productEntity);
@@ -37,8 +37,8 @@ const productTable = buildEntityTable("product", productEntity);
37
37
  const orderEntity = createEntity({
38
38
  table: "anon_orders",
39
39
  fields: {
40
- productName: createTextField({ required: true }),
41
- placedBy: createTextField({ default: "" }),
40
+ productName: createTextField({ personal: false, reason: "test_fixture", required: true }),
41
+ placedBy: createTextField({ personal: false, reason: "test_fixture", default: "" }),
42
42
  },
43
43
  });
44
44
  const orderTable = buildEntityTable("order", orderEntity);
@@ -23,7 +23,7 @@ import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } fr
23
23
  const gadgetEntity = createEntity({
24
24
  table: "derived_gadgets",
25
25
  fields: {
26
- name: createTextField({ required: true }),
26
+ name: createTextField({ personal: false, reason: "test_fixture", required: true }),
27
27
  priceCents: createNumberField({ required: true }),
28
28
  },
29
29
  derivedFields: {
@@ -19,7 +19,7 @@ import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } fr
19
19
 
20
20
  const widgetEntity = createEntity({
21
21
  table: "limit_widgets",
22
- fields: { name: createTextField({ required: true }) },
22
+ fields: { name: createTextField({ personal: false, reason: "test_fixture", required: true }) },
23
23
  });
24
24
 
25
25
  const widgetFeature = defineFeature("limitwidgets", (r) => {
@@ -35,7 +35,7 @@ import {
35
35
  const itemEntity = createEntity({
36
36
  table: "errctr_items",
37
37
  fields: {
38
- name: createTextField({ required: true }),
38
+ name: createTextField({ personal: false, reason: "test_fixture", required: true }),
39
39
  stock: createNumberField({ default: 0 }),
40
40
  },
41
41
  });
@@ -46,7 +46,7 @@ const memoEntity = createEntity({
46
46
  softDelete: true,
47
47
  fields: {
48
48
  ownerId: createTextField({ required: true }),
49
- title: createTextField({ required: true }),
49
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
50
50
  },
51
51
  access: {
52
52
  read: { Admin: "all", Member: "all" },
@@ -36,17 +36,21 @@ const contractEntity = createEntity({
36
36
  table: "h2_contracts",
37
37
  softDelete: true,
38
38
  fields: {
39
- teamId: createTextField({ required: true }),
39
+ teamId: createTextField({ personal: false, reason: "test_fixture", required: true }),
40
40
  assigneeId: createTextField(),
41
- title: createTextField({ required: true }),
41
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
42
42
  // propA: public on read + write
43
- propA: createTextField(),
43
+ propA: createTextField({ personal: false, reason: "test_fixture" }),
44
44
  // propB: Admin-only
45
45
  propB: createTextField({
46
+ personal: false,
47
+ reason: "test_fixture",
46
48
  access: { read: { Admin: "all" }, write: { Admin: "all" } },
47
49
  }),
48
50
  // propC: Admin full, TeamMember scoped to matching teamId
49
51
  propC: createTextField({
52
+ personal: false,
53
+ reason: "test_fixture",
50
54
  access: {
51
55
  read: { Admin: "all", TeamMember: from("claim:teams:teamId") },
52
56
  write: { Admin: "all", TeamMember: from("claim:teams:teamId") },
@@ -33,8 +33,8 @@ import { ensureTemporalPolyfill } from "../time/polyfill";
33
33
  const itemEntity = createEntity({
34
34
  table: "read_apply_items",
35
35
  fields: {
36
- groupId: createTextField({ required: true }),
37
- name: createTextField({ required: true }),
36
+ groupId: createTextField({ personal: false, reason: "test_fixture", required: true }),
37
+ name: createTextField({ personal: false, reason: "test_fixture", required: true }),
38
38
  },
39
39
  softDelete: true,
40
40
  });
@@ -21,7 +21,7 @@ import { expectErrorIncludes } from "../testing";
21
21
  const invoiceEntity = createEntity({
22
22
  table: "tg_invoices",
23
23
  fields: {
24
- title: createTextField({ required: true }),
24
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
25
25
  status: createSelectField({ options: ["draft", "sent", "paid"] as const, default: "draft" }),
26
26
  },
27
27
  transitions: {
@@ -36,7 +36,7 @@ const invoiceEntity = createEntity({
36
36
  const orderEntity = createEntity({
37
37
  table: "tg_orders",
38
38
  fields: {
39
- title: createTextField({ required: true }),
39
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
40
40
  status: createSelectField({
41
41
  options: ["open", "shipped", "delivered"] as const,
42
42
  default: "open",
@@ -55,7 +55,7 @@ const orderEntity = createEntity({
55
55
  const ticketEntity = createEntity({
56
56
  table: "tg_tickets",
57
57
  fields: {
58
- title: createTextField({ required: true }),
58
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
59
59
  status: createSelectField({ options: ["open", "closed"] as const, default: "open" }),
60
60
  isDeleted: createBooleanField({ default: false }),
61
61
  },
@@ -18,7 +18,13 @@ import { buildServer } from "../server";
18
18
  const JWT_SECRET = "test-secret-at-least-32-chars-long!!";
19
19
 
20
20
  const testFeature = defineFeature("test", (r) => {
21
- r.entity("item", createEntity({ table: "Items", fields: { name: createTextField() } }));
21
+ r.entity(
22
+ "item",
23
+ createEntity({
24
+ table: "Items",
25
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
26
+ }),
27
+ );
22
28
 
23
29
  r.writeHandler(
24
30
  "item:create",
@@ -726,7 +732,13 @@ describe("feature-declared HTTP routes (r.httpRoute)", () => {
726
732
  // → Hono-app.{get,post}(path) → Response. deps.app erlaubt internal-call
727
733
  // an /api/* (gleicher Auth-Pfad wie ein echter HTTP-Call).
728
734
  const routeFeature = defineFeature("routes", (r) => {
729
- r.entity("item", createEntity({ table: "Items", fields: { name: createTextField() } }));
735
+ r.entity(
736
+ "item",
737
+ createEntity({
738
+ table: "Items",
739
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
740
+ }),
741
+ );
730
742
  r.queryHandler("item:list", z.object({}), async () => [{ id: 7 }], {
731
743
  access: { openToAll: true },
732
744
  });
@@ -776,7 +788,13 @@ describe("feature-declared HTTP routes (r.httpRoute)", () => {
776
788
  // defaultTenantId macht den inner-Call ohne Bearer-Token möglich;
777
789
  // pinst dass deps.app.fetch identisch zu einem echten HTTP-Call läuft.
778
790
  const inner = defineFeature("inner", (r) => {
779
- r.entity("item", createEntity({ table: "Items", fields: { name: createTextField() } }));
791
+ r.entity(
792
+ "item",
793
+ createEntity({
794
+ table: "Items",
795
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
796
+ }),
797
+ );
780
798
  // Bewusst "anonymous" — openToAll schließt anonymous-User explizit
781
799
  // aus (siehe access.ts), damit das Aktivieren von anonymousAccess
782
800
  // nicht versehentlich jeden openToAll-Handler public macht.
@@ -22,7 +22,7 @@ import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } fr
22
22
  const itemEntity = createEntity({
23
23
  table: "batch_items",
24
24
  fields: {
25
- name: createTextField({ required: true }),
25
+ name: createTextField({ personal: false, reason: "test_fixture", required: true }),
26
26
  counter: createNumberField({ default: 0 }),
27
27
  },
28
28
  });
@@ -34,8 +34,8 @@ const itemTable = buildEntityTable("item", itemEntity);
34
34
  const auditEntity = createEntity({
35
35
  table: "batch_audit",
36
36
  fields: {
37
- action: createTextField({ required: true }),
38
- itemId: createTextField({ required: true }),
37
+ action: createTextField({ personal: false, reason: "test_fixture", required: true }),
38
+ itemId: createTextField({ personal: false, reason: "test_fixture", required: true }),
39
39
  },
40
40
  });
41
41
  // Brand (#742) is compile-time-only; the postSave hook writes this sink via method-form,
@@ -7,7 +7,13 @@ import { buildServer } from "../server";
7
7
  const JWT_SECRET = "test-secret-at-least-32-chars-long!!";
8
8
 
9
9
  const testFeature = defineFeature("blob", (r) => {
10
- r.entity("note", createEntity({ table: "Notes", fields: { body: createTextField() } }));
10
+ r.entity(
11
+ "note",
12
+ createEntity({
13
+ table: "Notes",
14
+ fields: { body: createTextField({ personal: false, reason: "test_fixture" }) },
15
+ }),
16
+ );
11
17
  r.writeHandler(
12
18
  "note:create",
13
19
  z.object({ body: z.string() }),
@@ -23,7 +23,7 @@ import { generateId } from "../../utils";
23
23
 
24
24
  const itemEntity = createEntity({
25
25
  table: "dispatcher_live_items",
26
- fields: { name: createTextField({ required: true }) },
26
+ fields: { name: createTextField({ personal: false, reason: "test_fixture", required: true }) },
27
27
  });
28
28
  const itemTable = buildEntityTable("item", itemEntity);
29
29
 
@@ -14,7 +14,13 @@ import { setupTestStack, type TestStack } from "../../stack";
14
14
  const SYSTEM_TENANT_ID = "00000000-0000-4000-8000-000000000000" as TenantId;
15
15
 
16
16
  const ipLimitedFeature = defineFeature("rl-http", (r) => {
17
- r.entity("item", createEntity({ table: "Items", fields: { name: createTextField() } }));
17
+ r.entity(
18
+ "item",
19
+ createEntity({
20
+ table: "Items",
21
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
22
+ }),
23
+ );
18
24
  r.queryHandler("ping", z.object({}), async () => ({ ok: true }), {
19
25
  access: { roles: ["anonymous"] },
20
26
  rateLimit: { per: "ip", limit: 2, windowSeconds: 60 },
@@ -10,7 +10,13 @@ import { buildServer } from "../server";
10
10
  const JWT = "metrics-endpoint-test-secret-minimum-32-chars!!";
11
11
 
12
12
  const noopFeature = defineFeature("m", (r) => {
13
- r.entity("widget", createEntity({ table: "Widgets", fields: { name: createTextField() } }));
13
+ r.entity(
14
+ "widget",
15
+ createEntity({
16
+ table: "Widgets",
17
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
18
+ }),
19
+ );
14
20
  });
15
21
 
16
22
  // Swap the NoopProvider's meter for a PrometheusMeter. Tracer + lifecycle
@@ -12,15 +12,15 @@ import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } fr
12
12
  // per entry — all in the same TX as the parent.
13
13
  const projectEntity = createEntity({
14
14
  table: "nested_projects",
15
- fields: { name: createTextField({ required: true }) },
15
+ fields: { name: createTextField({ personal: false, reason: "test_fixture", required: true }) },
16
16
  });
17
17
  const projectTable = buildEntityTable("project", projectEntity);
18
18
 
19
19
  const taskEntity = createEntity({
20
20
  table: "nested_tasks",
21
21
  fields: {
22
- projectId: createTextField({ required: true }),
23
- title: createTextField({ required: true }),
22
+ projectId: createTextField({ personal: false, reason: "test_fixture", required: true }),
23
+ title: createTextField({ personal: false, reason: "test_fixture", required: true }),
24
24
  },
25
25
  });
26
26
  const taskTable = buildEntityTable("task", taskEntity);
@@ -30,7 +30,10 @@ describe("buildServer — file-storage provider guard", () => {
30
30
  "doc",
31
31
  createEntity({
32
32
  table: "boot_guard_docs",
33
- fields: { title: createTextField(), attachment: createFileField() },
33
+ fields: {
34
+ title: createTextField({ personal: false, reason: "test_fixture" }),
35
+ attachment: createFileField(),
36
+ },
34
37
  }),
35
38
  );
36
39
  });
@@ -88,7 +91,9 @@ describe("buildServer — search-adapter boot warning (#2051)", () => {
88
91
  "note",
89
92
  createEntity({
90
93
  table: "boot_guard_notes",
91
- fields: { title: createTextField({ searchable: true }) },
94
+ fields: {
95
+ title: createTextField({ personal: false, reason: "test_fixture", searchable: true }),
96
+ },
92
97
  }),
93
98
  );
94
99
  r.screen({ id: "note-list", type: "entityList", entity: "note", columns: ["title"] });
@@ -99,7 +104,7 @@ describe("buildServer — search-adapter boot warning (#2051)", () => {
99
104
  "note",
100
105
  createEntity({
101
106
  table: "boot_guard_plain_notes",
102
- fields: { title: createTextField() },
107
+ fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
103
108
  }),
104
109
  );
105
110
  r.screen({ id: "note-list", type: "entityList", entity: "note", columns: ["title"] });
@@ -114,7 +119,9 @@ describe("buildServer — search-adapter boot warning (#2051)", () => {
114
119
  "download-attempt",
115
120
  createEntity({
116
121
  table: "boot_guard_download_attempts",
117
- fields: { title: createTextField({ searchable: true }) },
122
+ fields: {
123
+ title: createTextField({ personal: false, reason: "test_fixture", searchable: true }),
124
+ },
118
125
  }),
119
126
  );
120
127
  r.screen({
@@ -14,7 +14,10 @@ import { type AnyDb, deleteMany, insertOne, selectMany, updateMany } from "../qu
14
14
 
15
15
  const brandedEntity = buildEntityTable(
16
16
  "brandSample",
17
- createEntity({ table: "brand_sample", fields: { title: createTextField({ required: true }) } }),
17
+ createEntity({
18
+ table: "brand_sample",
19
+ fields: { title: createTextField({ personal: false, reason: "test_fixture", required: true }) },
20
+ }),
18
21
  );
19
22
 
20
23
  const unmanagedTable = defineUnmanagedTable({
@@ -29,7 +29,7 @@ import { buildEntityTable } from "../table-builder";
29
29
  const entity = createEntity({
30
30
  table: "read_apply_tenant_check",
31
31
  fields: {
32
- name: createTextField({ required: true }),
32
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
33
33
  },
34
34
  });
35
35
  const table = buildEntityTable("apply-tenant-check", entity);
@@ -14,7 +14,7 @@ import { createTenantDb } from "../tenant-db";
14
14
 
15
15
  const orderEntity = createEntity({
16
16
  table: "ax_orders",
17
- fields: { name: createTextField({ required: true }) },
17
+ fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
18
18
  });
19
19
  const orderTable = buildEntityTable("order", orderEntity);
20
20
 
@@ -26,8 +26,8 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
26
26
  const userEntity = createEntity({
27
27
  table: "read_unreachable_users",
28
28
  fields: {
29
- email: createTextField({ required: true }),
30
- firstName: createTextField(),
29
+ email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
30
+ firstName: createTextField({ personal: false, reason: "test_fixture" }),
31
31
  isEnabled: createBooleanField({ default: true }),
32
32
  },
33
33
  softDelete: true,
@@ -10,7 +10,7 @@ import { buildBaseColumns, buildEntityTable } from "../table-builder";
10
10
  function exampleEntity() {
11
11
  return createEntity({
12
12
  table: "read_units",
13
- fields: { name: createTextField() },
13
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
14
14
  });
15
15
  }
16
16
 
@@ -140,7 +140,9 @@ describe("collectTableMetas — r.entity backing table (#347)", () => {
140
140
  function widgetEntity() {
141
141
  return createEntity({
142
142
  table: "read_widgets",
143
- fields: { name: createTextField({ required: true }) },
143
+ fields: {
144
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
145
+ },
144
146
  });
145
147
  }
146
148
 
@@ -165,13 +167,15 @@ describe("collectTableMetas — r.entity backing table (#347)", () => {
165
167
  test("throws when the backing table is missing a field's column (superset violated)", () => {
166
168
  const thin = createEntity({
167
169
  table: "read_widgets",
168
- fields: { name: createTextField({ required: true }) },
170
+ fields: {
171
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
172
+ },
169
173
  });
170
174
  const rich = createEntity({
171
175
  table: "read_widgets",
172
176
  fields: {
173
- name: createTextField({ required: true }),
174
- extra: createTextField({ required: true }),
177
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
178
+ extra: createTextField({ required: true, personal: false, reason: "test_fixture" }),
175
179
  },
176
180
  });
177
181
  // Backing table built from the THIN entity lacks the `extra` column.
@@ -18,7 +18,7 @@ import { flattenCompoundTypes, rehydrateCompoundTypes } from "../compound-types"
18
18
  const mixedEntity: EntityDefinition = createEntity({
19
19
  defaultCurrency: "EUR",
20
20
  fields: {
21
- label: createTextField(),
21
+ label: createTextField({ personal: false, reason: "test_fixture" }),
22
22
  pickup: createLocatedTimestampField(),
23
23
  buyingPrice: createMoneyField(),
24
24
  },
@@ -23,9 +23,9 @@ import { buildEntityTable } from "../table-builder";
23
23
  const configEntity = createEntity({
24
24
  table: "read_cfg_seed_test",
25
25
  fields: {
26
- key: createTextField({ required: true }),
27
- value: createTextField({}),
28
- userId: createTextField({}),
26
+ key: createTextField({ required: true, personal: false, reason: "test_fixture" }),
27
+ value: createTextField({ personal: false, reason: "test_fixture" }),
28
+ userId: createTextField({ personal: false, reason: "test_fixture" }),
29
29
  },
30
30
  indexes: [
31
31
  {
@@ -30,12 +30,12 @@ import { createTenantDb } from "../tenant-db";
30
30
 
31
31
  const authorEntity = createEntity({
32
32
  table: "el_authors",
33
- fields: { name: createTextField({ required: true }) },
33
+ fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
34
34
  });
35
35
  const postEntity = createEntity({
36
36
  table: "el_posts",
37
37
  fields: {
38
- title: createTextField({ required: true }),
38
+ title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
39
39
  author: { type: "reference", entity: "author" },
40
40
  tags: { type: "reference", entity: "author", multiple: true },
41
41
  },
@@ -48,7 +48,7 @@ const authorTable = buildEntityTable("author", authorEntity);
48
48
  const contactEntity = createEntity({
49
49
  table: "el_contacts",
50
50
  fields: {
51
- name: createTextField({ required: true }),
51
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
52
52
  email: createTextField({ required: true, personal: "tenant", find: "none" }),
53
53
  iban: createTextField({ required: true, encrypted: true }),
54
54
  },
@@ -56,7 +56,7 @@ const contactEntity = createEntity({
56
56
  const leadEntity = createEntity({
57
57
  table: "el_leads",
58
58
  fields: {
59
- title: createTextField({ required: true }),
59
+ title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
60
60
  contact: { type: "reference", entity: "contact" },
61
61
  ownedContact: { type: "reference", entity: "ownedContact" },
62
62
  unrestrictedContact: { type: "reference", entity: "unrestrictedContact" },
@@ -70,7 +70,7 @@ const contactTable = buildEntityTable("contact", contactEntity);
70
70
  const ownedContactEntity = createEntity({
71
71
  table: "el_owned_contacts",
72
72
  fields: {
73
- name: createTextField({ required: true }),
73
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
74
74
  email: createTextField({ required: true, personal: "tenant", find: "none" }),
75
75
  iban: createTextField({ required: true, encrypted: true }),
76
76
  },
@@ -84,7 +84,7 @@ const ownedContactTable = buildEntityTable("ownedContact", ownedContactEntity);
84
84
  const unrestrictedContactEntity = createEntity({
85
85
  table: "el_unrestricted_contacts",
86
86
  fields: {
87
- name: createTextField({ required: true }),
87
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
88
88
  email: createTextField({ required: true, personal: "tenant", find: "none" }),
89
89
  },
90
90
  access: { read: { admin: "all", member: "all" } },
@@ -218,7 +218,7 @@ describe("collectReferenceFields", () => {
218
218
  const e = createEntity({
219
219
  table: "x",
220
220
  fields: {
221
- title: createTextField(),
221
+ title: createTextField({ personal: false, reason: "test_fixture" }),
222
222
  author: { type: "reference", entity: "users:user" },
223
223
  tags: { type: "reference", entity: "tag", multiple: true },
224
224
  },
@@ -7,7 +7,10 @@ import { entityTableFromRegistry } from "../entity-table-from-registry";
7
7
  import { buildEntityTable } from "../table-builder";
8
8
 
9
9
  function unitEntity() {
10
- return createEntity({ table: "read_units", fields: { name: createTextField() } });
10
+ return createEntity({
11
+ table: "read_units",
12
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
13
+ });
11
14
  }
12
15
 
13
16
  describe("entityTableFromRegistry", () => {
@@ -50,7 +53,10 @@ describe("entityTableFromRegistry", () => {
50
53
  }),
51
54
  ]);
52
55
 
53
- const other = createEntity({ table: "read_tenants", fields: { name: createTextField() } });
56
+ const other = createEntity({
57
+ table: "read_tenants",
58
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
59
+ });
54
60
  const derived = entityTableFromRegistry(registry, "tenant", other);
55
61
 
56
62
  expect(extractTableName(derived)).toBe("read_tenants");
@@ -14,7 +14,7 @@ import { diffSnapshots, snapshotFromMetas } from "../migrate-generator";
14
14
  const entity = createEntity({
15
15
  table: "source-probe",
16
16
  fields: {
17
- userId: createTextField({ required: true }),
17
+ userId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
18
18
  ip: createTextField({
19
19
  personal: { of: "userId" },
20
20
  find: "none",
@@ -61,7 +61,9 @@ describe("unmanaged builders reject read_ prefix (#1208)", () => {
61
61
  test("deriveEntityTableMeta(..., { source: unmanaged }) with read_ table throws", () => {
62
62
  const readEntity = createEntity({
63
63
  table: "read_source_probe",
64
- fields: { userId: createTextField({ required: true }) },
64
+ fields: {
65
+ userId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
66
+ },
65
67
  });
66
68
  expect(() =>
67
69
  deriveEntityTableMeta("source-probe", readEntity, { source: "unmanaged" }),
@@ -70,7 +72,9 @@ describe("unmanaged builders reject read_ prefix (#1208)", () => {
70
72
 
71
73
  test("default toTableName (read_*) + unmanaged throws", () => {
72
74
  const noTable = createEntity({
73
- fields: { userId: createTextField({ required: true }) },
75
+ fields: {
76
+ userId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
77
+ },
74
78
  });
75
79
  expect(() => deriveEntityTableMeta("source-probe", noTable, { source: "unmanaged" })).toThrow(
76
80
  /the "read_" prefix is reserved/,
@@ -28,7 +28,7 @@ describe("EntityTable<E> — Property-Names existieren", () => {
28
28
  const sampleEntity = createEntity({
29
29
  table: "x",
30
30
  fields: {
31
- title: createTextField({ required: true }),
31
+ title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
32
32
  done: createBooleanField({ default: false }),
33
33
  priority: createSelectField({ options: ["low", "high"] as const }),
34
34
  },
@@ -119,7 +119,7 @@ describe("EntityTable<E> — verschiedene Feld-Typen existieren", () => {
119
119
  const ent = createEntity({
120
120
  table: "many",
121
121
  fields: {
122
- txt: createTextField(),
122
+ txt: createTextField({ personal: false, reason: "test_fixture" }),
123
123
  num: createNumberField(),
124
124
  dt: createDateField(),
125
125
  ts: createTimestampField(),
@@ -142,12 +142,12 @@ describe("EntityTable<E> — verschiedene Feld-Typen existieren", () => {
142
142
  describe("EntityTable<E> — idType wirkt", () => {
143
143
  const uuidEnt = createEntity({
144
144
  table: "uuid_ent",
145
- fields: { name: createTextField() },
145
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
146
146
  // default: idType: "uuid"
147
147
  });
148
148
  const serialEnt = createEntity({
149
149
  table: "serial_ent",
150
- fields: { name: createTextField() },
150
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
151
151
  idType: "serial",
152
152
  });
153
153
  const tu = buildEntityTable("uuid_ent", uuidEnt);
@@ -26,7 +26,12 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
26
26
  const entity = createEntity({
27
27
  table: "read_pager_items",
28
28
  fields: {
29
- title: createTextField({ required: true, sortable: true }),
29
+ title: createTextField({
30
+ required: true,
31
+ sortable: true,
32
+ personal: false,
33
+ reason: "test_fixture",
34
+ }),
30
35
  rank: createNumberField({ sortable: true }),
31
36
  dueDate: createDateField({ sortable: true }),
32
37
  },
@@ -551,7 +556,9 @@ describe("event-store-executor.list — runtime SearchAdapter (Tier 2.7e Audit-F
551
556
  const sysEntity = createEntity({
552
557
  table: "read_pager_sys",
553
558
  systemStream: true,
554
- fields: { title: createTextField({ required: true }) },
559
+ fields: {
560
+ title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
561
+ },
555
562
  });
556
563
  const sysTable = buildEntityTable("pagerSys", sysEntity);
557
564
  await unsafeCreateEntityTable(testDb.db, sysEntity, "pagerSys");