@cosmicdrift/kumiko-bundled-features 0.1.0 → 0.2.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 (48) hide show
  1. package/LICENSE +57 -0
  2. package/package.json +3 -3
  3. package/src/audit/__tests__/audit.integration.ts +2 -2
  4. package/src/auth-email-password/__tests__/account-lockout-no-redis.integration.ts +5 -5
  5. package/src/auth-email-password/__tests__/account-lockout.integration.ts +5 -5
  6. package/src/auth-email-password/__tests__/auth-claims.integration.ts +14 -14
  7. package/src/auth-email-password/__tests__/auth.integration.ts +8 -8
  8. package/src/auth-email-password/__tests__/email-verification.integration.ts +5 -5
  9. package/src/auth-email-password/__tests__/identity-v3-login.integration.ts +5 -5
  10. package/src/auth-email-password/__tests__/invite-flow.integration.ts +6 -6
  11. package/src/auth-email-password/__tests__/multi-roles.integration.ts +5 -5
  12. package/src/auth-email-password/__tests__/password-reset.integration.ts +5 -5
  13. package/src/auth-email-password/__tests__/public-routes-rate-limit.integration.ts +5 -5
  14. package/src/auth-email-password/__tests__/seed-admin.integration.ts +5 -5
  15. package/src/auth-email-password/__tests__/session-callbacks.integration.ts +5 -5
  16. package/src/auth-email-password/__tests__/signup-flow.integration.ts +6 -6
  17. package/src/cap-counter/__tests__/cap-counter.integration.ts +2 -2
  18. package/src/cap-counter/__tests__/with-cap-enforcement.integration.ts +2 -2
  19. package/src/config/__tests__/config.integration.ts +2 -2
  20. package/src/delivery/__tests__/delivery-events.integration.ts +4 -4
  21. package/src/delivery/__tests__/delivery.integration.ts +4 -4
  22. package/src/feature-toggles/__tests__/feature-toggles.integration.ts +5 -5
  23. package/src/feature-toggles/__tests__/registered-system-tenant.test.ts +84 -0
  24. package/src/feature-toggles/handlers/registered.query.ts +7 -2
  25. package/src/file-foundation/__tests__/file-foundation.integration.ts +4 -4
  26. package/src/jobs/__tests__/job-system-user.integration.ts +3 -3
  27. package/src/jobs/__tests__/jobs-events.integration.ts +2 -2
  28. package/src/jobs/__tests__/jobs-feature.integration.ts +3 -3
  29. package/src/legal-pages/__tests__/legal-pages.integration.ts +3 -3
  30. package/src/mail-foundation/__tests__/mail-foundation.integration.ts +4 -4
  31. package/src/secrets/__tests__/rotate.integration.ts +2 -2
  32. package/src/secrets/__tests__/secrets-events.integration.ts +2 -2
  33. package/src/secrets/__tests__/secrets.integration.ts +2 -2
  34. package/src/sessions/__tests__/cleanup.integration.ts +2 -2
  35. package/src/sessions/__tests__/password-auto-revoke.integration.ts +6 -6
  36. package/src/sessions/__tests__/sessions.integration.ts +6 -6
  37. package/src/tenant/__tests__/multi-tenant.integration.ts +4 -4
  38. package/src/tenant/__tests__/seed-testing.integration.ts +4 -4
  39. package/src/tenant/__tests__/tenant.integration.ts +4 -4
  40. package/src/tenant/seeding.ts +12 -1
  41. package/src/text-content/README.md +6 -2
  42. package/src/text-content/__tests__/text-content.integration.ts +2 -2
  43. package/src/tier-engine/__tests__/resolver.integration.ts +183 -0
  44. package/src/tier-engine/__tests__/tier-engine.integration.ts +5 -5
  45. package/src/tier-engine/feature.ts +345 -48
  46. package/src/tier-engine/index.ts +5 -1
  47. package/src/user/__tests__/seed-testing.integration.ts +4 -4
  48. package/src/user/__tests__/user.integration.ts +2 -2
