Zum Hauptinhalt springen

Seed-Ablöse-Plan & Mandantenfähigkeit (OP-SEED-1 / OP-TENANT)

Status: Seed-Ablösung abgeschlossen — S-SEED-1…4 ✅ (Stand 0.16.0: kein Produktiv-Codepfad berührt den Seed mehr, s. §4); S-SEED-5 = Persistenz-Hygiene → OP-DATA-1 (docs/architektur/Persistenz.md), OP-TENANT-Slices (mehrere Vorlagen · Room=Tenant · Isolation · Registry) offen · Bezug: OP-SEED-1 (Owning-OP) / OP-TENANT · S-SEED-1…5 · OP-DATA-1 · G-1 · Zielgruppe: IT-Dev/Architektur · True North: nur indirekt — echte, editierbare Stammdaten (Buchten · Taxonomie · Schichten) statt Demo-Seed machen die Antworten auf Auslastung/Standort/Kapazität für den realen Betrieb korrekt.

Kernaussage. Konkreter Plan, wie der statische Beispiel-Seed (vestAutomotiveSeed) schrittweise aus dem Laufzeitpfad gelöst wird, und wie vest-automotive zur konfigurierbaren Tenant-Vorlage wird. Begleitend: die Purge-Funktion im Admin-Bereich (Datenbestand zurücksetzen + Vorlage laden). Audit-Hintergrund: Branch claude/seed-usage-audit-frsx52. Tiefe je Thema: HANDOFF.md §4.

Verhältnis zu Mandantenfähigkeit: dort die Zielarchitektur der Tenant-Isolation; hier der konkrete Migrationsweg (Seed → Vorlage). Beide teilen OP-TENANT.

1. Audit-Befund — wo Seeds noch verwendet werden (Stand 0.12.0)

Alle Fundstellen gehen auf einen Datensatz zurück: vestAutomotiveSeed in server/src/model/seed.ts. Kein Client-Code nutzt Seeds direkt. Zwei Gruppen:

1a. Produktiv-/Laufzeitpfad — server/party/leitstand.ts

DatenBezug zum SeedStatus
Mitarbeiter, Skills, Teilschritte, Leistungenbeim ersten Boot aus dem Seed geklont in den DO-Stateabgelöst — persistiert + editierbar (OP-R1-1 Phase B, OP-R3-3)
Buchten/Arbeitsplätze (arbeitsplaetze/bays)seed()-Buchten + read-only vestAutomotiveSeed.arbeitsplaetze (Belegung, Ausfall)noch am Seed — nicht editierbar
Taxonomie (Abteilungen, Arbeitsplatz-Typen, Abwesenheits-/Sperre-Typen, Ausstattung)read-only direkt aus vestAutomotiveSeed.taxonomy (Modul-Konstanten)noch am Seed — nicht editierbar (G-1: taxonomie-artig = admin-editierbar vorgesehen)
Schichten (SCHICHTEN, SCHICHT_DTOS)read-only aus vestAutomotiveSeed.schichtennoch am Seed — nicht editierbar
Solver-Eingabe schedulerInput()Stammdaten-Rest weiter ...vestAutomotiveSeed, Mitarbeiter/Skills/Teilschritte/Leistungen aus dem Stateteil-abgelöst
Demo-Historie seedDemoHistorie()Beispiel-Aufträge/Leistungsnachweise je BootDemo-Daten (kein Stammdatum)

1b. Demo-/Self-Test-/Spike-Skripte (CLI, nicht Laufzeit) — unkritisch

scheduler/spike.ts, solver/{demo,cpsat-demo,eligibility-demo,overflow-demo,pin-demo}.ts, operativ/{demo,replan-demo,teilplan-demo,prozess-demo}.ts, insights/insights-demo.ts. Diese importieren den Seed bewusst als Testdatensatz (npm run spike|solve|replan|…) und bleiben — sie sind kein Produktivpfad. Ablösung betrifft nur 1a.

2. Getroffene Entscheidungen (06-26)

