Handbuch

Bedienungsanleitung

Ausgelieferte Live-Dokumentation aus dem Repository-Stand. Damit bleiben Code, Oberfläche und Betriebshinweise synchron.

RLS aktiv Host ortho-live

Operative Dokumentation aus dem Live-Stand

Diese Ansicht rendert immer den aktuell ausgelieferten Stand von docs/bedienungsanleitung.md. Änderungen an Bedienung, Commands oder Betrieb müssen deshalb im Repository dokumentiert werden und werden anschließend automatisch in der Live-Oberfläche sichtbar.

2026-05-07 11:09:51 Aktualisiert

Repository View

Operative Live-Dokumentation

Stand: 2026-05-07 11:09:51

# Bedienungsanleitung Drive DataEngine ## 1. Zweck Drive DataEngine ist eine Symfony-basierte Kontrollschicht fuer den bestehenden Legacy-ETL-Bestand. Die Plattform stellt aktuell bereit: - Dashboard unter `https://dataengine.domgan.de` - modernisierte server-renderte Operator-Oberfläche mit dunklem Control-Plane-Shell-Layout, linker Rail-Navigation, kontextueller Top-Bar und ausgerolltem Redesign über Übersicht, Workbench, Infrastruktur, Editor, Kompatibilität, Legacy-YAML-Sicht, Run-Detail und Handbuch - responsive gehärtete Operator-Oberfläche ohne Body-Level-Horizontalscroll auf den geprüften Kernrouten; große Tabellen bleiben auf Smartphones lesbar und lange technische Werte umbrechen kontrolliert - oeffentlich lesbare Bedienungsanleitung unter `https://dataengine.domgan.de/manual` - tenant-isolierte Run-Historie in PostgreSQL mit RLS - CLI-Commands fuer Katalog, Verbindungsprofile, Run-Planung und Ausfuehrung - direkte Run-Buttons für aktive Managed Pipelines, aktive Managed Engines und gültige Legacy-YAML-Definitionen - kontrollierte Legacy-Ausfuehrung ueber die interne Bridge - erste native Symfony-Runtime fuer Legacy-Datenbankprofile auf MySQL- und PostgreSQL-Basis - erste native MySQL-Datapool-Struktur-, CSV- und JSON/YAML-Importpfade fuer Betrieb und Migration - tenant-faehige Managed Definitions Workbench fuer Engines und Pipelines in PostgreSQL - Commerce-Template-Katalog mit DataEngine Commerce Product v1 Standard, Importstartern, Channel-Export-Templates und installierbaren Pipeline-Recipes - erste native Symfony-Ausfuehrung fuer Managed Import-Engines sowie fuer eine wachsende native Transform-Runtime ueber `unitize`, `enhance` und `export`, inklusive Mapping-, SQL-, Join-, Filter- sowie erster `Field_Adapter`-, `Cross_Field_Adapter`-, `Cross_Dataset_Filter_Adapter`- und `File_Field_Adapter`-Teilsemantik mitsamt kontrolliertem Additional-Datapool-Loading in tenant-isolierte PostgreSQL-Staging-Datapools - tenant-aware MCP-Endpunkt fuer den Remote-Zugriff auf den Control Plane - repo-lokales Codex-Plugin zum Einbinden dieses MCP-Endpunkts aus anderen Codex-Projekten ## 1.1 Grundsatz: Tool vs. Anwendung Es wird strikt unterschieden zwischen: - `Tool-Implementierung` Symfony-Code, Docker-Setup, Datenbankschema, Runtime-Services, Bridge, Commands und GUI-Logik - `Anwendung` konkrete Engines, Pipelines und deren YAML-Inhalte Die Anwendungsdefinitionen gehoeren nicht in den Tool-Code. Neue Engines und Pipelines werden deshalb schrittweise als tenant-isolierte Daten in PostgreSQL verwaltet. ## 2. Aktueller Architekturstand ### 2.1 Komponenten - `dashboard` Symfony-Weboberflaeche und Symfony-CLI - `legacy-bridge` startet bestehende Legacy-Runner kontrolliert per HTTP - `postgres` speichert Tenants, Runs und synchronisierte Connection-Metadaten - `traefik` bindet `dataengine.domgan.de` von aussen an ### 2.2 Legacy vs. native Runtime Aktueller Stand: - Pipelines und Engines werden tenant-spezifisch aus Managed Definitions und Legacy-YAML kombiniert, nativ in Symfony erkannt und vorvalidiert. - Managed Import-Engines mit `Source_Connection_Type: file` und Ziel `native_runtime`, `native_staging` oder dem Legacy-Alias `importEngine` laufen bereits nativ in Symfony. - Managed Transform-Engines der Typen `unitize`, `enhance` und `export` koennen in einer wachsenden nativen Teilmenge ebenfalls in Symfony laufen, wenn `Source_Config` und `Target_Config` auf die nativen Staging-Aliasse oder die vertrauten Legacy-Aliasse wie `importEngine`, `unitizeEngine`, `enhanceEngine` und `exportEngine` zeigen. - Managed Pipelines koennen nativ laufen, wenn alle Schritte ueber die native Staging-Runtime unterstuetzt werden, derzeit insbesondere File-Import plus native Transform-Teilpfade fuer `unitize`, `enhance` und `export`. - Alle uebrigen fachlichen Pfade laufen weiterhin ueber die Legacy-Bridge. - Managed Definitions werden fuer Legacy-Runs als isolierter Overlay-Snapshot materialisiert und nicht in den Legacy-Bestand geschrieben. - Legacy-Datenbankprofile koennen in Symfony bereits nativ bewertet werden. - Fuer MySQL- und PostgreSQL-Profile existieren read-only Runtime-Probes; MySQL-Profile haben zusaetzlich Datapool-Inspektion sowie erste Write-, Import- und Strukturkopier-Operationen. - ODBC-Profile bleiben vorerst im Legacy-Pfad. ## 3. Zugriff ### 3.1 Web - URL: `https://dataengine.domgan.de` - aktueller Status: oeffentlich erreichbar ueber Traefik - Handbuch: `https://dataengine.domgan.de/manual` - öffentliche AI-Discovery-Dateien: `https://dataengine.domgan.de/llms.txt`, `https://dataengine.domgan.de/site-context.md`, `https://dataengine.domgan.de/ai-discovery.md`, `https://dataengine.domgan.de/manual.md` - Infrastruktur: `https://dataengine.domgan.de/infrastructure` - Scheduler: `https://dataengine.domgan.de/scheduler` - Product Master: `https://dataengine.domgan.de/commerce-products` - Product Master Live-Diff: `https://dataengine.domgan.de/commerce-products/diff` - Ortho-Vertrieb Google-Merchant-Feed: `https://dataengine.domgan.de/feeds/google/ortho-vertrieb-products.tsv` - Commerce-Templates: `https://dataengine.domgan.de/commerce-templates` - Legacy-YAML-Browser: `https://dataengine.domgan.de/legacy-definitions` - YAML-Kompatibilitaet: `https://dataengine.domgan.de/compatibility` - MCP: `POST https://dataengine.domgan.de/mcp` ### 3.2 Server - Deployment-Ziel: `ortho-live` - Projektpfad auf dem Server: `/opt/containers/drive-dataengine` - Compose-Datei: `/opt/containers/drive-dataengine/compose.yaml` - Dashboard-Healthcheck: `GET /healthz`; dieser leichte Endpunkt wird von Docker genutzt, damit Traefik den Webcontainer auch bei sehr großen Dashboard-Seiten stabil routen kann. ### 3.3 Codex Plugin Im Repository liegt zusaetzlich ein repo-lokales Codex-Plugin: - Plugin-Pfad: `plugins/dataengine-mcp` - MCP-Config: `plugins/dataengine-mcp/.mcp.json` - Marketplace-Eintrag: `.agents/plugins/marketplace.json` Das Plugin ist bewusst repo-lokal versioniert. Dadurch kann es aus anderen Codex-Projekten referenziert oder installiert werden, ohne dass in diesem Umsetzungsschritt globale Codex-Dateien ausserhalb des Repositories veraendert werden. ## 4. Mandantenmodell Die Multi-Tenant-Isolation gilt derzeit fuer die Kontrollschicht: - `tenants` - `execution_runs` - `connection_profiles` - `managed_definitions` - `managed_definition_revisions` - `native_staging_datapools` - `native_staging_datapool_rows` Die Isolation erfolgt ueber PostgreSQL Row Level Security und den gesetzten Tenant-Kontext in Symfony. Dieselbe Tenant-Isolation gilt auch fuer den MCP-Layer. MCP-Tools loesen den Tenant ueber ihr Argument `tenant` auf und arbeiten danach ueber dieselben Symfony-Repositories und Services wie GUI und CLI. ## 5. Dashboard bedienen ### 5.1 Startseite Die Startseite zeigt: - die neue linke Rail-Navigation fuer `Übersicht`, `Workbench`, `Commerce`, `Infrastruktur`, `Legacy YAML`, `Kompatibilität` und `Handbuch` - eine kontextuelle Top-Bar mit Seitenstatus, Tenant-Kontext und Primäraktionen - einen Control-Plane-Einstieg mit Schnellaktionen für Workbench, Infrastruktur, neue Pipelines, Legacy-YAML-Browser, Kompatibilitätsansicht und Live-Handbuch - Anzahl erkannter Pipelines und Engines - Tenant-Kontext - Runtime-Katalog aus Managed Definitions und Legacy-Bestand - erkannte Legacy-Verbindungsprofile - native Datenbank-Runtime-Abdeckung - native Datapool-Write-Abdeckung - native Staging-Runtime fuer Managed File-Importe und native Transform-Teilpfade fuer `unitize`, `enhance` und `export` - Managed-Definitions-Status aus PostgreSQL - letzte tenant-isolierte Ausfuehrungen - alle gefundenen Pipelines - alle gefundenen Engines pro Runner-Typ, nun als einklappbare Abschnitte statt als unstrukturierte Vollansicht - direkte `Pipeline ausführen`- und `Engine ausführen`-Buttons im Runtime-Katalog - Verweis auf die YAML-Kompatibilitaetsansicht - native Datapool-Formulare fuer Drop, Truncate, Blueprint, CSV, Datenableitung und LOAD DATA ### 5.1.1 Responsive Bedienung Die Operator-Oberfläche ist für Desktop, Laptop, Tablet und schmale Smartphone-Breiten ausgelegt. Wichtig für die Bedienung: - Auf den geprüften Kernrouten entsteht kein horizontaler Seiten-Scroll auf Body-Ebene. - Lange technische Werte wie UUIDs, Dateipfade, Runner-Namen, Datapool-Namen und Feed-URLs umbrechen innerhalb ihrer Karten, Tabellenzellen und Badges. - Dichte Tabellen bleiben auf breiten Viewports als Tabellen sichtbar. - Auf schmalen Viewports werden Tabellenzeilen automatisch als gelabelte Kartenzeilen dargestellt, damit Spaltenüberschriften nicht verloren gehen. - Große Inventarbereiche wie Runtime-Kataloge und Legacy-Engine-Gruppen sind standardmäßig eingeklappt oder in ihrer Höhe begrenzt, damit die Startseite nicht unnötig lang wird. - Alle Inhalte bleiben erreichbar; bei sehr großen Datenbereichen wird innerhalb des jeweiligen Bereichs gescrollt statt die gesamte Seite horizontal zu verbreitern. ### 5.5 Bedienungsanleitung im Dashboard Unter `https://dataengine.domgan.de/manual` wird immer die aktuelle Datei `docs/bedienungsanleitung.md` aus dem ausgelieferten Stand angezeigt. Damit gilt: - Jede Aenderung an Bedienung, Commands oder Betrieb muss die Markdown-Datei aktualisieren. - Nach jedem Deployment ist die Live-Anleitung automatisch synchron mit dem Container-Stand. - Die Seite läuft inzwischen im selben Control-Plane-Shell-System wie die übrigen Operator-Screens. ### 5.6 Native Datapool-Operationen im Dashboard Im Bereich `Native Datapool Operations` stehen direkte Formulare fuer die nativen MySQL-Pfade bereit. Unterstuetzt: - Datapool loeschen - Datapool leeren - Datapool aus Blueprint-Datei erzeugen - Datapool aus CSV-Kopfzeile erzeugen - Datapool aus JSON- oder YAML-Daten ableiten - JSON- oder YAML-Daten per Multi-Insert in bestehende Datapools laden - Datapool-Strukturen von bestehenden Tabellen kopieren - CSV per `LOAD DATA LOCAL INFILE` in bestehenden Datapool laden Wichtig: - Die Dateipfade muessen aus Sicht des Dashboard-Containers existieren. - Mitgelieferte Beispielpfade liegen unter `/srv/app/docs/examples/`. - Dashboard und CLI nutzen dieselben Symfony-Services, damit Bedienung und Ausfuehrungslogik synchron bleiben. ### 5.7 Managed Definitions Workbench Unter `Definitionen` im Kopfbereich liegt die neue Anwendungsebene. Der Einstieg erfolgt jetzt über die linke Rail-Navigation unter `Workbench`. Innerhalb der Seite führt die Top-Bar zusätzlich über die Bereiche `Überblick`, `Authoring` und `Bestand`. Dort werden Engines und Pipelines als tenant-faehige Daten gepflegt: - neue Pipelines und Engines aus Starter-Templates anlegen - beliebig viele Engines je Runner-Typ und beliebig viele Pipelines tenant-spezifisch anlegen - YAML im Browser bearbeiten - bei Pipelines vorhandene Managed Engines über eine globale Suche oder typbezogene Picker direkt in den `Engines`-Block einfügen - Validierungshinweise direkt beim Speichern sehen - Revisionen pro Definition nachhalten - Draft-, Active- und Archived-Status setzen - die mitgelieferten Templates fuer Import und Unitize bleiben bewusst nah am Legacy-YAML-Stil und verwenden standardmaessig `importEngine` beziehungsweise `unitizeEngine` - Editor, Metadaten, Revisionen und Validierung sind in einer gemeinsamen Operator-Ansicht zusammengefuehrt - Die Detailbearbeitung einzelner Definitionsdatensätze nutzt denselben Shell-Stil und führt zusätzlich über die Bereiche `Überblick`, `Editor`, `Validierung`, `Metadaten` und `Revisionen`. Wichtig: - Diese Definitionen sind bewusst getrennt vom Tool-Code. - Sie werden derzeit in PostgreSQL gespeichert und versioniert. - `Active`-Definitionen fliessen tenant-spezifisch direkt in Runtime-Katalog, Planung und Ausfuehrung ein. - `Active`-Definitionen können direkt aus der Workbench-Liste und aus der Detailbearbeitung über `Run` beziehungsweise `Run starten` ausgeführt werden. - `Draft`- und `Archived`-Definitionen bleiben in der Workbench sichtbar, werden aber nicht ausgefuehrt und zeigen stattdessen einen nicht-aktiven Hinweis. - Die Workbench ist die kuenftige Quelle fuer neue Anwendungen; die Legacy-YAML-Dateien bleiben vorerst lesbar als Referenzbestand. ### 5.8 Commerce Templates bedienen Unter `https://dataengine.domgan.de/commerce-templates` liegt der neue Commerce-Template-Katalog. Der Katalog enthält: - den kanonischen Enhance-Standard `DataEngine Commerce Product v2` - CSV-Importstarter für generische Artikeldaten und Google-Merchant-nahe CSVs - API-Pull-Starter für CommerceOps ERP, Shopify, Shopware 6, Adobe Commerce / Magento, WooCommerce und Akeneo - Export-Templates für Google Merchant, idealo, günstiger.de, billiger.de, Kelkoo, Amazon, OTTO, Kaufland, CHECK24, eBay, Rakuten, Meta, Pinterest, TikTok, Criteo, Awin, Shopware 6 und Shopify - installierbare Pipeline-Recipes, die Import, Standardisierung und Channel-Export als Managed Drafts anlegen Wichtig: - Die Template-Dateien sind Tool-Implementierung und werden nicht direkt in der GUI editiert. - Ein Klick auf eine Recipe legt tenant-isolierte Managed Drafts in PostgreSQL an. - Bestehende Definitionen werden standardmäßig übersprungen; nur mit aktivierter Aktualisierung werden Template-Drafts überschrieben. - Die Export-Engines erzeugen channel-ready native Staging-Datapools. Datei-, SFTP- oder API-Auslieferung bleibt ein separater Push-/Connection-Profile-Schritt. - API-Importstarter benötigen vor Ausführung ein tenant-isoliertes `ready` Connection-Profil. Der Standard ist dokumentiert unter `docs/commerce-template-plan.md`. Die YAML-Standarddefinition liegt unter `symfony/config/commerce_templates/definitions/enhance/commerce_enhance_product_standard_v1.yaml`. ### 5.8.1 Ortho-Vertrieb Product Master bedienen Unter `https://dataengine.domgan.de/commerce-products` liegt die zentrale Pflegefläche für den Commerce Product Master. Sobald der ERP-Import vollständig ist, liest die Ansicht `commerce_product_master_v2`; der alte Shop-Snapshot bleibt nur als Fallback und Vergleichspfad erhalten. Auf `ortho-live` ist zusätzlich `DATAENGINE_ERP_MIN_PRODUCTS=30` gesetzt, damit ein Teilimport nicht versehentlich als produktiver ERP-Master angezeigt oder exportiert wird. Der Datapool heißt: - `commerce_product_master_v2` für den ERP-geführten Zielzustand - `ortho_vertrieb_product_master_v1` Wichtig: - Das ERP ist führend für Produkttexte, Produktinformationen, Zutaten, Bilder, Mehrwertsteuersätze, Kostenbasis, Lager und Status. - Die DataEngine erzeugt daraus channel-spezifische Projektionen. Google-Titel, Marktplatz-Kategorien, MwSt.-Zielformate oder Channel-Ausschlüsse sind Channel Overrides und keine zweite Wahrheit. - Der Import schreibt ausschließlich in die DataEngine-PostgreSQL-Datenbank des aktuellen Tenants. - Der Rückweg in den Shop läuft über einen geprüften Sync-Plan und ein Importartefakt, nicht über direkte ungeprüfte Datenbankänderungen. Die Oberfläche bietet: - Suchfeld über SKU, Titel, Marke, MPN, Produkttyp und Labels - Produktliste mit Preis, Verfügbarkeit, Bestand und Qualitätsstatus - Detailmaske nach Commerce Product Feldgruppen - Read-only Ansicht für `commerce_product_master_v2`, weil ERP-Stammdaten nicht lokal überschrieben werden dürfen - Anlage neuer Produktzeilen nur im alten DataEngine-Arbeitskopie-/Snapshot-Pfad, nicht im ERP-geführten v2-Master - Pflege von Channel Overrides unter `https://dataengine.domgan.de/commerce-products/overrides` - read-only Live-Shop-Diff gegen einen eingefügten JSON-Snapshot - CSV-Export des Product-Master-Datapools über die Infrastrukturansicht Channel Overrides in der Oberfläche: - Ein Override gilt für eine SKU, Produkt-ID, Item-Group-ID oder ERP-SKU und einen Channel. - Einfache Fälle werden als `field` und `value` gepflegt, mehrere Felder als JSON-Objekt im Feld `overrides`. - Aktive Regeln haben Status `active`, `approved`, `published` oder leer. `draft`, `disabled` und `archived` bleiben sichtbar, werden aber nicht angewendet. - Nach jeder Änderung muss die betroffene Projektion neu laufen, zum Beispiel `app:commerce:project-channel google_merchant --commit`. Der sichere ERP-Importablauf ist: 1. Im ERP Produkte und Bestände pflegen. 2. DataEngine mit einer API-Quelle oder JSON-Datei versorgen. 3. Den ERP-Import per Dry-Run und Mindestproduktzahl prüfen. 4. Erst danach mit `--commit` in `commerce_product_master_v2` importieren. 5. Channel Overrides nur für kanalbezogene Abweichungen nutzen. Für den initialen Ortho-Vertrieb-Bootstrap existiert ein eigener Command, der den geprüften DataEngine Product Master einmalig in den ERP-Tenant schreibt. Er darf nur bewusst genutzt werden, um den ERP-Startbestand herzustellen: ```bash php /srv/app/symfony/bin/console app:commerce:bootstrap-erp-from-product-master --tenant=default --source-datapool=ortho_vertrieb_product_master_v1 --erp-tenant=ortho-vertrieb --sync-stock php /srv/app/symfony/bin/console app:commerce:bootstrap-erp-from-product-master --tenant=default --source-datapool=ortho_vertrieb_product_master_v1 --erp-tenant=ortho-vertrieb --sync-stock --commit ``` Der produktive ERP-Import nutzt danach die API-Quellen aus `.env`: ```bash php /srv/app/symfony/bin/console app:commerce:import-erp-products --tenant=default --erp-tenant=ortho-vertrieb --min-products=30 --json php /srv/app/symfony/bin/console app:commerce:import-erp-products --tenant=default --erp-tenant=ortho-vertrieb --min-products=30 --commit --json ``` Aktueller Stand: Der ERP-Tenant `ortho-vertrieb` ist gebootstrappt und der DataEngine-Token ist serverlokal konfiguriert. Der produktive ERP-Cutover bleibt blockiert, bis die ERP-API `/api/v1/products` einen vollständigen oder paginierten Export liefert; aktuell kommen nur 20 Produkte zurück. Beispiel mit Dummy-Daten: ```bash php /srv/app/symfony/bin/console app:commerce:import-erp-products docs/examples/erp-products.example.json --stock-source=docs/examples/erp-stock.example.json --tenant=default --min-products=1 --commit php /srv/app/symfony/bin/console app:commerce:load-channel-overrides docs/examples/channel-overrides.example.json --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:project-channel ortho_shop --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:build-repricing-plan docs/examples/repricing-snapshot.example.json --channel=ortho_shop --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:export-ortho-shop-sync-plan --tenant=default --commit --target-file=/srv/app/symfony/public/feeds/ortho-shop/ortho-vertrieb-shop-sync.csv php /srv/app/symfony/bin/console app:commerce:project-channel google_merchant --tenant=default --target-datapool=commerce_channel_google_merchant_products_v1 --commit php /srv/app/symfony/bin/console app:commerce:export-ortho-google-merchant-feed --tenant=default --skip-run --datapool=commerce_channel_google_merchant_products_v1 ``` Der alte Shop-Snapshot-Import bleibt möglich, wenn der Live-Shop mit dem DataEngine-Master verglichen werden soll: Der sichere Vergleichsablauf vor jedem späteren Shop-Rückweg ist: 1. Auf `ortho-live` einen frischen read-only JSON-Snapshot aus der Shop-Datenbank erzeugen. 2. Unter `https://dataengine.domgan.de/commerce-products/diff` den Snapshot einfügen. 3. Den Diff prüfen: geänderte Felder, nur in DataEngine vorhandene SKUs, nur im Live-Shop vorhandene SKUs und SKU-Duplikate. 4. Alternativ oder zusätzlich den CLI-Command `app:commerce:diff-ortho-vertrieb-products` mit `--json` für eine maschinelle Auswertung nutzen. 5. Erst wenn der Diff fachlich erklärt ist, darf eine separate Rückschreibpipeline geplant werden. Der Diff selbst aktiviert keinen Write-back. Der Sync-Plan für den späteren Shop-Importer besteht immer aus CSV plus Manifest. Wenn `--target-file` gesetzt ist, schreibt die DataEngine zusätzlich `<target-file>.manifest.json` mit SHA-256, Zeilenzahl, Spaltenliste und Transaktionspflichten. Der genaue Importvertrag steht in `docs/ortho-shop-transactional-import-contract.md`. ### 5.8.2 Ortho-Vertrieb Google-Merchant-Feed erzeugen Der Google-Merchant-Feed wird aus dem DataEngine Product Master erzeugt und nicht direkt aus dem Live-Shop. Feed-URL: ```text https://dataengine.domgan.de/feeds/google/ortho-vertrieb-products.tsv ``` Der technische Ablauf ist: 1. `ortho_product_master_to_google_merchant` installiert die Ortho-spezifische Export-Engine und Pipeline. 2. `commerce_pipeline_ortho_vertrieb_google_merchant` schreibt den Datapool `ortho_vertrieb_google_merchant_feed_v1`. 3. `app:commerce:export-ortho-google-merchant-feed` validiert die Zeilen und schreibt die tab-getrennte Feed-Datei. 4. `app:commerce:ortho-google-marketing-health` prüft nach dem Export kaufbare Produkte, URLs, Consent-/Tracking-Grundlagen und offene Google-Zugriffspunkte. 5. Der Compose-Service `scheduler` führt Export und Health-Check automatisch aus: einmal beim Containerstart und danach täglich um `23:45 Europe/Berlin`. Produktive Ausführung: ```bash php /srv/app/symfony/bin/console app:commerce:install-template ortho_product_master_to_google_merchant --tenant=default --overwrite --activate php /srv/app/symfony/bin/console app:etl:plan pipeline commerce_pipeline_ortho_vertrieb_google_merchant --tenant=default php /srv/app/symfony/bin/console app:commerce:export-ortho-google-merchant-feed --tenant=default php /srv/app/symfony/bin/console app:commerce:ortho-google-marketing-health --json ``` Wichtig: - Die Pipeline verändert nicht den Live-Shop `ortho-vertrieb.de`. - Die Feed-Datei ist ein Laufzeitartefakt unter `var/public-feeds` und wird nicht in Git versioniert. - Der Scheduler erzeugt die Datei vor dem Merchant-Center-Abruf um `00:00` neu, damit Product-Master-Änderungen täglich im Google-Feed landen. - Die Scheduler-Übersicht unter `https://dataengine.domgan.de/scheduler` zeigt den nächsten Lauf, den letzten Export, Zeilen, Blocker, Warnungen, Marketing-Health und die relevanten Operator-Kommandos. - Der Marketing-Health-Report liegt als JSON unter `https://dataengine.domgan.de/feeds/google/ortho-vertrieb-marketing-health.json` und als Markdown unter `https://dataengine.domgan.de/feeds/google/ortho-vertrieb-marketing-health.md`. - Der Export blockiert leere Feeds und Pflichtfeldfehler. - Landingpage-, Hauptbild- und zusätzliche Bild-URLs werden beim Export URL-sicher kodiert, damit Merchant Center nicht an Leerzeichen oder unkodierten Pfadzeichen scheitert. - Für Ortho-Vertrieb-Bilder aus `/images/Orthomed-middle/` bevorzugt der Export automatisch die passende größere Datei aus `/images/Orthomed-big/`, wenn sie erreichbar ist. Die bisherige mittlere Datei bleibt dann als zusätzliche Bild-URL im Feed, damit Merchant Center eine robuste Bildalternative erhält. - Produktkennzeichnungen werden getrennt gepflegt: `gtin` ist nur für echte GTIN/EAN/UPC/JAN/ISBN-Werte mit gültiger Prüfziffer, `mpn` ist die Herstellerartikelnummer, und `identifier_exists` steuert, ob Google eindeutige Produktkennzeichnungen erwarten soll. - PZN, interne SKU oder MPN dürfen nicht in `gtin` kopiert werden. PZN kann als Label oder in einem künftigen fachlichen PZN-Feld geführt werden, ist aber kein GTIN-Ersatz für Google Merchant. - Fehlende GTINs werden als Warnung gemeldet, solange Brand+MPN vorhanden sind. Echte GTIN/EAN-Werte dürfen nur aus belegten Quellen wie Verpackung, Herstellerdaten, GS1-Daten oder einem geprüften Lieferantenstamm nachgepflegt werden. - Der produktive Google-Feed ist eine channel-spezifische Projektion, nicht der vollständige Product Master. Aktueller Stand: Der Feed enthält 33 Produkte. `MS10`/`Orthoaurinor` wird nicht exportiert, weil es nicht öffentlich aktiv sichtbar ist; `ORTH31`/`Ortholuna` wird nicht exportiert, weil Merchant Center dafür ein Gesundheits-/Nahrungsergänzungsmittel-Policy-Thema angezeigt hatte. - Die Beschreibungen werden für den Google-Kanal neutral erzeugt und übernehmen keine ungeprüften Legacy-Wirkungs-, Heil- oder Therapieformulierungen. - Nach einem sauberen Merchant-Center-Abruf können einzelne Produkte trotzdem noch auf "Wird überprüft" oder "Nicht genehmigt" stehen. Solche Restfälle sind Google-seitige Bildverarbeitung, Richtlinien- oder Produktprüfungen und müssen in Merchant Center diagnostiziert werden. - Google Ads Kampagnen oder Werbeausgaben dürfen erst nach Merchant-Center-Freigabe, Konto-Verknüpfung, Conversion-Tracking-Prüfung und bestätigtem Budget gestartet werden. Aktueller Stand: Die bestehende Standard-Shopping-Kampagne `Domgan Google Shopping` ist mit `5,00 EUR/Tag` aktiviert; weitere Budget-, Gebots-, Zielgruppen- oder Kampagnenänderungen benötigen wieder eine explizite Freigabe. Aktueller geprüfter Stand vom 2026-05-07: - Merchant Center Datenquelle `PRODUCTS SOURCE 3` nutzt diese DataEngine-Feed-URL und hat die nachgeschärfte Datei um `09:21` mit `33` Produkten übernommen. - Der Export meldet `0` Blocker und `33` GTIN-Hinweise. - Alle aktuellen Feed-Produkt-, `srsltid`-, Bild- und Zusatzbild-URLs liefern mit Googlebot-User-Agent HTTP 200 und sind nicht per `X-Robots-Tag` blockiert. - Merchant Center hat sich weiter verbessert: Nach der angeforderten Websiteprüfung ist `Produktseite nicht verfügbar` nicht mehr sichtbar. Übrig sind derzeit Google-seitige Bildverarbeitungshinweise (`Bild nicht verarbeitet` und `Bild kann nicht angezeigt werden`), die der Feed nun durch bevorzugte größere Bilddateien unterstützt und der Health-Report weiter überwacht. - Die Datenquelle selbst meldet nach dem manuellen Abruf `Ihre Produkte wurden aktualisiert` und `Keine Probleme gefunden`; Produktfreigaben und Bildreview bleiben dennoch in der Produktdiagnose zu beobachten. - Google Analytics 4 ist mit Google Ads `116-425-2507`, Merchant Center `119414541` und Search Console `ortho-vertrieb.de` verknüpft. Die Search Console Domain-Property ist verifiziert, und die HTTPS-Sitemap `https://www.ortho-vertrieb.de/sitemap.xml` ist erfolgreich eingereicht. - Google Ads API ist weiterhin durch `DEVELOPER_TOKEN_NOT_APPROVED` blockiert. Bis Basic/Standard Access oder AgentGuard-Providerzugriff verfügbar ist, bleiben echte Google-Ads-, GA4-, Search-Console- und Merchant-Diagnosemetriken browsergestützte Prüfschritte oder manuelle Exporte. Die vollständige Rollout-Checkliste steht in `docs/google-merchant-rollout.md`. ### 5.2 Pipeline ausführen Pipelines können direkt gestartet werden über: 1. Runtime-Katalog auf der Startseite 2. Managed-Definitions-Workbench, wenn die Definition `active` ist 3. Managed-Definition-Detailseite, wenn die Definition `active` ist 4. Legacy-YAML-Browser oder Legacy-Detailseite, wenn die YAML-Datei gültig parsebar ist Ausführung: 1. Pipeline-Karte oder Tabellenzeile wählen 2. `Pipeline ausführen`, `Run` oder `Run starten` klicken 3. Das System legt einen Run in PostgreSQL an 4. Symfony plant die Ausfuehrung nativ und entscheidet zwischen `native_staging_pipeline` und Legacy-Bridge 5. Wenn alle Schritte nativen Import oder nativen Unitize nutzen, laeuft die Pipeline direkt als `native_staging_pipeline` 6. Nur falls kein nativer Pipeline-Pfad moeglich ist, wird fuer Managed Definitions ein isolierter Overlay-Snapshot fuer die Legacy-Bridge vorbereitet 7. Der Run wird nativ oder ueber die Legacy-Bridge abgearbeitet 8. Im Run-Detail ist der native Preflight mit Strategie, Quelle und Schritten sichtbar ### 5.3 Engine ausführen Engines können direkt gestartet werden über: 1. Runtime-Katalog auf der Startseite 2. Managed-Definitions-Workbench, wenn die Definition `active` ist 3. Managed-Definition-Detailseite, wenn die Definition `active` ist 4. Legacy-YAML-Browser oder Legacy-Detailseite, wenn die YAML-Datei gültig parsebar ist Ausführung: 1. Engine-Karte oder Tabellenzeile wählen 2. `Engine ausführen`, `Run` oder `Run starten` klicken 3. Der Run wird in PostgreSQL protokolliert 4. Symfony plant die Ausfuehrung nativ und entscheidet zwischen `native_import_file_to_staging` und Legacy-Bridge 5. Native Managed File-Importe schreiben direkt in tenant-isolierte PostgreSQL-Staging-Datapools 6. Native Managed Unitize-Engines lesen aus vorhandenen nativen Staging-Datapools und schreiben ihr Ziel ebenfalls dorthin 7. Standalone-Unitize braucht deshalb einen vorhandenen nativen Source-Datapool oder muss ueber eine passende Pipeline zusammen mit dem Import laufen 8. Nur nicht-native Engines erhalten bei Bedarf einen isolierten Overlay-Snapshot fuer die Legacy-Bridge ### 5.4 Run-Detail lesen Im Run-Detail werden angezeigt: - Run-Status - Runner-Typ und Name - Trigger-Quelle - Start-/Endzeit - Exit-Code - stdout/stderr - nativer Ausfuehrungsplan mit Quelle, Schritten, Connections und Validierungsfehlern - aktive Strategie der Ausfuehrung, inklusive Hinweis auf native PostgreSQL-Staging-Runtime - Anzahl und Herkunft von Managed-Definition-Overlays - gebuendelte Prozessausgaben fuer stdout und stderr in einer gemeinsamen Diagnoseansicht - dieselbe Top-Bar-Navigation mit direkten Sprüngen zu Metadaten, Ausführungsplan und Prozessausgaben ### 5.9 Infrastruktur bedienen Unter `https://dataengine.domgan.de/infrastructure` liegt die operative Infrastrukturansicht der DataEngine. Sie bündelt zwei getrennte Betriebsbereiche: - Connection-Profile als tenant-isolierte Verbindungsmetadaten - native PostgreSQL-Staging-Datapools der Managed Runtime Die Seite bietet: - KPI-Überblick über Profilbestand, Kategorien und Staging-Datapools - eine Coverage-Ansicht für fehlende und als Draft vorbereitete Connection-Profile mit Verwendungszählern, Runner-Typen, Bulk-Scaffold und Direktlink in den Profil-Editor - gruppierte Listen aller vorhandenen Connection-Profile - Detail- und Pflegeansicht pro Connection-Profil - Anlegen neuer Profile innerhalb derselben Shell - Bestandsliste nativer Staging-Datapools mit direktem Sprung in die Detailansicht Wichtig für die Provisionierung: - Connection-Profile besitzen jetzt einen expliziten Status `draft` oder `ready`. - `draft` bedeutet: Profil ist im Tenant inventarisiert und bearbeitbar, blockiert Planner und Runtime aber weiterhin bewusst. - `ready` bedeutet: Profil darf von Planner und Runtime als wirksam behandelt werden. - Über die Aktion `Alle fehlenden Drafts anlegen` wird der aktuelle Provisioning-Backlog als bearbeitbarer Draft-Bestand in PostgreSQL überführt, ohne externe Systeme zu kontaktieren. In den Profil-Detailseiten können gepflegt werden: - Kategorie - Profilname - Transport - Provisioning-Status - Source Path - `settings` als JSON-Objekt - Secret-Felder als zeilenweise Liste In den Datapool-Detailseiten sichtbar sind: - Name, Runner, Herkunft und Zeitstempel - Spaltenschema - Zeilenstichprobe mit bis zu 25 Zeilen - Vollansicht kleiner Datapools bis 200 Zeilen - gespeicherte Datapool-Metadaten als JSON Wichtig: - Connection-Profile bleiben Betriebsdaten des Tools und werden nicht zurück in Legacy-Dateien geschrieben. - Wenn serverlokale Legacy-Credentials fehlen, zeigt die Coverage-Ansicht die offenen Profilnamen und ihre konkrete Nutzung im Katalog. - Große Datapools werden absichtlich nicht standardmäßig vollständig gerendert. - Die Übersicht im Dashboard bleibt als Schnellzugriff erhalten; detaillierte Pflege liegt jetzt in der Infrastrukturansicht. ### 5.9 Legacy YAML Browser Unter `https://dataengine.domgan.de/legacy-definitions` liegt die read-only Sicht auf den bisherigen YAML-Bestand im Filesystem. Der Legacy-Browser und seine Detailseiten laufen inzwischen ebenfalls im neuen Shell-System mit Bereichsankern für Überblick, Pipelines, Engines, Raw YAML, Metadaten und gegebenenfalls Pipeline-Schritte. Die Ansicht bietet: - Liste aller gefundenen Legacy-Pipelines - Liste aller Legacy-Engines je Runner-Typ - Parse-Status pro Datei - Dateipfad der Originaldatei - erkannte Feature-Flags und Connection-Hinweise - Raw-YAML-Ansicht pro Definition - Anzeige, ob bereits eine passende Managed Definition existiert - sicheren Import als tenant-isolierter `Draft` in die Workbench - direkte Run-Buttons für gültig parsebare Legacy-Pipelines und Legacy-Engines Wichtig: - Der Browser bearbeitet keine Legacy-Dateien direkt. - Die Originaldateien im Filesystem bleiben unveraendert. - Ungültige Legacy-YAML-Dateien sind sichtbar, aber nicht direkt lauffähig. - Bearbeitet wird erst nach dem Import in die Managed-Definitions-Workbench. - Wenn fuer dieselbe Definition bereits eine Managed Definition existiert, wird diese geoeffnet statt eine Duplikatkopie anzulegen. Empfohlener Workflow: 1. Legacy-Definition im Browser suchen. 2. Detailansicht oeffnen und Raw-YAML sowie Metadaten pruefen. 3. `Als Managed Draft importieren` ausloesen. 4. In der Workbench weiter bearbeiten, validieren und aktivieren. ## 6. MCP verwenden Der Endpunkt `POST https://dataengine.domgan.de/mcp` spricht JSON-RPC im MCP-Stil. Daneben gibt es eine öffentliche Discovery-Schicht für Crawler und AI-Clients: - `GET https://dataengine.domgan.de/llms.txt` - `GET https://dataengine.domgan.de/site-context.md` - `GET https://dataengine.domgan.de/ai-discovery.md` - `GET https://dataengine.domgan.de/manual.md` - `GET https://dataengine.domgan.de/commerce-templates` Diese Dokumente sind bewusst read-only, enthalten keine tenant-spezifischen Betriebsdaten und verlinken auf denselben kanonischen MCP-Endpunkt der Plattform. Unterstuetzt werden aktuell mindestens: - `initialize` - `ping` - `tools/list` - `tools/call` - `resources/list` - `resources/read` - `prompts/list` Wichtige Tools: - `tenant_list`, `tenant_create` - `runtime_catalog_scan` - `managed_definition_list`, `managed_definition_get`, `managed_definition_create`, `managed_definition_update`, `managed_definition_delete`, `managed_definition_revisions` - `legacy_definition_list`, `legacy_definition_get`, `legacy_definition_import` - `connection_profile_list`, `connection_profile_coverage`, `connection_profile_get`, `connection_profile_upsert`, `connection_profile_delete`, `connection_profile_scaffold_missing` - `execution_plan`, `execution_start` - `run_list`, `run_get` - `native_staging_datapool_list`, `native_staging_datapool_get` - `commerce_template_list`, `commerce_template_get`, `commerce_template_install_recipe` Wichtig: - Legacy-Dateien bleiben auch ueber MCP read-only. - Schreibende Aenderungen laufen ueber Managed Definitions und andere tenant-eigene PostgreSQL-Daten. - Managed-Definitions-Tools akzeptieren entweder `yaml_content` oder ein strukturiertes `document`. - Dadurch lassen sich auch `Mapping`, `Filters`, `Source_Files`, `Datapool_Definition` und andere tiefe YAML-Abschnitte per MCP bearbeiten. ### 6.1 Beispiel: MCP initialisieren ```json { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {} } ``` ### 6.2 Beispiel: Tools auflisten ```json { "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} } ``` ### 6.3 Beispiel: Managed Definition per strukturiertem Dokument anlegen ```json { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "managed_definition_create", "arguments": { "tenant": "default", "definition_kind": "engine", "runner_type": "import", "name": "mcp_sample_import", "title": "MCP Sample Import", "status": "draft", "document": { "Source_Connection_Type": "file", "Target_Config": "importEngine", "Engine_Mode": "full", "Source_Files": [ { "Full_Path": "/srv/app/docs/examples/datapool-import.example.csv", "Datatype": "csv", "Headline": "yes", "Field_Termination": ";", "Field_Enclosure": "\"", "Line_Termination": "\\n", "Target_Datapool": "mcp_sample_import_pool" } ] } } } } ``` ### 6.4 Beispiel: Pipeline planen ```json { "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "execution_plan", "arguments": { "tenant": "default", "runner_type": "pipeline", "name": "pipeline_update_articles_wandmontage", "arguments": [] } } } ``` ### 6.5 Beispiel: Pipeline oder Engine starten ```json { "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "execution_start", "arguments": { "tenant": "default", "runner_type": "pipeline", "name": "pipeline_update_articles_wandmontage", "mode": "queue", "arguments": [] } } } ``` ## 7. Codex Plugin verwenden Das Plugin `plugins/dataengine-mcp` kapselt denselben Endpunkt fuer Codex. Ziel: - Nutzung dieses DataEngine-MCP-Servers aus anderen Codex-Projekten - versionierte Plugin-Definition direkt im privaten Repository - keine globale Systemaenderung ausserhalb dieses Projekts in diesem Schritt Die relevante Datei ist: - `plugins/dataengine-mcp/.mcp.json` Dort zeigt der konfigurierte MCP-Server `dataengine` auf: - `https://dataengine.domgan.de/mcp` Wenn ein anderes Codex-Projekt dieses Plugin referenziert oder installiert, kann es darueber direkt auf die DataEngine-Funktionen zugreifen. ### 5.9 Native Staging Runtime Die native Staging-Runtime ist die erste vollstaendig neue fachliche Laufzeit im Symfony-Tool. Aktuell unterstuetzt: - Managed Import-Engines vom Typ `import` - Managed Transform-Engines vom Typ `unitize`, `enhance` und `export` - Dateiquellen `csv`, `json`, `yaml` - Ziel `native_runtime`, `native_staging` oder der Legacy-Alias `importEngine` - Managed Pipelines, deren Schritte vollstaendig aus nativ unterstuetzten Import- und Transform-Engines bestehen Verhalten: - die Quelldateien werden im Dashboard-Container gelesen - die Daten werden tenant-isoliert in PostgreSQL gespeichert - native Transform-Runs lesen aus vorhandenen nativen Staging-Datapools und erzeugen neue tenant-isolierte Zieldatapools - Staging-Datapools werden pro `tenant + datapool_name` serialisiert ersetzt, damit parallele Trigger keine Unique-Constraint-Fehler erzeugen - Dashboard, CLI und Worker verwenden dafuer dieselbe Symfony-Laufzeit - fuer Query-basierte Transform-Pfade wird intern eine lokale SQLite-Runtime gegen die PostgreSQL-Staging-Datapools aufgebaut; dadurch bleiben Tests und Ausfuehrung innerhalb der Tool-DB Aktuell unterstuetzte native Transform-Teilmenge: - `Source_Config` und `Target_Config` duerfen `native_runtime`, `native_staging` oder fuer den Legacy-kompatiblen Managed-Pfad `importEngine`, `unitizeEngine`, `enhanceEngine` beziehungsweise `exportEngine` sein - `Source_Datapool`, `Datapool` oder `Target_Datapool`, `Mapping` und optional `Datapool_Definition` werden ausgewertet - direkte Mapping-Werte wie `source_pool.field`, `field` und Literale wie `(foo)` werden unterstuetzt - generierte Query-Ausfuehrung fuer `Joins`, `Left_Join`, einfache `Read_Conditions` und Ausdrucks-Mappings wie `CONCAT(...) AS alias` wird unterstuetzt - freie `Sql`-Bloecke werden in einer nativen Teilmenge unterstuetzt, aktuell vor allem `SELECT`, `UNION`, `GROUP_CONCAT`, `CONCAT`, `COALESCE`, `SUBSTRING`, `IF`, `MAX`, `TRIM` sowie MySQL-Trim-Modifikatoren wie `TRIM(LEADING ...)`, `TRIM(TRAILING ...)` und `TRIM(BOTH ... FROM ...)` gegen native Staging-Datapools - `Field_Adapter` wird nativ in einer wachsenden Teilmenge ausgefuehrt, derzeit unter anderem `replace`, `replace_empty`, `replace_empty_else`, `replace_greater`, `replace_smaller`, `replace_not_equals`, `trim`, `ltrim`, `rtrim`, `substr`, `get_preg_match`, `explode`, `tolower`, `round`, `float_pricision`, `str_pad`, `simple_multiplication`, `simple_division`, `select_max_field`, `concat_fields`, `getfromjsonfield`, `absolutevalue`, `source`, `concat`, `concat_source`, `extend_if_not_empty`, `add_string`, `add_prefix`, `addslashes`, `change_charset`, `nl2br`, `strtotime`, `md5` und `if` - `Filters` werden nativ in einer wachsenden Teilmenge ausgewertet, derzeit stringbasierte Bedingungen, `Equals`, `In_String`, `In_Pool_Filter_Adapter` und `Not_In_Pool_Filter_Adapter` auf nativen Staging-Datapools - `Cross_Field_Adapter`, `Cross_Field_Adapters` und `Cross_Field_Adapters_Target_Injection` werden nativ in einer ersten Staging-Teilmenge unterstuetzt, derzeit fuer native PostgreSQL-Staging-Datapools mit einfacher Lookup-Form, Mapping-Lookups und den Optionen `keep_existing`, `concat`, `match_only`, `match_not_empty_only` und `case_sensitiv` - passive Legacy-Metadaten wie `In_Export` werden fuer die native Ausfuehrung toleriert und nicht als Blocker gewertet - Query-Modi sind `direct`, `generated` und `sql`; sie erscheinen im Ergebnis- und Datapool-Metadatenbild - `Cross_Dataset_Filter_Adapter` wird nativ in einer ersten benannten Teilmenge unterstuetzt, derzeit fuer Duplicate-Key-, No-Picture-, Slow-Delivery-, Marketplace-, Non-Parent- und Variant-Without-Parent-Filter auf nativen PostgreSQL-Staging-Datapools - `File_Field_Adapter`, Legacy-Alias `File_Field_Adapters` und `File_Field_Adapter_Source_Injection` werden nativ in einer sicheren Teilmenge unterstuetzt: erlaubt sind lokale Legacy-Adapterdateien pro Runner-Typ, target- und source-injection, verkettete `Files`, lokal sichere row-mutating In-Memory-Semantik ueber `cross_dataset_buffer` beziehungsweise `dataset_amount` sowie kontrolliertes Additional-Datapool-Loading ueber interne Legacy-Aliasse plus `Datapool`, `Identifier`, `Fields` und einfache skalare `Conditions` auf nativen Staging-Datapools sowie read-only Helper-Lookups ueber verifizierbare lokale Legacy-Datenbankprofile in `mysql` oder `pgsql`, solange keine Datei-, Netzwerk- oder Prozess-Nebenwirkungen benoetigt werden - nicht unterstuetzte SQL-Konstrukte sowie weitere Legacy-Sondersemantik bleiben vorerst im Legacy-Pfad Wichtig fuer die native Pool-Filter: - `In_Pool_Filter_Adapter` und `Not_In_Pool_Filter_Adapter` arbeiten derzeit nur gegen native PostgreSQL-Staging-Datapools innerhalb des Tools - die Mapping-Variante von `Not_In_Pool_Filter_Adapter` behaelt bewusst die Legacy-Semantik bei, bei der jede nicht passende Pool-Zeile als Filtertreffer zaehlt - dadurch koennen mehrere Filtergruende fuer eine einzelne Datensatzzeile entstehen; diese werden in den Datapool-Metadaten mitgezaehlt Wichtig fuer die native Cross-Field-Adapter: - die native Cross-Field-Teilmenge arbeitet derzeit nur gegen native PostgreSQL-Staging-Datapools innerhalb des Tools - die einfache Legacy-Form mit `Local_Key` und `Cross_Key` behaelt bewusst das beobachtete Legacy-Verhalten bei: die aktuelle Zeile wird fuer den Lookup ueber den Wert von `Cross_Key` adressiert - Mapping-basierte Cross-Lookups nutzen ihre explizite lokale Feldzuordnung und koennen auf Wunsch case-insensitiv arbeiten - `Cross_Field_Adapters_Target_Injection` liest gegen den bereits aufgebauten Ziel-Datensatz derselben Zeile; dadurch muss das referenzierte Zielfeld vor dem injizierenden Mapping aufgebaut werden Wichtig fuer die native Cross-Dataset-Filter: - die native Cross-Dataset-Teilmenge arbeitet derzeit nur gegen native PostgreSQL-Staging-Datapools innerhalb des Tools - unterstuetzt sind aktuell erste benannte Legacy-Adapter fuer Duplicate-Key-, No-Picture-, Slow-Delivery-, Marketplace-, Non-Parent- und Variant-Without-Parent-Semantik - die nativen Filter behalten bewusst die beobachtete Legacy-State-Semantik bei: ein Engine-Lauf teilt einen gemeinsamen Cross-Dataset-Zustand ueber alle Quellzeilen und unterstuetzten Cross-Dataset-Filter - row-mutierende Legacy-Sonderfaelle auf verworfenen Zeilen sind noch nicht Teil der nativen Teilmenge und bleiben bis zur spaeteren Portierung im Legacy-Pfad Wichtig fuer die native File-Field-Adapter: - die native File-Field-Teilmenge arbeitet derzeit nur fuer Managed Transform-Engines auf nativen PostgreSQL-Staging-Datapools innerhalb des Tools - unterstuetzt sind `File_Field_Adapter`, Legacy-Alias `File_Field_Adapters` und `File_Field_Adapter_Source_Injection`, wenn die referenzierte Legacy-PHP-Datei im runner-spezifischen Adapterordner liegt und innerhalb der sicheren nativen Teilmenge bleibt - `Files`-Ketten werden in derselben Reihenfolge ausgefuehrt wie im YAML - `File_Field_Adapters` wird dabei bewusst als Legacy-Kompatibilitaetsalias derselben target-seitigen Adaptersemantik behandelt wie `File_Field_Adapter` - wenn `File` fehlt, wird wie im Legacy-Bestand die Default-Aufloesung `Target_Datapool.Zielfeld` verwendet - Additional-Datapool-Loading ist nativ erlaubt, wenn die Definition interne Runtime-Aliasse nutzt und `Datapool`, `Identifier` sowie `Fields` auf einen nativen Staging-Datapool innerhalb des Tools verweisen - zusaetzlich sind fuer diesen internen Helper-Pfad einfache skalare SQL-aehnliche `Conditions` erlaubt, zum Beispiel `active = 1`; die Bedingung wird vor dem Adapter-Aufruf auf demselben nativen Staging-Datapool ausgewertet - alternativ sind read-only Helper-Lookups ueber `Config` oder `Engine` erlaubt, wenn das referenzierte lokale Legacy-Datenbankprofil in Symfony als `native_ready` verifizierbar ist; aktuell ist dieser Pfad fuer `mysql` und `pgsql` vorgesehen - wenn fuer den konfigurierten `Identifier` kein passender Wert in der aktuellen Quell- oder Zielzeile gefunden wird, wird wie im Legacy-Pfad die vollstaendige geladene Additional-Datapool-Collection an den Adapter uebergeben - ebenfalls verifiziert ist eine erste row-mutating Teilmenge, bei der der Legacy-Adapter nur den nativen In-Memory-Status innerhalb eines Engine-Runs veraendert; bestaetigt wurde das lokal unter anderem mit `export_articles_oms.attr22` - bewusst nicht nativ unterstuetzt sind aktuell komplexe oder nicht-skalare `Conditions`, nicht native-ready externe `Config`- oder `Engine`-Profile, ODBC-basierte Helper-Profile sowie Adapterdateien mit Datei-, Netzwerk-, Prozess- oder sonstigen Seiteneffekten - solche Definitionen bleiben planbar, fallen aber fuer die fachliche Ausfuehrung weiterhin auf den Legacy-Pfad zurueck ### 5.10 YAML-Kompatibilitaetsansicht Unter `https://dataengine.domgan.de/compatibility` wird die Kompatibilitaet der bestehenden YAML-Dateien explizit ausgewertet. Die Seite nutzt nun dieselbe Shell-Struktur und führt über `Mandantenkontext`, `Vergleich` und `Blocker` durch die Auswertung. Die Ansicht trennt zwei Perspektiven: - `active` tenant-spezifische Runtime-Sicht; gleichnamige aktive Managed Definitions koennen hier Legacy-YAMLs uebersteuern - `legacy-filesystem` direkter Blick auf die vorhandenen Legacy-YAML-Dateien ohne Managed-Overrides Damit gilt fuer die bestehende Prozesssteuerung: - Das aktuelle YAML-Format bleibt erhalten und soll auch im Zielsystem weiterhin funktionieren. - Nicht alles muss dafuer sofort nativ in Symfony laufen. - Solange eine Definition fachlich korrekt ist, darf sie weiterhin ueber die Legacy-Bridge ausgefuehrt werden. - Erst wenn ein nativer Symfony-Pfad verfuegbar ist, wird dieselbe Definition tenant-spezifisch nativ geplant oder ausgefuehrt. - Neue Managed Definitions duerfen fuer native Import- und Transform-Pfade weiterhin die vertrauten Legacy-Konfigurationswerte `importEngine`, `unitizeEngine`, `enhanceEngine` und `exportEngine` verwenden. - Blockierte YAMLs sind keine Migrationsentscheidung, sondern echte Inkonsistenzen wie fehlende referenzierte Engines oder Connections. ## 6. Wichtige CLI-Commands Alle Commands laufen im Dashboard-Container. Beispiel: ```bash ssh ortho-live 'cd /opt/containers/drive-dataengine && docker compose -f compose.yaml exec -T dashboard php /srv/app/symfony/bin/console <command>' ``` ### 6.1 Katalog und Planung - `app:etl:list [--tenant=default]` listet den tenant-spezifischen Runtime-Katalog aus Managed Definitions und Legacy-Definitionen - `app:etl:plan <runner-type> <name> [--tenant=default]` erzeugt den nativen Ausfuehrungsplan inklusive Definitionsquelle und Managed-Overlay-Zusammenfassung - `app:etl:report-yaml-compatibility [--tenant=default] [--source=legacy|managed|all] [--scope=active|legacy-filesystem] [--format=table|json]` bewertet die YAML-Kompatibilitaet entweder fuer den aktiven Runtime-Katalog oder direkt fuer den rohen Legacy-Dateibestand - `app:commerce:templates [--json]` listet den Commerce-Template-Katalog, die Exportkanäle und installierbaren Recipes - `app:commerce:install-template <recipe> [--tenant=default] [--overwrite] [--json]` importiert eine Commerce-Recipe als tenant-isolierte Managed Drafts - `app:commerce:install-template <recipe> [--tenant=default] [--overwrite] [--activate] [--json]` importiert eine Commerce-Recipe explizit als aktive Managed Definitions; nur für geprüfte operative Recipes verwenden - `app:commerce:bootstrap-erp-from-product-master [--tenant=default] [--source-datapool=ortho_vertrieb_product_master_v1] [--erp-base-url=https://erp.domgan.de] [--erp-tenant=ortho-vertrieb] [--sync-stock] [--limit=0] [--commit] [--json]` initialisiert den ERP-Tenant aus einem geprüften DataEngine Product Master; ohne `--commit` ist es ein Dry-Run - `app:commerce:import-erp-products <products-json-or-url> [--stock-source=<stock-json-or-url>] [--tenant=default] [--erp-tenant=default] [--datapool=commerce_product_master_v2] [--min-products=0] [--commit] [--json]` importiert ERP-Produkte und Bestände in den kanonischen Product Master v2 - `app:commerce:load-channel-overrides <overrides-json|-> [--tenant=default] [--datapool=commerce_channel_overrides_v1] [--commit] [--json]` lädt channel-spezifische Override-Regeln in die DataEngine - `app:commerce:project-channel <channel> [--tenant=default] [--source-datapool=commerce_product_master_v2] [--override-datapool=commerce_channel_overrides_v1] [--commit] [--json]` erzeugt einen kanalbezogenen Projektions-Datapool aus ERP-Master und Overrides - `app:commerce:build-repricing-plan [<repricing-json|->] [--channel=ortho_shop] [--tenant=default] [--source-datapool=commerce_product_master_v2] [--commit] [--json]` prüft ecommerceOS-Preisempfehlungen gegen Kostenbasis und Mindestmargen - `app:commerce:export-ortho-shop-sync-plan [--tenant=default] [--source-datapool=commerce_channel_ortho_shop_products_v1] [--price-plan-datapool=commerce_repricing_plan_v1] [--target-file=<csv>] [--commit] [--json]` erzeugt den Ortho-Shop-Importplan als DataEngine-Datapool und optional als CSV plus `<csv>.manifest.json` - `app:commerce:import-ortho-vertrieb-products <snapshot-file|-> [--tenant=default] [--datapool=ortho_vertrieb_product_master_v1] [--include-inactive] [--commit] [--json]` prüft oder importiert einen read-only Ortho-Vertrieb Produkt-Snapshot in den Commerce Product Master Datapool - `app:commerce:diff-ortho-vertrieb-products <snapshot-file|-> [--tenant=default] [--datapool=ortho_vertrieb_product_master_v1] [--include-inactive] [--field=<feld>] [--max-details=50] [--json]` vergleicht den Product Master read-only mit einem frischen Ortho-Vertrieb Live-Shop-Snapshot und schreibt weder in den Shop noch in den Product Master - `app:commerce:export-ortho-google-merchant-feed [--tenant=default] [--pipeline=commerce_pipeline_ortho_vertrieb_google_merchant] [--datapool=ortho_vertrieb_google_merchant_feed_v1] [--skip-run] [--json]` führt die Ortho-Vertrieb Google-Merchant-Pipeline aus, validiert den Feed und schreibt die TSV-Datei für Merchant Center Scheduled Fetch - `app:commerce:ortho-google-marketing-health [--check-urls] [--json]` prüft den aktuellen Ortho-Vertrieb Google-Merchant-Feed, Product-/Image-URLs, Tracking-Grundlagen und dokumentiert Google-/API-Gates als JSON und Markdown Beispiel: ```bash php /srv/app/symfony/bin/console app:etl:list --tenant=default php /srv/app/symfony/bin/console app:etl:plan pipeline pipeline_update_articles_wandmontage --tenant=default php /srv/app/symfony/bin/console app:etl:report-yaml-compatibility --tenant=default --source=legacy --scope=legacy-filesystem --format=table php /srv/app/symfony/bin/console app:commerce:templates php /srv/app/symfony/bin/console app:commerce:install-template csv_to_google_merchant --tenant=default php /srv/app/symfony/bin/console app:commerce:install-template ortho_product_master_to_google_merchant --tenant=default --overwrite --activate php /srv/app/symfony/bin/console app:commerce:import-erp-products docs/examples/erp-products.example.json --stock-source=docs/examples/erp-stock.example.json --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:load-channel-overrides docs/examples/channel-overrides.example.json --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:project-channel ortho_shop --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:build-repricing-plan docs/examples/repricing-snapshot.example.json --channel=ortho_shop --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:export-ortho-shop-sync-plan --tenant=default --commit --target-file=/srv/app/symfony/public/feeds/ortho-shop/ortho-vertrieb-shop-sync.csv php /srv/app/symfony/bin/console app:commerce:import-ortho-vertrieb-products /tmp/ortho-products.json --tenant=default php /srv/app/symfony/bin/console app:commerce:import-ortho-vertrieb-products /tmp/ortho-products.json --tenant=default --commit php /srv/app/symfony/bin/console app:commerce:diff-ortho-vertrieb-products /tmp/ortho-products.json --tenant=default php /srv/app/symfony/bin/console app:commerce:diff-ortho-vertrieb-products /tmp/ortho-products.json --tenant=default --json php /srv/app/symfony/bin/console app:commerce:export-ortho-google-merchant-feed --tenant=default php /srv/app/symfony/bin/console app:commerce:ortho-google-marketing-health --json ``` ### 6.2 Ausfuehrung - `app:etl:run-pipeline <name> [--tenant=default] [--async]` - `app:etl:run-engine <runner-type> <name> [--tenant=default] [--async]` fuehrt je nach nativem Plan direkt in Symfony oder ueber die Legacy-Bridge aus - `app:execution:run <run-id> [--tenant=default]` interner Worker-Command ### 6.3 Verbindungsprofile - `app:etl:list-connections` zeigt tenant-wirksame Verbindungsprofile inklusive `draft`- und `ready`-Status - `app:legacy:sync-connections --tenant=default` synchronisiert redigierte Metadaten tenant-sicher nach PostgreSQL - `app:etl:report-missing-connections [--tenant=default] [--source=all|legacy|managed] [--format=table|json] [--limit=50]` aggregiert alle referenzierten Connection-Profile über Engines und Pipelines, trennt zwischen `ready`, `draft` und `missing`, und zeigt Verwendungsbeispiele - `app:etl:scaffold-missing-connections [--tenant=default] [--source=all|legacy|managed] [--name=<profil>] [--limit=<n>] [--format=table|json]` legt fehlende Connection-Profile als tenant-isolierte Drafts an, ohne sie auf `ready` zu setzen - `app:etl:report-missing-connection-profiles [--tenant=default] [--runner-type=push --runner-type=trigger] [--scope=legacy-filesystem|active] [--source=legacy|managed|all] [--format=table|json]` fokussiert die ältere Detailauswertung auf blockierte Legacy-Runner und gruppiert ungelöste Connection-Profile, also fehlende oder nur als Draft vorhandene Profile ### 6.4 Native Datenbank-Runtime - `app:etl:list-database-runtime` zeigt, welche Legacy-Datenbankprofile in Symfony nativ nutzbar sind - `app:etl:test-database-connection <profile>` fuehrt einen read-only Verbindungsprobe-Lauf fuer ein nativen `mysql`- oder `pgsql`-Profil aus - `app:etl:list-datapools <profile>` listet Datapools eines nativen MySQL-Profils read-only auf - `app:etl:inspect-datapool <profile> <table> [--with-count] [--show-create-sql]` zeigt Spaltenstruktur eines Datapools und optional Zeilenzahl bzw. `SHOW CREATE TABLE` ### 6.5 Native Datapool-Write-Operationen - `app:etl:drop-datapool <profile> <table>` fuehrt `DROP TABLE IF EXISTS` kontrolliert fuer ein natives MySQL-Profil aus - `app:etl:truncate-datapool <profile> <table>` fuehrt `TRUNCATE TABLE` kontrolliert fuer ein natives MySQL-Profil aus - `app:etl:create-datapool-definition <profile> <table> <definition-file> [--drop-existing]` erzeugt einen Datapool aus einer YAML- oder JSON-Blueprint-Datei - `app:etl:create-datapool-csv <profile> <table> <csv-file> [--drop-existing] [--load-after-create]` erzeugt einen Datapool aus der CSV-Kopfzeile und laedt optional direkt die CSV-Daten - `app:etl:create-datapool-data <profile> <table> <data-file> [--drop-existing]` leitet einen Datapool aus JSON- oder YAML-Daten ab - `app:etl:load-datapool-data <profile> <table> <data-file> [--truncate-before-load]` laedt JSON- oder YAML-Daten nativ per Multi-Insert in einen bestehenden MySQL-Datapool - `app:etl:copy-datapool-structure <profile> <source-table> <target-table> [--drop-existing]` kopiert die Struktur eines bestehenden MySQL-Datapools auf eine neue Tabelle - `app:etl:load-datapool-csv <profile> <table> <csv-file>` fuehrt nativ `LOAD DATA LOCAL INFILE` fuer einen bestehenden MySQL-Datapool aus Beispiele: ```bash php /srv/app/symfony/bin/console app:etl:drop-datapool importEngine temp_articles php /srv/app/symfony/bin/console app:etl:truncate-datapool importEngine temp_articles php /srv/app/symfony/bin/console app:etl:create-datapool-definition importEngine temp_articles /srv/app/docs/examples/datapool-definition.example.yaml --drop-existing php /srv/app/symfony/bin/console app:etl:create-datapool-csv importEngine temp_articles /srv/app/docs/examples/datapool-import.example.csv --drop-existing --load-after-create php /srv/app/symfony/bin/console app:etl:create-datapool-data importEngine temp_articles /srv/app/docs/examples/datapool-data.example.json --drop-existing --load-after-create php /srv/app/symfony/bin/console app:etl:load-datapool-data importEngine temp_articles /srv/app/docs/examples/datapool-data.example.json --truncate-before-load php /srv/app/symfony/bin/console app:etl:copy-datapool-structure importEngine articles_source articles_target --drop-existing php /srv/app/symfony/bin/console app:etl:load-datapool-csv importEngine temp_articles /srv/app/docs/examples/datapool-import.example.csv ``` Blueprint-Format: - `columns` Pflichtfeld, Mapping aus Spaltenname auf MySQL-Spaltendefinition - `primary_key` optionale Liste von Spalten fuer den Primary Key - `indices` optionale Liste von Indexdefinitionen, einzelne Werte duerfen auch `firma,ordernumber` enthalten - `engine` optional, Standard `INNODB` - `charset` optional, Standard `latin1` - `add_filter_reason` optional, fuegt die Spalte `filter_reason MEDIUMTEXT` hinzu, falls sie noch fehlt Ein lauffaehiges Beispiel liegt unter: - `docs/examples/datapool-definition.example.yaml` - `docs/examples/datapool-import.example.csv` - `docs/examples/datapool-data.example.json` Beispiele: ```bash php /srv/app/symfony/bin/console app:etl:list-database-runtime php /srv/app/symfony/bin/console app:etl:test-database-connection domgan php /srv/app/symfony/bin/console app:etl:list-datapools importEngine php /srv/app/symfony/bin/console app:etl:inspect-datapool importEngine articles --with-count --show-create-sql ``` ### 6.6 Native Staging Runtime - `app:etl:list-native-staging-datapools [--tenant=default]` zeigt tenant-isolierte Staging-Datapools der nativen Managed-Import- und Transform-Runtime - `app:etl:inspect-native-staging-datapool <name> [--tenant=default] [--limit=5]` zeigt Metadaten und Beispielzeilen eines nativen Staging-Datapools - `app:etl:export-native-staging-csv <name> <target-file> [--tenant=default] [--delimiter=;]` schreibt einen nativen Staging-Datapool als lokale CSV-Datei im Container Beispiele: ```bash php /srv/app/symfony/bin/console app:etl:plan import codex_native_import_smoke_engine --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_import_smoke_engine --tenant=default php /srv/app/symfony/bin/console app:etl:list-native-staging-datapools --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_native_import_smoke --tenant=default php /srv/app/symfony/bin/console app:etl:export-native-staging-csv commerce_feed_google_merchant /srv/app/var/export/google-merchant.csv --tenant=default ``` Weitere Beispiele fuer den nativen Import-plus-Unitize-Pfad: ```bash php /srv/app/symfony/bin/console app:etl:plan unitize codex_native_unitize_engine --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_unitize_import_engine --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine unitize codex_native_unitize_engine --tenant=default php /srv/app/symfony/bin/console app:etl:run-pipeline codex_native_unitize_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_native_unitize_target --tenant=default ``` Verifizierte erweiterte Beispiele fuer den nativen Unitize-Query-Pfad: ```bash php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_join_left_import --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_join_right_import --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine unitize codex_native_join_unitize --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_join_target --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_sql_a_import --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_sql_b_import --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine unitize codex_native_sql_unitize --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_sql_target --tenant=default ``` Dabei wurde am 12. Maerz 2026 verifiziert: - `codex_native_join_unitize` schreibt im Query-Mode `generated` genau eine Zielzeile aus `Left_Join` plus `Read_Conditions` - `codex_native_sql_unitize` schreibt im Query-Mode `sql` aggregierte Ergebniszeilen mit `GROUP_CONCAT` und `UNION` - alle Smoke-Test-Definitionen, Datapools und Runs wurden danach wieder entfernt Verifizierter nativer Import-plus-Enhance-plus-Export-Pfad am 14. Maerz 2026: ```bash php /srv/app/symfony/bin/console app:etl:plan enhance codex_native_transform_enhance --tenant=default php /srv/app/symfony/bin/console app:etl:plan export codex_native_transform_export --tenant=default php /srv/app/symfony/bin/console app:etl:plan pipeline codex_native_transform_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:run-pipeline codex_native_transform_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_native_transform_enhanced --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_native_transform_exported --tenant=default ``` - `codex_native_transform_pipeline` lief voll nativ als `native_staging_pipeline` - `codex_native_transform_enhance` lief nativ als `native_enhance_to_staging` und filterte eine von zwei Zeilen ueber einen stringbasierten `Filter` - `codex_native_transform_export` lief nativ als `native_export_to_staging` - verifiziert wurden dabei unter anderem `trim`, `tolower`, `str_pad`, `replace_empty`, `concat_source` und `add_prefix` - die Zielzeilen wurden in PostgreSQL-Staging geschrieben und danach vollstaendig wieder entfernt Verifizierter nativer Pool-Filter-Pfad am 15. Maerz 2026: ```bash php /srv/app/symfony/bin/console app:etl:plan export codex_poolfilter_export --tenant=default php /srv/app/symfony/bin/console app:etl:plan pipeline codex_poolfilter_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:run-pipeline codex_poolfilter_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_poolfilter_result --tenant=default --limit=10 ``` Dabei wurde lokal gegen die Tool-DB verifiziert: - `codex_poolfilter_export` plant als `native_export_to_staging` - `codex_poolfilter_pipeline` plant als `native_staging_pipeline` - die Pipeline schrieb genau eine Zielzeile in `codex_poolfilter_result` - drei von vier Quellzeilen wurden nativ herausgefiltert - die gespeicherten Datapool-Metadaten enthielten `filtered_row_count = 3` - `filter_reasons` enthielt `draft row`, `blocked title marker`, `sku denied` und `missing allow mapping` - alle Testdefinitionen, Datapools und Runs wurden danach wieder entfernt Verifizierter nativer Cross-Dataset-Filter-Pfad am 15. Maerz 2026: ```bash php /srv/app/symfony/bin/console app:etl:plan export codex_cross_dataset_export_a --tenant=default php /srv/app/symfony/bin/console app:etl:plan export codex_cross_dataset_export_b --tenant=default php /srv/app/symfony/bin/console app:etl:plan export codex_cross_dataset_export_c --tenant=default php /srv/app/symfony/bin/console app:etl:plan pipeline codex_cross_dataset_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:run-pipeline codex_cross_dataset_pipeline --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_cross_dataset_result_a --tenant=default --limit=10 php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_cross_dataset_result_b --tenant=default --limit=10 php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_cross_dataset_result_c --tenant=default --limit=10 ``` Dabei wurde lokal gegen die Tool-DB verifiziert: - `codex_cross_dataset_export_a`, `codex_cross_dataset_export_b` und `codex_cross_dataset_export_c` planten jeweils als `native_export_to_staging` - `codex_cross_dataset_pipeline` plante als `native_staging_pipeline` und lief erfolgreich voll nativ - `codex_cross_dataset_result_a` enthielt genau die erwartete Keep-Zeile; `filter_reasons` zaehlte `duplicate ordernumber`, `no picture family` und `slow delivery` - `codex_cross_dataset_result_b` enthielt genau die erwarteten Zeilen fuer vorhandenen Parent und Plain-Fall; `filter_reasons` zaehlte `marketplace orders` und `variants without parents` - `codex_cross_dataset_result_c` enthielt genau die erwarteten Variant-Zeilen; `filter_reasons` zaehlte `non parents only` - alle Testdefinitionen, Datapools und Runs wurden danach wieder vollstaendig entfernt Verifizierte weitere SQL-Funktionsabdeckung am 13. Maerz 2026: ```bash php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_trim_idealo_import --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine import codex_native_trim_google_import --tenant=default php /srv/app/symfony/bin/console app:etl:plan unitize codex_native_trim_unitize --tenant=default php /srv/app/symfony/bin/console app:etl:run-engine unitize codex_native_trim_unitize --tenant=default php /srv/app/symfony/bin/console app:etl:inspect-native-staging-datapool codex_trim_target --tenant=default ``` - `codex_native_trim_unitize` lief nativ im Query-Mode `sql` - verschachtelte MySQL-Trim-Syntax mit `TRIM(LEADING ...)`, `TRIM(TRAILING ...)` und `TRIM(BOTH ... FROM ...)` wurde korrekt in SQLite-kompatible Funktionen uebersetzt - die Ergebniszeilen wurden tenant-isoliert in PostgreSQL-Staging geschrieben und danach wieder vollstaendig entfernt ## 7. Deployment und Betrieb ### 7.1 Compose-Stack starten oder aktualisieren ```bash ssh ortho-live 'cd /opt/containers/drive-dataengine && docker compose -f compose.yaml build dashboard && docker compose -f compose.yaml up -d dashboard' ``` ### 7.2 Stack-Status pruefen ```bash ssh ortho-live 'cd /opt/containers/drive-dataengine && docker compose -f compose.yaml ps' ``` ### 7.3 Oeffentliche Erreichbarkeit pruefen ```bash curl -sS -I https://dataengine.domgan.de ``` ### 7.4 Datenbankschema anwenden Wenn sich `docker/postgres/init/001-rls.sql` geaendert hat und der Container bereits initialisiert wurde: ```bash ssh ortho-live 'cd /opt/containers/drive-dataengine && docker compose -f compose.yaml exec -T postgres psql -U dataengine -d dataengine -f /docker-entrypoint-initdb.d/001-rls.sql' ``` ### 7.5 Repo-Guardrail lokal pruefen Vor Pushes oder Releases kann die Doku-Synchronitaet lokal geprueft werden: ```bash cd /opt/containers/drive-dataengine ./scripts/check-doc-sync.sh HEAD^ HEAD ``` ## 8. Dokumentationsstandard Diese Anleitung ist die operative Fuehrungsdokumentation fuer den aktuellen Stand. Pflicht bei jeder Aenderung: 1. `README.md` aktualisieren, wenn Einstieg oder Architektur betroffen sind. 2. Diese Bedienungsanleitung aktualisieren, wenn Bedienung, Commands, Deployment oder Grenzen betroffen sind. 3. `docs/replatforming-plan.md` aktualisieren, wenn sich Zielbild oder Migrationsgrenze verschiebt. Details stehen in `CONTRIBUTING.md`. ## 9. Entwicklungsprozess Weiterentwicklung folgt ab jetzt diesem Ablauf: 1. Tool-Ebene und Anwendungsebene getrennt modellieren. 2. Neue Tool-Funktionalitaet zuerst gegen lokale Container und die lokale PostgreSQL des Systems testen. 3. Keine Tests gegen Fremdsysteme oder externe Server fahren, solange sie nicht ausdruecklich freigegeben sind. 4. Neue GUI-Funktionen immer ueber dieselben Services bedienen wie CLI und Worker. 5. Logs, Container-Status und lokale DB nutzen, um Fehler iterativ zu beseitigen. 6. Neue Runtime-Pfade mit lokalen Smoke-Tests gegen die Tool-DB verifizieren und Testartefakte danach wieder entfernen. 7. Bei schreibenden Runtime-Pfaden auch Wiederholungs- und Parallel-Trigger gegen die lokale Tool-DB pruefen. 8. Erst nach erfolgreicher lokaler Verifikation auf `ortho-live` deployen. ## 10. GitHub und Versionierung Der GitHub-Stand wird ohne produktive Secrets versioniert. Nicht versioniert werden: - `.env` - SSH-Schluessel - Cloud-Service-Account-Dateien - Legacy-Connection-Profile mit Live-Credentials Fuer diese Dateien bleibt der Server die Quelle. Neue Umgebungen muessen die Secrets separat erhalten. Das Repository erzwingt auf GitHub ueber `scripts/check-doc-sync.sh` und `.github/workflows/repository-guardrails.yml`, dass Code- und BetriebsAenderungen nicht ohne aktualisierte Dokumentation gemerged werden. Privates Repository: - `https://github.com/dominikgantenberg/drive-dataengine-clean` Das fruehere private Repository `drive-dataengine` wurde geloescht und darf nicht wieder angelegt oder verwendet werden. ### 10.1 Legacy-Secrets Historische Hilfs- und Testskripte im Legacy-Bestand laden produktive Zugangsdaten nicht mehr aus getrackten PHP-Dateien, sondern aus: - `backend/secrets/legacy_runtime_secrets.php` Diese Datei bleibt serverlokal und wird nicht versioniert. Die Struktur fuer neue Umgebungen steht in: - `backend/secrets/legacy_runtime_secrets.example.php.dist` ## 11. Bekannte Grenzen - Managed File-Importe und eine wachsende native Transform-Teilmenge fuer `unitize`, `enhance` und `export` mit `direct`, `generated` und `sql` laufen derzeit voll nativ; dazu gehoeren jetzt auch MySQL-Trim-Modifikatoren, stringbasierte Filters, `Equals`, `In_String`, `In_Pool_Filter_Adapter`, `Not_In_Pool_Filter_Adapter` und eine breite Auswahl haeufiger Field-Adapter. - ODBC-Profile sind noch nicht nativ in Symfony nutzbar. - Read-only Datenbank-Probes haengen von der Netzwerkerreichbarkeit des Zielsystems vom Host `ortho-live` ab. - Native Datapool-Write- und Import-Operationen decken aktuell nur MySQL ab; andere Treiber bleiben im Legacy-Pfad. - Native Transform-Runtime deckt noch nicht die gesamte Legacy-Semantik ab; insbesondere Cross-Field-, File-Field- und Cross-Dataset-Filter-Adapter bleiben vorerst im Legacy-Pfad. - Managed Definitions werden tenant-spezifisch in PostgreSQL gepflegt, in Planung und Katalog priorisiert und fuer nicht-native Runs als isolierter Overlay-Snapshot materialisiert. - Der lokale Mount des Projektpfads kann instabil sein; im Stoerungsfall wird ueber `ssh/scp` gearbeitet.