package/LICENSE ADDED
@@ -0,0 +1,57 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: Marc Frost
6
+
7
+ Licensed Work: @cosmicdrift/kumiko-framework
8
+ The Licensed Work is © 2026 Marc Frost.
9
+
10
+ Additional Use Grant:
11
+ You may use the Licensed Work in production for any purpose, including
12
+ commercially, EXCEPT for the Restricted Use.
13
+
14
+ "Restricted Use" is defined as using the Licensed Work to provide a platform
15
+ or service to third parties that allows them to host, deploy, or run their
16
+ own applications built with the Licensed Work. This includes, but is not
17
+ limited to: managed hosting services, software-as-a-service (SaaS) platforms,
18
+ platform-as-a-service (PaaS), developer platforms, or any multi-tenant
19
+ managed offering of the Licensed Work.
20
+
21
+ This restriction does not apply to the Licensor, any entity controlled by,
22
+ controlling, or under common control with the Licensor ("Affiliates"), or
23
+ contractors acting on their behalf. The Licensor remains free to use the
24
+ Licensed Work for any purpose, including for the operation of kumiko.so.
25
+
26
+ Change Date: 2030-05-05
27
+ Change License: Apache License, Version 2.0
28
+
29
+
30
+ Terms
31
+
32
+ The Licensor hereby grants you the right to copy, modify, create derivative works,
33
+ redistribute, and make non-production use of the Licensed Work. The Licensor may
34
+ make an Additional Use Grant, above, permitting limited production use.
35
+
36
+ Effective on the Change Date, or the fourth anniversary of the first publicly
37
+ available distribution of the Licensed Work under this License, whichever comes
38
+ first, this License will convert to the Change License.
39
+
40
+ This Business Source License governs use of the Licensed Work in all cases, except
41
+ as to any use that is explicitly granted in the Additional Use Grant above or
42
+ under the Change License after the Change Date.
43
+
44
+ If your use of the Licensed Work does not comply with the requirements of this
45
+ License, you must cease use of the Licensed Work immediately.
46
+
47
+ All copies of the Licensed Work, and all derivative works thereof, must include
48
+ this License.
49
+
50
+ This License does not grant you any right, title, or interest in any trademark,
51
+ logo, or branding of the Licensor, except as required to comply with this License.
52
+
53
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN
54
+ “AS IS” BASIS. LICENSOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
55
+ WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
56
+ TITLE, AND NON-INFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY DAMAGES
57
+ ARISING OUT OF OR RELATED TO THIS LICENSE OR THE USE OF THE LICENSED WORK.
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-bundled-features",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/cosmicdriftgamestudio/kumiko-framework.git",
9
+ "url": "git+https://github.com/CosmicDriftGameStudio/kumiko-framework.git",
10
10
  "directory": "packages/bundled-features"
11
11
  },
12
12
  "bugs": {
13
- "url": "https://github.com/cosmicdriftgamestudio/kumiko-framework/issues"
13
+ "url": "https://github.com/CosmicDriftGameStudio/kumiko-framework/issues"
14
14
  },
15
15
  "homepage": "https://kumiko.so",
16
16
  "type": "module",
@@ -10,13 +10,13 @@ import {
10
10
  type SessionUser,
11
11
  } from "@cosmicdrift/kumiko-framework/engine";
12
12
  import {
13
- createEntityTable,
14
13
  createTestUser,
15
14
  resetEventStore,
16
15
  setupTestStack,
17
16
  type TestStack,
18
17
  TestUsers,
19
18
  testTenantId,
19
+ unsafeCreateEntityTable,
20
20
  } from "@cosmicdrift/kumiko-framework/stack";
21
21
  import { sql } from "drizzle-orm";
22
22
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -60,7 +60,7 @@ beforeAll(async () => {
60
60
  stack = await setupTestStack({
61
61
  features: [widgetFeature, createAuditFeature()],
62
62
  });
63
- await createEntityTable(stack.db, widgetEntity);
63
+ await unsafeCreateEntityTable(stack.db, widgetEntity);
64
64
  });
65
65
 
