diff --git a/STATUS.md b/STATUS.md index 859ad57..d09deb1 100644 --- a/STATUS.md +++ b/STATUS.md @@ -71,7 +71,7 @@ Verteilung: M1 11 · M2 17 · M3 4 · M4 11 · M5 15 _none active_ -## ADRs (22) +## ADRs (23) | ADR | Status | Title | |---|---|---| @@ -97,6 +97,7 @@ _none active_ | [0020](docs/adr/0020-bekannte-befunde-quittieren.md) | accepted | ADR-0020: Bekannte Befunde werden quittiert, damit Rot wieder etwas bedeutet | | [0021](docs/adr/0021-foederation-geschlossen.md) | accepted | ADR-0021: Föderation wird geschlossen — leere Whitelist statt offener Tür | | [0022](docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md) | accepted | ADR-0022: Anschluss an Upstream durch einen einmaligen Merge, nicht durch einen geteilten Graft | +| [0023](docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md) | accepted | ADR-0023: Fremde Historie von der Git-Hygiene ausnehmen — erklärt, nicht global | ## Open AARs (0) diff --git a/docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md b/docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md index cc52102..0140ea7 100644 --- a/docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md +++ b/docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md @@ -73,31 +73,3 @@ und ohne diese Messung wäre der Merge auf eine erfundene Grundlage gelaufen. empfangen) ist der Merge nicht abgenommen. - Schritt 4 aus #0099 — ein Verfahren zum Auftragen der Patches — wird damit gegenstandslos. - -## Nachtrag 2026-08-19: ausgeführt, und was die Ausführung korrigiert - -Vollzogen. `ThreadNet-Web:main` steht auf `8ca03fe`, der Merge-Commit `88c4e15` trägt -beide echten Eltern. Produktion läuft auf `v0.6.0`. Zwei Annahmen dieser ADR haben sich -in der Praxis verschoben: - -**Die stille Klasse verschwindet nicht ganz — sie dreht sich um.** Die Entscheidung -begründet sich damit, dass Git künftig meldet, wenn Upstream eine Datei verschiebt, die -wir angefasst haben. Das hat gehalten (`RoomListItemWrapper`-Umbenennung wurde als -Konflikt gemeldet). Was ein Drei-Wege-Merge **nicht** meldet, ist der umgekehrte Fall: -Beide Seiten überleben die Auflösung, aber nur eine ergibt noch Sinn. Genau das brach -`v0.6.0-rc.2` in Produktion — eine `getValue`-Zeile auf einen von Upstream entfernten -Einstellungsschlüssel, die niemand mehr liest und die trotzdem wirft. - -**Ein grüner Build ist keine Abnahme, und war nie eine.** Diese ADR sagt richtig -„Abnahme ist kein Build, sondern ein Funktionstest" — gemeint war der ClamAV-Test. Der -rc.2-Vorfall zeigt die Lücke davor: Der CI-Job `web` **baut** nur, webpack entfernt -Typen ohne sie zu prüfen. `tsc` meldete den Fehler durchgehend, gefragt hatte ihn -niemand. Seit `8ca03fe` führt `docker_web` den Job `typecheck` als `needs`; kein Image -entsteht mehr ohne bestandene Typprüfung. - -**Daraus die stehende Regel für künftige Upstream-Merges:** Nach der Konfliktauflösung -gehört eine Prüfung auf *überlebende* Reste — nicht nur auf verlorene Zeilen. Der -billigste Hebel ist die Typprüfung; sie fand beide Reste sofort. Wo Zeichenketten statt -Typen im Spiel sind (Einstellungsschlüssel, Feature-Namen, Übersetzungs-IDs), reicht sie -nicht, und es braucht einen Abgleich gegen die jeweilige Registry — für Einstellungen -wurde er einmalig gefahren: 135 abgefragte gegen 152 registrierte. diff --git a/docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md b/docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md new file mode 100644 index 0000000..76a5719 --- /dev/null +++ b/docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md @@ -0,0 +1,81 @@ +--- +type: adr +id: "0023" +status: accepted +date: 2026-08-19 +supersedes: null +superseded_by: null +related: + - "docs/adr/0009-commit-konventionen-und-historien-anonymisierung.md" + - "docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md" + - "docs/issues/0104-daueralarme-melden-nichts-mehr.md" +--- + +# ADR-0023: Fremde Historie von der Git-Hygiene ausnehmen — erklärt, nicht global + +## Kontext + +Der Upstream-Merge aus [ADR-0022](0022-upstream-anschluss-durch-einmaligen-merge.md) +hat am 2026-08-19 **70.265 fremde Commits** in `ThreadNet-Web` geholt. Sie stammen von +Element und tragen deren Zeitstempel und Identitäten. + +Die Git-Hygiene-Prüfung aus [ADR-0009](0009-commit-konventionen-und-historien-anonymisierung.md) +(`gruppenpruefung.py`, Prüfung 5) bemängelte davon sofort **39 Commits** als +„Echtzeit-Stempel" — alle im Fenster seit der Regel-Grenze 2026-08-07. + +Das ist kein Fehlalarm im engeren Sinn: Die Commits verletzen die Konvention wirklich. +Sie konnten ihr aber nie folgen, weil sie nicht bei uns entstanden sind, und sie werden +sich nie ändern lassen. Damit war die Prüfung dauerhaft rot — genau der Zustand, den +[#0104](../issues/0104-daueralarme-melden-nichts-mehr.md) am selben Tag beseitigt hatte. +Ein Alarm, der immer rot ist, meldet nichts mehr. + +## Optionen + +**A: Quittieren** über den Mechanismus aus ADR-0020. Verworfen: 39 Einträge, und die +Quittung verlangt eine Frist — hier gäbe es keine, weil sich nichts ändern wird. +ADR-0020 lässt „permanent" ausdrücklich nur als ADR zu, was auf diese ADR hinausläuft, +aber mit 39 Zeilen Ballast im Quittungs-Log. + +**B: Regel-Grenze verschieben oder die Prüfung global lockern.** Verworfen: Das nähme +allen Repos den Schutz, um einem zu helfen. + +**C: Fremde Absender hart im Code ausnehmen** (`releases@riot.im`, +`noreply@github.com`). Verworfen: Das ist eine Liste, die mit jedem neuen fremden +Beitragenden wächst — dieselbe Falle, die MASCHINEN bewusst per Adresse und nicht per +Name matched, nur eine Ebene höher. + +**D: Erklärte Ausnahme pro Komponente.** Neues Feld `fremdhistorie` in +`docs/components/*.md`. Wo es gesetzt ist, prüft die Hygiene nur noch Commits, die von +**eigenen Identitäten committet** wurden. + +## Entscheidung + +**Option D** (sorb, 2026-08-19: „gruppenprüfung fixen, upstream-commits ausnehmen"). + +Der Trennschnitt ist der **Committer**, nicht der Autor. Gemessen an ThreadNet-Web im +Fenster seit 2026-08-07: 18 eigene Commits, alle von `cfx@riot.8shield.net` committet; +39 fremde, committet von `GitHub ` (35) und `RiotRobot` (4). **Keine +Überschneidung.** Der Autor taugt nicht als Kriterium — unsere eigenen Commits können +fremde Autoren tragen (Cherry-Picks), und fremde Commits tragen Autoren, die wie +Menschen aussehen. + +Der Feldwert ist die **Begründung**, kein Schalter: Wer die Ausnahme erklärt, sagt, +woher die fremden Commits stammen. Das folgt dem Muster der Quittungen aus ADR-0020 — +eine Ausnahme ohne Begründung gibt es nicht. + +## Konsequenzen + +- Die Alarmanlage ist wieder grün und damit wieder aussagekräftig: 0 offene Befunde, + 20 quittiert. +- Die Prüfung bleibt in ThreadNet-Web **wirksam** — nachgewiesen, nicht angenommen: + Nach dem Fix werden dort weiterhin 18 Commits geprüft, alle auf `12:00:00`. +- ⚠️ **Der Preis, ehrlich benannt:** In Repos mit erklärter Fremdhistorie fällt ein + Commit durchs Raster, den jemand von uns unter einer **völlig unbekannten** Identität + erzeugt — also weder eigene Adresse als Autor noch als Committer. Genau diesen Fall + fängt die Identitätsprüfung sonst. Deshalb gilt die Ausnahme nur dort, wo sie + deklariert ist, und nicht global. +- Wer künftig ein Repo mit fremder Historie aufnimmt, muss das Feld setzen — sonst + färbt die Prüfung rot, und das ist richtig so: Die Ausnahme soll eine bewusste + Erklärung sein, kein stiller Nebeneffekt. +- Nicht gelöst: Der Gitea-Spiegel von ThreadNet-Web scheitert seit demselben Merge am + Umfang des Pushs (70.269 Commits, ~600 MB, `HTTP 499`). Eigener Vorgang. diff --git a/docs/components/ThreadNet-Web.md b/docs/components/ThreadNet-Web.md index 50a5c3f..325b89f 100644 --- a/docs/components/ThreadNet-Web.md +++ b/docs/components/ThreadNet-Web.md @@ -5,8 +5,10 @@ anzeigename: "ThreadNet Web" phase: active gitlab: "axion1337.chat/ThreadNet-Web" mirror: "rohana.axion1337.de/sorb/ThreadNet-Web" +fremdhistorie: "Element Web, seit dem Upstream-Merge 88c4e15 am 2026-08-19 (ADR-0022): 70.265 fremde Commits" related: - "docs/adr/0013-gruppenregeln-kanonisch-mit-pruefung.md" + - "docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md" --- # ThreadNet Web diff --git a/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md b/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md index 817b75b..1b15d05 100644 --- a/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md +++ b/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md @@ -360,6 +360,23 @@ eingesetzter Zeile scheitert es und benennt beide Fehler, ohne sie besteht es scheitert zusätzlich bei leerer `tsc`-Ausgabe, damit ein stiller Erfolg nicht als Prüfung durchgeht. +### Was ADR-0022 dabei nicht vorhergesehen hat + +Die ADR begründet die Entscheidung damit, dass Git künftig **meldet**, wenn Upstream +eine Datei verschiebt, die wir angefasst haben. Das hat gehalten — die Umbenennung +`RoomListItemAccessibilityWrapper` → `RoomListItemWrapper` kam als Konflikt. + +Was ein Drei-Wege-Merge **nicht** meldet, ist der umgekehrte Fall: Beide Seiten +überleben die Auflösung, und nur eine ergibt noch Sinn. Die stille Klasse verschwindet +also nicht, sie dreht sich um — aus „unsere Zeile ist weg" wird „ihre Zeile ist noch +da". Für künftige Merges heißt das: nach der Konfliktauflösung auf **überlebende** +Reste prüfen, nicht nur auf verlorene. Der billigste Hebel ist die Typprüfung, sie fand +beide sofort. Wo Zeichenketten statt Typen im Spiel sind — Einstellungsschlüssel, +Feature-Namen, Übersetzungs-IDs — reicht sie nicht und es braucht einen Abgleich gegen +die jeweilige Registry. + +(Kein Nachtrag in ADR-0022 selbst: Eine angenommene ADR wird nicht editiert.) + ### Die Abnahme, wie dieses Issue sie verlangt Gefordert war „verschlüsselte Datei senden, abgelehnte empfangen" — geprüft am diff --git a/schema.yaml b/schema.yaml index 91aac50..b6c202b 100644 --- a/schema.yaml +++ b/schema.yaml @@ -118,6 +118,11 @@ types: phase: { enum: [active, staged, external] } gitlab: { kind: str } mirror: { kind: str, nullable: true } + # Repo traegt fremde Historie (z. B. durch einen Upstream-Merge). Der Wert ist + # die Begruendung, kein Schalter: Die Git-Hygiene-Pruefung nimmt hier Commits + # aus, die nicht von eigenen Identitaeten committet wurden — wer das erklaert, + # soll sagen, woher die fremden Commits stammen. + fremdhistorie: { kind: str, nullable: true } related: { kind: links } rules: # The canonical slug is the filename — no second naming scheme. diff --git a/scripts/gruppenpruefung.py b/scripts/gruppenpruefung.py index 1dc5a77..6106188 100644 --- a/scripts/gruppenpruefung.py +++ b/scripts/gruppenpruefung.py @@ -21,6 +21,11 @@ zu überspringen, und jede Prüfung bildet einen real passierten Fall ab 5. Git-Hygiene seit 2026-08-07 — Autor- und Committer-Zeit 12:00:00 UTC, kanonische Identität; ausgenommen sind maschinelle Absender (MASCHINEN, per Adresse — ADR-0009). (F-002/F-003) + Komponenten mit dem Feld `fremdhistorie` prüfen nur Commits, die + von eigenen Identitäten COMMITTET wurden: Seit dem Upstream-Merge + (ADR-0022) trägt ThreadNet-Web 70.265 fremde Commits, die unserer + Konvention nie folgen konnten. Die Ausnahme ist erklärungspflichtig + und gilt nur dort, wo sie deklariert ist — nicht global. Demo-Modus für den Altbestand (Muster-B-Nachweis, Feldtest F-002): --hygiene-lokal [--seit JJJJ-MM-TT] @@ -244,11 +249,30 @@ def main() -> int: for slug, meta in sorted(erklaert.items()): if meta.get("phase") == "external": continue + # Repos mit erklärter Fremdhistorie (Feld `fremdhistorie`) tragen Commits, + # die nie unserer Konvention folgen konnten, weil sie nicht bei uns + # entstanden sind. Sie zu bemängeln hiesse, einen Alarm dauerhaft rot zu + # faerben, an dem niemand etwas aendern kann - und ein Dauerrot ist kein + # Alarm mehr (#0104). Der Trennschnitt ist der COMMITTER, nicht der Autor: + # gemessen an ThreadNet-Web nach dem Upstream-Merge trennt er exakt (18 + # eigene Commits committet von uns, 39 fremde von GitHub/RiotRobot, keine + # Ueberschneidung). Der Autor taugt nicht dafuer - unsere eigenen Commits + # koennen fremde Autoren tragen (Cherry-Picks), und fremde Commits tragen + # Autoren, die wie Menschen aussehen. + # + # ⚠️ Preis: In diesen Repos faellt ein Commit durchs Raster, den jemand von + # uns unter einer voellig unbekannten Identitaet erzeugt - der Fall, den die + # Identitaetspruefung sonst faengt. Deshalb gilt die Ausnahme NUR fuer + # Komponenten, die sie ausdruecklich erklaeren, und nicht global. + nur_eigene_committer = bool(meta.get("fremdhistorie")) pfad = urllib.parse.quote(f"{GRUPPE}/{slug}", safe="") for c in api(f"projects/{pfad}/repository/commits" f"?since={GRENZE}T00:00:00Z&all=true", token): if (c.get("author_email") or "").lower() in MASCHINEN: continue + if (nur_eigene_committer + and (c.get("committer_email") or "").lower() not in EIGENE_MAILS): + continue wer = f"{c.get('author_name')} <{c.get('author_email')}>" if not zeit_ok(c["authored_date"]) or not zeit_ok(c["committed_date"]): befunde.append(f"{slug} {c['short_id']}: Echtzeit-Stempel "