# Vendoo Production Updater 3.4

## Zweck

Updater 3.4 ersetzt den linearen, branchorientierten Ablauf von Updater 3.3 durch einen idempotenten Release-Lifecycle. Der Updater arbeitet auf einen nachprüfbaren Zielzustand hin und erzeugt keine weiteren Quelländerungen, sobald `main` oder die Produktion die Zielversion bereits erreicht haben.

Der Vertrag schützt insbesondere:

- den aktuellen Stand von `main` vor veralteten Payloads,
- den Pull Request vor Merge eines nicht mehr geprüften Head-SHA,
- vorhandene Releases vor doppelten Branches und Pull Requests,
- persistente Produktionsdaten unter `/app/data`,
- Datenbanken, Uploads, Benutzer, Artikel, Einstellungen, API-Schlüssel, FLUX-Modelle und Backups.

## Quellwahrheit

Der Updater wertet den Zustand in dieser Reihenfolge aus:

1. aktueller GitHub-Branch `main`,
2. aktueller Pull-Request-Head und konkrete GitHub-Workflow-Runs,
3. öffentliche Produktionsantwort `/readyz`,
4. lokaler Sitzungsstand nur als Wiederaufnahmekontext.

Ein lokaler Sitzungsstand darf niemals einen neueren GitHub- oder Produktionszustand überschreiben.

## Zustandsautomat

```text
PACKAGE_VALIDATED
  -> TOOLS_READY
  -> GITHUB_READY
  -> TARGET_OBSERVED

TARGET_OBSERVED
  -> COMPLETED
       wenn main == target und production == target
  -> DEPLOY_REQUIRED
       wenn main == target und production != target
  -> PR_RESUME
       wenn ein passender offener PR existiert
  -> DEPLOY_REQUIRED
       wenn ein passender PR bereits gemergt ist
  -> SOURCE_REQUIRED
       nur wenn main noch nicht target ist und kein passender PR existiert

SOURCE_REQUIRED
  -> PAYLOAD_GUARD
  -> LOCAL_CONTRACT
  -> TARGET_REOBSERVED
  -> PR_RECONCILED

PR_RESUME | PR_RECONCILED
  -> CHECKS_TRACKING

CHECKS_TRACKING
  -> CHECKS_TRACKING
       wenn sich der PR-Head-SHA ändert; Grace Period beginnt erneut
  -> CHECKS_TRACKING
       wenn Checks noch nicht registriert, queued, pending oder in_progress sind
  -> MERGE_READY
       wenn alle Pflichtchecks und Pflichtworkflows am stabilen finalen Head erfolgreich sind
  -> FAILED
       bei terminalem Pflichtfehler, Abbruch oder Gesamtzeitüberschreitung

MERGE_READY
  -> MERGED
       nur per --match-head-commit für den geprüften Head-SHA
  -> DEPLOY_REQUIRED
  -> PRODUCTION_VERIFIED
  -> COMPLETED
```

## Idempotenzregeln

### Bereits aktuelle Produktion

Wenn `main` und `/readyz` bereits die Zielversion melden, endet der Updater sofort erfolgreich. Es werden weder Arbeitskopie noch Branch, Pull Request, Commit oder Deployment erzeugt.

### `main` bereits auf Zielversion

Wenn `main` bereits die Zielversion enthält, wird die Sourcephase vollständig übersprungen. Der Updater prüft nur noch, ob die Produktion nachziehen muss.

### Bereits gemergter Pull Request

Ein bereits gemergter passender Pull Request wird als abgeschlossene Sourcephase behandelt. Der Updater erzeugt keinen zweiten Pull Request und setzt beim Deployment beziehungsweise bei der Produktionsprüfung fort.

### Bereits offener Pull Request

Ein vorhandener offener Pull Request des deterministischen Releasebranches wird übernommen. Sein aktueller `headRefOid` ist die alleinige Prüfreferenz.

### Doppelter oder paralleler Start

Die Desktopoberfläche verhindert parallele lokale Prozesse per Mutex. Zusätzlich gleicht jeder Lauf GitHub und Produktion erneut ab. Ein konkurrierender Lauf, der zwischen lokaler Prüfung und Push einen Pull Request erzeugt oder `main` aktualisiert, wird bei der zweiten Zielbeobachtung erkannt und übernommen.

## Paket-Provenienz

Auslieferbare Pakete verwenden das Schema `vendoo-release-package-v2` und enthalten:

- `targetVersion`,
- `updaterVersion`,
- `sourceCommit`,
- `baseCommit`,
- `createdAt`,
- `payloadHash`,
- die vollständige SHA-256-Dateiliste,
- explizite Löschungen.

`payloadHash` wird aus den stabilen Manifestfeldern berechnet. Jede Änderung an Herkunft, Zieldateien oder Löschungen verändert die Paketidentität.

Vor dem Overlay wird geprüft:

1. `baseCommit` und aktueller `main` müssen lokal auflösbar sein.
2. `baseCommit` muss Vorfahr des aktuellen `main` sein.
3. Alle Pfade, die Payload und `main` seit `baseCommit` beide verändert haben, werden verglichen.
4. Weicht der gewünschte Payloadstand vom aktuellen `main` ab, wird der Lauf vor jeder Quelländerung blockiert.
5. Nicht kollidierende Fortschritte in `main` dürfen bestehen bleiben.

Damit kann ein altes Paket neuere Änderungen aus `main` weder still noch per Force-Push zurücksetzen.

## GitHub-Check-Lifecycle

Updater 3.4 verwendet nicht mehr `gh pr checks --watch` als Blackbox.

Für jeden aktuellen PR-Head werden ausgewertet:

- `statusCheckRollup` des Pull Requests,
- Workflow-Runs aus `actions/runs?head_sha=<finaler-head>&per_page=100`,
- die Pflichtchecks `Syntax, Sicherheit und Release-Gates`, `Windows – vollständiger Releasevertrag` und `Updater-3.4-Paket nach Abnahme`,
- die Pflichtworkflows `Vendoo CI` und `Vendoo Release Manifest Sync`.

Regeln:

- `no checks reported` ist während der 90-sekündigen Registrierungs-Grace-Period kein Fehler.
- `queued`, `pending`, `in_progress`, `waiting` und `requested` sind laufende Zustände.
- Bei mehreren Runs desselben Workflows entscheidet der zeitlich neueste Run; ein alter Erfolg darf einen neueren Fehler nicht verdecken.
- Ändert der Manifest-Sync den Head-SHA, werden Grace Period und Checkauswertung für den neuen Head vollständig neu gestartet.
- Vor dem Merge wird der Head-SHA erneut gelesen.
- Der Merge verwendet `--match-head-commit`; ein weiterer Headwechsel verhindert den Merge atomar.

### Final-Head-Registrierung nach Manifest-Sync

Ein Push mit dem GitHub-Workflow-Token startet für den dadurch erzeugten Commit nicht automatisch einen weiteren Push-Workflow. Deshalb bestätigt der Manifest-Sync nach seinem Commit zuerst den tatsächlichen Remote-Head und dispatcht anschließend explizit:

1. `Vendoo CI` für den neuen Head,
2. `Vendoo Release Manifest Sync` für denselben Head.

Der zweite Manifest-Sync-Lauf findet ein unverändertes Manifest, erzeugt keinen weiteren Commit und dient als konkreter erfolgreicher Workflow-Nachweis am finalen SHA. Die Concurrency des Sync-Workflows darf den auslösenden Lauf nicht abbrechen.

### Paket erst nach Plattformabnahme

Das auslieferbare ZIP entsteht im Job `Updater-3.4-Paket nach Abnahme`. Dieser Job besitzt eine harte `needs`-Abhängigkeit auf Linux- und Windows-Abnahme. Er läuft daher erst, wenn beide Verträge erfolgreich abgeschlossen wurden. Danach werden Root-Manifest, Paketmanifest v2, Zielversion, Updater-Version und ZIP-SHA-256 erneut geprüft. Nur dieses Artefakt ist ein auslieferbarer Kandidat.

## Sitzungsvertrag

Sitzungen verwenden `vendoo-updater-session-v2`. Die Identität besteht aus:

- Repository,
- Zielversion,
- Payload-Hash,
- deterministischem Releasebranch.

Gespeichert werden unter anderem Pull-Request-Nummer und URL, finaler geprüfter Head-SHA, Merge-Commit, Produktionsversion, Releasezustand und Abschlusszeitpunkt. Der Sitzungsstand dient ausschließlich der Wiederaufnahme; jeder Lauf validiert die externen Zustände erneut.

## Branch- und Push-Sicherheit

- Releasebranch: `release/<zielversion>-production-update-v4`
- kein unbedingtes `git push --force`
- vorhandene Branches werden nur mit `--force-with-lease=<erwarteter-remote-sha>` aktualisiert
- Merge ausschließlich für den nachgewiesenen finalen Head-SHA
- kein Quell-PR, wenn `main` bereits auf Zielversion ist

## Produktionsvertrag

Das Deployment verändert keine persistenten Nutzdaten. `/app/data` bleibt außerhalb des Release-Payloads. Der Updater akzeptiert Erfolg erst, wenn `/readyz` sowohl `ok: true` als auch exakt die Zielversion meldet.

Die Option `-SkipProductionDeploy` ist ausschließlich für Source-/CI-Abnahmen vorgesehen. Sie darf nicht als Nachweis eines vollständigen Produktionsupdates ausgegeben werden.

## Fehlerdiagnose

Bei Fehler oder Timeout werden protokolliert:

- aktuelle Phase,
- aktueller PR und Head-SHA,
- Pflichtcheck- und Workflow-Matrix,
- Prozessausgabe und Exit-Code,
- Payload-Konfliktpfade,
- konkrete Wiederanlaufempfehlung.

Ein erneuter Start beginnt nicht blind von vorn, sondern beobachtet Zielzustand, Pull Requests, Merge und Produktion erneut und setzt beim tatsächlich offenen Zustand fort.
