@cosmicdrift/kumiko-framework 0.258.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 (114) 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__/schema-migration.integration.test.ts +30 -14
  40. package/src/db/__tests__/source-shadow-create.integration.test.ts +1 -1
  41. package/src/db/__tests__/table-builder-indexes.test.ts +14 -12
  42. package/src/db/__tests__/table-builder-required.test.ts +2 -2
  43. package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
  44. package/src/db/__tests__/tenant-db-where-merge.test.ts +5 -2
  45. package/src/db/__tests__/tenant-db.integration.test.ts +2 -2
  46. package/src/db/__tests__/unique-violation-mapping.integration.test.ts +2 -2
  47. package/src/engine/__tests__/boot-validator-action-wiring.test.ts +50 -8
  48. package/src/engine/__tests__/boot-validator-detail-for.test.ts +28 -4
  49. package/src/engine/__tests__/boot-validator-entity-list.test.ts +20 -4
  50. package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +9 -3
  51. package/src/engine/__tests__/boot-validator.test.ts +488 -91
  52. package/src/engine/__tests__/define-feature-entity-mapping.test.ts +2 -2
  53. package/src/engine/__tests__/engine.test.ts +128 -37
  54. package/src/engine/__tests__/entity-handlers.test.ts +3 -3
  55. package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +4 -4
  56. package/src/engine/__tests__/entity-restore-tenant-isolation.integration.test.ts +1 -1
  57. package/src/engine/__tests__/entity-write-crosstenant.integration.test.ts +1 -1
  58. package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
  59. package/src/engine/__tests__/extends-registrar.test.ts +13 -3
  60. package/src/engine/__tests__/factories-long-text.test.ts +10 -6
  61. package/src/engine/__tests__/feature-crud-shorthand.test.ts +1 -1
  62. package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +1 -1
  63. package/src/engine/__tests__/multiselect-filter.integration.test.ts +1 -1
  64. package/src/engine/__tests__/nav.test.ts +1 -1
  65. package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
  66. package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
  67. package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
  68. package/src/engine/__tests__/projection-detail-actions.test.ts +6 -1
  69. package/src/engine/__tests__/projection-detail-singleton.test.ts +6 -1
  70. package/src/engine/__tests__/projection-detail-tabs.test.ts +6 -1
  71. package/src/engine/__tests__/projection-list-filter.integration.test.ts +7 -2
  72. package/src/engine/__tests__/projection.test.ts +1 -1
  73. package/src/engine/__tests__/registry.test.ts +13 -3
  74. package/src/engine/__tests__/schema-builder.test.ts +39 -11
  75. package/src/engine/__tests__/screen.test.ts +21 -15
  76. package/src/engine/__tests__/search-payload-extension.test.ts +15 -3
  77. package/src/engine/__tests__/store-table.test.ts +6 -3
  78. package/src/engine/__tests__/validate-projection-allowlist.test.ts +12 -4
  79. package/src/engine/__tests__/validation-hooks.test.ts +7 -1
  80. package/src/engine/boot-validator/__tests__/ownership.test.ts +2 -2
  81. package/src/engine/build-config-feature-schema.ts +2 -2
  82. package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
  83. package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
  84. package/src/files/__tests__/file-field-pipeline.integration.test.ts +1 -1
  85. package/src/files/__tests__/files.integration.test.ts +1 -1
  86. package/src/files/file-ref-entity.ts +9 -9
  87. package/src/i18n/__tests__/i18n.test.ts +7 -1
  88. package/src/migrations/__tests__/kumiko-drift.integration.test.ts +3 -1
  89. package/src/migrations/__tests__/pending-rebuilds.integration.test.ts +2 -2
  90. package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
  91. package/src/pipeline/__tests__/cascade-handler.integration.test.ts +23 -8
  92. package/src/pipeline/__tests__/cascade-handler.test.ts +18 -3
  93. package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
  94. package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +5 -3
  95. package/src/pipeline/__tests__/dispatcher.test.ts +42 -6
  96. package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +2 -2
  97. package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
  98. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +42 -6
  99. package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +2 -2
  100. package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
  101. package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +6 -2
  102. package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +6 -2
  103. package/src/pipeline/__tests__/perf-rebuild.integration.test.ts +1 -1
  104. package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
  105. package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +3 -3
  106. package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
  107. package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +2 -2
  108. package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +13 -2
  109. package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
  110. package/src/search/__tests__/reindex-entity.integration.test.ts +6 -1
  111. package/src/search/__tests__/search-pii-derived-index.integration.test.ts +7 -1
  112. package/src/stack/__tests__/ownership-boot-guard.integration.test.ts +1 -1
  113. package/src/testing/__tests__/e2e-generator.test.ts +15 -5
  114. package/src/testing/shared-entities.ts +4 -2