Die interaktive Rückfrage scheiterte technisch (Permission-Stream, Remote-Session); umgesetzt wurden die empfohlenen Defaults — jederzeit über den Purge-Dialog (Laufzeit) bzw. hier (Plan) überstimmbar.

  • D1 — Purge-Kategorien: Alle vier Seed-Kategorien sind im Purge-Dialog einzeln wählbar: Taxonomie & Struktur · Prozess-Katalog · Demo-Mitarbeiter · Demo-Historie & Aufträge.
  • D2 — Purge-Default (Schnellwahl): „Leeres Gerüst" = Taxonomie+Struktur+Prozess-Katalog laden, keine Mitarbeiter/Aufträge/Historie (sauberer Produktiv-Start). Alternativ ein Klick: „Voller Demo-Seed" (wie heute) oder „Komplett leer".
  • D3 — Tenant-Umfang dieser PR: „Fundament + OP" — Seed → benannte Tenant-Vorlage vest-automotive, Purge lädt die gewählten Kategorien daraus; echtes Tenant-Switching/-Isolation als spätere Slices (OP-TENANT, hängt an OP-AUTH-2 + OP-DATA-1).

3. Was in dieser PR gebaut wurde (0.12.0, Build 15)

  1. Tenant-Vorlage als einzige Seeding-StellebaueState(kategorien) in leitstand.ts ist die einzige Stelle, an der die Vorlage vest-automotive (TENANT_ID) zu State wird. Boot-Default = baueState(ALLE) → bit-identisch zum bisherigen Voll-Seed-Boot (Regressionsfreiheit).
  2. Purge-Kommando admin.purge (admin-gegated über denselben Access-Owner-Gate wie Kosten, interim bis OP-AUTH-1): baut den State aus den gewählten Kategorien neu, löscht alle Aufträge/Historien/Fotos/ Kosten + transiente Arbeitszustände (Vorschau/Vorschläge/Live-Tasks), setzt schemaVersion aktuell.
  3. Demo-Historie-Unterdrückung — neues persistiertes Flag demoHistorieGeseedet verhindert, dass seedDemoHistorie() nach einem Purge ohne Demo-Historie beim nächsten Cold-Boot wieder Demo-Daten nachschiebt. Legacy/undefiniert = altes Verhalten (kein Migrationsbedarf, rein additiv).
  4. Admin-Bereich (neu) — Workspace /administration (Cluster „System", nav-gegated wie Kosten): aktiver Mandant + Gefahrenzone mit Preset-Schnellwahl, Einzel-Checkboxen je Kategorie, Ergebnis-Vorschau und Tipp-Bestätigung (LÖSCHEN) vor der destruktiven Aktion. Rot nur für die Warnung/den Bestätigungs-Button (Design-Regel), nur --tk-*-Tokens.

4. Ablöse-Plan für den Rest-Seed (Slices, je eigene PR/Entscheidung)

Ziel: die noch hart verdrahteten Stammdaten (Buchten, Taxonomie, Schichten) genauso aus dem Laufzeitpfad lösen, wie es für Mitarbeiter/Skills/Teilschritte/Leistungen bereits geschah — persistiert, editierbar, je Mandant aus der Vorlage initialisiert. Reihenfolge nach Risiko/Nutzen:

  • S-SEED-1 · Buchten/Arbeitsplätze persistieren & editieren — ✅ gebaut (0.13.0). arbeitsplaetze (Arbeitsplatz R2) ist jetzt im DO-State (persistiert + onStart-Backfill für Altzustände + in baueState/Purge unter „Taxonomie & Struktur"). Die Modul-Konstante BELEGUNG_SLOTS wurde zum Instanz-Getter belegungSlots (leitet aus state.arbeitsplaetze ab); ressourcenDTO().bays und schedulerInput() lesen ebenfalls aus dem State statt aus dem Seed. CRUD: arbeitsplatz.create/update/remove (validiert gegen Typ-/Skill-/Ausstattungs-IDs; remove räumt die Belegung des Slots mit auf) + neuer Editor in /administration (Name, Typ, Kapazität, Konfig-Status, Skills, Ausstattung). True North: direkter Treffer auf „Wo stehen die Fahrzeuge / wann ist frei" (Frage 2/3) — der Betrieb pflegt seine echten Buchten. Offen (Folge): Sperren-Editor (heute nur read-only Zähler sperrenAnzahl); state.bays (UI-Board) und arbeitsplaetze perspektivisch vereinheitlichen (zwei parallele Repräsentationen); Taxonomie der Typen bleibt bis S-SEED-2 Seed-basiert.
  • S-SEED-2 · Taxonomie-Editor (G-1) — ✅ gebaut (0.14.0). taxonomy: TaxonomyValue[] ist jetzt im DO-State (persistiert + onStart-Backfill + in baueState/Purge unter „Taxonomie & Struktur"). Alle bisher statischen Modul-Konstanten (ABTEILUNGEN, TYP_LABEL, ARBEITSPLATZ_TYPEN, AUSSTATTUNG_TYPEN, ABWESENHEIT_TYPEN, … + die Validierungs-Sets) wurden zu Instanz-Gettern über state.taxonomy; die Modul-Funktionen toAuftragDTO, buildProzessKatalog, bauBelegungSlots bekommen die Taxonomie/Label-Map als Parameter; schedulerInput() reicht taxonomy: state.taxonomy an Scheduler/CP-SAT. CRUD: taxonomie.create|update|remove (Label + aktiv-Soft-Deaktivierung; Anlegen reaktiviert gleichnamige deaktivierte Werte; hartes Löschen nur unreferenzierttaxonomieInUse prüft Mitarbeiter/Arbeitsplätze/Teilschritte/Leistungen/Sperren) + generischer Taxonomie-Editor in /administration (Art-Auswahl × Werte mit Umbenennen/Aktiv/Löschen). Logik-tragend bleibt fix (G-1): die Label-Regex-Konventionen im Scheduler — Parkplatz /parkplatz/i, Indoor /indoor|folierbucht/i — der Editor warnt, solche Typen nicht umzubenennen. Offen: die Mangel-Kategorien (§4.9.1, MANGEL_KATEGORIEN) sind eine separate feste Liste (nicht Teil der Stamm-Taxonomie) und bleiben vorerst hart; kind-Flag statt Label-Regex für Parkplatz/Indoor als robustere Folge.
  • S-SEED-3 · Schicht-Katalog persistieren & editieren — ✅ gebaut (0.15.0). schichten: SchichtKatalog[] ist jetzt im DO-State (persistiert + onStart-Backfill + in baueState/Purge unter „Taxonomie & Struktur"). Die Modul-Konstanten SCHICHTEN/SCHICHT_DTOS/SCHICHT_IDS wurden zu Instanz-Gettern (schichtenMap/schichtDtos/schichtIds) über state.schichten; schedulerInput() reicht schichten an Scheduler/CP-SAT (Verfügbarkeit/Ausfall). CRUD: schicht.create/update/remove (Name + Wochentage + Zeit-Slots HH:mm validiert [start<ende], art regulär/standard/überlauf, aktiv-Soft-Deaktivierung; hartes Löschen nur unzugewiesen via schichtInUse über Mitarbeiter-Schichten und Abwesenheits-Schichtbezug) + Schicht-Editor in /administration (Wochentag-Picker, variable Zeit-Slots mit type=time, Art, Aktiv). Mitarbeiter-Schicht-Zuweisung + Abwesenheits-Schichtbezug referenzieren die persistierten Schichten. Logik-tragend bleibt fix: Wochentage/Zeitfenster steuern die Solver-Verfügbarkeit — Werte editierbar, das HH:mm-Format ist validiert/fix.
  • S-SEED-4 · Vorlage extrahieren — ✅ gebaut (0.16.0). Die Stammdaten sind aus server/src/model/seed.ts nach server/src/tenants/vest-automotive.ts umgezogen (git mv, Historie erhalten) und als benannte Tenant-Vorlage gewrappt: vestAutomotive: TenantVorlage = { id: 'vest-automotive', name: 'Vest Automotive GmbH', daten: <SchedulerInput> } (TenantVorlage-Typ in tenants/types.ts). Eine Registry tenants/index.ts (TENANT_VORLAGEN, tenantVorlage(id), DEFAULT_TENANT_ID, aktiveTenantVorlage()) ist die einzige Bezugsquelle; leitstand.ts zieht die Vorlage über aktiveTenantVorlage() (→ TENANT_ID + interne vestAutomotiveSeed-Referenz). model/seed.ts bleibt als dünner Re-Export-Shim (export { vestAutomotiveSeed } from '../tenants/vest-automotive'), damit die Demo-/Spike-Skripte (1b) ihren Import unverändert behalten. Damit ist der Seed kein impliziter Laufzeit-Default mehr, sondern eine explizit benannte Vorlage — das Code-Fundament für Multi-Tenancy (OP-TENANT). Offen: Demo-Imports später direkt auf tenants/ umstellen + Shim entfernen; mehrere Vorlagen + Room=Tenant (OP-TENANT).
  • S-SEED-5 (OP-DATA-1) — Design ausgearbeitet 06-27 → docs/architektur/Persistenz.md. Persistenz-Konvention vereinheitlichen: Drizzle-Schema als Single Source, generierte Migrationen + CI-Gate statt handgepflegter onStart-Remaps. Kern: Heimat der Daten (DO-Blob · DO-SQLite · D1) — ⮕ Entscheidung E-DATA-1. Slices D5-1…D5-4. Kein Teil der Seed-Ablösung mehr (die ist mit S-SEED-4 abgeschlossen) — reine Persistenz-/Migrations-Hygiene.

Stand 0.16.0: S-SEED-1..4 ✅ — kein Produktiv-Codepfad berührt mehr den Seed direkt; der DO bezieht die Stammdaten ausschließlich über die benannte Tenant-Vorlage (aktiveTenantVorlage()baueState). Damit ist das Code-Fundament für echtes Multi-Tenancy (OP-TENANT) gelegt; offen bleibt S-SEED-5 (Drizzle/Migrationen, OP-DATA-1) sowie die OP-TENANT-Slices (mehrere Vorlagen, Room=Tenant, Isolation, Registry in D1/KV).

5. Mandantenfähigkeit — OP-TENANT (Zielbild)

vest-automotive ist der erste Mandant, nicht der einzige. Zielbild (mehrere Slices, hängt an OP-AUTH-2 „Mandanten-/Cross-Tenant-Trennung" und OP-DATA-1):

  • Tenant-Identität je DO-Room (heute fix leitstand-vest) → Room = Tenant; TENANT_ID aus der Room-/Access-Identität statt Konstante. Datenisolation strikt je Tenant (kein Cross-Read).
  • Tenant-Registry (welche Mandanten existieren, welche Vorlage/welcher Plan) — D1/KV, EU-Residenz.
  • Provisionierung: neuen Mandanten anlegen = neuen Room + baueState(gewählte Kategorien) der passenden Vorlage; Self-Service-Onboarding folgt dem Billing-/Access-Pfad (docs/Billing-Zugang.md, OP-BILLING-1/OP-ACCESS-1).
  • Owner-Gate scharf (OP-AUTH-1/OP-COST-3): der heutige interim-kostenAdmin-Gate wird durch echte Rollen ersetzt; Purge/Tenant-Admin sind dann owner-/admin-rollen-gebunden.

Abgrenzung: Diese PR liefert das Fundament (eine benannte Vorlage + selektives (Re-)Seeding via Purge). Tenant-Switching, -Isolation und -Registry sind nicht enthalten und bleiben OP-TENANT.

6. Risiken & Sicherheit

  • Destruktiv & irreversibel: Purge löscht den Datenbestand ohne Backup. Schutz heute: Admin-Gate + Tipp-Bestätigung. Vor Produktivgang: echtes Rollen-Gate (OP-AUTH-1), zusätzlich Export/Backup vor Purge (Bezug OP-EXPORT-1 + OP-BACKUP-1 — Point-in-Time-Restore, Rollback-Punkt über das Audit-Log, Umgang mit dem Audit-Log beim Rollback; noch auszuarbeiten) und ein Audit-Event je Purge ins D1-Audit (OP-AUDIT-1) — heute nur Ops-Log-Zeile (console, OP-LOG-1) mit Actor.
  • Mehrbenutzer-Live: Purge broadcastet sofort den neuen (leeren) State an alle Verbindungen — bewusst, da der ganze Mandant zurückgesetzt wird.
  • DSGVO/Residenz: Tenant-Daten + -Registry in EU (D1 weur/eu), konsistent mit OP-AUDIT-1/OP-AUTH-1.

7. Verweise

HANDOFF.md §4 (OP-SEED-1, OP-TENANT, OP-AUTH-1/2, OP-DATA-1, OP-AUDIT-1, OP-EXPORT-1) · docs/Lastenheft.md (G-1) · server/party/leitstand.ts (baueState, admin.purge) · server/src/model/seed.ts · client/.../pages/administration.component.ts.


↩ Zurück zur Doku-Landkarte · Lesepfade · Register (alle OPs)