Files
claude-wuerth-plato/memory/project_cleanup_timeline.md
2026-07-09 09:21:42 +02:00

11 KiB
Raw Permalink Blame History

name, description, metadata
name description metadata
project-cleanup-timeline Cleanup-Sprint plato-customer Mai 2026 — Status nach BFF-Umbau und nächste Themen (User-DB, Postgres).
node_type type originSessionId
memory project 9259f85f-e34d-4327-89e2-534bbfbc48c2

10-PT-Aufräum-Sprint auf development. Linie: feedback-priorisierung.

Status Ende 2026-05-22 (Fr):

  • Storage-Layout (Subdirs + .crypt) + AES → Base64 (94d19a5)
  • Auto-Migration plato5/crm.sqlite bei Init (ee57b86)
  • IdP-Anbindung verifiziert (siehe project-idp-witglobal)
  • Auth-Umbau auf BFF abgeschlossen (00e2c37 "activate odic login" + weitere Commits): Dummy-JWT raus, passport-jwt+jwks-rsa raus, openid-client+express-session rein, client_secret server-seitig (nicht mehr im Browser), Session-Cookie-basiert. Siehe project-idp-witglobal und project-run-commands.
  • User ex08802409 in user.json ergänzt (provisorisch, ohne echten Datensatz)
  • Test-Rig scripts/oidc-test.mjs uncommitted (separater Scope, war Pre-BFF-Verifikation)

Nächste Themen (am 2026-05-22 angerissen, Implementierung steht aus):

  • User-DB: aktuell statisch aus user.json via UserRegistry (Konstruktor readFileSync). Soll eine richtige DB werden — Marcus hat das explizit als nächstes Thema benannt nachdem die User-Mapping-Lücke beim Login auffiel.
  • Kunden-Persistenz: SQLite → Postgres: aktuell SQLite via TypeORM in data/customer.db (PVC-mounted im Container). Bedeutet Single-Pod, kein Rolling-Deploy. Plan: separater Postgres-Pod (StatefulSet, im Gitops-Repo zu definieren), TypeORM-DataSource auf postgres umstellen, Migrations neu generieren, lokal Compose o.ä. — kein Managed-Service bei Würth (außer SQL Server).
  • Infrastruktur-Repo existiert ("haben wir") — noch nicht im Detail angeschaut.

Plan 2026-05-26 (Di) — "alles fertig":

  • Übergabe an Kollegen zum Testen
  • Test-Automatisierung
  • QS-Übergabe
  • Blocker für Auth-Rollout: Windows-Kollege braucht funktionierenden Weg zum IdP. Solange nicht geklärt, kann der BFF-Stand nicht "scharf" für ihn werden — er kommt sonst nicht in die App.

Stand 2026-05-27 (Mi) — Deployment-Cleanup-Runde (siehe Commits f6d7b6d, acafac5, b6856e9):

  • OIDC_CLIENT_SECRET + SESSION_SECRET aus Image, via Sealed-Secret im GitOps-Repo (plato-customer-secrets), envFrom im Deployment-Patch backend.yaml
  • trust proxy für Session-Cookies hinter OCP-Router
  • Proxy-ENVs (HTTPS_PROXY etc.) aus Image, in Deployment-env:-Block; undici-ProxyAgent für Node-22-fetch
  • Fail-Fast in main.ts und oidc.service.ts wenn Secrets fehlen (Crash statt stille Dev-Fallbacks)
  • Alte GHCR-Versionen mit eingebackenem Secret gelöscht (manuell via Web-UI), aktuelle Version 0.3.0
  • ⏸️ Session-Store-Umzug (MemoryStore → Redis) verschoben: replicas=1, kein akuter Bedarf, kein Redis im Namespace deploybar