66
66
  afterAll(async () => {
@@ -14,11 +14,11 @@ import { randomBytes } from "node:crypto";
14
14
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
15
15
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
16
16
  import {
17
- createEntityTable,
18
- pushTables,
19
17
  setupTestStack,
20
18
  type TestStack,
21
19
  TestUsers,
20
+ unsafeCreateEntityTable,
21
+ unsafePushTables,
22
22
  } from "@cosmicdrift/kumiko-framework/stack";
23
23
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
24
24
  import { createConfigFeature } from "../../config";
@@ -74,9 +74,9 @@ beforeAll(async () => {
74
74
  },
75
75
  });
76
76
 
77
- await createEntityTable(stack.db, userEntity);
78
- await createEntityTable(stack.db, tenantEntity);
79
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
77
+ await unsafeCreateEntityTable(stack.db, userEntity);
78
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
79
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
80
80
  });
81
81
 
82
82
  afterAll(async () => {
@@ -13,11 +13,11 @@ import { randomBytes } from "node:crypto";
13
13
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
14
14
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
15
15
  import {
16
- createEntityTable,
17
- pushTables,
18
16
  setupTestStack,
19
17
  type TestStack,
20
18
  TestUsers,
19
+ unsafeCreateEntityTable,
20
+ unsafePushTables,
21
21
  } from "@cosmicdrift/kumiko-framework/stack";
22
22
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
23
23
  import { createConfigFeature } from "../../config";
@@ -74,9 +74,9 @@ beforeAll(async () => {
74
74
  },
75
75
  });
76
76
 
77
- await createEntityTable(stack.db, userEntity);
78
- await createEntityTable(stack.db, tenantEntity);
79
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
77
+ await unsafeCreateEntityTable(stack.db, userEntity);
78
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
79
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
80
80
  });
81
81
 
82
82
  afterAll(async () => {
@@ -3,12 +3,12 @@ import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
5
5
  import {
6
- createEntityTable,
7
- pushTables,
8
6
  setupTestStack,
9
7
  type TestStack,
10
8
  TestUsers,
11
9
  testTenantId,
10
+ unsafeCreateEntityTable,
11
+ unsafePushTables,
12
12
  } from "@cosmicdrift/kumiko-framework/stack";
13
13
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
14
14
  import { createConfigFeature } from "../../config";
@@ -91,9 +91,9 @@ beforeAll(async () => {
91
91
  },
92
92
  });
93
93
 
94
- await createEntityTable(stack.db, userEntity);
95
- await createEntityTable(stack.db, tenantEntity);
96
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
94
+ await unsafeCreateEntityTable(stack.db, userEntity);
95
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
96
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
97
97
  });
98
98
 