@@ -50,7 +50,13 @@ describe("boot-validator", () => {
50
50
  test("passes for valid features with no issues", () => {
51
51
  const features = [
52
52
  defineFeature("a", (r) => {
53
- r.entity("user", createEntity({ table: "Users", fields: { name: createTextField() } }));
53
+ r.entity(
54
+ "user",
55
+ createEntity({
56
+ table: "Users",
57
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
58
+ }),
59
+ );
54
60
  }),
55
61
  ];
56
62
  expect(() => validateBoot(features)).not.toThrow();
@@ -404,7 +410,7 @@ describe("boot-validator", () => {
404
410
  "item",
405
411
  createEntity({
406
412
  table: "Items",
407
- fields: { name: createTextField() },
413
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
408
414
  }),
409
415
  );
410
416
  r.extendsRegistrar("custom", {
@@ -426,7 +432,7 @@ describe("boot-validator", () => {
426
432
  "item",
427
433
  createEntity({
428
434
  table: "Items",
429
- fields: { status: createTextField() },
435
+ fields: { status: createTextField({ personal: false, reason: "test_fixture" }) },
430
436
  derivedFields: {
431
437
  status: createDerivedField({ valueType: "text", derive: () => "computed" }),
432
438
  },
@@ -446,7 +452,7 @@ describe("boot-validator", () => {
446
452
  "item",
447
453
  createEntity({
448
454
  table: "Items",
449
- fields: { status: createTextField() },
455
+ fields: { status: createTextField({ personal: false, reason: "test_fixture" }) },
450
456
  derivedFields: {
451
457
  statusLabel: createDerivedField({ valueType: "text", derive: () => "computed" }),
452
458
  },
@@ -498,7 +504,7 @@ describe("boot-validator", () => {
498
504
  "item",
499
505
  createEntity({
500
506
  table: "Items",
501
- fields: { name: createTextField() },
507
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
502
508
  }),
503
509
  );
504
510
  r.extendsRegistrar("custom", {
@@ -514,7 +520,13 @@ describe("boot-validator", () => {
514
520
  test("accepts bare CRUD write handler when feature name matches entity", () => {
515
521
  const features = [
516
522
  defineFeature("credit", (r) => {
517
- r.entity("credit", createEntity({ table: "Credits", fields: { name: createTextField() } }));
523
+ r.entity(
524
+ "credit",
525
+ createEntity({
526
+ table: "Credits",
527
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
528
+ }),
529
+ );
518
530
  r.writeHandler(
519
531
  "create",
520
532
  z.object({ name: z.string() }),
@@ -540,7 +552,13 @@ describe("boot-validator", () => {
540
552
  });
541
553
  const consumer = defineFeature("money-horse", (r) => {
542
554
  r.requires("cap-ext");
543
- r.entity("credit", createEntity({ table: "Credits", fields: { name: createTextField() } }));
555
+ r.entity(
556
+ "credit",
557
+ createEntity({
558
+ table: "Credits",
559
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
560
+ }),
561
+ );
544
562
  r.writeHandler(
545
563
  "doSomething",
546
564
  z.object({}),
@@ -583,7 +601,9 @@ describe("boot-validator", () => {
583
601
  test("registerEntityCrud without access options fails boot (no implicit openToAll)", () => {
584
602
  const widgetEntity = createEntity({
585
603
  table: "phase0_widgets",
586
- fields: { name: createTextField({ required: true }) },
604
+ fields: {
605
+ name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
606
+ },
587
607
  });
588
608
  const features = [
589
609
  defineFeature("phase0", (r) => {
@@ -948,7 +968,13 @@ describe("boot-validator", () => {
948
968
  "order",
949
969
  createEntity({
950
970
  table: "orders",
951
- fields: { teamId: createTextField({ required: true }) },
971
+ fields: {
972
+ teamId: createTextField({
973
+ required: true,
974
+ personal: false,
975
+ reason: "test_fixture",
976
+ }),
977
+ },
952
978
  access: {
953
979
  read: { Admin: "all", TeamMember: from("claim:teams:teamId") },
954
980
  },
@@ -966,7 +992,13 @@ describe("boot-validator", () => {
966
992
  "order",
967
993
  createEntity({
968
994
  table: "orders",
969
- fields: { teamId: createTextField({ required: true }) },
995
+ fields: {
996
+ teamId: createTextField({
997
+ required: true,
998
+ personal: false,
999
+ reason: "test_fixture",
1000
+ }),
1001
+ },
970
1002
  access: {
971
1003
  // No "teams" feature registered — claim doesn't exist.
972
1004
  read: { TeamMember: from("claim:teams:teamId") },
@@ -990,7 +1022,13 @@ describe("boot-validator", () => {
990
1022
  "order",
991
1023
  createEntity({
992
1024
  table: "orders",
993
- fields: { teamId: createTextField({ required: true }) },
1025
+ fields: {
1026
+ teamId: createTextField({
1027
+ required: true,
1028
+ personal: false,
1029
+ reason: "test_fixture",
1030
+ }),
1031
+ },
994
1032
  access: {
995
1033
  read: {
996
1034
  // column "nonExistentColumn" not on entity
@@ -1017,12 +1055,18 @@ describe("boot-validator", () => {
1017
1055
  createEntity({
1018
1056
  table: "contracts",
1019
1057
  fields: {
1020
- teamId: createTextField({ required: true }),
1058
+ teamId: createTextField({
1059
+ required: true,
1060
+ personal: false,
1061
+ reason: "test_fixture",
1062
+ }),
1021
1063
  propC: createTextField({
1022
1064
  access: {
1023
1065
  read: { Admin: "all", TeamMember: from("claim:teams:teamId") },
1024
1066
  write: { Admin: "all", TeamMember: from("claim:teams:teamId") },
1025
1067
  },
1068
+ personal: false,
1069
+ reason: "test_fixture",
1026
1070
  }),
1027
1071
  },
1028
1072
  }),
@@ -1040,12 +1084,18 @@ describe("boot-validator", () => {
1040
1084
  createEntity({
1041
1085
  table: "contracts",
1042
1086
  fields: {
1043
- teamId: createTextField({ required: true }),
1087
+ teamId: createTextField({
1088
+ required: true,
1089
+ personal: false,
1090
+ reason: "test_fixture",
1091
+ }),
1044
1092
  propC: createTextField({
1045
1093
  access: {
1046
1094
  // claim not declared anywhere
1047
1095
  read: { TeamMember: from("claim:nowhere:teamId") },
1048
1096
  },
1097
+ personal: false,
1098
+ reason: "test_fixture",
1049
1099
  }),
1050
1100
  },
1051
1101
  }),
@@ -1064,7 +1114,7 @@ describe("boot-validator", () => {
1064
1114
  "order",
1065
1115
  createEntity({
1066
1116
  table: "orders",
1067
- fields: { assigneeId: createTextField() },
1117
+ fields: { assigneeId: createTextField({ personal: false, reason: "test_fixture" }) },
1068
1118
  access: {
1069
1119
  read: { Driver: from("user:id", "assigneeId") },
1070
1120
  },
@@ -1082,7 +1132,7 @@ describe("boot-validator", () => {
1082
1132
  "order",
1083
1133
  createEntity({
1084
1134
  table: "orders",
1085
- fields: { assigneeId: createTextField() },
1135
+ fields: { assigneeId: createTextField({ personal: false, reason: "test_fixture" }) },
1086
1136
  access: {
1087
1137
  read: {
1088
1138
  Admin: "all",
@@ -1106,7 +1156,13 @@ describe("boot-validator", () => {
1106
1156
  "order",
1107
1157
  createEntity({
1108
1158
  table: "orders",
1109
- fields: { entityId: createTextField({ required: true }) },
1159
+ fields: {
1160
+ entityId: createTextField({
1161
+ required: true,
1162
+ personal: false,
1163
+ reason: "test_fixture",
1164
+ }),
1165
+ },
1110
1166
  access: {
1111
1167
  read: {
1112
1168
  Auditor: {
@@ -1132,7 +1188,13 @@ describe("boot-validator", () => {
1132
1188
  "order",
1133
1189
  createEntity({
1134
1190
  table: "orders",
1135
- fields: { entityId: createTextField({ required: true }) },
1191
+ fields: {
1192
+ entityId: createTextField({
1193
+ required: true,
1194
+ personal: false,
1195
+ reason: "test_fixture",
1196
+ }),
1197
+ },
1136
1198
  access: {
1137
1199
  read: {
1138
1200
  Auditor: {
@@ -1196,7 +1258,13 @@ describe("boot-validator", () => {
1196
1258
  "order",
1197
1259
  createEntity({
1198
1260
  table: "orders",
1199
- fields: { teamId: createTextField({ required: true }) },
1261
+ fields: {
1262
+ teamId: createTextField({
1263
+ required: true,
1264
+ personal: false,
1265
+ reason: "test_fixture",
1266
+ }),
1267
+ },
1200
1268
  access: {
1201
1269
  read: { Admi: "all" },
1202
1270
  },
@@ -1225,7 +1293,11 @@ describe("boot-validator", () => {
1225
1293
  createEntity({
1226
1294
  table: "orders",
1227
1295
  fields: {
1228
- secret: createTextField({ access: { read: ["Admni"] } }),
1296
+ secret: createTextField({
1297
+ access: { read: ["Admni"] },
1298
+ personal: false,
1299
+ reason: "test_fixture",
1300
+ }),
1229
1301
  },
1230
1302
  }),
1231
1303
  );
@@ -1251,7 +1323,13 @@ describe("boot-validator", () => {
1251
1323
  "order",
1252
1324
  createEntity({
1253
1325
  table: "orders",
1254
- fields: { teamId: createTextField({ required: true }) },
1326
+ fields: {
1327
+ teamId: createTextField({
1328
+ required: true,
1329
+ personal: false,
1330
+ reason: "test_fixture",
1331
+ }),
1332
+ },
1255
1333
  access: {
1256
1334
  read: { Admin: "all", TeamMember: "all" },
1257
1335
  },
@@ -1273,7 +1351,13 @@ describe("boot-validator", () => {
1273
1351
  "order",
1274
1352
  createEntity({
1275
1353
  table: "orders",
1276
- fields: { teamId: createTextField({ required: true }) },
1354
+ fields: {
1355
+ teamId: createTextField({
1356
+ required: true,
1357
+ personal: false,
1358
+ reason: "test_fixture",
1359
+ }),
1360
+ },
1277
1361
  access: {
1278
1362
  read: { AnyRole: "all" },
1279
1363
  },
@@ -1807,7 +1891,12 @@ describe("boot-validator", () => {
1807
1891
  describe("entityList column renderer form", () => {
1808
1892
  function shopFeature(renderer: unknown) {
1809
1893
  return defineFeature("shop", (r) => {
1810
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
1894
+ r.entity(
1895
+ "product",
1896
+ createEntity({
1897
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
1898
+ }),
1899
+ );
1811
1900
  r.screen({
1812
1901
  id: "product-list",
1813
1902
  type: "entityList",
@@ -1970,7 +2059,12 @@ describe("boot-validator", () => {
1970
2059
  describe("entityList virtual labeled column", () => {
1971
2060
  function noteFeature(column: unknown) {
1972
2061
  return defineFeature("notes", (r) => {
1973
- r.entity("note", createEntity({ fields: { title: createTextField() } }));
2062
+ r.entity(
2063
+ "note",
2064
+ createEntity({
2065
+ fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
2066
+ }),
2067
+ );
1974
2068
  r.screen({
1975
2069
  id: "note-list",
1976
2070
  type: "entityList",
@@ -2030,7 +2124,10 @@ describe("boot-validator", () => {
2030
2124
  return defineFeature("notes", (r) => {
2031
2125
  r.entity(
2032
2126
  "note",
2033
- createEntity({ fields: { title: createTextField() }, softDelete: options?.softDelete }),
2127
+ createEntity({
2128
+ fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
2129
+ softDelete: options?.softDelete,
2130
+ }),
2034
2131
  );
2035
2132
  r.screen({
2036
2133
  id: "note-list",
@@ -2089,7 +2186,12 @@ describe("boot-validator", () => {
2089
2186
  for (const typo of typoColumns) {
2090
2187
  test(`"${typo}" fails validateScreens (via validateBoot)`, () => {
2091
2188
  const feature = defineFeature("notes", (r) => {
2092
- r.entity("note", createEntity({ fields: { title: createTextField() } }));
2189
+ r.entity(
2190
+ "note",
2191
+ createEntity({
2192
+ fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
2193
+ }),
2194
+ );
2093
2195
  r.screen({
2094
2196
  id: "note-list",
2095
2197
  type: "entityList",
@@ -2104,7 +2206,12 @@ describe("boot-validator", () => {
2104
2206
 
2105
2207
  test(`"${typo}" fails validateEntityListScreens directly ("unknown column field")`, () => {
2106
2208
  const feature = defineFeature("notes", (r) => {
2107
- r.entity("note", createEntity({ fields: { title: createTextField() } }));
2209
+ r.entity(
2210
+ "note",
2211
+ createEntity({
2212
+ fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
2213
+ }),
2214
+ );
2108
2215
  r.screen({
2109
2216
  id: "note-list",
2110
2217
  type: "entityList",
@@ -2137,11 +2244,11 @@ describe("boot-validator", () => {
2137
2244
  "product",
2138
2245
  createEntity({
2139
2246
  fields: {
2140
- name: createTextField({ sortable: true }),
2247
+ name: createTextField({ sortable: true, personal: false, reason: "test_fixture" }),
2141
2248
  // Bewusst NICHT sortable: bestätigt dass Validator das
2142
2249
  // unterscheidet und nur sortable-Felder als defaultSort
2143
2250
  // akzeptiert.
2144
- description: createTextField(),
2251
+ description: createTextField({ personal: false, reason: "test_fixture" }),
2145
2252
  },
2146
2253
  }),
2147
2254
  );
@@ -2956,7 +3063,12 @@ describe("boot-validator", () => {
2956
3063
  describe("entityEdit extension section", () => {
2957
3064
  function makeFeature(component: unknown) {
2958
3065
  return defineFeature("shop", (r) => {
2959
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3066
+ r.entity(
3067
+ "product",
3068
+ createEntity({
3069
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3070
+ }),
3071
+ );
2960
3072
  r.screen({
2961
3073
  id: "product-edit",
2962
3074
  type: "entityEdit",
@@ -2997,7 +3109,12 @@ describe("boot-validator", () => {
2997
3109
  return defineFeature("shop", (r) => {
2998
3110
  r.entity(
2999
3111
  "product",
3000
- createEntity({ fields: { name: createTextField(), sku: createTextField() } }),
3112
+ createEntity({
3113
+ fields: {
3114
+ name: createTextField({ personal: false, reason: "test_fixture" }),
3115
+ sku: createTextField({ personal: false, reason: "test_fixture" }),
3116
+ },
3117
+ }),
3001
3118
  );
3002
3119
  r.screen({
3003
3120
  id: "product-edit",
@@ -3054,7 +3171,12 @@ describe("boot-validator", () => {
3054
3171
  return defineFeature("shop", (r) => {
3055
3172
  r.entity(
3056
3173
  "product",
3057
- createEntity({ fields: { name: createTextField(), sku: createTextField() } }),
3174
+ createEntity({
3175
+ fields: {
3176
+ name: createTextField({ personal: false, reason: "test_fixture" }),
3177
+ sku: createTextField({ personal: false, reason: "test_fixture" }),
3178
+ },
3179
+ }),
3058
3180
  );
3059
3181
  r.screen({
3060
3182
  id: "product-edit",
@@ -3188,7 +3310,7 @@ describe("boot-validator", () => {
3188
3310
  "order",
3189
3311
  createEntity({
3190
3312
  fields: {
3191
- kind: createTextField(),
3313
+ kind: createTextField({ personal: false, reason: "test_fixture" }),
3192
3314
  lines: createEmbeddedField({ note: { type: "text" } }, { required: true }),
3193
3315
  },
3194
3316
  }),
@@ -3292,7 +3414,12 @@ describe("boot-validator", () => {
3292
3414
  test("reference auf bestehende Entity → kein Throw", () => {
3293
3415
  const features = [
3294
3416
  defineFeature("shop", (r) => {
3295
- r.entity("customer", createEntity({ fields: { name: createTextField() } }));
3417
+ r.entity(
3418
+ "customer",
3419
+ createEntity({
3420
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3421
+ }),
3422
+ );
3296
3423
  stubListHandler(r, "customer");
3297
3424
  r.entity(
3298
3425
  "order",
@@ -3328,7 +3455,12 @@ describe("boot-validator", () => {
3328
3455
  test("reference labelField auf unknown Field → Throw", () => {
3329
3456
  const features = [
3330
3457
  defineFeature("shop", (r) => {
3331
- r.entity("customer", createEntity({ fields: { name: createTextField() } }));
3458
+ r.entity(
3459
+ "customer",
3460
+ createEntity({
3461
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3462
+ }),
3463
+ );
3332
3464
  r.entity(
3333
3465
  "order",
3334
3466
  createEntity({
@@ -3347,7 +3479,12 @@ describe("boot-validator", () => {
3347
3479
  test("reference labelField=id ist immer ok (PK)", () => {
3348
3480
  const features = [
3349
3481
  defineFeature("shop", (r) => {
3350
- r.entity("customer", createEntity({ fields: { name: createTextField() } }));
3482
+ r.entity(
3483
+ "customer",
3484
+ createEntity({
3485
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3486
+ }),
3487
+ );
3351
3488
  stubListHandler(r, "customer");
3352
3489
  r.entity(
3353
3490
  "order",
@@ -3369,7 +3506,7 @@ describe("boot-validator", () => {
3369
3506
  "category",
3370
3507
  createEntity({
3371
3508
  fields: {
3372
- name: createTextField(),
3509
+ name: createTextField({ personal: false, reason: "test_fixture" }),
3373
3510
  parentId: { type: "reference", entity: "category", labelField: "name" },
3374
3511
  },
3375
3512
  }),
@@ -3383,13 +3520,18 @@ describe("boot-validator", () => {
3383
3520
  test("reference mit multiple: true → kein Throw (Tier 2.7e-Multi)", () => {
3384
3521
  const features = [
3385
3522
  defineFeature("shop", (r) => {
3386
- r.entity("tag", createEntity({ fields: { name: createTextField() } }));
3523
+ r.entity(
3524
+ "tag",
3525
+ createEntity({
3526
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3527
+ }),
3528
+ );
3387
3529
  stubListHandler(r, "tag");
3388
3530
  r.entity(
3389
3531
  "post",
3390
3532
  createEntity({
3391
3533
  fields: {
3392
- title: createTextField(),
3534
+ title: createTextField({ personal: false, reason: "test_fixture" }),
3393
3535
  tagIds: {
3394
3536
  type: "reference",
3395
3537
  entity: "tag",
@@ -3408,7 +3550,12 @@ describe("boot-validator", () => {
3408
3550
  test("cross-feature reference (feature:entity) → kein Throw", () => {
3409
3551
  const features = [
3410
3552
  defineFeature("users", (r) => {
3411
- r.entity("user", createEntity({ fields: { email: createTextField() } }));
3553
+ r.entity(
3554
+ "user",
3555
+ createEntity({
3556
+ fields: { email: createTextField({ personal: false, reason: "test_fixture" }) },
3557
+ }),
3558
+ );
3412
3559
  stubListHandler(r, "user");
3413
3560
  }),
3414
3561
  defineFeature("shop", (r) => {
@@ -3428,7 +3575,12 @@ describe("boot-validator", () => {
3428
3575
  test("Audit-Fix #2: cross-feature reference ohne list-handler → Throw", () => {
3429
3576
  const features = [
3430
3577
  defineFeature("users", (r) => {
3431
- r.entity("user", createEntity({ fields: { email: createTextField() } }));
3578
+ r.entity(
3579
+ "user",
3580
+ createEntity({
3581
+ fields: { email: createTextField({ personal: false, reason: "test_fixture" }) },
3582
+ }),
3583
+ );
3432
3584
  // KEINE stubListHandler — das ist der Punkt des Tests
3433
3585
  }),
3434
3586
  defineFeature("shop", (r) => {
@@ -3468,7 +3620,12 @@ describe("boot-validator", () => {
3468
3620
  test("cross-feature reference auf unknown entity → Throw mit feature-context", () => {
3469
3621
  const features = [
3470
3622
  defineFeature("users", (r) => {
3471
- r.entity("user", createEntity({ fields: { email: createTextField() } }));
3623
+ r.entity(
3624
+ "user",
3625
+ createEntity({
3626
+ fields: { email: createTextField({ personal: false, reason: "test_fixture" }) },
3627
+ }),
3628
+ );
3472
3629
  }),
3473
3630
  defineFeature("shop", (r) => {
3474
3631
  r.entity(
@@ -3489,7 +3646,12 @@ describe("boot-validator", () => {
3489
3646
  test("cross-feature labelField auf unknown Field → Throw", () => {
3490
3647
  const features = [
3491
3648
  defineFeature("users", (r) => {
3492
- r.entity("user", createEntity({ fields: { email: createTextField() } }));
3649
+ r.entity(
3650
+ "user",
3651
+ createEntity({
3652
+ fields: { email: createTextField({ personal: false, reason: "test_fixture" }) },
3653
+ }),
3654
+ );
3493
3655
  }),
3494
3656
  defineFeature("shop", (r) => {
3495
3657
  r.entity(
@@ -3540,7 +3702,12 @@ describe("boot-validator", () => {
3540
3702
  test("reference sub-field with a valid target + registered list-handler → kein Throw", () => {
3541
3703
  const features = [
3542
3704
  defineFeature("shop", (r) => {
3543
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3705
+ r.entity(
3706
+ "product",
3707
+ createEntity({
3708
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3709
+ }),
3710
+ );
3544
3711
  stubListHandler(r, "product");
3545
3712
  r.entity(
3546
3713
  "invoice",
@@ -3560,7 +3727,12 @@ describe("boot-validator", () => {
3560
3727
  test("reference sub-field with a valid target but no registered list-handler → Throw", () => {
3561
3728
  const features = [
3562
3729
  defineFeature("shop", (r) => {
3563
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3730
+ r.entity(
3731
+ "product",
3732
+ createEntity({
3733
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3734
+ }),
3735
+ );
3564
3736
  // KEIN stubListHandler — das ist der Punkt des Tests
3565
3737
  r.entity(
3566
3738
  "invoice",
@@ -3582,7 +3754,12 @@ describe("boot-validator", () => {
3582
3754
  test("reference sub-field labelField referencing an unknown field → Throw with the parent.child field path", () => {
3583
3755
  const features = [
3584
3756
  defineFeature("shop", (r) => {
3585
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3757
+ r.entity(
3758
+ "product",
3759
+ createEntity({
3760
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3761
+ }),
3762
+ );
3586
3763
  stubListHandler(r, "product");
3587
3764
  r.entity(
3588
3765
  "invoice",
@@ -3610,7 +3787,12 @@ describe("boot-validator", () => {
3610
3787
  describe("entityList rowAction kind=navigate (Tier 2.7e-1)", () => {
3611
3788
  function makeFeature(targetScreen: string, withTarget: boolean) {
3612
3789
  return defineFeature("shop", (r) => {
3613
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3790
+ r.entity(
3791
+ "product",
3792
+ createEntity({
3793
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3794
+ }),
3795
+ );
3614
3796
  r.screen({
3615
3797
  id: "product-list",
3616
3798
  type: "entityList",
@@ -3650,7 +3832,12 @@ describe("boot-validator", () => {
3650
3832
  // Custom-Editor der Consumer-App (anderes Feature). Runtime löst die bare
3651
3833
  // id app-weit auf → der Validator muss das erlauben.
3652
3834
  const list = defineFeature("shop", (r) => {
3653
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3835
+ r.entity(
3836
+ "product",
3837
+ createEntity({
3838
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3839
+ }),
3840
+ );
3654
3841
  r.screen({
3655
3842
  id: "product-list",
3656
3843
  type: "entityList",
@@ -3673,7 +3860,12 @@ describe("boot-validator", () => {
3673
3860
  // open with no entity context at runtime. The validator must catch it
3674
3861
  // at boot instead.
3675
3862
  const list = defineFeature("shop", (r) => {
3676
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3863
+ r.entity(
3864
+ "product",
3865
+ createEntity({
3866
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3867
+ }),
3868
+ );
3677
3869
  r.screen({
3678
3870
  id: "product-list",
3679
3871
  type: "entityList",
@@ -3685,7 +3877,12 @@ describe("boot-validator", () => {
3685
3877
  });
3686
3878
  });
3687
3879
  const consumer = defineFeature("billing", (r) => {
3688
- r.entity("invoice", createEntity({ fields: { name: createTextField() } }));
3880
+ r.entity(
3881
+ "invoice",
3882
+ createEntity({
3883
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3884
+ }),
3885
+ );
3689
3886
  r.screen({
3690
3887
  id: "invoice-edit",
3691
3888
  type: "entityEdit",
@@ -3702,7 +3899,12 @@ describe("boot-validator", () => {
3702
3899
  const list = defineFeature("shop", (r) => {
3703
3900
  r.entity(
3704
3901
  "product",
3705
- createEntity({ fields: { name: createTextField(), invoiceId: createTextField() } }),
3902
+ createEntity({
3903
+ fields: {
3904
+ name: createTextField({ personal: false, reason: "test_fixture" }),
3905
+ invoiceId: createTextField({ personal: false, reason: "test_fixture" }),
3906
+ },
3907
+ }),
3706
3908
  );
3707
3909
  r.screen({
3708
3910
  id: "product-list",
@@ -3721,7 +3923,12 @@ describe("boot-validator", () => {
3721
3923
  });
3722
3924
  });
3723
3925
  const consumer = defineFeature("billing", (r) => {
3724
- r.entity("invoice", createEntity({ fields: { name: createTextField() } }));
3926
+ r.entity(
3927
+ "invoice",
3928
+ createEntity({
3929
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3930
+ }),
3931
+ );
3725
3932
  r.screen({
3726
3933
  id: "invoice-edit",
3727
3934
  type: "entityEdit",
@@ -3734,7 +3941,12 @@ describe("boot-validator", () => {
3734
3941
 
3735
3942
  test("same-feature navigate to entityEdit WITHOUT entityId → kein Throw (same-feature fallback applies)", () => {
3736
3943
  const feature = defineFeature("shop", (r) => {
3737
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3944
+ r.entity(
3945
+ "product",
3946
+ createEntity({
3947
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3948
+ }),
3949
+ );
3738
3950
  r.screen({
3739
3951
  id: "product-list",
3740
3952
  type: "entityList",
@@ -3759,7 +3971,12 @@ describe("boot-validator", () => {
3759
3971
  describe("entityList rowAction kind=navigate entity-target (fw#2228)", () => {
3760
3972
  test("entity-target resolving via detailFor → kein Throw", () => {
3761
3973
  const feature = defineFeature("shop", (r) => {
3762
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3974
+ r.entity(
3975
+ "product",
3976
+ createEntity({
3977
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
3978
+ }),
3979
+ );
3763
3980
  r.screen({
3764
3981
  id: "product-list",
3765
3982
  type: "entityList",
@@ -3779,7 +3996,12 @@ describe("boot-validator", () => {
3779
3996
 
3780
3997
  test("entity-target with no detailFor screen anywhere → Throw mit klarer Message", () => {
3781
3998
  const feature = defineFeature("shop", (r) => {
3782
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
3999
+ r.entity(
4000
+ "product",
4001
+ createEntity({
4002
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4003
+ }),
4004
+ );
3783
4005
  r.screen({
3784
4006
  id: "product-list",
3785
4007
  type: "entityList",
@@ -3795,7 +4017,12 @@ describe("boot-validator", () => {
3795
4017
 
3796
4018
  test("both screen and entity set → Throw", () => {
3797
4019
  const feature = defineFeature("shop", (r) => {
3798
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4020
+ r.entity(
4021
+ "product",
4022
+ createEntity({
4023
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4024
+ }),
4025
+ );
3799
4026
  r.screen({
3800
4027
  id: "product-list",
3801
4028
  type: "entityList",
@@ -3825,7 +4052,12 @@ describe("boot-validator", () => {
3825
4052
 
3826
4053
  test("neither screen nor entity set → Throw", () => {
3827
4054
  const feature = defineFeature("shop", (r) => {
3828
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4055
+ r.entity(
4056
+ "product",
4057
+ createEntity({
4058
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4059
+ }),
4060
+ );
3829
4061
  r.screen({
3830
4062
  id: "product-list",
3831
4063
  type: "entityList",
@@ -3844,7 +4076,12 @@ describe("boot-validator", () => {
3844
4076
  // detailFor resolution — the owning feature's list navigates to a
3845
4077
  // detail screen a consumer app registers for the entity.
3846
4078
  const list = defineFeature("shop", (r) => {
3847
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4079
+ r.entity(
4080
+ "product",
4081
+ createEntity({
4082
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4083
+ }),
4084
+ );
3848
4085
  r.screen({
3849
4086
  id: "product-list",
3850
4087
  type: "entityList",
@@ -3871,7 +4108,12 @@ describe("boot-validator", () => {
3871
4108
  // row["id"]), so the same-feature-fallback gap that check guards
3872
4109
  // against doesn't exist here.
3873
4110
  const list = defineFeature("shop", (r) => {
3874
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4111
+ r.entity(
4112
+ "product",
4113
+ createEntity({
4114
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4115
+ }),
4116
+ );
3875
4117
  r.screen({
3876
4118
  id: "product-list",
3877
4119
  type: "entityList",
@@ -3881,7 +4123,12 @@ describe("boot-validator", () => {
3881
4123
  });
3882
4124
  });
3883
4125
  const consumer = defineFeature("billing", (r) => {
3884
- r.entity("invoice", createEntity({ fields: { name: createTextField() } }));
4126
+ r.entity(
4127
+ "invoice",
4128
+ createEntity({
4129
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4130
+ }),
4131
+ );
3885
4132
  r.screen({
3886
4133
  id: "invoice-edit",
3887
4134
  type: "entityEdit",
@@ -3898,7 +4145,12 @@ describe("boot-validator", () => {
3898
4145
  // guaranteed "id" field, unlike entityList rows — an entity-target
3899
4146
  // there must name the field to read the id from.
3900
4147
  const feature = defineFeature("shop", (r) => {
3901
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4148
+ r.entity(
4149
+ "product",
4150
+ createEntity({
4151
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4152
+ }),
4153
+ );
3902
4154
  r.queryHandler("products", z.object({}), async () => ({ rows: [], nextCursor: null }), {
3903
4155
  access: { openToAll: true },
3904
4156
  });
@@ -3923,7 +4175,12 @@ describe("boot-validator", () => {
3923
4175
 
3924
4176
  test("projectionList rowAction entity-target with explicit entityId → kein Throw", () => {
3925
4177
  const feature = defineFeature("shop", (r) => {
3926
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4178
+ r.entity(
4179
+ "product",
4180
+ createEntity({
4181
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4182
+ }),
4183
+ );
3927
4184
  r.queryHandler("products", z.object({}), async () => ({ rows: [], nextCursor: null }), {
3928
4185
  access: { openToAll: true },
3929
4186
  });
@@ -3954,7 +4211,12 @@ describe("boot-validator", () => {
3954
4211
 
3955
4212
  test("projectionDetail action entity-target without explicit entityId → Throw", () => {
3956
4213
  const feature = defineFeature("shop", (r) => {
3957
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4214
+ r.entity(
4215
+ "product",
4216
+ createEntity({
4217
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4218
+ }),
4219
+ );
3958
4220
  r.screen({
3959
4221
  id: "order-detail",
3960
4222
  type: "projectionDetail",
@@ -4004,7 +4266,12 @@ describe("boot-validator", () => {
4004
4266
 
4005
4267
  test('entityEdit.actions drawer-target unknown → throw with actionLabel "action"', () => {
4006
4268
  const feature = defineFeature("shop", (r) => {
4007
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4269
+ r.entity(
4270
+ "product",
4271
+ createEntity({
4272
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4273
+ }),
4274
+ );
4008
4275
  r.screen({
4009
4276
  id: "product-edit",
4010
4277
  type: "entityEdit",
@@ -4022,7 +4289,12 @@ describe("boot-validator", () => {
4022
4289
 
4023
4290
  test("entityEdit.actions drawer-target → registered actionForm → no throw", () => {
4024
4291
  const feature = defineFeature("shop", (r) => {
4025
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4292
+ r.entity(
4293
+ "product",
4294
+ createEntity({
4295
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4296
+ }),
4297
+ );
4026
4298
  r.writeHandler(
4027
4299
  "add-note",
4028
4300
  z.object({ note: z.string() }),
@@ -4187,7 +4459,12 @@ describe("boot-validator", () => {
4187
4459
  describe("entityList rowAction rowClick", () => {
4188
4460
  function makeFeature(rowClickCount: number) {
4189
4461
  return defineFeature("shop", (r) => {
4190
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4462
+ r.entity(
4463
+ "product",
4464
+ createEntity({
4465
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4466
+ }),
4467
+ );
4191
4468
  r.screen({ id: "product-editor", type: "custom", renderer: { react: "stub" } });
4192
4469
  r.screen({
4193
4470
  id: "product-list",
@@ -4220,7 +4497,12 @@ describe("boot-validator", () => {
4220
4497
  describe("entityList rowAction kind=writeHandler handler-QN", () => {
4221
4498
  function makeFeature(handlerQn: string, register: boolean) {
4222
4499
  return defineFeature("shop", (r) => {
4223
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4500
+ r.entity(
4501
+ "product",
4502
+ createEntity({
4503
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4504
+ }),
4505
+ );
4224
4506
  r.screen({
4225
4507
  id: "product-list",
4226
4508
  type: "entityList",
@@ -4261,7 +4543,12 @@ describe("boot-validator", () => {
4261
4543
  describe("entityList rowAction payload pick (Tier 2.7e-3)", () => {
4262
4544
  function makeFeature(pick: readonly string[]) {
4263
4545
  return defineFeature("shop", (r) => {
4264
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4546
+ r.entity(
4547
+ "product",
4548
+ createEntity({
4549
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4550
+ }),
4551
+ );
4265
4552
  r.screen({
4266
4553
  id: "product-list",
4267
4554
  type: "entityList",
@@ -4318,7 +4605,7 @@ describe("boot-validator", () => {
4318
4605
  r.entity(
4319
4606
  "product",
4320
4607
  createEntity({
4321
- fields: { name: createTextField() },
4608
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4322
4609
  softDelete: opts.softDelete ?? false,
4323
4610
  }),
4324
4611
  );
@@ -4394,7 +4681,12 @@ describe("boot-validator", () => {
4394
4681
  describe("entityList toolbarAction navigate (Tier 2.7e-2)", () => {
4395
4682
  function makeFeature(targetScreen: string, withTarget: boolean) {
4396
4683
  return defineFeature("shop", (r) => {
4397
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4684
+ r.entity(
4685
+ "product",
4686
+ createEntity({
4687
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4688
+ }),
4689
+ );
4398
4690
  r.screen({
4399
4691
  id: "product-list",
4400
4692
  type: "entityList",
@@ -4422,7 +4714,12 @@ describe("boot-validator", () => {
4422
4714
 
4423
4715
  test("navigate-target → screen in ANOTHER feature → kein Throw (cross-feature)", () => {
4424
4716
  const list = defineFeature("shop", (r) => {
4425
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4717
+ r.entity(
4718
+ "product",
4719
+ createEntity({
4720
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4721
+ }),
4722
+ );
4426
4723
  r.screen({
4427
4724
  id: "product-list",
4428
4725
  type: "entityList",
@@ -4443,7 +4740,12 @@ describe("boot-validator", () => {
4443
4740
  describe("entityList toolbarAction writeHandler handler-QN (Tier 2.7e-2)", () => {
4444
4741
  function makeFeature(handlerQn: string, register: boolean) {
4445
4742
  return defineFeature("shop", (r) => {
4446
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4743
+ r.entity(
4744
+ "product",
4745
+ createEntity({
4746
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4747
+ }),
4748
+ );
4447
4749
  r.screen({
4448
4750
  id: "product-list",
4449
4751
  type: "entityList",
@@ -4485,7 +4787,12 @@ describe("boot-validator", () => {
4485
4787
  }) {
4486
4788
  const targetId = opts.targetId ?? "restock-form";
4487
4789
  return defineFeature("shop", (r) => {
4488
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4790
+ r.entity(
4791
+ "product",
4792
+ createEntity({
4793
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4794
+ }),
4795
+ );
4489
4796
  r.screen({
4490
4797
  id: "product-list",
4491
4798
  type: "entityList",
@@ -4542,7 +4849,12 @@ describe("boot-validator", () => {
4542
4849
 
4543
4850
  test("drawer-target → actionForm in ANOTHER feature → throw (drawer resolves same-feature only)", () => {
4544
4851
  const list = defineFeature("shop", (r) => {
4545
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4852
+ r.entity(
4853
+ "product",
4854
+ createEntity({
4855
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4856
+ }),
4857
+ );
4546
4858
  r.screen({
4547
4859
  id: "product-list",
4548
4860
  type: "entityList",
@@ -4582,7 +4894,12 @@ describe("boot-validator", () => {
4582
4894
  }) {
4583
4895
  const targetId = opts.targetId ?? "restock-form";
4584
4896
  return defineFeature("shop", (r) => {
4585
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
4897
+ r.entity(
4898
+ "product",
4899
+ createEntity({
4900
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
4901
+ }),
4902
+ );
4586
4903
  r.screen({
4587
4904
  id: "product-list",
4588
4905
  type: "entityList",
@@ -4804,7 +5121,12 @@ describe("boot-validator", () => {
4804
5121
  test('screen.id mit "." → defineFeature throws (kebab-case)', () => {
4805
5122
  expect(() =>
4806
5123
  defineFeature("shop", (r) => {
4807
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5124
+ r.entity(
5125
+ "product",
5126
+ createEntity({
5127
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5128
+ }),
5129
+ );
4808
5130
  r.screen({
4809
5131
  id: "product.list",
4810
5132
  type: "entityList",
@@ -4817,7 +5139,12 @@ describe("boot-validator", () => {
4817
5139
 
4818
5140
  test("screen.id im kebab-case → kein Throw", () => {
4819
5141
  const feature = defineFeature("shop", (r) => {
4820
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5142
+ r.entity(
5143
+ "product",
5144
+ createEntity({
5145
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5146
+ }),
5147
+ );
4821
5148
  r.screen({ id: "product-list", type: "entityList", entity: "product", columns: ["name"] });
4822
5149
  });
4823
5150
  expect(() => validateBoot([feature])).not.toThrow();
@@ -4849,7 +5176,12 @@ describe("boot-validator — config key backing × scope", () => {
4849
5176
 
4850
5177
  test("navigate with params targeting a dashboard screen without a filter → Throw (params would be a no-op)", () => {
4851
5178
  const feature = defineFeature("shop", (r) => {
4852
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5179
+ r.entity(
5180
+ "product",
5181
+ createEntity({
5182
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5183
+ }),
5184
+ );
4853
5185
  r.screen({
4854
5186
  id: "product-list",
4855
5187
  type: "entityList",
@@ -4889,7 +5221,12 @@ describe("boot-validator — config key backing × scope", () => {
4889
5221
 
4890
5222
  test("navigate with params targeting a dashboard screen with a matching filter → no throw (useFilterParams reads it, fw#1708 follow-up)", () => {
4891
5223
  const feature = defineFeature("shop", (r) => {
4892
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5224
+ r.entity(
5225
+ "product",
5226
+ createEntity({
5227
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5228
+ }),
5229
+ );
4893
5230
  r.screen({
4894
5231
  id: "product-list",
4895
5232
  type: "entityList",
@@ -4933,7 +5270,12 @@ describe("boot-validator — config key backing × scope", () => {
4933
5270
 
4934
5271
  test("navigate with params targeting a dashboard screen whose filter id doesn't match any extracted key → Throw", () => {
4935
5272
  const feature = defineFeature("shop", (r) => {
4936
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5273
+ r.entity(
5274
+ "product",
5275
+ createEntity({
5276
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5277
+ }),
5278
+ );
4937
5279
  r.screen({
4938
5280
  id: "product-list",
4939
5281
  type: "entityList",
@@ -4979,8 +5321,18 @@ describe("boot-validator — config key backing × scope", () => {
4979
5321
 
4980
5322
  test("navigate with params targeting a cross-entity entityList screen → no throw (list screens read URL search params for filter-prefill, fw#1708)", () => {
4981
5323
  const feature = defineFeature("housing", (r) => {
4982
- r.entity("unit", createEntity({ fields: { id: createTextField() } }));
4983
- r.entity("contract", createEntity({ fields: { unitId: createTextField() } }));
5324
+ r.entity(
5325
+ "unit",
5326
+ createEntity({
5327
+ fields: { id: createTextField({ personal: false, reason: "test_fixture" }) },
5328
+ }),
5329
+ );
5330
+ r.entity(
5331
+ "contract",
5332
+ createEntity({
5333
+ fields: { unitId: createTextField({ personal: false, reason: "test_fixture" }) },
5334
+ }),
5335
+ );
4984
5336
  r.screen({
4985
5337
  id: "unit-list",
4986
5338
  type: "entityList",
@@ -5008,7 +5360,12 @@ describe("boot-validator — config key backing × scope", () => {
5008
5360
 
5009
5361
  test("navigate with params targeting a custom screen → no throw (author owns the component, may read searchParams itself)", () => {
5010
5362
  const feature = defineFeature("shop", (r) => {
5011
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5363
+ r.entity(
5364
+ "product",
5365
+ createEntity({
5366
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5367
+ }),
5368
+ );
5012
5369
  r.screen({
5013
5370
  id: "product-list",
5014
5371
  type: "entityList",
@@ -5038,7 +5395,12 @@ describe("boot-validator — config key backing × scope", () => {
5038
5395
  // runNavigate() auto-fills row["id"], landing in EntityEditUpdateBody,
5039
5396
  // which never reads searchParams. Params would silently no-op.
5040
5397
  const feature = defineFeature("shop", (r) => {
5041
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5398
+ r.entity(
5399
+ "product",
5400
+ createEntity({
5401
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5402
+ }),
5403
+ );
5042
5404
  r.screen({
5043
5405
  id: "product-list",
5044
5406
  type: "entityList",
@@ -5068,8 +5430,18 @@ describe("boot-validator — config key backing × scope", () => {
5068
5430
 
5069
5431
  test("navigate with params + explicit entityId targeting an entityEdit screen → Throw (forced update mode)", () => {
5070
5432
  const feature = defineFeature("housing", (r) => {
5071
- r.entity("unit", createEntity({ fields: { name: createTextField() } }));
5072
- r.entity("contract", createEntity({ fields: { unitId: createTextField() } }));
5433
+ r.entity(
5434
+ "unit",
5435
+ createEntity({
5436
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5437
+ }),
5438
+ );
5439
+ r.entity(
5440
+ "contract",
5441
+ createEntity({
5442
+ fields: { unitId: createTextField({ personal: false, reason: "test_fixture" }) },
5443
+ }),
5444
+ );
5073
5445
  r.screen({
5074
5446
  id: "unit-list",
5075
5447
  type: "entityList",
@@ -5102,7 +5474,12 @@ describe("boot-validator — config key backing × scope", () => {
5102
5474
  // extended to projectionList rowActions (#1680 covered entityList only).
5103
5475
  test("projectionList rowAction: navigate with params to an entityEdit target + explicit entityId → Throw", () => {
5104
5476
  const feature = defineFeature("shop", (r) => {
5105
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5477
+ r.entity(
5478
+ "product",
5479
+ createEntity({
5480
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5481
+ }),
5482
+ );
5106
5483
  r.screen({
5107
5484
  id: "product-projection",
5108
5485
  type: "projectionList",
@@ -5133,7 +5510,12 @@ describe("boot-validator — config key backing × scope", () => {
5133
5510
 
5134
5511
  test("projectionList rowAction: navigate with params to an entityEdit-create target (no entityId) → no throw", () => {
5135
5512
  const feature = defineFeature("shop", (r) => {
5136
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5513
+ r.entity(
5514
+ "product",
5515
+ createEntity({
5516
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5517
+ }),
5518
+ );
5137
5519
  r.queryHandler("products", z.object({}), async () => ({ rows: [], nextCursor: null }), {
5138
5520
  access: { openToAll: true },
5139
5521
  });
@@ -5168,8 +5550,18 @@ describe("boot-validator — config key backing × scope", () => {
5168
5550
  // renderer's same-entity row["id"] fallback does NOT fire, so this stays
5169
5551
  // in create mode and EntityEditCreateBody reads the params.
5170
5552
  const feature = defineFeature("housing", (r) => {
5171
- r.entity("unit", createEntity({ fields: { name: createTextField() } }));
5172
- r.entity("contract", createEntity({ fields: { unitId: createTextField() } }));
5553
+ r.entity(
5554
+ "unit",
5555
+ createEntity({
5556
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5557
+ }),
5558
+ );
5559
+ r.entity(
5560
+ "contract",
5561
+ createEntity({
5562
+ fields: { unitId: createTextField({ personal: false, reason: "test_fixture" }) },
5563
+ }),
5564
+ );
5173
5565
  r.screen({
5174
5566
  id: "unit-list",
5175
5567
  type: "entityList",
@@ -5197,7 +5589,12 @@ describe("boot-validator — config key backing × scope", () => {
5197
5589
 
5198
5590
  test("navigate with params targeting an actionForm screen → no throw", () => {
5199
5591
  const feature = defineFeature("shop", (r) => {
5200
- r.entity("product", createEntity({ fields: { name: createTextField() } }));
5592
+ r.entity(
5593
+ "product",
5594
+ createEntity({
5595
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5596
+ }),
5597
+ );
5201
5598
  r.writeHandler(
5202
5599
  "create",
5203
5600
  z.object({ name: z.string() }),
@@ -5223,7 +5620,7 @@ describe("boot-validator — config key backing × scope", () => {
5223
5620
  id: "product-form",
5224
5621
  type: "actionForm",
5225
5622
  handler: "shop:write:create",
5226
- fields: { name: createTextField() },
5623
+ fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
5227
5624
  layout: { sections: [{ columns: 1, fields: ["name"] }] },
5228
5625
  });
5229
5626
  });