Plan 2026-05-28 (Do) — umgestellt:

  • Vormittag (statt Postgres-Backbone): Migration + Import-Handling. Postgres-Backbone wurde verschoben. Code-Bereich: apps/plato-customer-be/src/migration/ (Controller /import/sqlite + /import/excel, SqliteImportService/MsExcelImportService, CustomerRehydrator, DuplicateFinderUtils, SQL-Selects, SQliteDb); shared xlImport2Customer+excel2json; FE migrationUploadClient + legacyMigration (./plato5/crm.sqlite). Import liefert nur MigrationCheck (Vorschau, BE persistiert nicht selbst — Persistenz FE über persistentStorage/Outbox bzw. CustomerCoreService.createOrUpdateList).
  • Offene Schwachstellen im Import (28.05. analysiert): (1) DuplicateFinderUtils.fuzzyFinds (Kunden ohne customer_number) wird gesammelt aber nie ins Ergebnis/Report übernommen; getByCustomerFuzzy existiert im Core-Service, wird aber nicht aufgerufen — angefangenes Feature. (2) SQliteDb.executeSelect als Promise<string> typisiert, liefert aber Row-Array. (3) Import schreibt nichts BE-seitig.
  • Architektur-Klarstellung Marcus (28.05.): SQLite-Migration ist ein EINMALIGER Prozess beim ersten App-Start — main.js Boot-Schritt 5.5 ruft legacyMigration.migrateIfPresent() nur if (manifest.created) (Cache-Verzeichnis frisch). Ab dann wird mit SAP-Daten gearbeitet. Die manuellen Header-Buttons ⇆ SQLite/⇆ Excel (CustomerHeaderActions.vue) widersprechen dem → auf Marcus' Wunsch disabled (nicht gelöscht, reaktivierbar). Wie es mit dem Import-Pfad weitergeht, will Marcus noch besprechen.
  • SAP-Einzel-Flow umgebaut (28.05., erledigt, typecheck grün): SAP-Nummer ist führend, Eingabe über SapImportDialog (bleibt). CustomerStore.fetchFromSap sucht lokal nach customer_number; gefunden → hart aus SAP überschreiben (8 Stammdaten-Felder, Identität bleibt), nicht gefunden → neu anlegen. Verdrängte alte Email → geretteter Kontakt (overwriteWithSap + guessNameFromEmail in sap-adapter.ts), Name aus Email-Local-Part geraten, Match per Email. Bestehende Kontakte/Adressen bleiben beim Überschreiben erhalten; SAP-Partner-Kontakt/-Adresse kommen nur bei Neuanlage rein.
  • SAP-Mock ins BE integriert (28.05., erledigt, typecheck grün) — Variante B, bewusst Notlösung & komplett removable: Marcus' Vorgabe war „muss ohne großes Aufhebens vollständig rausnehmbar sein". Neues self-contained Modul apps/plato-customer-be/src/sap-mock/ (Controller @Get('CustomerSet'), Service liest crm.sqlite via better-sqlite3, Query/XML 1:1 aus altem Express-Mock portiert). In app.module.ts flag-gegatet via SAP_MOCK_ENABLED=true. Dockerfile bekommt eine COPY apps/sap-mock/crm.sqlite-Zeile (30 MB). Begründung B statt eigenem Pod: SAP-Call kommt aus dem Browser (sapClientVITE_SAP_URL), eigener Pod bräuchte Route+HTTPS+CORS+FE-Build-URL; B = ein Deployment, same-origin. Rausnehmen = Ordner löschen + 2 Zeilen in app.module.ts + COPY-Zeile + VITE_SAP_URL aufs echte SAP. Standalone apps/sap-mock/ bleibt unangetastet (Quelle der crm.sqlite).
  • SAP-Mock Container-Build + Runtime VERIFIZIERT (28.05., podman): better-sqlite3 baut auf node:22-alpine ohne Build-Tools (prebuilt musl-binary), Modul wird vom nx-Webpack externalisiert, Image ~853 MB. Container bootet mit SAP_MOCK_ENABLED=true + Dummy-OIDC_CLIENT_SECRET/SESSION_SECRET (OIDC-Discovery-Fehler crasht NICHT). /CustomerSet liefert OData-XML aus /app/apps/sap-mock/crm.sqlite. Lokal: docker nicht da (kein Daemon) → podman nutzen.
  • SAP-Mock Query an neuen Flow angepasst (28.05.): Lookup jetzt per customer_number (war interne customer_id) — die SAP-Nummer ist führend, und der FE-Adapter mappt d:CustomerIDcustomer_number, also gibt der Query auch cu.customer_number as CustomerID aus. Contacts/Addresses-Joins von INNER auf LEFT OUTER umgestellt, damit auch Kunden ohne Kontakt/Adresse auflösen (404 nur noch bei unbekannter Nummer). OFFEN (Marcus klärt): CustomerToplevelNumber = customer_number (→ FE verband_nummer = Kundennummer), weil Legacy-DB keine eigene Verband-Spalte hat — evtl. auf leer setzen.
  • Postgres-Backbone — am 2026-05-28 abend LIVE auf DEV gebracht (war "verschoben"): Zweiter Pod plato-postgres im GitOps-Repo (base/postgres.yaml: Deployment RHEL-Image registry.redhat.io/rhel9/postgresql-16 + ClusterIP-Service plato-postgres:5432, KEINE Route). Creds via Sealed-Secret plato-postgres-secrets (User plato_admin, DB Plato). Bewusst OHNE PVC = ephemer (Daten weg bei Restart). Backend-DataSource umschaltbar gemacht (DB_TYPE=postgrespg, sonst sqlite-Default), synchronize:true für Postgres (keine PG-Migrations, da eh ephemer). Im DEV-Backend-Deployment via envFrom plato-postgres-secrets + DB_TYPE=postgres aktiviert. Verifiziert: Pod 0.6.1 Running, mit Postgres verbunden, Tabellen (customer/contact/address/contact_addresses) per synchronize angelegt, DB leer. Stolperstein gefixt: Entities hatten hartes type:'datetime' (SQLite-only) → auf Dialekt-Default umgestellt (kein Typ bei @CreateDateColumn/@UpdateDateColumn), sonst DataTypeNotSupportedError auf Postgres. Namespace 1401-plato-development, RedHat-Image pullt im Cluster.
  • PVC konfiguriert (2026-05-28 abend): StorageClass-Frage geklärt — Plattform-Team: PVC selbst als K8s-Objekt anlegen, CSI-Treiber legt PV automatisch an; thin-csi = Default/OLTP (für DB), trident-nas nur für File-RWX. In base/postgres.yaml ergänzt: PVC plato-postgres-data (thin-csi, RWO, 50Gi — Marcus' Wahl quota-sparsam: 400 Nutzer × 50MB ≈ 20GB Rohdaten + DB-Overhead; nicht die beantragten 100GB), gemountet an /var/lib/pgsql/data, dazu strategy: Recreate (sonst RWO-Mount-Deadlock beim Redeploy). Kustomize-Build grün. Noch nicht committet/deployed (Stand Reden). data/customer.db bleibt uncommitted, sqlite-Daten werden NICHT nach Postgres migriert (leerer Start gewollt).
  • synchronize → PG-Migrations umgestellt (2026-05-28, Weg „B" hand-portiert): Marcus' Entscheidung — synchronize raus, weil mit PVC persistent; „wenn der Pod dann deterministisch crasht, ist offensichtlich was an der Migration falsch" (Crash+Log = Diagnose, feedback-keine-zwischenstufen). Befund: die einzige bestehende Migration ist rein SQLite (datetime, Temp-Table-Tanz) → läuft auf PG nie. Daher neue PG-Migration libs/customer/customer-be/src/lib/db/1780000000000-…-customer-pg-migration.js hand-portiert aus den Entities (uuid-PK gen_random_uuid(), TIMESTAMP/now(), FKs per ALTER, Constraint-/Index-Namen 1:1 aus M000). customer-data-source.ts: Postgres synchronize:false + eigener Glob *customer-pg-migration.js (disjunkt vom SQLite-Glob *customer-migration.js). Asset-Copy (apps/plato-customer-be/project.json: **/db/**/*migration.js) erfasst beide; Prod-Build verifiziert, beide JS landen in dist, Globs trennen sauber. Deploy-Hinweis: Backend gegen ALTEN synchronize-Pod → CREATE TABLE … already exists; gitops-PVC-Change zuerst deployen (Pod neu = leeres PVC), dann läuft Migration clean.
  • Migrations-Features angefragt (2026-05-28, noch offen, Rückfragen unbeantwortet): (1) Bei Import zusätzlich per customer_number prüfen ob Kunde existiert → wenn ja, "aus SAP updaten" und an Client zurückgeben (offen: BE-seitig SAP-Mock rufen + sap-adapter-Logik BE-portieren, oder FE macht fetchFromSap?). (2) Neuer FE-Dialog: aus ALLEN Kunden (CustomerCoreService.findAll aus Postgres) auswählen, welche in den lokalen Stand geladen werden.

Plan 2026-05-29 (Fr):

  • Outbox / Inflight / BadBox Pattern + eine weitere Sync-Schnittstelle. Marcus will erst "genau anschauen" bevor implementiert wird.

Why: Marcus hat den Sprint explizit als "10 PT" geframet mit Test-/QS-Übergabe Di 26.05.2026.

How to apply: Wenn am Montag/Dienstag oder später eine neue Session startet, hier reinschauen für aktuellen Stand, statt aus git log zu rekonstruieren. Beim Aufgreifen der User-DB oder Postgres-Themen: Marcus wollte beide Sachen aufgreifen, hatte aber explizit das Postgres-Thema vor sich her geschoben (Kunden-DB zuerst). Reihenfolge mit ihm abklären.