Zum Inhalt

ARCH-2026-004 – Reproduzierbare Prüf-, Release- und Container-Baseline

Status: Entwurf
Proposal-Status: under_review
Kategorie: architecture
Erstellt: 2026-07-05
Stand: 2026-07-07
Geprüfter Repository-Stand: f84c881aace65ff9aa857b43fc2de4b0a7998397

Anlass

Die aktuelle technische Laufzeit- und Deploymentbasis ist nur teilweise fixiert. Bewegliche Image-Tags, unterschiedliche Prüfpfade in CI und Deployment sowie direkte Bind-Mounts auf den produktiven Git-Working-Tree verhindern eine eindeutig identifizierbare und reproduzierbare Releasekette.

Das ursprüngliche Proposal betrachtete hauptsächlich das Pinning externer Images. Die Prüfung des aktuellen Repository-Standes zeigt, dass die Reproduzierbarkeitslücke die vollständige Kette von der Prüfung bis zur produktiven Aktivierung betrifft.

Bestätigte Teilentscheidung 1 – Umfang

Am 2026-07-07 wurde Variante B bestätigt:

ARCH-2026-004 wird nicht auf das Pinning externer Image-Tags begrenzt.

Das Proposal umfasst die vollständige technische Kette vom verifizierten
Git-Commit über eine fixierte Prüf- und Runtime-Baseline bis zu einem
eindeutig identifizierbaren, unveränderbaren und rückrollbaren Release.

Die produktive App und Dokumentation dürfen nach der Integration nicht
mehr unmittelbar aus einem während des Deployments veränderten
Git-Working-Tree ausgeliefert werden.

CI und Deployment verwenden denselben kanonischen Prüfauftrag.

Die konkrete Artefaktform, Pinning-Tiefe, Releaseaktivierung und Rollbacktechnik bleiben Gegenstand weiterer Einzelentscheidungen.

Ausgangsproblem

Die aktuelle technische Kette ist vereinfacht:

GitHub Pull Request
-> GitHub-hosted Runner
-> bewegliche Host- und Action-Versionen
-> teilweise containerisierte Prüfungen
-> separater Deployment-Prüfpfad
-> git pull im produktiv gemounteten Working-Tree
-> docker compose up
-> App und Doku lesen direkt aus diesem Working-Tree

Damit ist nicht eindeutig festgelegt:

welche konkreten Images und Tools verwendet wurden
welcher Prüfauftrag einen Release freigibt
welches unveränderbare Artefakt ausgeliefert wurde
wann eine neue Version tatsächlich produktiv aktiv wurde
wie exakt auf den vorherigen Stand zurückgerollt wird

Relevanter bestehender Stand

Betroffene Dateien mindestens:

docker-compose.yml
.github/workflows/contract-check.yml
scripts/check-frontend-baseline.sh
scripts/run-single-analysis-browser-check.sh
scripts/check-single-analysis-browser.mjs
scripts/deploy-and-verify.sh
deploy/nginx/default.conf
docs/operations/deployment.md
docs/specification/architecture/overview.md
docs/specification/architecture/project-structure.md
docs/operations/browser-acceptance.md
README.md
docs/roadmap/current-status.md

Derzeit nicht vorhanden:

Dockerfile für ein Immohai-Webimage
Dockerfile für ein statisch gebautes Immohai-Dokumentationsimage
.dockerignore
versioniertes Release-Manifest für technische Artefakte
unveränderbares Releaseverzeichnis je Git-Commit
kanonischer gemeinsamer CI-/Deployment-Prüfeinstieg

Nachgewiesene aktuelle Architekturabweichungen

1. Bewegliche produktive Image-Tags

docker-compose.yml verwendet:

nginx:latest
squidfunk/mkdocs-material:latest

Derselbe Repository-Commit kann dadurch abhängig von Pull-Zeitpunkt und lokalem Image-Cache auf unterschiedlichen Laufzeitständen ausgeführt werden.

2. Bewegliche CI- und Prüfgrundlagen

Der Workflow verwendet unter anderem:

runs-on: ubuntu-latest
actions/checkout@v4
actions/upload-artifact@v4
node:22-alpine

Node ist nur auf Major- und Distributionslinie fixiert. Runner, Actions und weitere Hostwerkzeuge bleiben beweglich.