99
99
  afterAll(async () => {
@@ -294,9 +294,9 @@ describe("scenario 2.5: reserved separator + multi-feature isolation", () => {
294
294
  },
295
295
  });
296
296
  try {
297
- await createEntityTable(localStack.db, userEntity);
298
- await createEntityTable(localStack.db, tenantEntity);
299
- await pushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
297
+ await unsafeCreateEntityTable(localStack.db, userEntity);
298
+ await unsafeCreateEntityTable(localStack.db, tenantEntity);
299
+ await unsafePushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
300
300
 
301
301
  const hash = await hashPassword("pw-long-enough");
302
302
  const created = await localStack.http.writeOk<{ id: string }>(
@@ -386,9 +386,9 @@ describe("scenario 2.6: multi-feature drift warnings fire independently", () =>
386
386
  },
387
387
  });
388
388
  try {
389
- await createEntityTable(localStack.db, userEntity);
390
- await createEntityTable(localStack.db, tenantEntity);
391
- await pushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
389
+ await unsafeCreateEntityTable(localStack.db, userEntity);
390
+ await unsafeCreateEntityTable(localStack.db, tenantEntity);
391
+ await unsafePushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
392
392
 
393
393
  const hash = await hashPassword("pw-long-enough");
394
394
  const created = await localStack.http.writeOk<{ id: string }>(
@@ -472,9 +472,9 @@ describe("scenario 3: a broken claims hook does not break login", () => {
472
472
  },
473
473
  });
474
474
  try {
475
- await createEntityTable(localStack.db, userEntity);
476
- await createEntityTable(localStack.db, tenantEntity);
477
- await pushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
475
+ await unsafeCreateEntityTable(localStack.db, userEntity);
476
+ await unsafeCreateEntityTable(localStack.db, tenantEntity);
477
+ await unsafePushTables(localStack.db, { configValuesTable, tenantMembershipsTable });
478
478
 
479
479
  const hash = await hashPassword("pw-long-enough");
480
480
  const created = await localStack.http.writeOk<{ id: string }>(
@@ -2,13 +2,13 @@ import { randomBytes } from "node:crypto";
2
2
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import {
5
- createEntityTable,
6
5
  createTestUser,
7
- pushTables,
8
6
  setupTestStack,
9
7
  type TestStack,
10
8
  TestUsers,
11
9
  testTenantId,
10
+ unsafeCreateEntityTable,
11
+ unsafePushTables,
12
12
  } from "@cosmicdrift/kumiko-framework/stack";
13
13
  import {
14
14
  expectErrorIncludes,
@@ -57,9 +57,9 @@ beforeAll(async () => {
57
57
  },
58
58
  });
59
59
 
60
- await createEntityTable(stack.db, userEntity);
61
- await createEntityTable(stack.db, tenantEntity);
62
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
60
+ await unsafeCreateEntityTable(stack.db, userEntity);
61
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
62
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
63
63
  });
64
64
 
65
65
  afterAll(async () => {
@@ -359,9 +359,9 @@ describe("scenario 7b: login rate limiting", () => {
359
359
  loginRateLimit: createInMemoryLoginRateLimiter(3, 60_000),
360
360
  },
361
361
  });
362
- await createEntityTable(rlStack.db, userEntity);
363
- await createEntityTable(rlStack.db, tenantEntity);
364
- await pushTables(rlStack.db, { configValuesTable, tenantMembershipsTable });
362
+ await unsafeCreateEntityTable(rlStack.db, userEntity);
363
+ await unsafeCreateEntityTable(rlStack.db, tenantEntity);
364
+ await unsafePushTables(rlStack.db, { configValuesTable, tenantMembershipsTable });
365
365
 
366
366
  // Seed one real user
367
367
  const hash = await hashPassword("right-password");
@@ -2,11 +2,11 @@ import { randomBytes } from "node:crypto";
2
2
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import {
5
- createEntityTable,
6
- pushTables,
7
5
  setupTestStack,
8
6
  type TestStack,
9
7
  TestUsers,
8
+ unsafeCreateEntityTable,
9
+ unsafePushTables,
10
10
  } from "@cosmicdrift/kumiko-framework/stack";
11
11
  import { eq } from "drizzle-orm";
12
12
  import { Temporal } from "temporal-polyfill";
@@ -84,9 +84,9 @@ beforeAll(async () => {
84
84
  },
85
85
  });
86
86
 
87
- await createEntityTable(stack.db, userEntity);
88
- await createEntityTable(stack.db, tenantEntity);
89
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
87
+ await unsafeCreateEntityTable(stack.db, userEntity);
88
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
89
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
90
90
  });
91
91
 
92
92
  afterAll(async () => {
@@ -9,11 +9,11 @@ import { pbkdf2Sync, randomBytes } from "node:crypto";
9
9
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
10
10
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
11
11
  import {
12
- createEntityTable,
13
- pushTables,
14
12
  setupTestStack,
15
13
  type TestStack,
16
14
  TestUsers,
15
+ unsafeCreateEntityTable,
16
+ unsafePushTables,
17
17
  } from "@cosmicdrift/kumiko-framework/stack";
18
18
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
19
19
  import { createConfigFeature } from "../../config";
@@ -69,9 +69,9 @@ beforeAll(async () => {
69
69
  },
70
70
  });
71
71
 
72
- await createEntityTable(stack.db, userEntity);
73
- await createEntityTable(stack.db, tenantEntity);
74
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
72
+ await unsafeCreateEntityTable(stack.db, userEntity);
73
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
74
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
75
75
  });
76
76
 
