@cosmicdrift/kumiko-dispatcher-live 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-dispatcher-live",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "HTTP-only Dispatcher for Kumiko UIs. Always-online; failures surface immediately. Default client for web admin/cockpit apps.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -24,7 +24,7 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@cosmicdrift/kumiko-headless": "0.13.0"
27
+ "@cosmicdrift/kumiko-headless": "0.14.0"
28
28
  },
29
29
  "publishConfig": {
30
30
  "registry": "https://registry.npmjs.org",
@@ -35,4 +35,4 @@
35
35
  "README.md",
36
36
  "LICENSE"
37
37
  ]
38
- }
38
+ }
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "vitest";
1
+ import { describe, expect, test } from "bun:test";
2
2
  import { CSRF_COOKIE_NAME, CSRF_HEADER_NAME, readCsrfToken } from "../csrf";
3
3
 
4
4
  describe("CSRF token extraction", () => {
@@ -1,4 +1,4 @@
1
- import { describe, expect, test, vi } from "vitest";
1
+ import { describe, expect, mock, test } from "bun:test";
2
2
  import { createLiveDispatcher } from "../dispatcher-live";
3
3
 
4
4
  // Builds a fake fetch that returns a JSON body with the given
@@ -9,7 +9,7 @@ function makeFetch(respond: { readonly status?: number; readonly body: unknown }
9
9
  readonly calls: Array<{ url: string; init: RequestInit }>;
10
10
  } {
11
11
  const calls: Array<{ url: string; init: RequestInit }> = [];
12
- const fetchMock = vi.fn(async (url: string, init: RequestInit) => {
12
+ const fetchMock = mock(async (url: string, init: RequestInit) => {
13
13
  calls.push({ url, init });
14
14
  return {
15
15
  ok: (respond.status ?? 200) < 400,
@@ -139,7 +139,7 @@ describe("createLiveDispatcher", () => {
139
139
  });
140
140
 
141
141
  test("network error → failure with code='network_error', status flips offline", async () => {
142
- const fetch = vi.fn(async () => {
142
+ const fetch = mock(async () => {
143
143
  throw new Error("ECONNREFUSED");
144
144
  }) as unknown as typeof globalThis.fetch;
145
145
  const disp = createLiveDispatcher({ fetch, readCsrf: () => "t" });
@@ -157,7 +157,7 @@ describe("createLiveDispatcher", () => {
157
157
 
158
158
  test("network recovery: after offline → successful call flips back to online", async () => {
159
159
  let failNext = true;
160
- const fetch = vi.fn(async () => {
160
+ const fetch = mock(async () => {
161
161
  if (failNext) {
162
162
  failNext = false;
163
163
  throw new Error("boom");
@@ -184,7 +184,7 @@ describe("createLiveDispatcher", () => {
184
184
 
185
185
  test("abort signal: request propagated + AbortError mapped to 'aborted'", async () => {
186
186
  const controller = new AbortController();
187
- const fetch = vi.fn(async (_url: string, init: RequestInit) => {
187
+ const fetch = mock(async (_url: string, init: RequestInit) => {
188
188
  // Simulate real fetch: throw AbortError synchronously when signal
189
189
  // is already aborted.
190
190
  if (init.signal?.aborted) {
@@ -214,7 +214,7 @@ describe("createLiveDispatcher", () => {
214
214
  });
215
215
 
216
216
  test("non-JSON server response (HTML 502 page) maps to network_error", async () => {
217
- const fetch = vi.fn(async () => {
217
+ const fetch = mock(async () => {
218
218
  return {
219
219
  ok: false,
220
220
  status: 502,
@@ -254,18 +254,18 @@ describe("createLiveDispatcher", () => {
254
254
  });
255
255
 
256
256
  test("pendingWrites / pendingFiles always return empty arrays for live dispatcher", () => {
257
- const disp = createLiveDispatcher({ fetch: vi.fn() as unknown as typeof globalThis.fetch });
257
+ const disp = createLiveDispatcher({ fetch: mock() as unknown as typeof globalThis.fetch });
258
258
  expect(disp.pendingWrites()).toEqual([]);
259
259
  expect(disp.pendingFiles()).toEqual([]);
260
260
  });
261
261
 
262
262
  test("subscribeStatus returns unsubscribe handle", async () => {
263
- const fetch = vi.fn(async () => {
263
+ const fetch = mock(async () => {
264
264
  throw new Error("boom");
265
265
  }) as unknown as typeof globalThis.fetch;
266
266
  const disp = createLiveDispatcher({ fetch, readCsrf: () => "t" });
267
267
 
268
- const listener = vi.fn();
268
+ const listener = mock();
269
269
  const unsub = disp.statusStore.subscribe(listener);
270
270
  await disp.write("x", {});
271
271
  expect(listener).toHaveBeenCalledTimes(1);
@@ -274,7 +274,7 @@ describe("createLiveDispatcher", () => {
274
274
  // A second status change (back to online) should not fire listener.
275
275
  // But — if fetch keeps throwing we stay offline (no transition).
276
276
  // Force a flip back by resetting fetch to success:
277
- const fetchOk = vi.fn(async () => ({
277
+ const fetchOk = mock(async () => ({
278
278
  ok: true,
279
279
  status: 200,
280
280
  async json() {
@@ -1,4 +1,4 @@
1
- import { describe, expect, test, vi } from "vitest";
1
+ import { describe, expect, spyOn, test } from "bun:test";
2
2
  import { buildAbortError, buildNetworkError, mapServerError } from "../error-mapping";
3
3
 
4
4
  describe("mapServerError", () => {
@@ -80,7 +80,7 @@ describe("mapServerError", () => {
80
80
  // gleichzeitig prüfen: jeder der drei Malformed-Inputs muss genau
81
81
  // einen warn() ausgelöst haben. Das macht das "silence" im Test-
82
82
  // Output zur Assertion, nicht zu einem Sweep-under-the-rug.
83
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
83
+ const warnSpy = spyOn(console, "warn").mockImplementation(() => {});
84
84
  try {
85
85
  const mapped = mapServerError({
86
86
  code: "validation_error",
package/CHANGELOG.md DELETED
@@ -1,429 +0,0 @@
1
- # @cosmicdrift/kumiko-dispatcher-live
2
-
3
- ## 0.13.0
4
-
5
- ### Patch Changes
6
-
7
- - @cosmicdrift/kumiko-headless@0.13.0
8
-
9
- ## 0.12.2
10
-
11
- ### Patch Changes
12
-
13
- - @cosmicdrift/kumiko-headless@0.12.2
14
-
15
- ## 0.12.1
16
-
17
- ### Patch Changes
18
-
19
- - @cosmicdrift/kumiko-headless@0.12.1
20
-
21
- ## 0.12.0
22
-
23
- ### Patch Changes
24
-
25
- - @cosmicdrift/kumiko-headless@0.12.0
26
-
27
- ## 0.11.2
28
-
29
- ### Patch Changes
30
-
31
- - @cosmicdrift/kumiko-headless@0.11.2
32
-
33
- ## 0.11.1
34
-
35
- ### Patch Changes
36
-
37
- - @cosmicdrift/kumiko-headless@0.11.1
38
-
39
- ## 0.11.0
40
-
41
- ### Patch Changes
42
-
43
- - @cosmicdrift/kumiko-headless@0.11.0
44
-
45
- ## 0.10.0
46
-
47
- ### Patch Changes
48
-
49
- - @cosmicdrift/kumiko-headless@0.10.0
50
-
51
- ## 0.9.0
52
-
53
- ### Patch Changes
54
-
55
- - @cosmicdrift/kumiko-headless@0.9.0
56
-
57
- ## 0.8.1
58
-
59
- ### Patch Changes
60
-
61
- - @cosmicdrift/kumiko-headless@0.8.1
62
-
63
- ## 0.8.0
64
-
65
- ### Patch Changes
66
-
67
- - @cosmicdrift/kumiko-headless@0.8.0
68
-
69
- ## 0.7.0
70
-
71
- ### Minor Changes
72
-
73
- - bcf43b6: es-ops: `SeedMembershipRow` exposes `streamTenantId` (stream-tenant aus `kumiko_events.v1`) neben dem payload-`tenantId`. Seed-Authors müssen den `kumiko_events`-JOIN nicht mehr selbst bauen — `m.streamTenantId` ist der korrekte Wert für `systemWriteAs`'s `tenantIdOverride` wenn das Aggregate von einem fremden Executor angelegt wurde (typisches `seedTenantMembership(by=systemAdmin)`-Pattern).
74
-
75
- ### Patch Changes
76
-
77
- - Updated dependencies [bcf43b6]
78
- - @cosmicdrift/kumiko-headless@0.7.0
79
-
80
- ## 0.6.0
81
-
82
- ### Minor Changes
83
-
84
- - 8489d18: feat(es-ops): Phase 1.5 — tenantIdOverride + dry-run-validator + E2E-Test + Doku
85
-
86
- Phase 1.5 schließt die Lücken aus Phase 1 die den ersten Driver-Use-Case
87
- (publicstatus admin-roles) blockten. Siehe Retro:
88
- `kumiko-platform/docs/plans/features/es-ops-phase1-retro.md` (PR #9).
89
-
90
- **A1 — tenantIdOverride:**
91
- `SeedMigrationContext.systemWriteAs(qn, payload, tenantIdOverride?)`.
92
- Default SYSTEM_TENANT_ID (unverändert für System-scope-Aggregates wie
93
- config-values). Mit override: `createSystemUser(tenantIdOverride)` als
94
- Executor, damit der Event-Store-Executor den Aggregate-Stream im
95
- richtigen Tenant findet. Fix für die `version_conflict`-Klasse-Bug
96
- (Memory `feedback_event_store_tenant_consistency.md`).
97
-
98
- **A2 — dry-run-validator:**
99
- Runner parsed seed-files vor `migration.run()` per regex
100
- `systemWriteAs\(["']([^"']+)["']`, sammelt handler-QNs, validiert
101
- gegen `registry.getWriteHandler(qn)`. Fail-fast mit klarer Message
102
-
103
- - Datei + QN statt zur Runtime "handler not found". Catched camelCase-
104
- typos (kebab-case-vs-camelCase Drift) + andere QN-Drift zur Boot-Zeit.
105
- runProdApp reicht den richtigen Registry rein (`registry` neu in
106
- RunPendingSeedMigrationsArgs).
107
-
108
- **A3 — E2E-Test:**
109
- `packages/bundled-features/src/__tests__/es-ops-e2e.integration.ts`
110
- mit `setupTestStack`-Pattern: tenant+config Features echt geladen,
111
- echtes Membership-Aggregate via TenantHandlers.addMember im Demo-Tenant,
112
- seed-migration ruft update-member-roles mit tenantIdOverride → write
113
- geht durch, Marker landed, Event in Store, Read-Model aktualisiert.
114
- Plus typo-Test: seed mit camelCase fail-t Dry-Run mit
115
- `/dry-run found.*unknown handler-QN/`. **TDD-First**: ohne A1+A2 wäre
116
- der test rot.
117
-
118
- **A4 — Doku:**
119
- `framework/src/es-ops/README.md` erweitert um „Wann brauche ich
120
- tenantIdOverride?" + „Deployment-Anforderungen" (Docker COPY, Idempotenz,
121
- Multi-Replica) + „Lokaler Smoke vor Push". Recipe-README + seed-files
122
- auf neue API aktualisiert.
123
-
124
- **A5 — Smoke-Skript-Template:**
125
- `samples/recipes/seed-migration/scripts/smoke.ts` als copy-paste-Template
126
- für App-Authors: Bun-runnable, offline (read-only, kein DB-Write),
127
- validiert Module-Load + QN-Resolution + System-User-Access. Recipe-
128
- README dokumentiert Pflicht-Pattern.
129
-
130
- **Bonus-Fix:**
131
- `tenant:write:create`-access auf `["system", "SystemAdmin"]` erweitert
132
- (symmetrisch zu update-member-roles). Aufgedeckt durch Recipe-Smoke +
133
- initial-tenants-Seed. Pinning-Test in `tenant.integration.ts` updated.
134
-
135
- **Test-State:** 45/45 grün (Pre-Push). Typecheck clean. Biome clean.
136
- as-cast-Audit clean. Guard-silent-skip clean. Recipe-Smoke clean.
137
-
138
- **Folge-Step (separater PR):** publicstatus driver-sample reaktivieren
139
- mit lokalem Pre-Push-Smoke gegen publicstatus' echtes Feature-Set.
140
-
141
- ### Patch Changes
142
-
143
- - Updated dependencies [8489d18]
144
- - @cosmicdrift/kumiko-headless@0.6.0
145
-
146
- ## 0.5.2
147
-
148
- ### Patch Changes
149
-
150
- - 4f0d781: fix(tenant): updateMemberRoles erlaubt "system"-Rolle (symmetrisch zu create)
151
-
152
- Drift innerhalb des tenant-Features: `tenant:write:create` akzeptierte
153
- `["system", "SystemAdmin"]`, `tenant:write:update-member-roles` aber
154
- nur `["SystemAdmin"]`. Konsequenz: ops-tooling und seed-migrations
155
- (`createSystemUser` mit `roles: ["system"]`) konnten den Handler nicht
156
- aufrufen — `access_denied`.
157
-
158
- Live entdeckt beim ersten Driver-Sample der es-ops Phase 1: publicstatus
159
- seed `2026-05-20-fix-admin-roles.ts` rief `update-member-roles` via
160
- `systemWriteAs` → access_denied → Pod CrashLoopBackOff.
161
-
162
- Plus access-rule-Pinning-Test in `tenant.integration.ts`-scenario-7.
163
-
164
- - Updated dependencies [4f0d781]
165
- - @cosmicdrift/kumiko-headless@0.5.2
166
-
167
- ## 0.5.1
168
-
169
- ### Patch Changes
170
-
171
- - 0e00015: fix(es-ops): path.resolve statt path.join für seedsDir → seed-files
172
-
173
- Bun's `await import()` braucht absolute Pfade. Wenn der App-Author
174
- `runProdApp({ seedsDir: "./seeds" })` setzt (relativ), würde
175
- `path.join("./seeds", "foo.ts")` einen relativen Pfad liefern → Bun's
176
- Import-Resolver such relativ zum `runner.ts`-Modul (nicht zum
177
- `process.cwd()`) → `Cannot find module 'seeds/...' from '<runner-path>'`.
178
-
179
- `path.resolve` löst gegen `process.cwd()` auf → absolute Pfade →
180
- Import funktioniert. Aufgedeckt beim ersten Live-Boot der publicstatus-
181
- Driver-Migration (Pod CrashLoopBackOff).
182
-
183
- - Updated dependencies [0e00015]
184
- - @cosmicdrift/kumiko-headless@0.5.1
185
-
186
- ## 0.5.0
187
-
188
- ### Minor Changes
189
-
190
- - 7ff69ab: feat(es-ops): Phase 1 — file-based seed-migrations
191
-
192
- Neues first-class Operations-Pattern fürs Framework. Liefert `seed-migrations`
193
- als drizzle-migrate-equivalent für Event-Sourcing-Aggregate-Updates die
194
- idempotent-Seeder nicht erfassen können (z.B. „Member hat schon eine
195
- Rolle, aber jetzt soll noch eine dazukommen").
196
-
197
- Public-API:
198
-
199
- - `runProdApp({ seedsDir })` — Auto-apply pending Migrations beim Boot
200
- - `SeedMigration`-Interface (default-Export einer `seeds/<id>.ts`-File)
201
- - `SeedMigrationContext` mit `systemWriteAs` (ruft existing write-handler
202
- als System-User) + Read-Helpers (`findUserByEmail`,
203
- `findMembershipsOfUser`, `findTenants`)
204
- - CLI: `bunx kumiko ops seed:new|status|apply`
205
- - Tracking-Table `kumiko_es_operations` mit `operation_type`-Discriminator
206
- (vorbereitet auf Phase 2+ Operations: projection-rebuild, event-replay,
207
- stream-migration, ...)
208
- - Env-Flags: `KUMIKO_SKIP_ES_OPS=1` (alle skippen für Recovery),
209
- `KUMIKO_SKIP_ES_OPS_<ID>=1` (einzelne kaputte skippen)
210
-
211
- Garantien: single-run via tracking, atomic via per-migration-Tx,
212
- chronological order via filename-prefix, fail-stop bei Failure (kein
213
- Partial-Apply), ES-konform via Handler-Dispatch.
214
-
215
- Sub-path-Export: `@cosmicdrift/kumiko-framework/es-ops`
216
-
217
- Plan-Doc: `kumiko-platform/docs/plans/features/es-ops.md`
218
- Recipe: `samples/recipes/seed-migration/`
219
- Driver-Use-Case: publicstatus admin-roles-drift (parallel-Branch
220
- `feat/es-ops-driver-admin-roles`).
221
-
222
- Phase 2+ skizziert + offen markiert — Implementation pro Use-Case.
223
-
224
- ### Patch Changes
225
-
226
- - Updated dependencies [7ff69ab]
227
- - @cosmicdrift/kumiko-headless@0.5.0
228
-
229
- ## 0.4.1
230
-
231
- ### Patch Changes
232
-
233
- - 010b410: feat(auth-email-password): "Bestätigungs-Mail erneut senden" im LoginScreen
234
-
235
- LoginScreen bietet bei reason=email_not_verified jetzt einen Resend-Link
236
- im Fehler-Banner — der existierende `requestEmailVerification`-Endpoint
237
- wird direkt aufgerufen, der Banner wechselt nach Erfolg zum Info-Variant
238
- ("Wir haben dir eine neue Bestätigungs-Mail geschickt.").
239
-
240
- UX-Details:
241
-
242
- - Bei 429 → inline-Hint "Bitte warte kurz und versuche es erneut."
243
- - Bei Netzwerk/sonstigen Fehlern → inline-Hint "Konnte nicht senden."
244
- - Anti-Typo-Gate: ändert der User die Email-Eingabe nach dem Login-Fail,
245
- verschwindet der Resend-Link — sonst würde Resend silent-success an die
246
- geänderte (potentiell typoed) Adresse gehen ohne User-Feedback.
247
- - Andere Failure-Codes (invalid_credentials etc.) zeigen weiterhin keinen
248
- Resend-Link.
249
-
250
- i18n: 4 neue Keys (DE+EN) im `auth.login.resend*`-Namespace, additive.
251
- Apps die ihre Translations override-en müssen nichts ändern.
252
-
253
- Additive UI-Feature — keine API-Breaks, keine Schema-Migration.
254
-
255
- - Updated dependencies [010b410]
256
- - @cosmicdrift/kumiko-headless@0.4.1
257
-
258
- ## 0.4.0
259
-
260
- ### Minor Changes
261
-
262
- - 825e7d2: Visual-Tree V.1.4 → V.1.6 — Feature-complete Editor + Folder-Hierarchy + Roving-tabindex.
263
-
264
- **V.1.4** — explicit `folder?: string` Schema-Field auf text-block-entity. Slug bleibt
265
- kebab-only validiert, Folder explizit gesetzt. Tree gruppiert via `groupBlocksByFolder`
266
- (ersetzt `groupBlocksBySlugPrefix`). `Subscribe<T>` Signature um optional `emitError`
267
- erweitert für explicit async-error-Pfade. ProviderBranch zeigt Error-Banner mit
268
- Retry-Button. Drift-Test pinnt seedTextBlock-vs-set.write Slug-Validation.
269
-
270
- **V.1.4b** — URL-State-Routing für Editor-Target via `nav.searchParams`. F5 + Back-Button
271
- stellen den Editor-State wieder her. Format: `?t=text-content:edit&a_slug=...&a_lang=...`.
272
- Plus `useDispatchTarget` hook ersetzt globalen `dispatchTarget` als empfohlenen Production-
273
- Pfad (legacy bleibt für Test-Hooks).
274
-
275
- **V.1.5** — Arrow-Key-Navigation (`<aside role="tree">`, ARIA-tree-Pattern) + SSE-driven
276
- Tree-Refresh. `ClientFeatureDefinition.treeEntities?: string[]` listet Entity-Namen pro
277
- Provider; live-events triggern provider-re-mount → Stale-Tree-state="stub"→"filled"
278
- flippt nach save automatisch.
279
-
280
- **V.1.5c+d** — Active-Node-Highlight (explicit blue + 2px border-l + scrollIntoView),
281
- VS-Code-Polish (compact spacing, focus-visible, folder-icon-color text-amber, indent-
282
- guides per ancestor-depth), Folder-Wrapper für legal-pages ("📁 Legal" + slug-first
283
- Verschachtelung) und text-content ("📁 Content").
284
-
285
- **V.1.6** — Multi-level Folder-Splitting (`folder="page/marketing"` → nested folders,
286
- walk-or-create-pattern, folder/leaf-collision-tolerant). Roving-tabindex (nur focused-
287
- treeitem hat tabIndex=0, Tab cyclt aus dem Tree raus).
288
-
289
- 35/35 kumiko check PASS, 13/13 group-blocks + 22/22 text-content integration tests grün.
290
- Browser + Keyboard lokal validated.
291
-
292
- **Breaking**: `TreeContext` Type entfernt (V.1.2 SR2-Rip — war nie genutzt). Provider sind
293
- session-bound: `TreeChildrenSubscribe = () => Subscribe<T>` statt `(ctx) => Subscribe<T>`.
294
-
295
- **V.1.7-Followups**: useEffect-deps in VisualTree-focus-init (Performance), Cancellation-
296
- Token in TreeProvider's fetch (emit-after-unmount-warning), inline-rename, drag-drop,
297
- file-icons per slug-extension, parent-jump bei ArrowLeft auf collapsed-item.
298
-
299
- ### Patch Changes
300
-
301
- - Updated dependencies [825e7d2]
302
- - @cosmicdrift/kumiko-headless@0.4.0
303
-
304
- ## 0.3.0
305
-
306
- ### Minor Changes
307
-
308
- - 0.3.0 bringt zwei neue Subsysteme (Step-Engine Tier-3 + Visual-Tree) plus
309
- eine AST-Codemod-Pipeline als Vorarbeit für den L2-AI-Layer.
310
-
311
- ### Breaking Changes
312
-
313
- - `skipTransitionGuard` → `unsafeSkipTransitionGuard` (Rename in
314
- feature-ast + engine). Der `unsafe`-Prefix macht die Tragweite des
315
- Casts sichtbar und ist konsistent zur `unsafeProjectionUpsert`- und
316
- `r.rawTable`-Konvention. Migration: 1:1-Ersetzung, keine Verhaltens-Änderung.
317
-
318
- ### Features
319
-
320
- - **Step-Engine M.4 — Tier-3 Workflow-Engine.** Neue Step-Vocabulary
321
- `wait`, `waitForEvent`, `retry` ermöglicht persistierte Long-Running-Flows
322
- über Job-Boundaries hinweg. Q7 Snapshot-at-Start hängt jedem Step-Run
323
- einen SHA-256-Fingerprint des Aggregat-Zustands an, sodass Replays
324
- deterministisch gegen den ursprünglichen Eingangszustand laufen.
325
- - **Visual-Tree V.1.x — Tree-API + Editor-Panel.** Neue `VisualTree`-
326
- Component plus TreeProvider-Pattern; erste TreeProviders für
327
- `text-content` und `legal-pages` (CMS-light + Impressum/Privacy).
328
- Fundament für den späteren No-Code-Designer (~3000 LOC, 98 Tests).
329
- - **Codemod-Pipeline.** AST-basierte Patcher-Module für strukturelle
330
- Feature-Edits — wird vom kommenden L2-AI-Layer als Tool-Surface
331
- verwendet, ist aber eigenständig nutzbar für ts-morph-style Migrationen.
332
- - **user-data-rights Sample-Recipe.** DSGVO Art. 15/17/18/20 vollständig
333
- als Sample-Recipe (`samples/recipes/`) inklusive README — zeigt die
334
- Export- und Forget-Pipeline gegen den `compliance-profiles`-Default
335
- (`eu-dsgvo`).
336
-
337
- ### Fixes
338
-
339
- - `tier-engine`: auto-default-tier-Hook benutzt jetzt `ctx.db.raw` für
340
- Event-Store-Operationen (#37, vorher: stiller Bug, 22 Tage live).
341
- - `engine`: unsafe-projection-upsert nutzt `as never` statt `as any` —
342
- schmaler Cast-Surface, weniger Compiler-Knebel.
343
- - `visual-tree`: runtime-isolation marker für client-konsumierte Files,
344
- damit der Multi-Entry-Build den richtigen Bundle-Split bekommt.
345
- - `feature-ast`: vollständiger `unsafeSkipTransitionGuard`-Rename (war
346
- in zwei Modulen noch der alte Name).
347
- - `framework`: Error-Reasons + `noConsole`-Lint + No-Date-API-Guard
348
- wieder push-ready.
349
-
350
- ### Library-Updates
351
-
352
- hono 4.12, jose 6.2, stripe 22.1, meilisearch 0.58, marked 18,
353
- bun-types 1.3.13, lucide-react 1.14, bullmq 5.76, ioredis 5.10,
354
- i18next 26.0, react + radix-ui-primitives auf aktuelle Minors.
355
-
356
- ### Patch Changes
357
-
358
- - Updated dependencies
359
- - @cosmicdrift/kumiko-headless@0.3.0
360
-
361
- ## 0.2.3
362
-
363
- ### Patch Changes
364
-
365
- - @cosmicdrift/kumiko-headless@0.2.3
366
-
367
- ## 0.2.2
368
-
369
- ### Patch Changes
370
-
371
- - 7a7da3e: Re-publish 0.2.1 → 0.2.2 mit korrekt aufgelösten cross-package-Versionen.
372
- 0.2.1 hatte `workspace:*` als Wert in den dependencies (npm publish ohne
373
- yarn-pack rewrite), Konsumenten bekamen "Workspace not found".
374
-
375
- publish-with-oidc.sh nutzt jetzt `yarn pack` (rewrited workspace:\*) +
376
- `npm publish <tarball>` (OIDC + provenance).
377
-
378
- - Updated dependencies [7a7da3e]
379
- - @cosmicdrift/kumiko-headless@0.2.2
380
-
381
- ## 0.2.1
382
-
383
- ### Patch Changes
384
-
385
- - 48b7f6a: CI: switch publish to npm-CLI with OIDC Trusted Publishing + provenance.
386
- No source changes — verifies the new publish path produces a verified-
387
- provenance attestation on npmjs.com instead of token-based publish.
388
- - Updated dependencies [48b7f6a]
389
- - @cosmicdrift/kumiko-headless@0.2.1
390
-
391
- ## 0.2.0
392
-
393
- ### Minor Changes
394
-
395
- - 6c70b6f: fix(tenant): seedTenant idempotent gegen Event-Store-Projection-Drift.
396
-
397
- Verhindert version_conflict beim App-Boot wenn Aggregat existiert aber
398
- Projection-Row fehlt (rebuild-drift, async-lag, manueller DB-Eingriff).
399
-
400
- ### Patch Changes
401
-
402
- - Updated dependencies [6c70b6f]
403
- - @cosmicdrift/kumiko-headless@0.2.0
404
-
405
- ## 0.1.0
406
-
407
- ### Minor Changes
408
-
409
- - 59ba6d7: Initial public release of Kumiko — AI-native backend builder.
410
-
411
- What ships in 0.1.0:
412
-
413
- - **Engine** (`@cosmicdrift/kumiko-framework`): `defineFeature`, `r.entity`, `r.writeHandler`, `r.queryHandler`, `r.projection`, `r.multiStreamProjection`, `r.hook`, `r.translations`, `r.crud`, `r.referenceData`, `r.screen`, `r.nav`, `r.authClaims`, full lifecycle pipeline with field-level access checks
414
- - **Pipeline** (`@cosmicdrift/kumiko-framework`): `createDispatcher`, JWT auth via jose, Zod schema validation, role-based access checks, command/write/query split
415
- - **DB** (`@cosmicdrift/kumiko-framework`): Drizzle helpers (`buildDrizzleTable`, `applyCursorQuery`), CRUD executor, Postgres dialect, optimistic locking, soft delete, multi-tenant scoping
416
- - **Event sourcing** (`@cosmicdrift/kumiko-framework`): aggregate streams, single + multi-stream projections, event upcasters, asOf queries, archive support, AsyncDaemon-pattern dispatcher
417
- - **Bundled features** (`@cosmicdrift/kumiko-bundled-features`): auth-email-password, sessions, tenants, users, jobs, secrets, file-provider-s3, mail-transport-smtp/inmemory, billing-foundation, cap-counter, channel-in-app, delivery, feature-toggles, legal-pages
418
- - **Renderer** (`@cosmicdrift/kumiko-renderer`, `@cosmicdrift/kumiko-renderer-web`): schema-driven CRUD UI for React + Expo Web, override paths, list debounce, theme tokens
419
- - **Headless** (`@cosmicdrift/kumiko-headless`): view-models for list/edit screens, locale-aware
420
- - **Dev server** (`@cosmicdrift/kumiko-dev-server`): `runDevApp`, `runProdApp`, `kumiko-build` for production bundles (client + server), Docker-ready
421
- - **Realtime** (`@cosmicdrift/kumiko-dispatcher-live`): SSE broadcast across tenants, Redis Pub/Sub backend
422
- - **CLI** (`bin/kumiko.ts`): interactive dev menu, test runners, check pipeline (Biome + TypeScript + 18 guards + Vitest)
423
-
424
- This is a pre-1.0 release — APIs may change between minor versions. Breaking changes will be documented per release.
425
-
426
- ### Patch Changes
427
-
428
- - Updated dependencies [59ba6d7]
429
- - @cosmicdrift/kumiko-headless@0.1.0