3. Kein unveränderbares Release-Artefakt

Die produktiven Container verwenden direkte Bind-Mounts:

./frontend -> /usr/share/nginx/html
./ -> /docs

Die ausgelieferte Anwendung ist deshalb kein eigenes, unveränderbares Releaseobjekt, sondern der aktuelle Inhalt des Server-Working-Trees in Kombination mit lokal vorhandenen Basisimages.

4. Nicht atomare Aktivierung

scripts/deploy-and-verify.sh führt zuerst git pull --ff-only im produktiv gemounteten Repository aus und prüft erst danach den neuen Stand.

Da die laufenden Container direkt auf diesen Working-Tree zugreifen, können neue oder inkonsistente Dateien bereits sichtbar werden, bevor alle Prüfungen erfolgreich abgeschlossen sind.

5. Geprüfter Dokumentationsbuild wird nicht produktiv ausgeliefert

CI und Deployment führen zwar mkdocs build --strict aus. Produktiv läuft jedoch mkdocs serve auf dem eingebundenen Repository.

Damit wird nicht exakt das zuvor geprüfte statische site/-Artefakt ausgeliefert.

6. CI und Deployment verwenden unterschiedliche Prüfketten

Der GitHub-Workflow führt mehr Prüfungen aus als scripts/check-frontend-baseline.sh im Deploymentpfad.

Unter anderem fehlen im Deploymentpfad Teile der aktuellen Prüfungen zu:

Szenariovergleich
Chartstandardisierung
Dashboard-KPI-Layout
Scenario-Rating-Findings
Annahmenherkunft
Headless-Chrome-Einzelanalyse
Nginx-Cache-Policy

Damit gibt es heute keinen einzigen kanonischen Release-Gate-Auftrag.

7. Browserprüfung ist hostabhängig

Der Browsertest sucht ein vorhandenes google-chrome, chromium oder vergleichbares Binary auf dem Host und startet diese Version direkt.

Die Browserregression hängt dadurch vom jeweiligen GitHub-Runner oder Serverstand ab.

8. Deploymentidentität ist unvollständig

Nach dem Deployment werden Commit, Modellversion und Engineversion ausgegeben. Die öffentliche Prüfung kontrolliert jedoch nur Modell- und Engineversion aus dem Manifest.

Nicht eindeutig festgehalten werden unter anderem:

vollständiger ausgelieferter Git-Commit
Release-ID
Web-Artefakt oder Web-Image-Digest
Docs-Artefakt oder Docs-Image-Digest
Node-Prüfimage
Browser-Testversion
Compose-Konfigurationsidentität
Buildzeitpunkt

9. Rollback ist nicht formalisiert

Das ursprüngliche Proposal erwähnt Rollback auf Tags oder Digests. Der aktuelle Deploymentpfad besitzt jedoch kein explizites vorheriges Releaseobjekt und keinen dokumentierten atomaren Umschalt- oder Rückfallmechanismus.

10. Deploymentstand wird mehrfach manuell dokumentiert

README, Deploymentdokumentation und current-status.md führen einen produktiven Integrationscommit manuell.

Diese Dokumentation kann korrekt sein, ist aber nicht aus einem maschinenlesbaren technischen Release-Manifest abgeleitet.

Zieldefinition: operative Reproduzierbarkeit

Für die private Immohai-App ist keine vollständig bitidentische Supply-Chain-Infrastruktur erforderlich.

Ziel ist operative Reproduzierbarkeit:

Ein festgelegter Git-Commit
+ eine festgelegte Runtime-Baseline
+ ein festgelegter Prüfauftrag
+ ein expliziter Build-Kontext
= eindeutig identifizierbare App- und Dokumentationsartefakte
  mit nachvollziehbaren Tool- und Containerständen.

Nicht erforderlich:

eigene Container Registry als zwingende Voraussetzung
Kubernetes
vollständige SLSA-Plattform
Signaturserver
selbst gehostete GitHub-Runner
komplexe SBOM- oder Provenance-Plattform

Zielprinzip

verifizierter Git-Commit
-> fixierte technische Baseline
-> kanonischer Contract Check
-> reproduzierbarer App- und Docs-Build
-> unveränderbares Release-Artefakt
-> explizite Releaseaktivierung
-> lokale und öffentliche Verifikation
-> dokumentierter Rollback

