# Semantic Versioning

Alle `@mittwald/flow-*`-Packages teilen sich eine gemeinsame Version. Dieselbe
Zusage gilt damit einheitlich für jedes Package. Es gibt keine
Package-spezifischen Sonderregeln.

Mit Version `1.0.0` wird aus einer guten Absicht eine verlässliche Zusage: Wir
halten uns an [Semantic Versioning](https://semver.org) und gehen Änderungen
planbar und nachvollziehbar an.

- **Major** – enthält Breaking Changes. Ein Update kann Anpassungen in deinem
  Code erfordern. Major-Versionen bleiben bewusst selten.
- **Minor** – fügt neue Funktionen hinzu und ist abwärtskompatibel.
- **Patch** – enthält Bugfixes und ist abwärtskompatibel.

Entscheidend ist die Grenze: Welche Änderung erzwingt eine neue Major-Version,
und welche darf in einem Minor oder Patch erscheinen? Die folgenden Abschnitte
beschreiben diese Grenze aus Sicht der Entwickler.

---

# Worauf du dich verlassen kannst

Diese Bereiche sind durch die Versionierung geschützt. Eine inkompatible
Änderung daran erscheint nur in einer neuen Major-Version:

- **Runtime Public API von `public.ts`** – welche Components und Exports
  existieren und welche Props sie zur Laufzeit akzeptieren, sowie das
  dokumentierte Verhalten dokumentierter Funktionen. Die Type-Ebene ist hiervon
  ausdrücklich ausgenommen (siehe unten).
- **Components aus `@mittwald/flow-remote-react-components`** – die in
  mStudio-Extensions verwendete API. Ihre Props sind der Vertrag mit
  Extension-Entwicklern und unterliegen derselben Zusage.
- **Veröffentlichte Icons** – ein Icon zu entfernen oder umzubenennen ist ein
  Breaking Change. Icons werden ohnehin nie entfernt, sondern nur deprecated.
- **Das Remote-Protokoll** – die versionierte Verbindungsschicht zwischen
  Extension und Host bleibt kompatibel, solange dies möglich ist.

Wenn ein Teil der öffentlichen API entfernt werden soll, wird er zunächst als
deprecated gekennzeichnet und nicht sofort entfernt. Der alte Pfad bleibt
erhalten und wird zur Laufzeit über eine Deprecation-Warnung angekündigt, bevor
er in einer Major-Version entfernt wird. Das betrifft die gesamte öffentliche
API, nicht nur die in Extensions verwendeten Components.

---

# Node- und React-Unterstützung

Node und React sind echte Runtime-Voraussetzungen. Auch hier gibt es klare
Regeln, welche Änderung eine neue Major-Version erzwingt.

**Node**

- Der garantierte Node-Floor ist die aktiv unterstützte Node-LTS, aktuell
  `node >=24`, einheitlich über alle Packages. Er wird nur bei konkretem Bedarf
  angehoben, nicht um neuen Releases hinterherzulaufen.
- Eine Node-Version fallen zu lassen, die noch in ihrem LTS-/Maintenance-Fenster
  liegt, ist ein Breaking Change (→ Major). Eine bereits End-of-Life-Version
  fallen zu lassen, darf in einem Minor erscheinen.
- Strenger sind die Node-Runtime-Packages `@mittwald/ext-bridge` und
  `@mittwald/flow-remote-core`: Für sie ist jedes Anheben des Node-Floors ein
  Breaking Change (→ Major), unabhängig von EOL, und ihr Floor kann
  konservativer sein als der der übrigen Packages.

**React**

- Das **Erweitern** der akzeptierten Range (z. B. `^19` → `^19 || ^20`) ist
  abwärtskompatibel (Minor).
- Das **Anheben der Mindestversion** oder das Fallenlassen einer React-Major ist
  ein Breaking Change (→ Major).

---

# Was nicht garantiert ist

Damit sich das Design System weiterentwickeln kann, sind die folgenden Bereiche
bewusst nicht durch die Versionierung abgedeckt. Sie können sich in jedem
Release ändern, auch in einem Minor oder Patch:

- **Alle Änderungen auf Type-Ebene (TypeScript).** Die Typen sind best-effort
  und nicht durch Semantic Versioning geschützt. Auch das Entfernen oder
  Umbenennen eines exportierten Typs oder das Verengen eines Prop-Typs ist für
  sich genommen kein Breaking Change. Nennenswerte Type-Änderungen werden
  dennoch im Changelog erwähnt.
- **Das visuelle Erscheinungsbild.**
- **Die interne DOM-Struktur.**
- **CSS-Klassennamen.**
- **Namen und Werte von Design Tokens.**

---

# So schützt du dich

Weil die oben genannten Bereiche bewusst nicht garantiert sind, gibt es zwei
Regeln, an die du dich als Entwickler halten solltest.

  Zwei Regeln für den stabilen Betrieb

    Style nicht gegen interne CSS-Klassen, und behandle Flows TypeScript-Typen
    als best-effort. Beide Bereiche können sich in jedem Release ändern.

## Style nicht gegen interne CSS-Klassen

Die CSS-Klassennamen der Components sind ein internes Implementierungsdetail und
können sich in jedem Release ändern. Verlasse dich für eigenes Styling nicht
darauf, dass eine bestimmte interne Klasse existiert oder gleich heißt.
Andernfalls kann bereits ein Patch dein Styling brechen.

## Behandle TypeScript-Typen als best-effort

Flows TypeScript-Typen folgen nicht Semantic Versioning. Ein `tsc`-Fehler kann
daher theoretisch schon in einem Patch auftreten. Wenn ein solcher Bruch für
dein Projekt teuer wäre, pinne exakte Versionen (statt `^`-Ranges), sodass ein
Update bewusst und kontrolliert erfolgt. Zu einem bewusst herbeigeführten
Type-Breaking-Change gehört eine Migrationsnotiz in den Release Notes – so
bekommst du einen konkreten Upgrade-Pfad, auch wenn die Änderung in einem Minor
oder Patch erscheint.

---

# Migration bei einer Breaking Change

Jede Änderung, die eine Anpassung in deinem Code erfordert, steht mit
Vorher-Nachher-Beispiel im Migrationsleitfaden des betroffenen Packages:

- [Migrationsleitfaden `@mittwald/flow-react-components`](https://github.com/mittwald/flow/blob/main/packages/components/MIGRATION.md)
  – deckt auch `@mittwald/flow-remote-react-components` ab
- [Migrationsleitfaden `@mittwald/ext-bridge`](https://github.com/mittwald/flow/blob/main/packages/ext-bridge/MIGRATION.md)

Die Einträge sind nach Version absteigend sortiert und nennen jeweils die
Version, ab der die Änderung greift. Suche die Version, von der du kommst, und
arbeite dich nach oben durch.

## Nutze den Codemod, wenn es einen gibt

Umbenennungen liefern wir als
[Codemod](https://github.com/mittwald/flow/tree/main/packages/codemods/src/transforms)
aus – ein Skript, das die Anpassung in deinen Sourcen automatisch vornimmt.
Welcher Codemod zu einer Änderung gehört, steht im jeweiligen Eintrag des
Migrationsleitfadens, zusammen mit dem fertigen Aufruf:

```shell
npx jscodeshift \
  -t https://raw.githubusercontent.com/mittwald/flow/refs/heads/main/packages/codemods/src/transforms/<name>.ts \
  --parser tsx \
  src
```

Ein Codemod ändert Dateien direkt. Führe ihn auf einem sauberen Git-Stand aus
und prüfe das Diff.

Wenn du mehrere Versionen auf einmal aufholst, nimm `flowAlphaAll` – der Codemod
führt alle Migrations-Codemods der `0.2.0-alpha`-Reihe in der Reihenfolge ihrer
Releases aus:

```shell
npx jscodeshift \
  -t https://raw.githubusercontent.com/mittwald/flow/refs/heads/main/packages/codemods/src/transforms/flowAlphaAll.ts \
  --parser tsx \
  src
```

## Deprecation-Warnungen sind der Vorlauf

Wird ein Pfad deprecated, bleibt er funktionsfähig und meldet sich zur Laufzeit
per `console.warn`. Diese Warnungen sind die Vorwarnzeit vor der nächsten
Major-Version – behandle sie als Aufgabenliste, nicht als Rauschen. Um sie
zentral einzusammeln, etwa im Error-Tracking, umschließe deine Anwendung mit
einem `DeprecationWarningProvider` und gib ihm einen `onWarning`-Handler:

```tsx
<DeprecationWarningProvider onWarning={(message) => reportToTracking(message)}>
  <App />
</DeprecationWarningProvider>
```

---

# Component Lifecycle

Der Vertrag gilt nicht für jede Component gleich. Jede Component hat einen
Lifecycle-Status, der die obigen Regeln überschreibt:

- **Beta** – von der Breaking-Change-Zusage ausgenommen. Die API kann sich auch
  außerhalb einer Major-Version ändern.
- **Stable** (Standard) – vollständig durch die obigen Regeln gebunden.
- **Deprecated** – bis zur Entfernung in einer Major-Version weiter abgesichert
  und mit einem Migrationspfad versehen.

Das vollständige Lifecycle-Modell beschreibt
[ADR 0003](https://github.com/mittwald/flow/blob/main/docs/adr/0003-component-lifecycle-status.md).