77
77
  afterAll(async () => {
@@ -21,10 +21,10 @@ import {
21
21
  type TenantId,
22
22
  } from "@cosmicdrift/kumiko-framework/engine";
23
23
  import {
24
- createEntityTable,
25
- pushTables,
26
24
  setupTestStack,
27
25
  type TestStack,
26
+ unsafeCreateEntityTable,
27
+ unsafePushTables,
28
28
  } from "@cosmicdrift/kumiko-framework/stack";
29
29
  import { eq } from "drizzle-orm";
30
30
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -103,10 +103,10 @@ beforeAll(async () => {
103
103
  },
104
104
  });
105
105
 
106
- await createEntityTable(stack.db, userEntity);
107
- await createEntityTable(stack.db, tenantEntity);
108
- await createEntityTable(stack.db, tenantInvitationEntity);
109
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
106
+ await unsafeCreateEntityTable(stack.db, userEntity);
107
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
108
+ await unsafeCreateEntityTable(stack.db, tenantInvitationEntity);
109
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
110
110
  });
111
111
 
112
112
  afterAll(async () => {
@@ -10,12 +10,12 @@
10
10
 
11
11
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
12
12
  import {
13
- createEntityTable,
14
- pushTables,
15
13
  setupTestStack,
16
14
  type TestStack,
17
15
  TestUsers,
18
16
  testTenantId,
17
+ unsafeCreateEntityTable,
18
+ unsafePushTables,
19
19
  } from "@cosmicdrift/kumiko-framework/stack";
20
20
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
21
21
  import { createConfigFeature } from "../../config";
@@ -61,9 +61,9 @@ beforeAll(async () => {
61
61
  },
62
62
  });
63
63
 
64
- await createEntityTable(stack.db, userEntity);
65
- await createEntityTable(stack.db, tenantEntity);
66
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
64
+ await unsafeCreateEntityTable(stack.db, userEntity);
65
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
66
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
67
67
  });
68
68
 
69
69
  afterAll(async () => {
@@ -2,11 +2,11 @@ import { randomBytes } from "node:crypto";
2
2
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import {
5
- createEntityTable,
6
- pushTables,
7
5
  setupTestStack,
8
6
  type TestStack,
9
7
  TestUsers,
8
+ unsafeCreateEntityTable,
9
+ unsafePushTables,
10
10
  } from "@cosmicdrift/kumiko-framework/stack";
11
11
  import { Temporal } from "temporal-polyfill";
12
12
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -79,9 +79,9 @@ beforeAll(async () => {
79
79
  },
80
80
  });
81
81
 
82
- await createEntityTable(stack.db, userEntity);
83
- await createEntityTable(stack.db, tenantEntity);
84
- await pushTables(stack.db, {
82
+ await unsafeCreateEntityTable(stack.db, userEntity);
83
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
84
+ await unsafePushTables(stack.db, {
85
85
  configValuesTable,
86
86
  tenantMembershipsTable,
87
87
  userSessionTable,
@@ -7,10 +7,10 @@
7
7
  import { randomBytes } from "node:crypto";
8
8
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
9
9
  import {
10
- createEntityTable,
11
- pushTables,
12
10
  setupTestStack,
13
11
  type TestStack,
12
+ unsafeCreateEntityTable,
13
+ unsafePushTables,
14
14
  } from "@cosmicdrift/kumiko-framework/stack";
15
15
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
16
16
  import { createConfigFeature } from "../../config";
@@ -67,9 +67,9 @@ beforeAll(async () => {
67
67
  },
68
68
  });
69
69
 
70
- await createEntityTable(stack.db, userEntity);
71
- await createEntityTable(stack.db, tenantEntity);
72
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
70
+ await unsafeCreateEntityTable(stack.db, userEntity);
71
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
72
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
73
73
  });
74
74
 
75
75
  afterAll(async () => {
@@ -13,10 +13,10 @@
13
13
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
14
14
  import { createEventsTable, eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
15
15
  import {
16
- createEntityTable,
17
- pushTables,
18
16
  setupTestStack,
19
17
  type TestStack,
18
+ unsafeCreateEntityTable,
19
+ unsafePushTables,
20
20
  } from "@cosmicdrift/kumiko-framework/stack";
21
21
  import { and, eq } from "drizzle-orm";
22
22
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -42,9 +42,9 @@ beforeAll(async () => {
42
42
  features: [createConfigFeature(), createUserFeature(), createTenantFeature()],
43
43
  extraContext: { configResolver: resolver },
44
44
  });
45
- await createEntityTable(stack.db, tenantEntity);
46
- await createEntityTable(stack.db, userEntity);
47
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
45
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
46
+ await unsafeCreateEntityTable(stack.db, userEntity);
47
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
48
48
  await createEventsTable(stack.db);
49
49
  });
50
50
 
@@ -2,11 +2,11 @@ import { randomBytes } from "node:crypto";
2
2
  import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import {
5
- createEntityTable,
6
- pushTables,
7
5
  setupTestStack,
8
6
  type TestStack,
9
7
  TestUsers,
8
+ unsafeCreateEntityTable,
9
+ unsafePushTables,
10
10
  } from "@cosmicdrift/kumiko-framework/stack";
11
11
  import * as jose from "jose";
12
12
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -116,9 +116,9 @@ beforeAll(async () => {
116
116
  },
117
117
  });
118
118
 
119
- await createEntityTable(stack.db, userEntity);
120
- await createEntityTable(stack.db, tenantEntity);
121
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
119
+ await unsafeCreateEntityTable(stack.db, userEntity);
120
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
121
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
122
122
  });