Geltungsbereich

ARCH-2026-004 umfasst:

Pinning-Strategie für produktive Container
Pinning-Strategie für Prüfimages und GitHub Actions
technische Runtime-Baseline als dokumentierte Quelle
kanonischen Contract-Check-Einstieg
Parität zwischen CI und Deploymentprüfung
gekapselte Browser-Testumgebung
reproduzierbare App-Ausgabe
statisch gebautes Dokumentationsartefakt
unveränderbares Release-Artefakt
Trennung von Build und produktiver Aktivierung
explizite Release-ID
technische Release-Metadaten
kontrollierten Updateprozess
Rollback auf vorherigen Release
lokale und öffentliche Smoke- und Manifestprüfungen

Nicht Teil dieses Proposals:

fachliche Modell- oder Engineänderungen
Änderung von Formeln, KPIs oder Ratings
Backend oder Datenbank
Kubernetes oder Orchestrierungsplattform
eigene Registry als zwingende Voraussetzung
allgemeine Server-, Docker-, Nginx- oder Certbot-Anleitungen
vollständige Supply-Chain-Zertifizierung

Allgemeine Infrastruktur- und Setupregeln gehören in das Developer Playbook. Immohai dokumentiert nur seine konkrete Release- und Deploymentkette.

Abgrenzung zu ARCH-2026-005

ARCH-2026-004 verantwortet

wie ein technischer Release reproduzierbar erzeugt wird
welche Tool- und Containerbasis gilt
welcher Prüfauftrag einen Release freigibt
welches unveränderbare Artefakt ausgeliefert wird
wie der Release technisch identifiziert wird
wie Aktivierung und Rollback funktionieren

ARCH-2026-005 verantwortet voraussichtlich

wie nachgewiesen wird, dass Proposal, Spezifikation, Code,
Tests, Dokumentation und produktives Deployment denselben
vollständig integrierten Stand darstellen

Gemeinsame Grenze:

ARCH-2026-004 erzeugt einen eindeutig identifizierbaren Release.
ARCH-2026-005 verifiziert den integrierten Wahrheits- und Deploymentstand.

Die endgültige Abgrenzung wird im Audit von ARCH-2026-005 erneut geprüft.

Technische Baseline

Die genaue Form ist noch zu entscheiden. Sie soll mindestens erfassen:

Webserver-Image und Version oder Digest
Dokumentations-Buildimage und Version oder Digest
Node-Prüfimage und Version oder Digest
Browser-Testimage oder Browser-Binary-Version
GitHub-Action-Versionen
CI-Runner-Linie
Docker-Compose-Mindestversion
Release-Schema- oder Manifestversion

Empfohlene Richtung ist eine einzige repository-lokale, maschinenlesbare Baseline, aus der CI, lokale Prüfung und Deployment lesen oder gegen die sie prüfen.

Doppelte manuelle Versionslisten in mehreren Shell- und Workflowdateien sind zu vermeiden.

Pinning-Grundsätze

Produktive Runtime

keine latest-Tags
mindestens konkrete Patch-Tags
bevorzugt Digest-Pinning für produktive Basisimages
menschenlesbarer Tag plus Digest zulässig

Prüfimages

Node und Browser eindeutig versionieren
lokale Prüfung, CI und Deployment verwenden denselben freigegebenen Stand

GitHub Actions

Mögliche Stufen:

Major-Tag
  einfacher, aber beweglich

vollständige Commit-SHA
  reproduzierbarer und sicherer, höherer Pflegeaufwand

Die konkrete Tiefe bleibt eine offene Einzelentscheidung. Für sicherheitsrelevante oder releasekritische Actions wird SHA-Pinning empfohlen.

Kanonischer Contract Check

Es soll genau einen fachlich vollständigen lokalen Einstiegspunkt geben, beispielsweise:

scripts/check-contract.sh

Dieser Einstiegspunkt wird verwendet von:

lokaler Entwicklung
GitHub Actions
deploy-and-verify
späteren Releaseprozessen

Der Workflow darf einzelne Schritte für lesbare Logs darstellen, muss jedoch denselben kanonischen Prüfumfang abbilden.

Der kanonische Check soll mindestens enthalten:

Konfigurations- und Schema-Synchronisation
Engine- und Versionssynchronisation
Syntax- und Vertragsprüfungen
Baseline-Regressionen
PropertyRecord- und Adaptertests
Szenario- und Ratingprüfungen
Report- und Chartprüfungen
Browser-Readiness
gekapselte Headless-Browserprüfung
Spezifikationskonsistenz
Docker-Compose-Validierung
Nginx-Konfigurations- und Cacheprüfung
MkDocs strict build

Release-Artefakt

Die konkrete Form bleibt offen. Zulässige Zielrichtungen sind:

A. lokal gebaute Immohai-Dockerimages mit Git-SHA-Tag
B. unveränderbare Releaseverzeichnisse je Git-Commit
C. Kombination aus Releaseverzeichnis und gepinnten Runtime-Containern

Unabhängig von der Form gelten:

Build erfolgt außerhalb des produktiv aktiven Pfads.
Artefakt wird nach erfolgreicher Prüfung nicht mehr verändert.
Aktivierung erfolgt explizit.
Vorheriger Release bleibt für Rollback verfügbar.

App-Artefakt

Die statische App soll als genau definierter Dateibaum ausgeliefert werden.

Zulässige Richtung:

frontend/
+ deploy/nginx/default.conf
+ veröffentlichte technische Release-Metadaten
-> versioniertes Web-Artefakt oder Web-Image

Das produktive App-Verzeichnis darf nach Integration nicht mehr direkt der während des Deployments aktualisierte Git-Working-Tree sein.

Dokumentationsartefakt

Der in CI erfolgreich geprüfte MkDocs-Build soll der produktiven Ausgabe entsprechen:

Repository-Dokumentation
-> mkdocs build --strict
-> unveränderbares site/-Artefakt
-> statische Auslieferung

mkdocs serve bleibt für lokale Entwicklung zulässig, soll aber nicht die endgültige produktive Releaseausgabe bilden.

Release-ID und technische Metadaten

Jeder Release benötigt eine eindeutige ID, mindestens abgeleitet aus dem vollständigen Git-Commit.

Empfohlene Richtung:

release_id
git_commit
built_at
runtime_baseline_version
web_artifact_identity
docs_artifact_identity
model_version
calculation_engine_version
schema_versions

Diese Metadaten sind technische Deploymentinformationen. Sie gehören nicht in AnalysisResult oder PropertyRecord.

Ein öffentlich oder lokal abrufbares technisches Release-Manifest ist zu prüfen.

Aktivierung und Rollback

Zielregel:

prüfen
-> bauen
-> Release unveränderbar ablegen
-> explizit aktivieren
-> Endpunkte prüfen

Rollback:

vorherige Release-ID bestimmen
-> vorheriges Artefakt wieder aktivieren
-> Services neu laden oder umschalten
-> lokale und öffentliche Verifikation

Ein fehlgeschlagener Build oder Check darf den aktuell aktiven Release nicht verändern.

Updateprozess für externe Abhängigkeiten

Update bewusst anstoßen
Release Notes und Breaking Changes prüfen
Pins beziehungsweise Digests aktualisieren
kanonischen Contract Check ausführen
App- und Docs-Artefakte bauen
lokale Containerprüfung
Browserabnahme bei sichtbaren Änderungen
Deployment und öffentliche Verifikation
technischen Release-Stand dokumentieren

Ein regelmäßiger Update-Rhythmus ist erforderlich, weil striktes Pinning Sicherheitsupdates nicht automatisch übernimmt.

Automatische Tools wie Dependabot oder Renovate dürfen später Updatevorschläge erstellen, aber keine ungeprüften produktiven Updates auslösen.

Weitere offene Einzelentscheidungen

2. Artefaktstrategie
   Git-SHA-Dockerimages, Releaseverzeichnisse oder Kombination?

3. Runtime-Baseline
   Welche Datei ist die einzige maschinenlesbare Quelle?

4. Pinning-Tiefe
   Patch-Tags, Digests und Action-SHAs für welche Komponenten?

5. Kanonischer Contract Check
   Welche Prüfungen sind zwingender Release-Gate-Bestandteil?

6. Browser-Testumgebung
   Containerisiertes Chromium oder festes Hostpaket mit Versionsprüfung?

7. Dokumentationsauslieferung
   Eigenes statisches Docs-Image oder Releaseverzeichnis?

