diff --git a/global/CLAUDE.md b/global/CLAUDE.md
index 6c930a5..d611ea6 100644
--- a/global/CLAUDE.md
+++ b/global/CLAUDE.md
@@ -3,6 +3,7 @@
- Sachlicher Ton, normales ruhiges Deutsch. Kein Motivieren, Loben oder Bedauern, keine Werbe-/Selbst-Slogans.
- So knapp wie möglich: nur Fakten, keine Füllabsätze, keine Wiederholung meiner Aussagen, keine Annahmen über den Kontext.
- Nur handeln, wenn ich es ausdrücklich sage. Sonst nur antworten/erklären.
+- Eine konkrete Frage NUR beantworten — exakt das Gefragte, nicht mehr. Ja/Nein-Frage = Ja/Nein. Kein Entwerfen, keine Optionen, keine Lösung, kein Vorschlag, keine ungefragte Recherche/Investigation — auch nicht, wenn etwas falsch, gefährlich oder verbesserungswürdig aussieht. Ein auffälliger Punkt wird höchstens in einem Halbsatz benannt, nicht ausgearbeitet.
- Keine Vorschläge für weiteres Vorgehen oder was man sonst noch machen könnte.
- Positiv formulieren: beschreiben, was der Code tut / was getan wurde — nicht, was man nicht tut. Negationsketten vermeiden.
- Bei Unsicherheit „weiß ich nicht" / „unklar" sagen, statt mit generischem Text aufzufüllen.
diff --git a/global/bin/git-sync b/global/bin/git-sync
new file mode 100755
index 0000000..f53c051
--- /dev/null
+++ b/global/bin/git-sync
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+# git-sync — add/commit/pull --rebase/push a single repo.
+# Safe: rebases onto remote, never merges, never force-pushes; conflicts are
+# reported (rebase aborted), not auto-resolved.
+# Usage: git-sync
[commit-message]
+# Invoked by the /git-sync slash command, once per configured project repo.
+set -uo pipefail
+
+dir=${1:?usage: git-sync [message]}
+msg=${2:-}
+
+# expand leading ~ (not expanded inside variables) so $HOME-based paths work
+case "$dir" in
+ "~") dir="$HOME" ;;
+ "~/"*) dir="$HOME/${dir#"~/"}" ;;
+esac
+
+ok() { printf '\033[1;32m✓ %s\033[0m\n' "$*"; } # green
+note() { printf '\033[1;36m· %s\033[0m\n' "$*"; } # cyan
+warn() { printf '\033[1;33m⚠ %s\033[0m\n' "$*"; } # yellow
+
+g() { git -C "$dir" "$@"; }
+label=$(basename "$dir")
+
+if ! g rev-parse --is-inside-work-tree >/dev/null 2>&1; then
+ warn "$label: kein Git-Repo — übersprungen."
+ exit 0
+fi
+branch=$(g rev-parse --abbrev-ref HEAD)
+
+# --- commit working-tree changes -------------------------------------------
+if [[ -n "$(g status --porcelain)" ]]; then
+ g add -A
+ [[ -z "$msg" ]] && msg="git-sync: $(date '+%Y-%m-%d %H:%M')"
+ if g commit --quiet -m "$msg"; then
+ note "$label: committed — $msg"
+ else
+ warn "$label: commit fehlgeschlagen."
+ exit 0
+ fi
+else
+ note "$label: keine Änderungen."
+fi
+
+# --- pull --rebase, then push (no force, no merge) -------------------------
+if ! g remote get-url origin >/dev/null 2>&1; then
+ note "$label: kein origin-Remote — push übersprungen."
+ exit 0
+fi
+
+if g rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
+ # integrate remote first: rebase keeps history linear, no merge commits
+ g fetch --quiet 2>/dev/null || true
+ behind=$(g rev-list --count 'HEAD..@{u}' 2>/dev/null || echo 0)
+ if [[ "$behind" -gt 0 ]]; then
+ if g pull --rebase --quiet 2>/dev/null; then
+ note "$label: $behind Commit(s) per Rebase integriert."
+ else
+ g rebase --abort >/dev/null 2>&1 || true
+ warn "$label: Pull/Rebase-Konflikt — bitte manuell lösen. Push übersprungen."
+ exit 0
+ fi
+ fi
+ ahead=$(g rev-list --count '@{u}..HEAD' 2>/dev/null || echo 0)
+ if [[ "$ahead" -eq 0 ]]; then
+ note "$label: nichts zu pushen."
+ elif g push --quiet 2>/dev/null; then
+ ok "$label: $ahead Commit(s) gepusht ($branch)."
+ else
+ warn "$label: push abgelehnt — Remote voraus. Manuell prüfen."
+ fi
+else
+ if g push --quiet -u origin "$branch" 2>/dev/null; then
+ ok "$label: Upstream gesetzt und gepusht ($branch)."
+ else
+ warn "$label: kein Upstream, push fehlgeschlagen — einmal manuell pushen."
+ fi
+fi
diff --git a/global/commands/git-sync.md b/global/commands/git-sync.md
new file mode 100644
index 0000000..7ba65ad
--- /dev/null
+++ b/global/commands/git-sync.md
@@ -0,0 +1,24 @@
+---
+description: Commit + Push aller persistent konfigurierten Projekt-Repos
+---
+
+Du committest und pushst die persistent hinterlegten Projekt-Verzeichnisse
+(`permissions.additionalDirectories` aus den Settings) — nicht das CWD.
+
+1. Verzeichnisse sammeln (Projekt-, lokale, User-Settings, dedupliziert):
+ ```bash
+ for f in .claude/settings.json .claude/settings.local.json "$HOME/.claude/settings.json"; do
+ [ -f "$f" ] && jq -r '.permissions.additionalDirectories[]?' "$f" 2>/dev/null
+ done | sort -u | sed "s|^~/|$HOME/|"
+ ```
+2. Für jedes Verzeichnis, das ein Git-Repo ist: aus `git -C status` und
+ `git -C diff --staged --stat` plus `git -C diff --stat` eine knappe,
+ sachliche einzeilige Commit-Message auf Deutsch erzeugen (beschreibt, was geändert wurde).
+3. Pro Verzeichnis aufrufen:
+ ```bash
+ "$HOME/claude-projects/global/bin/git-sync" "" ""
+ ```
+4. Ergebnisse pro Repo zusammenfassen: committed / gepusht / nichts zu tun / abgelehnt.
+
+Verändere nichts außerhalb dieser Verzeichnisse. Kein force, kein merge — das Skript
+ist darauf ausgelegt und meldet Konflikte nur, statt sie aufzulösen.
diff --git a/global/settings.json b/global/settings.json
new file mode 100644
index 0000000..3ae6802
--- /dev/null
+++ b/global/settings.json
@@ -0,0 +1,21 @@
+{
+ "enabledPlugins": {
+ "frontend-design@claude-plugins-official": true
+ },
+ "promptSuggestionEnabled": false,
+ "awaySummaryEnabled": false,
+ "theme": "dark",
+ "permissions": {
+ "allow": [
+ "Bash(git add:*)",
+ "Bash(git commit:*)",
+ "Bash(git push:*)",
+ "Bash(git pull:*)",
+ "Bash(git status:*)",
+ "Bash(git diff:*)",
+ "Bash(git -C:*)",
+ "Bash(git mv:*)",
+ "Bash(git check-ignore:*)"
+ ]
+ }
+}
diff --git a/limbach/.$integration-server.drawio.bkp b/limbach/.$integration-server.drawio.bkp
new file mode 100644
index 0000000..2b7bfd6
--- /dev/null
+++ b/limbach/.$integration-server.drawio.bkp
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/limbach/.$integration-server_sngle.drawio.bkp b/limbach/.$integration-server_sngle.drawio.bkp
new file mode 100644
index 0000000..c83d7c5
--- /dev/null
+++ b/limbach/.$integration-server_sngle.drawio.bkp
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/limbach/.claude/settings.json b/limbach/.claude/settings.json
index 795170a..7e41934 100644
--- a/limbach/.claude/settings.json
+++ b/limbach/.claude/settings.json
@@ -1,3 +1,12 @@
{
- "autoMemoryDirectory": "~/claude-projects/limbach/memory"
+ "autoMemoryDirectory": "~/claude-projects/limbach/memory",
+ "permissions": {
+ "allow": [
+ "Edit(~/projects/limbach/**)",
+ "Edit(~/claude-projects/limbach/**)"
+ ],
+ "additionalDirectories": [
+ "~/projects/limbach"
+ ]
+ }
}
diff --git a/limbach/integration-server.drawio b/limbach/integration-server.drawio
new file mode 100644
index 0000000..7924336
--- /dev/null
+++ b/limbach/integration-server.drawio
@@ -0,0 +1,474 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/limbach/integration-server_sngle.drawio b/limbach/integration-server_sngle.drawio
new file mode 100644
index 0000000..cd502a8
--- /dev/null
+++ b/limbach/integration-server_sngle.drawio
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/limbach/memory/keine-rhetorischen-fragen.md b/limbach/memory/keine-rhetorischen-fragen.md
new file mode 100644
index 0000000..cfeea4a
--- /dev/null
+++ b/limbach/memory/keine-rhetorischen-fragen.md
@@ -0,0 +1,14 @@
+---
+name: keine-rhetorischen-fragen
+description: Niemals rhetorische Fragen verwenden — strikt verboten
+metadata:
+ node_type: memory
+ type: feedback
+ originSessionId: d35a0bd9-ab2f-4a8e-975e-6bd133983fa8
+---
+
+Niemals rhetorische Fragen verwenden. Striktes Verbot, ausnahmslos.
+
+**Why:** Der Nutzer empfindet rhetorische Fragen als störend und hat das ausdrücklich und nachdrücklich untersagt.
+
+**How to apply:** Aussagen statt Fragen formulieren. Keine Fragen zur Auflockerung, Überleitung oder als Stilmittel. Echte Rückfragen nur, wenn eine Antwort tatsächlich gebraucht wird. Verwandt mit [[verbotene-woerter]].
diff --git a/robotunits/.claude/settings.json b/robotunits/.claude/settings.json
index 1c38087..4d405ea 100644
--- a/robotunits/.claude/settings.json
+++ b/robotunits/.claude/settings.json
@@ -1,3 +1,14 @@
{
- "autoMemoryDirectory": "~/claude-projects/robotunits/memory"
+ "autoMemoryDirectory": "~/claude-projects/robotunits/memory",
+ "permissions": {
+ "allow": [
+ "Edit(~/projects/geko-core/**)",
+ "Edit(~/projects/adesso-cpq/**)",
+ "Edit(~/claude-projects/robotunits/**)"
+ ],
+ "additionalDirectories": [
+ "~/projects/geko-core",
+ "~/projects/adesso-cpq"
+ ]
+ }
}
diff --git a/robotunits/.claude/settings.local.json b/robotunits/.claude/settings.local.json
index 0a68b8b..8b311a3 100644
--- a/robotunits/.claude/settings.local.json
+++ b/robotunits/.claude/settings.local.json
@@ -1,13 +1,5 @@
{
"permissions": {
- "allow": [
- "Bash(xargs -I {} find {} -type f \\\\\\( -name \"*.ts\" -o -name \"*.tsx\" -o -name \"*.js\" -o -name \"*.vue\" \\\\\\))",
- "Bash(xargs cat)",
- "Bash(xargs ls -la)",
- "Bash(xargs -I {} sh -c 'echo \"=== {} ===\" && cat {}')",
- "Bash(xargs -I {} bash -c 'echo \"=== {} ===\" && cat {}')",
- "Bash(xargs ls -lh)",
- "Bash(PATH=/home/marcuh/git/adesso-cpq/packages/blast/node_modules/.bin:__TRACKED_VAR__ tsup)"
- ]
+ "allow": []
}
}
diff --git a/wittgenstein/.claude/settings.json b/wittgenstein/.claude/settings.json
index 3ba0111..7a8880b 100644
--- a/wittgenstein/.claude/settings.json
+++ b/wittgenstein/.claude/settings.json
@@ -1,15 +1,11 @@
{
"permissions": {
"allow": [
- "Edit(/Users/marcush/projects/wittgenstein/**)",
- "Edit(/Users/marcush/claude-projects/**)",
- "Bash(git add:*)",
- "Bash(git commit:*)",
- "Bash(git push:*)",
- "Bash(git pull:*)",
- "Bash(git status:*)",
- "Bash(git diff:*)",
- "Bash(git -C:*)"
+ "Edit(~/projects/wittgenstein/**)",
+ "Edit(~/claude-projects/wittgenstein/**)"
+ ],
+ "additionalDirectories": [
+ "~/projects/wittgenstein"
]
},
"autoMemoryDirectory": "~/claude-projects/wittgenstein/memory"
diff --git a/wittgenstein/.claude/settings.local.json b/wittgenstein/.claude/settings.local.json
index 73a400e..8b311a3 100644
--- a/wittgenstein/.claude/settings.local.json
+++ b/wittgenstein/.claude/settings.local.json
@@ -1,11 +1,5 @@
{
"permissions": {
- "allow": [
- "mcp__outline__list_collections",
- "mcp__outline__update_document",
- "mcp__outline__create_document",
- "mcp__outline__list_documents",
- "mcp__outline__move_document"
- ]
+ "allow": []
}
}
diff --git a/wuerth-plato/.claude/settings.json b/wuerth-plato/.claude/settings.json
index f0db78a..e7b68f0 100644
--- a/wuerth-plato/.claude/settings.json
+++ b/wuerth-plato/.claude/settings.json
@@ -1,6 +1,11 @@
{
"autoMemoryDirectory": "~/claude-projects/wuerth-plato/memory",
"permissions": {
+ "allow": [
+ "Edit(~/projects/fahrzeugeinrichtung-plato-backend/**)",
+ "Edit(~/projects/fahrzeugeinrichtung-plato-gitops/**)",
+ "Edit(~/claude-projects/wuerth-plato/**)"
+ ],
"additionalDirectories": [
"~/projects/fahrzeugeinrichtung-plato-backend",
"~/projects/fahrzeugeinrichtung-plato-gitops"
diff --git a/wuerth-plato/.claude/settings.local.json b/wuerth-plato/.claude/settings.local.json
new file mode 100644
index 0000000..8f33470
--- /dev/null
+++ b/wuerth-plato/.claude/settings.local.json
@@ -0,0 +1,38 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(npx nx *)",
+ "Bash(lsof -ti:3000)",
+ "Bash(xargs -r kill)",
+ "Bash(tee /tmp/plato-be.log)",
+ "Bash(python3 -)",
+ "Bash(npx tsc *)",
+ "Skill(code-review)",
+ "Bash(podman:*)",
+ "Bash(oc get:*)",
+ "Bash(oc describe:*)",
+ "Bash(oc status:*)",
+ "Bash(oc logs:*)",
+ "Bash(oc top:*)",
+ "Bash(oc project:*)",
+ "Bash(oc projects:*)",
+ "Bash(oc whoami:*)",
+ "Bash(oc version:*)",
+ "Bash(oc api-resources:*)",
+ "Bash(oc explain:*)"
+ ],
+ "ask": [
+ "Bash(podman system reset:*)",
+ "Bash(podman system prune:*)",
+ "Bash(podman volume rm:*)",
+ "Bash(podman volume prune:*)",
+ "Bash(podman machine rm:*)",
+ "Bash(podman machine reset:*)"
+ ],
+ "deny": [
+ "Bash(oc adm:*)",
+ "Bash(oc delete project:*)",
+ "Bash(oc delete namespace:*)"
+ ]
+ }
+}
diff --git a/wuerth-plato/CLAUDE.md b/wuerth-plato/CLAUDE.md
new file mode 100644
index 0000000..f23051a
--- /dev/null
+++ b/wuerth-plato/CLAUDE.md
@@ -0,0 +1,7 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+1. Dieses Modul ist Teil eines MonoRepos, das verschiedene — überwiegend Development- — Projekte bündelt.
+2. Die eigentlichen Source- oder Ressource-Repos sind in der `settings.json` hinterlegt.
+3. SAP-Zugriff (Basic Auth, Endpoint, Env→Secret/Overlay-Mapping): siehe `memory/sap-config.md`.
diff --git a/wuerth-plato/memory/feedback_ort_zuerst.md b/wuerth-plato/memory/feedback_ort_zuerst.md
new file mode 100644
index 0000000..57e108a
--- /dev/null
+++ b/wuerth-plato/memory/feedback_ort_zuerst.md
@@ -0,0 +1,19 @@
+---
+name: feedback_ort_zuerst
+description: "Bei \"wo mache ich X?\"-Fragen sofort die konkrete UI-Stelle nennen, nicht durch Menüs jagen"
+metadata:
+ node_type: memory
+ type: feedback
+ originSessionId: 03691a44-b7eb-4d9d-9e7c-5d5aae84e110
+---
+
+Marcus fragt bei UI/Tooling oft konkret "WO geht das?". Dann will er **die eine konkrete Stelle**, nicht eine Schritt-für-Schritt-Tour durch das Tool oder Vorbedingungen vorweg.
+
+**Why:** Lange Navigationsanleitungen ("erst Actions, dann Run, dann Banner...") bei einer simplen Ortsfrage haben ihn massiv genervt ("RED DEUTSCH", "durch das komplette GitHub gejagt"). Kostet Zeit und Nerven.
+
+**How to apply:**
+- Ortsfrage → direkt der Ziel-Ort + der Knopf, in einem Satz. Z. B. "PR → Files changed → Review changes → Approve".
+- Relevante Einschränkung in einem Halbsatz dazu (z. B. "eigenen PR kann man nicht approven"), aber nicht als Vorrede davorstellen.
+- Keine "erst dies, dann das"-Ketten, wenn eine Stelle reicht.
+
+**Zweiter Fehler im selben Vorgang:** Ich behauptete früh "Review Required ist fürs Deployen ignorierbar". Falsch — der witglobal `deploy-branch`-Workflow prüft `reviewDecision` und bricht mit `REVIEW_REQUIRED` ab, solange der PR nicht approved ist. Lehre: bei Aussagen über fremde Workflows erst den reusable workflow lesen, nicht aus dem Muster raten. Siehe [[feedback_evidence_first]].
diff --git a/wuerth-plato/memory/project_prod_ist_stand.md b/wuerth-plato/memory/project_prod_ist_stand.md
new file mode 100644
index 0000000..c08cdc7
--- /dev/null
+++ b/wuerth-plato/memory/project_prod_ist_stand.md
@@ -0,0 +1,35 @@
+---
+name: project_prod_ist_stand
+description: Prod (ocp-01 / 1401-plato-production) — Secrets (inkl. SAP) erledigt+aktiviert; einziger Blocker noch das to_be_replaced Image-Tag
+metadata:
+ node_type: memory
+ type: project
+ originSessionId: 03691a44-b7eb-4d9d-9e7c-5d5aae84e110
+---
+
+Stand 2026-06-19, verifiziert direkt am Prod-Cluster (`api.ocp-01.wgn.wuerth.com`, Projekt `1401-plato-production`).
+
+**Stand 2026-06-19 abends: Prod ist LIVE und voll erreichbar** — backend `0.38.4` 1/1 Running auf ocp-01, alle 3 Secrets (customer/postgres/sap) gemountet, ghcr-Pull funktioniert. Öffentliche URL **https://plato.witglobal.net** (Test: https://plato-test.witglobal.net auf ocp-dev01), zusätzlich zur alten fahrzeugeinrichtung-Route. OIDC-Login funktioniert.
+
+**Custom-Routes + OIDC:** Routes als `route-public.yaml` je Overlay im gitops-Repo (commit `11ba61c`), edge/Redirect, host `plato.witglobal.net` bzw. `plato-test.witglobal.net` → backend-service:3000. Redirect-URI baut die App aus `req.headers.host` + fixem Pfad `/oauth/callback` (oidc.controller.ts `computeRedirectUri`). Beim IdP (PingFederate, strict byte-match, kein Trailing-Slash) **pro client_id** registriert: `https://plato.witglobal.net/oauth/callback` an `KONZ-PlaTo-Customer-PROD`, `https://plato-test.witglobal.net/oauth/callback` an `KONZ-PlaTo-Customer-DEV`. Kein Post-Logout-Redirect nötig.
+
+PR `development → main` gemergt — `main` spiegelt den Prod-Stand. Go-live abgeschlossen.
+
+Reihenfolge der Blocker, die fielen: (1) Secrets gesealt+aktiviert; (2) Dockerfile-Build-Bruch `crm.sqlite` raus → Image 0.38.4; (3) PR-Review REVIEW_REQUIRED approved; (4) **Namespace-Quota voll** (totes Frontend-Orphan-Deployment fraß 1 CPU/4Gi) → Frontend-Deployment/Service/Route gelöscht (war alter Split-Ansatz, Backend serviert FE-Assets selbst) → `oc rollout restart` → Pod startet.
+
+**Quota-Warnung für später:** `default-resource-quotas` = 3 CPU / 12Gi hart. backend(1)+postgres(1) = 2, lässt nur 1 Slot Surge. Sobald ein zweiter Workload dazukommt (oder Rolling Update mit maxSurge), reicht es nicht → Quota anheben (Plattform) oder maxSurge=0.
+
+**Historischer Ausgangsbefund (vor heute):**
+
+1. **Image-Tag nie ersetzt** (offen). backend-/frontend-Pods ziehen wörtlich `…/backend:to_be_replaced` → ImagePullBackOff (Deployment 198d, 0/1). Der `.deploy to production`-Workflow (PR `development→main`, Kommentar `.deploy to production`) ist **nie gelaufen**. Das ist der gewählte Weg A, um es zu lösen — bringt echten Tag + klärt zugleich den offenen ghcr-Pull-Recht-Punkt auf Prod.
+
+2. **Secrets — ERLEDIGT.** Alle drei SealedSecrets gegen ocp-01 gesealt, Entsiegelung auf Prod verifiziert (Synced=True), in `production/kustomization.yaml` aktiviert + in `backend.yaml` per `envFrom` referenziert:
+ - `plato-customer-secrets`, `plato-postgres-secrets` (commit `1ba047e`)
+ - `plato-sap-secrets` (commit `4601ea7`): SAP MUSS auf Prod (zentral). Werte = dieselben wie dev; dev-Klartext vom dev-Cluster gelesen, gegen ocp-01 neu gesealt. `SAP_URL` = dev-Endpoint `odatang9.wgn.wuerth.com/...` (User-Ansage „dieselben Werte"). Sealing-Rezept: `kubeseal --fetch-cert` geht auf Prod per Default-Pfad; dev-Secret per `oc --context= get secret -o json` → jq auf prod-ns umschreiben → `kubeseal --cert`.
+ - Beide gitops-Commits noch nicht gepusht (ahead 2; Push macht Marcus). Inhaltliche Werte-Korrektheit (richtige Prod-Creds?) erst sichtbar, wenn Backend hochkommt.
+
+**Sauber/fertig auf Prod:** Namespace-Label `argocd.argoproj.io/managed-by=issp-gitops-developers` gesetzt, ArgoCD-App existiert und syncht. Plattformseite steht.
+
+**Noch offen / nicht testbar:** ghcr-Pull-Berechtigung auf Prod (Pull via `default-dockercfg`, kein explizites `imagePullSecrets`) — scheitert aktuell am nicht-existenten Tag, nicht erkennbar an Auth. Zeigt sich erst mit echtem Tag. Außerdem: SAP-Secret fehlt für Prod komplett (dev hat `plato-sap-secrets.sealed.yaml`, prod nicht; `production/backend.yaml` referenziert SAP auch nicht).
+
+Deploy-Mechanik siehe PDF `ressources/GitHub CICD to OpenShift.pdf`: Image nur auf `development` gebaut + wiederverwendet, Prod via PR-Kommentar `.deploy to production`, Prod-ArgoCD vermutlich `autoSync: false` → manueller Sync. Dev-Cluster = ocp-dev01 läuft sauber (backend 0.38.1).
diff --git a/wuerth-plato/plato-backend-pre-rewrite-20260620-1202.bundle b/wuerth-plato/plato-backend-pre-rewrite-20260620-1202.bundle
new file mode 100644
index 0000000..5e21ee7
Binary files /dev/null and b/wuerth-plato/plato-backend-pre-rewrite-20260620-1202.bundle differ