@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.
- package/package.json +3 -3
- package/src/__tests__/anonymous-access.integration.test.ts +3 -3
- package/src/__tests__/derived-fields.integration.test.ts +1 -1
- package/src/__tests__/entity-list-limits.integration.test.ts +1 -1
- package/src/__tests__/error-contract.integration.test.ts +1 -1
- package/src/__tests__/ownership-where-write-path.integration.test.ts +1 -1
- package/src/__tests__/ownership.integration.test.ts +7 -3
- package/src/__tests__/schema-cli-rebuild.integration.test.ts +2 -2
- package/src/__tests__/transition-guard.integration.test.ts +3 -3
- package/src/api/__tests__/api.test.ts +21 -3
- package/src/api/__tests__/batch.integration.test.ts +3 -3
- package/src/api/__tests__/body-limit.test.ts +7 -1
- package/src/api/__tests__/dispatcher-live.integration.test.ts +1 -1
- package/src/api/__tests__/http-route-rate-limit.integration.test.ts +7 -1
- package/src/api/__tests__/metrics-endpoint.test.ts +7 -1
- package/src/api/__tests__/nested-write.integration.test.ts +3 -3
- package/src/api/__tests__/server-boot-guards.test.ts +11 -4
- package/src/bun-db/__tests__/write-brand.test.ts +4 -1
- package/src/db/__tests__/apply-entity-event-tenant.integration.test.ts +1 -1
- package/src/db/__tests__/assert-exists-in.integration.test.ts +1 -1
- package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +2 -2
- package/src/db/__tests__/collect-table-metas.test.ts +9 -5
- package/src/db/__tests__/compound-types.test.ts +1 -1
- package/src/db/__tests__/config-seed.integration.test.ts +3 -3
- package/src/db/__tests__/eagerload.integration.test.ts +7 -7
- package/src/db/__tests__/entity-table-from-registry.test.ts +8 -2
- package/src/db/__tests__/entity-table-meta-source.test.ts +7 -3
- package/src/db/__tests__/entity-table-types.test.ts +4 -4
- package/src/db/__tests__/event-store-executor-list.integration.test.ts +9 -2
- package/src/db/__tests__/event-store-executor-reference-search.integration.test.ts +4 -4
- package/src/db/__tests__/event-store-executor-reference-sort.integration.test.ts +3 -3
- package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +4 -4
- package/src/db/__tests__/event-store-executor.integration.test.ts +11 -6
- package/src/db/__tests__/event-store-system-stream.integration.test.ts +2 -2
- package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +6 -4
- package/src/db/__tests__/located-timestamp.test.ts +1 -1
- package/src/db/__tests__/money.test.ts +1 -1
- package/src/db/__tests__/multi-row-insert.integration.test.ts +3 -3
- package/src/db/__tests__/parent-ref-clause.test.ts +213 -0
- package/src/db/__tests__/schema-migration.integration.test.ts +30 -14
- package/src/db/__tests__/source-shadow-create.integration.test.ts +1 -1
- package/src/db/__tests__/table-builder-indexes.test.ts +14 -12
- package/src/db/__tests__/table-builder-required.test.ts +2 -2
- package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
- package/src/db/__tests__/tenant-db-where-merge.test.ts +5 -2
- package/src/db/__tests__/tenant-db.integration.test.ts +2 -2
- package/src/db/__tests__/unique-violation-mapping.integration.test.ts +2 -2
- package/src/db/event-store-executor-read.ts +97 -19
- package/src/db/parent-ref-clause.ts +182 -0
- package/src/db/table-builder.ts +7 -0
- package/src/engine/__tests__/boot-validator-action-wiring.test.ts +50 -8
- package/src/engine/__tests__/boot-validator-detail-for.test.ts +28 -4
- package/src/engine/__tests__/boot-validator-entity-list.test.ts +20 -4
- package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +9 -3
- package/src/engine/__tests__/boot-validator.test.ts +716 -91
- package/src/engine/__tests__/define-feature-entity-mapping.test.ts +2 -2
- package/src/engine/__tests__/engine.test.ts +128 -37
- package/src/engine/__tests__/entity-handlers.test.ts +3 -3
- package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +4 -4
- package/src/engine/__tests__/entity-restore-tenant-isolation.integration.test.ts +1 -1
- package/src/engine/__tests__/entity-write-crosstenant.integration.test.ts +1 -1
- package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
- package/src/engine/__tests__/extends-registrar.test.ts +13 -3
- package/src/engine/__tests__/factories-long-text.test.ts +10 -6
- package/src/engine/__tests__/feature-crud-shorthand.test.ts +1 -1
- package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +1 -1
- package/src/engine/__tests__/multiselect-filter.integration.test.ts +1 -1
- package/src/engine/__tests__/nav.test.ts +1 -1
- package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
- package/src/engine/__tests__/projection-detail-actions.test.ts +6 -1
- package/src/engine/__tests__/projection-detail-singleton.test.ts +6 -1
- package/src/engine/__tests__/projection-detail-tabs.test.ts +6 -1
- package/src/engine/__tests__/projection-list-filter.integration.test.ts +7 -2
- package/src/engine/__tests__/projection.test.ts +1 -1
- package/src/engine/__tests__/registry.test.ts +13 -3
- package/src/engine/__tests__/schema-builder.test.ts +39 -11
- package/src/engine/__tests__/screen.test.ts +21 -15
- package/src/engine/__tests__/search-payload-extension.test.ts +15 -3
- package/src/engine/__tests__/store-table.test.ts +6 -3
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +12 -4
- package/src/engine/__tests__/validation-hooks.test.ts +7 -1
- package/src/engine/boot-validator/__tests__/ownership.test.ts +2 -2
- package/src/engine/boot-validator/__tests__/parent-ref.test.ts +149 -0
- package/src/engine/boot-validator/action-wiring.ts +7 -7
- package/src/engine/boot-validator/index.ts +2 -0
- package/src/engine/boot-validator/parent-ref.ts +96 -0
- package/src/engine/boot-validator/projection-list-screens.ts +36 -23
- package/src/engine/boot-validator/query-output-columns.ts +2 -1
- package/src/engine/boot-validator/query-refs.ts +2 -1
- package/src/engine/boot-validator/screens.ts +322 -131
- package/src/engine/build-config-feature-schema.ts +2 -2
- package/src/engine/define-handler.ts +6 -0
- package/src/engine/entity-handlers.ts +6 -1
- package/src/engine/factories.ts +2 -0
- package/src/engine/feature-entity-handlers.ts +5 -0
- package/src/engine/index.ts +6 -0
- package/src/engine/ownership.ts +15 -0
- package/src/engine/pattern-library/mixed-schemas.ts +1 -0
- package/src/engine/screen-helpers.ts +25 -0
- package/src/engine/types/index.ts +5 -0
- package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
- package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
- package/src/files/__tests__/file-field-pipeline.integration.test.ts +1 -1
- package/src/files/__tests__/files.integration.test.ts +1 -1
- package/src/files/file-ref-entity.ts +9 -9
- package/src/i18n/__tests__/i18n.test.ts +7 -1
- package/src/i18n/required-surface-keys.ts +48 -0
- package/src/migrations/__tests__/kumiko-drift.integration.test.ts +3 -1
- package/src/migrations/__tests__/pending-rebuilds.integration.test.ts +2 -2
- package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
- package/src/pipeline/__tests__/cascade-handler.integration.test.ts +23 -8
- package/src/pipeline/__tests__/cascade-handler.test.ts +18 -3
- package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +5 -3
- package/src/pipeline/__tests__/dispatcher.test.ts +42 -6
- package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +2 -2
- package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +42 -6
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +2 -2
- package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
- package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +6 -2
- package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +6 -2
- package/src/pipeline/__tests__/perf-rebuild.integration.test.ts +1 -1
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
- package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +3 -3
- package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
- package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +2 -2
- package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +13 -2
- package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
- package/src/search/__tests__/reindex-entity.integration.test.ts +6 -1
- package/src/search/__tests__/search-pii-derived-index.integration.test.ts +7 -1
- package/src/stack/__tests__/ownership-boot-guard.integration.test.ts +1 -1
- package/src/testing/__tests__/e2e-generator.test.ts +15 -5
- package/src/testing/e2e-generator.ts +2 -0
- package/src/testing/shared-entities.ts +4 -2
- 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.
|
|
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.
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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({
|
|
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: {
|
|
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: {
|
|
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({
|
|
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({
|
|
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: {
|
|
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: {
|
|
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({
|
|
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: {
|
|
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");
|