8. Release-Metadaten
   Welche Felder und welcher öffentliche beziehungsweise interne Endpunkt?

9. Aktivierungsmechanismus
   Compose-Imagewechsel, Symlink auf Releaseverzeichnis oder anderer atomarer Wechsel?

10. Rollback und Aufbewahrung
    Wie viele frühere Releases bleiben verfügbar?

11. Update-Rhythmus
    Monatlich, quartalsweise oder anlassbezogen bei Security-Releases?

Entscheidungsmehrwert

reproduzierbare technische Releases
kein stiller Wechsel durch latest-Tags
kein Deployment aus einem gleichzeitig veränderten Working-Tree
identischer Prüfauftrag in CI und Deployment
geprüfter Docs-Build entspricht produktiver Ausgabe
eindeutige Release- und Artefaktidentität
belastbarer Rollback
bessere Fehleranalyse und Auditierbarkeit
kontrollierte statt implizite Abhängigkeitsupdates

Auswirkungen auf Architektur, Roadmap und Spezifikation

Architektur:

Build, Prüfung, Releaseablage und Aktivierung werden getrennte Schritte.
Deployment- und Runtimebasis werden explizit versioniert.
Die App-Schichten und Facharchitektur bleiben unverändert.

Roadmap:

Stabilisierungsschritt vor größeren Architektur- und Produktumbauten
keine neue Produktphase
kleiner technischer Pflegeaufwand für regelmäßige Updates

Spezifikation:

Architektur- und Deploymentdokumentation werden nach Annahme ergänzt.
Keine fachliche Spezifikationsänderung.

Auswirkungen auf Formeln, KPIs und Datenverträge

keine Änderung
keine Modellversion
keine Schemaänderung
keine fachliche Engineänderung

Eine technische Release- oder Baselineversion ist unabhängig von Modell- und Engineversion zu prüfen.

Auswirkungen auf UI, Reporting und Speicherung

keine beabsichtigte sichtbare Änderung
keine Änderung gespeicherter PropertyRecords
keine Änderung der Browser-Speicherverträge
App- und Docs-Routing müssen nach Umstellung unverändert funktionieren

Auswirkungen auf Tests und Referenzfälle

Erforderlich:

kanonischer Contract Check lokal erfolgreich
GitHub CI verwendet denselben Prüfumfang
Deployment verwendet denselben Prüfumfang
fixierte Images sind auflösbar
docker compose config --quiet
Web-Artefakt enthält erwartete Dateien
Docs-Artefakt stammt aus mkdocs build --strict
Release-Manifest entspricht Git-Commit und Versionen
Nginx-Konfiguration und Cache-Header bleiben korrekt
Headless-Browsercheck läuft in definierter Umgebung
lokale App- und Docs-Endpunkte erfolgreich
öffentliche App- und Docs-Endpunkte erfolgreich
öffentliche Release- und Modellmetadaten entsprechen dem aktivierten Release
Rollback auf vorherigen Release erfolgreich getestet

Legacy- und Migrationsfolgen

keine Datenmigration
bestehende PropertyRecords bleiben unverändert
aktueller Bind-Mount-Deploymentpfad bleibt bis zur kontrollierten Umschaltung bestehen
alter und neuer Deploymentpfad dürfen nur kurzzeitig parallel existieren
bestehende Ports und Reverse-Proxy-Ziele sollen unverändert bleiben
vorheriger produktiver Stand wird als Rollbackrelease gesichert

Ein dauerhafter Mischbetrieb aus unveränderbaren Releases und direkt gemountetem Working-Tree ist zu vermeiden.

Risikoanalyse

Risiko der Proposal-Aktualisierung

niedrig

Risiko der späteren Umsetzung

mittel

Produkt- und Laufzeitrisiko während der Umstellung

mittel

Besonders regressionsgefährdet:

statische Assetpfade
Nginx-Konfiguration
Dokumentationsrouting
MkDocs-Plugins und Themes
Dateiberechtigungen
Cache-Header
Compose-Start- und Restartverhalten
Releaseaktivierung
Rollback
öffentliche Reverse-Proxy-Ziele
Browsercheck

Mögliche Fehlerbilder:

