Seed-Migration
File-based migrations for Event-Sourcing operations — like kumiko schema apply, but for aggregate-state-changes after the initial seed.
What it shows
Section titled “What it shows”seedsDir-Option inrunProdApp({ seedsDir: "./seeds" })— beim Boot werden pending Files in chronologischer Reihenfolge angewendet und inkumiko_es_operationsmarkiert.SeedMigration-Interface — default-Export einer seed-File mitdescription+run(ctx). ctx liefertsystemWriteAs(System-User bypassed Access-Check) + Read-Helpers (findUserByEmail,findMembershipsOfUser,findTenants).- Idempotency — Marker landet nach Erfolg in der Tracking-Tabelle, zweiter Boot skipped applied Seeds.
- Tx-Atomicity — Jede Migration läuft in eigener Transaction; Failure rollt zurück + bricht Boot ab (kein Partial-Apply).
- Chronologische File-IDs — Filename
<date>-<slug>.ts(z.B.2026-05-20-fix-admin-roles.ts) ist die ID.
Phase 1.5 hinzugefügt
Section titled “Phase 1.5 hinzugefügt”tenantIdOverrideinctx.systemWriteAs(qn, payload, tenantId)— Pflicht wenn das Aggregate in einem Tenant-Stream lebt (sonstversion_conflict).- Dry-Run-Validator — Runner parsed seed-files vor Run + checked alle handler-QNs gegen registry. camelCase-typos & andere QN-Drift werden BEFORE the write erkannt.
scripts/smoke.ts— copy-paste-Template für lokalen Pre-Push-Smoke. Bun-runnable, validiert Module-Load + QN-Resolution + Access offline. Pflicht-Pattern vor Push.- Docker-COPY-Pflicht dokumentiert in
framework/src/es-ops/README.md.
Lokaler Smoke vor Push (Pflicht)
Section titled “Lokaler Smoke vor Push (Pflicht)”# Im App-Root:bun samples/recipes/seed-migration/scripts/smoke.ts --seeds-dir ./seedsErwarteter Output:
seed: 2026-05-20-fix-admin-roles.ts ✓ loads: "ergänze TenantAdmin-Rolle" ✓ "tenant:write:update-member-roles" registered + accessible
✓ all 1 seed-file(s) pass smoke.Bei typo / drift fail-t mit klarer message + exit-code 1 — CI nutzt es als prä-build-step. App-Author muss in smoke.ts den features-Array gegen die eigene App-Feature-Set tauschen (siehe TODO im File).
When to reach for it
Section titled “When to reach for it”Du hast einen idempotent-Seeder der bei initialer Erstellung „Insert wenn nicht existiert” macht (z.B. auth.admin.memberships), und dann ändern sich die Soll-Daten — neue Rolle, anderer Tier, korrigierte Bezeichnung. Idempotent-Seeder skippen die existing Rows → DB driftet vom Code-Stand ab.
Seed-Migrations sind der saubere Fix: ein File schreibt das gewünschte Update einmalig in den Event-Store, Projection läuft automatisch.
Don’t reach for it when
Section titled “Don’t reach for it when”- Initial Seeding (erste Daten beim leeren Stack). Dafür gibt es
r.config({seeds})+options.seeds-Array — idempotent-by-design durch deterministische Aggregate-IDs. - Schema-Migrations. Dafür gibt es
kumiko schema generate. Seed-migrations sind Data-Layer, nicht Schema-Layer. - Read-only Operationen / Reports. Dafür gibt es App-spezifische Routes / Queries.
How it works
Section titled “How it works”- Bei
runProdApp-Boot scannt das FrameworkseedsDirnach*.ts-Files. - SELECT
idFROMkumiko_es_operationsWHEREoperation_type='seed-migration'→ applied-Set. - Pending = files-on-disk minus applied-set, sortiert chronologisch.
- Pro pending: Tx auf,
migration.run(ctx)(kann beliebige Handler viasystemWriteAsrufen), Marker einfügen, Tx commit. - Failure → Tx rollback, kein Marker, Boot bricht ab. Operator fixt + Retry.
# Scaffold neue Migration mit Datum-Prefixbunx kumiko ops seed:new fix-admin-roles# → seeds/2026-05-20-fix-admin-roles.ts
# Was applied, was pendingbunx kumiko ops seed:status
# (Phase 1.5) Direct apply ohne Bootbunx kumiko ops seed:apply [--dry-run]Skippable im Notfall
Section titled “Skippable im Notfall”Wenn eine kaputte Migration den Boot blockiert: setze skippable: true im seed-File und beim nächsten Boot KUMIKO_SKIP_ES_OPS_<sanitized-id>=1 env-var. Marker wird nicht geschrieben → beim nächsten Boot ohne Flag würde der Seed wieder laufen. NICHT als Standard-Workflow — Recovery-only.
See also
Section titled “See also”- Plan-Doc:
kumiko-platform/docs/plans/features/es-ops.md— Phase-2+ Operations (projection-rebuild, event-replay, stream-migration, …) - Driver-Use-Case: publicstatus
seeds/2026-05-20-fix-admin-roles.ts(Branchfeat/es-ops-driver-admin-roles)
Source
Section titled “Source”📄 On GitHub: samples/recipes/seed-migration