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