Artefakt enthält nicht alle Frontenddateien
Docs-Build unterscheidet sich vom bisher sichtbaren Serve-Verhalten
Release-Metadaten nennen falschen Commit
CI und Deployment driften erneut auseinander
Rollback referenziert nicht mehr vorhandene Artefakte
Image-Pin ist veraltet oder nicht mehr verfügbar
Berechtigungen verhindern statische Auslieferung

Sicherungs- und Rückfallstrategie vor Umsetzung

Vor dem ersten Code- oder Deploymentcommit sind mindestens zu sichern:

aktueller main-Commit
aktuell produktiver Git-Commit
vollständige docker compose config
docker compose ps
aktuelle Image-IDs und Repo-Digests
aktuelle Web- und Docs-Containerkonfiguration
aktuelle lokale und öffentliche Smoke-Tests
aktuelle Nginx-Cache-Header
aktuelle Browserabnahme
Kopie oder Tag des produktiven Serverstands

Zusätzlich ist eine explizite Rückfallbaseline zu dokumentieren:

web:
  aktives Basisimage
  aktiver Frontend-Dateistand

docs:
  aktives MkDocs-Image
  aktiver Dokumentationsstand

server:
  Compose-Konfiguration
  Reverse-Proxy-Ziele
  produktiver Commit

Git allein genügt nicht als vollständiger Rollback, solange externe Image-Tags beweglich sind. Die tatsächlich verwendeten Image-Identitäten müssen mitgesichert werden.

Empfohlene Umsetzungsstruktur nach vollständiger Annahme

Phase 0
  produktive Baseline und Image-Identitäten sichern
  Rückfalltest vorbereiten

Phase 1
  technische Runtime-Baseline und Pins definieren
  kanonischen Contract Check herstellen

Phase 2
  Browserprüfung kapseln
  CI und Deployment auf denselben Prüfumfang bringen

Phase 3
  reproduzierbares App- und statisches Docs-Artefakt bauen
  Release-Metadaten erzeugen

Phase 4
  neuen Release parallel zum aktiven Stand lokal prüfen
  Aktivierungs- und Rollbackmechanismus testen

Phase 5
  produktiv umschalten
  lokale und öffentliche Verifikation
  Dokumentation und Arbeitsstand synchronisieren

Diese Struktur wird erst nach den offenen Einzelentscheidungen verbindlich.

Prüfergebnis

Die ursprüngliche Problemfeststellung ist bestätigt, aber zu eng gefasst.

Nachgewiesen sind:

bewegliche Runtime- und CI-Abhängigkeiten
keine unveränderbaren Immohai-Releaseartefakte
produktive Bind-Mounts auf den Git-Working-Tree
nicht atomare Aktivierung nach git pull
abweichende CI- und Deploymentprüfungen
hostabhängige Browserprüfung
geprüfter MkDocs-Build wird nicht produktiv ausgeliefert
unvollständige Releaseidentität
kein formalisiertes Rollback

Eine reine Pinning-Strategie würde nur einen Teil dieser Risiken beheben. Die Erweiterung auf eine vollständige reproduzierbare Prüf-, Release- und Container-Baseline ist deshalb sachlich erforderlich.

Entscheidung

Teilentscheidung 1 am 2026-07-07 bestätigt:

Variante B – ARCH-2026-004 umfasst die vollständige technische Kette
vom verifizierten Git-Commit bis zum eindeutig identifizierbaren,
unveränderbaren und rückrollbaren Release.

CI und Deployment sollen denselben kanonischen Prüfauftrag verwenden.
Die produktive Ausgabe soll nicht mehr direkt aus einem während des
Deployments veränderten Git-Working-Tree erfolgen.

Gesamtentscheidung: offen
Proposal-Status: under_review

Zieldokumente bei späterer Annahme

docker-compose.yml
.github/workflows/contract-check.yml
scripts/check-contract.sh oder entsprechender kanonischer Einstieg
scripts/check-frontend-baseline.sh
scripts/run-single-analysis-browser-check.sh
scripts/deploy-and-verify.sh
technische Runtime-Baseline oder Release-Manifestdatei
Dockerfile beziehungsweise Release-Builddefinitionen
.dockerignore
deploy/nginx/default.conf
docs/operations/deployment.md
docs/specification/architecture/overview.md
docs/specification/architecture/project-structure.md
docs/operations/browser-acceptance.md
README.md
docs/roadmap/current-status.md

Integrationscommit

offen