123
123
 
124
124
  afterAll(async () => {
@@ -25,10 +25,10 @@
25
25
  // zusammen).
26
26
 
27
27
  import {
28
- createEntityTable,
29
- pushTables,
30
28
  setupTestStack,
31
29
  type TestStack,
30
+ unsafeCreateEntityTable,
31
+ unsafePushTables,
32
32
  } from "@cosmicdrift/kumiko-framework/stack";
33
33
  import { eq } from "drizzle-orm";
34
34
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -77,12 +77,12 @@ beforeAll(async () => {
77
77
  },
78
78
  });
79
79
 
80
- await createEntityTable(stack.db, userEntity);
80
+ await unsafeCreateEntityTable(stack.db, userEntity);
81
81
  // tenant-entity hat den unique-constraint auf .key (siehe
82
- // tenant.schema.indexes). createEntityTable baut das via
82
+ // tenant.schema.indexes). unsafeCreateEntityTable baut das via
83
83
  // buildDrizzleTable nach — pinst den TOCTOU-Schutz für signup-confirm.
84
- await createEntityTable(stack.db, tenantEntity);
85
- await pushTables(stack.db, { configValuesTable, tenantMembershipsTable });
84
+ await unsafeCreateEntityTable(stack.db, tenantEntity);
85
+ await unsafePushTables(stack.db, { configValuesTable, tenantMembershipsTable });
86
86
  });
87
87
 
88
88
  afterAll(async () => {
@@ -10,12 +10,12 @@ import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
10
10
  import { defineFeature, type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
11
11
  import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
12
12
  import {
13
- createEntityTable,
14
13
  createTestUser,
15
14
  setupTestStack,
16
15
  type TestStack,
17
16
  TestUsers,
18
17
  testTenantId,
18
+ unsafeCreateEntityTable,
19
19
  } from "@cosmicdrift/kumiko-framework/stack";
20
20
  import { afterAll, beforeAll, describe, expect, test } from "vitest";
21
21
  import { z } from "zod";
@@ -180,7 +180,7 @@ beforeAll(async () => {
180
180
  });
181
181
  db = stack.db;
182
182
 
183
- await createEntityTable(db, capCounterEntity);
183
+ await unsafeCreateEntityTable(db, capCounterEntity);
184
184
  await createEventsTable(db);
185
185
  });
186
186
 
@@ -12,11 +12,11 @@ import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
12
12
  import { defineFeature, type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
13
13
  import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
14
14
  import {
15
- createEntityTable,
16
15
  createTestUser,
17
16
  setupTestStack,
18
17
  type TestStack,
19
18
  testTenantId,
19
+ unsafeCreateEntityTable,
20
20
  } from "@cosmicdrift/kumiko-framework/stack";
21
21
  import { afterAll, beforeAll, describe, expect, test } from "vitest";
22
22
  import { z } from "zod";
@@ -95,7 +95,7 @@ let db: DbConnection;
95
95
  beforeAll(async () => {
96
96
  stack = await setupTestStack({ features: [capCounterFeature, newsletterFeature] });
97
97
  db = stack.db;
98
- await createEntityTable(db, capCounterEntity);
98
+ await unsafeCreateEntityTable(db, capCounterEntity);
99
99
  await createEventsTable(db);
100
100
  });
101
101
 
@@ -10,10 +10,10 @@ import {
10
10
  import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
11
11
  import {
12
12
  createTestUser,
13
- pushTables,
14
13
  setupTestStack,
15
14
  type TestStack,
16
15
  TestUsers,
16
+ unsafePushTables,
17
17
  } from "@cosmicdrift/kumiko-framework/stack";
18
18
  import { expectErrorIncludes } from "@cosmicdrift/kumiko-framework/testing";
19
19
  import { eq } from "drizzle-orm";
@@ -199,7 +199,7 @@ beforeAll(async () => {
199
199
  });
200
200
  db = stack.db;
201
201
 
202
- await pushTables(db, { configValuesTable });
202
+ await unsafePushTables(db, { configValuesTable });
203
203
  // setupTestStack already calls createEventsTable + createArchivedStreamsTable
204
204
  // for us; nothing extra needed for the config-changed event-store writes.
205
205
  });
@@ -9,12 +9,12 @@
9
9
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
10
10
  import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
11
11
  import {
12
- createEntityTable,
13
12
  createTestUser,
14
- pushTables,
15
13
  setupTestStack,
16
14
  type TestStack,
17
15
  TestUsers,
16
+ unsafeCreateEntityTable,
17
+ unsafePushTables,
18
18
  } from "@cosmicdrift/kumiko-framework/stack";
19
19
  import { eq } from "drizzle-orm";
20
20
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -51,12 +51,12 @@ beforeAll(async () => {
51
51
  extraContext: { configResolver: createConfigResolver() },
52
52
  });
53
53
  db = stack.db;
54
- await createEntityTable(db, tenantEntity);
54
+ await unsafeCreateEntityTable(db, tenantEntity);
55
55
  // Events-table is auto-pushed by setupTestStack; we only need to add
56
56
  // the feature-specific projection + lookup tables here. notificationPre-
57
57
  // ferencesTable is explicit because delivery-service queries it on
58
58
  // every notify() — without it, notify() crashes before the event append.
59
- await pushTables(db, {
59
+ await unsafePushTables(db, {
60
60
  configValuesTable,
61
61
  tenantMembershipsTable,
62
62
  inAppMessagesTable,
@@ -10,10 +10,10 @@ import {
10
10
  } from "@cosmicdrift/kumiko-framework/engine";
11
11
  import {
12
12
  createTestUser,
13
- pushTables,
14
13
  setupTestStack,
15
14
  type TestStack,
16
15
  TestUsers,
16
+ unsafePushTables,
17
17
  } from "@cosmicdrift/kumiko-framework/stack";
18
18
  import { and, eq } from "drizzle-orm";
19
19
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
@@ -289,7 +289,7 @@ beforeAll(async () => {
289
289
  // deliveryAttemptsTable is auto-pushed by setupTestStack as MSP-projection-table;
290
290
  // notificationPreferencesTable is an ES-entity, so it still needs explicit
291
291
  // push here (entity-tables are not auto-provisioned — only projection ones).
292
- await pushTables(db, {
292
+ await unsafePushTables(db, {
293
293
  configValuesTable,
294
294
  tenantMembershipsTable,
295
295
  notificationPreferencesTable,
@@ -298,8 +298,8 @@ beforeAll(async () => {
298
298
  });
299
299
 
300
300
  // Create tenant entity table + seed memberships for tenant broadcast tests
301
- const { createEntityTable } = await import("@cosmicdrift/kumiko-framework/stack");
302
- await createEntityTable(db, tenantEntity, "tenant");
301
+ const { unsafeCreateEntityTable } = await import("@cosmicdrift/kumiko-framework/stack");
302
+ await unsafeCreateEntityTable(db, tenantEntity, "tenant");
303
303
 
304
304
  // Create tenant + members via real API
305
305
  await stack.http.writeOk(