9 Commits
Author SHA1 Message Date
Thore Cimbal 6731d2a70f ADR-0023: fremde Historie erklaert von der Git-Hygiene ausnehmen
Der Upstream-Merge holte 70.265 fremde Commits nach ThreadNet-Web; 39 davon
faerbten die Gruppenpruefung als Echtzeit-Stempel rot. Sie verletzen die
Konvention wirklich, konnten ihr aber nie folgen und werden sich nie aendern -
also ein Dauerrot, und ein Dauerrot meldet nichts mehr (#0104).

Neues Feld fremdhistorie in docs/components/*.md. Wo gesetzt, prueft die
Hygiene nur Commits, die von eigenen Identitaeten COMMITTET wurden. Der
Trennschnitt ist gemessen, nicht geraten: 18 eigene Commits, alle von uns
committet; 39 fremde von GitHub/RiotRobot; keine Ueberschneidung. Der Autor
taugt nicht - eigene Commits koennen fremde Autoren tragen (Cherry-Picks).

Der Feldwert ist die Begruendung, kein Schalter - Muster der Quittungen aus
ADR-0020. Die Ausnahme gilt nur, wo sie deklariert ist, nicht global; der Preis
(ein Commit unter voellig unbekannter Identitaet faellt dort durchs Raster)
steht in den Konsequenzen.

Belegt: nach dem Fix 0 offene Befunde bei 20 Quittungen, und in ThreadNet-Web
werden weiterhin 18 Commits geprueft, alle auf 12:00:00.

Ausserdem zurueckgenommen: mein Nachtrag an ADR-0022. Eine angenommene ADR wird
nicht editiert (Regel in der Vorlage) - die Erkenntnis steht jetzt in #0099.
2026-08-19 12:00:00 +00:00
Thore Cimbal 6652125ed3 #0099 geschlossen: Upstream-Anschluss vollzogen, v0.6.0 in Produktion
ThreadNet-Web:main auf 8ca03fe, Merge-Commit 88c4e15 mit beiden echten Eltern.
GHSA-wrcp-5v3v-3j6v ist mit dem Versionssprung erledigt.

Drei Anlaeufe: rc.1 erzeugte kein Image (.npmrc fehlte im Docker-Kontext, unter
pnpm 11 fatal), rc.2 ging live und brach die Raumliste, rc.3 bestand die Abnahme.

ADR-0022 um zwei Korrekturen ergaenzt, die erst die Ausfuehrung gezeigt hat:

Die stille Klasse verschwindet nicht ganz, sie dreht sich um. Der Merge meldet,
wenn Upstream eine Datei verschiebt - das hat gehalten. Er meldet nicht, wenn
beide Seiten die Aufloesung ueberleben und nur eine noch Sinn ergibt. Genau das
brach rc.2.

Und: ein gruener Build war nie eine Abnahme. Der web-Job baut nur, webpack
wirft Typen weg. tsc meldete den Fehler durchgehend, gefragt hatte ihn niemand.
Seit 8ca03fe fuehrt docker_web den Job typecheck als needs.

Daraus die stehende Regel fuer kuenftige Merges: nach der Konfliktaufloesung auf
ueberlebende Reste pruefen, nicht nur auf verlorene Zeilen. Wo Zeichenketten
statt Typen im Spiel sind, braucht es einen Abgleich gegen die Registry - fuer
Einstellungen einmalig gefahren, 135 abgefragte gegen 152 registrierte.
2026-08-19 12:00:00 +00:00
Thore Cimbal bae97e6ca6 docs(adr): ADR-0022 for the upstream reconnection, corrected by the test
Decision sorb: option B, a one-time real merge rather than a shared replace ref. What
decided it was visibility, not effort - a replace ref works only while everyone
remembers to fetch it, and for a repo whose core problem is "git says nothing", a
mechanism that silently differs per clone is the wrong shape.

The test corrected the option's own description. --allow-unrelated-histories on its own
gives a two-way comparison and 1757 conflicts; with the graft set locally it is 32. So
the graft is not the alternative to B, it is how B is performed: set it, let the merge
compute against it, commit, and the merge commit then carries the real parents so the
graft can go.

Also recorded because it cost time and looked like a fundamental problem: tags fetched
with --depth=1 leave a shallow boundary, so v1.12.26 was walled off at a single commit
even though develop carried the same commit in full. Every merge attempt failed with
"refusing to merge unrelated histories" until fetch --unshallow.

The merge itself is measured but deliberately not executed. apps/web/package.json
carries two product decisions rather than conflicts - our Element Call fork against
upstream's, and a matrix-js-sdk git pin against a released version - and resolving the
first one wrongly would silently delete the noise suppression work from #0054. Neither
is safe without a build and the ClamAV functional test.
2026-08-19 12:00:00 +00:00
Thore Cimbal 1874ddfa92 docs(issues): #0099 step 3 - the graft holds and turns twelve patches into four
With the full upstream history the common ancestor could be searched rather than
guessed: measuring tree distance, not dates, over every develop commit in the import
window. deadd548 from 2026-05-08 wins with 43 differing files against 783 for the tag
we wrongly assumed. Thirty-one of those are mode-only, the historical import bug, and
the content remainder is precisely our own Discord feature plus LICENSE and CHANGELOG.

Tested in a throwaway clone rather than asserted: without the graft there is no
merge-base, with it deadd548 becomes one, and merging three months of develop yields
32 conflicting files. Only four are source, and they are exactly our patches - the
rest are GitHub workflows we do not use and the lockfile.

One intermediate result was worthless and nearly passed as success: merging v1.12.26
reported zero conflicts while not running at all, because the tag was fetched shallow
and carries a single commit. Checking MERGE_HEAD is what caught it.

The real gain is not the number. The issue warns that if Element moves a viewmodels
file during the MVVM rework, our lines vanish without a conflict and git says nothing.
With a genuine ancestor, git says something.

Adopting this is ADR-worthy either way - a shared replace ref or a one-time unrelated-
histories merge - so the decision stays with sorb.
2026-08-19 12:00:00 +00:00
Thore Cimbal 8c07c365f6 docs(issues): #0099 step 2 - the remote is in place and it contradicts the premise
upstream is configured and both tags are fetched, so updates can finally be looked at
as a diff. The first diff disproved what this issue and the fork doc have both said
since August: the import is not the v1.12.17 tag. 783 files differ, 115 exist only on
our side, and two of them date the tree - TextualBodyViewModel.tsx and
RovingTabIndex.tsx are absent from the tag, present in v1.12.26 and present in our
import. The changelog stops at 1.12.17 only because it is written at release time.

So the base is a develop state after the 1.12.17 release. Fittingly it is the MVVM
files that prove it - the area this issue already warned about.

Step 3 changes accordingly: grafting onto v1.12.17 would put every future merge on an
invented ancestry, and worse than raising false conflicts, it could hide real ones.
Finding the actual ancestor means searching develop history, which needs the full
upstream repository rather than a shallow tag fetch.

The advisory assessment is unchanged - the base sits below 1.12.22 either way.
2026-08-19 12:00:00 +00:00
Thore Cimbal d82b8d517a docs(issues): #0099 - disable_custom_urls set in both clients, with its limits stated
Decision sorb, and it needed two files rather than one: the desktop client loads its
own config.json, so changing only element-values.yaml would have hardened the web
client and left the distributed builds alone - the themes-rollout trap again.

Read out of our own code rather than assumed: the edit button beside the server name
disappears, and the 401/403 login error names the server. That is a surface
restriction. MatrixChat still accepts hs_url from the query string in two registration
flows without consulting the setting, so a crafted link is untouched.

Recorded as a narrowing, not a mitigation. GHSA-wrcp-5v3v-3j6v still applies to
1.12.17 and the upstream update in steps 2-4 remains the actual fix.
2026-08-19 12:00:00 +00:00
Thore Cimbal 22775e499c docs(issues): close #0031 and #0104 - green is the normal state again
Pipeline 540 has both management checks passing, and canonize_rotation has been green
since yesterday. That is the condition AGENTS.md's alarm rule silently assumed, and it
holds again.

#0031 is done because the Authentik blueprint check now runs rather than skipping:
sorb supplied the variables, the token carries exactly one permission on its own
service account, and the run says "Geprueft: 11 Projekte" with no skip line. The blind
spot it named - a blueprint discarded on every pass while Flux reported green - would
now surface.

#0104 closes on all four criteria. Twice the route was the cause rather than an
acknowledgement: gitops had no workflow block and created pipelines with no jobs,
which is red without a fault, and management had the same gap for API triggers and was
closed pre-emptively. Exactly one thing is acknowledged, because it cannot be unmade -
pipeline 518 exists in history and sits inside the check's eight-day window, so the
entry expires with the window on 2026-08-28.

From 25 open findings this morning to none, with nothing hidden: 26 entries carry a
reason and a date in the log.
2026-08-19 12:00:00 +00:00
Thore Cimbal cc3c43052b ci: close the same empty-pipeline gap here before it opens
gitops produced a red pipeline with no jobs today because nothing guarded pipeline
creation. This repo has the same shape: its three jobs cover schedule, web and push,
so an API-triggered pipeline matches none of them and would be created empty and
marked failed.

Nobody triggers this repo by API today, which is why it has not happened yet - not a
reason to leave it. One block, and the class is gone in both places.
2026-08-19 12:00:00 +00:00
Thore Cimbal bb4bbd711b chore(pruefungen): acknowledge the one empty pipeline the fix cannot unmake
The workflow rules stop new empty pipelines; they do not remove pipeline 518, which
already exists and stays inside the check's eight-day window. Acknowledged until
2026-08-28 so the entry expires with the window rather than outliving it - if it is
still red afterwards, the fix was incomplete and the check says so again.

This is the case the mechanism was built for: known, dated, self-clearing, with the
root cause fixed rather than papered over.
2026-08-19 12:00:00 +00:00
11 changed files with 578 additions and 10 deletions
+12
View File
@@ -5,6 +5,18 @@
# die Retro vom 2026-08-09: sechs solcher Faelle in neun Tagen, keiner davon durch
# eine Ueberwachung gefunden.
# Ohne workflow-Block legt GitLab auch dann eine Pipeline an, wenn KEIN Job auf sie
# passt, und fuehrt sie als "failed" - rot ohne Fehler, genau das, wogegen #0104
# angeht. Die drei Jobs unten decken schedule, web und push ab; ein API-Trigger
# traefe keinen davon. Im gitops-Repo ist dieser Fall am 2026-08-19 real eingetreten
# (Pipeline 518), hier wird er vorbeugend ausgeschlossen.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "push"
- when: never
stages:
- pruefen
+5 -6
View File
@@ -2,9 +2,9 @@
<!-- Generated by scripts/gen_status.py — do not edit. -->
## Issues (61 open, 38 closed)
## Issues (58 open, 41 closed)
Verteilung: M1 14 · M2 17 · M3 4 · M4 11 · M5 15
Verteilung: M1 11 · M2 17 · M3 4 · M4 11 · M5 15
| Issue | Status | Meilenstein | Priorität | Title |
|---|---|---|---|---|
@@ -19,7 +19,6 @@ Verteilung: M1 14 · M2 17 · M3 4 · M4 11 · M5 15
| [0027](docs/issues/0027-audit-01-acht-widersprueche-aus-dem-labnet-02.md) | open | M2 | medium | AUDIT-01: Acht Widersprüche aus dem LABNET-02-Nachlauf (Selbst-Audit CFGMON-Session) |
| [0029](docs/issues/0029-ui-harmonisieren-gleiche-farben-und-formen.md) | open | M4 | medium | UI harmonisieren: gleiche Farben und Formen über alle Oberflächen |
| [0030](docs/issues/0030-der-restore-ist-nie-geprobt-sicherungen-sind.md) | in-progress | M1 | medium | Der Restore ist nie geprobt — Sicherungen sind bisher eine Vermutung |
| [0031](docs/issues/0031-stillstandspruefung-gitea-token-und-authentik.md) | open | M1 | low | Stillstandsprüfung: GITEA_TOKEN und Authentik-Teil nachziehen |
| [0032](docs/issues/0032-gameserver-hat-keinen-push-mirror-und-auf-gitea.md) | open | M2 | medium | gameserver hat keinen Push-Mirror — und auf Gitea liegt ein anderer Stand |
| [0033](docs/issues/0033-overmind-01-element-desktop-build-lab-registry.md) | open | M2 | low | OVERMIND-01 — element-desktop-build von rohana in die Lab-Registry umziehen |
| [0034](docs/issues/0034-cfgmon-11-gitea-ci-rueckbau-abschliessen.md) | open | M2 | medium | CFGMON-11 — Gitea-CI-Rückbau abschließen (sicher rückbaubare Schritte) |
@@ -62,19 +61,17 @@ Verteilung: M1 14 · M2 17 · M3 4 · M4 11 · M5 15
| [0095](docs/issues/0095-threadnet-web-6-windows-desktop-code-signing-installer-brandi.md) | open | M4 | low | Windows-Desktop: Code-Signing (+ Installer-Branding) |
| [0096](docs/issues/0096-threadnet-web-7-rebranding-element-axion1337-web-desktop-gesa.md) | waiting | M4 | medium | Rebranding: Element → aXion1337 (Web + Desktop, Gesamtklammer) |
| [0097](docs/issues/0097-threadnet-web-9-feedback-bugreport-weg-eigener-rageshake-oder.md) | open | M4 | low | Feedback-/Bugreport-Weg: eigener Rageshake oder Alternative (Zammad nachhalten) |
| [0099](docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md) | open | M1 | medium | Upstream-Sicherheitsfixes lassen sich nicht mergen — kein gemeinsamer Vorfahre |
| [0100](docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md) | open | M4 | low | Asset-Pfade tragen weiterhin "element" (themes/element/…) |
| [0101](docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md) | open | M4 | low | Kaputtes Paket 0.19.2-threadnet.6 in der Registry — Herkunft ungeklärt |
| [0102](docs/issues/0102-dmarc-und-mail-haertung-der-zone-axion1337-chat.md) | open | M1 | medium | DMARC der Plattform-Zone `axion1337.chat` steht auf p=none — und gehört IONOS, nicht uns |
| [0103](docs/issues/0103-wiki-zugang-ohne-gruppe-endet-stumm.md) | open | M1 | medium | Wiki: Anmeldung ohne Gruppe endet stumm — `wiki-anwender` hat null Mitglieder |
| [0104](docs/issues/0104-daueralarme-melden-nichts-mehr.md) | open | M1 | high | Alle geplanten Prüfungen sind dauerhaft rot — damit meldet keine mehr etwas |
| [0105](docs/issues/0105-projekt-wiki-vor-projektabschluss-klaeren.md) | waiting | M2 | low | Projekt `wiki`: Verbleib klären — erst unmittelbar vor Projektabschluss |
## Active design docs (0)
_none active_
## ADRs (21)
## ADRs (23)
| ADR | Status | Title |
|---|---|---|
@@ -99,6 +96,8 @@ _none active_
| [0019](docs/adr/0019-komponenten-issues-adoptiert.md) | accepted | ADR-0019: Komponenten-Issues in docs/issues/ adoptiert — eine Nummernwelt für die Gruppe |
| [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)
@@ -0,0 +1,75 @@
---
type: adr
id: "0022"
status: accepted
date: 2026-08-19
supersedes: null
superseded_by: null
related:
- "docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md"
---
# ADR-0022: Anschluss an Upstream durch einen einmaligen Merge, nicht durch einen geteilten Graft
## Kontext
`ThreadNet-Web` enthält keine Upstream-Historie: Am 2026-05-10 kam ein kompletter
Element-Web-Baum in einem Commit herein. Ohne gemeinsamen Vorfahren ist
`git merge upstream/develop` unmöglich, und jedes Update bedeutet, zwölf eigene Patches
von Hand auf einen neuen Baum aufzutragen. Das ist nicht nur mühsam, sondern gefährlich:
Verschiebt Element eine Datei, verschwinden unsere Zeilen **ohne Konflikt** (#0099).
Am 2026-08-19 wurde der tatsächliche Ursprung gemessen statt geraten: **`deadd548`
vom 2026-05-08** (nicht der Tag `v1.12.17`, wie zuvor angenommen). Der Beleg ist die
Baumdistanz — 43 abweichende Dateien, davon 31 reine Modus-Änderungen und der Rest
unser eigenes Feature.
Im Wegwerf-Klon getestet: Mit gesetztem Vorfahren läuft ein Merge von drei Monaten
`develop` durch und erzeugt **32 konfliktbehaftete Dateien, davon nur vier Quellcode**
genau unsere Patches.
## Optionen
**A: Geteilter Replace-Ref.** `git replace --graft` und `refs/replace/*` mitliefern.
Die Historie bleibt formal unverändert, Git *interpretiert* sie nur anders. Nachteil:
Jeder Klon braucht einen zusätzlichen Fetch, und wer ihn vergisst, sieht eine andere
Historie als alle anderen — ein stiller Unterschied, der sich erst im Konfliktfall
zeigt.
**B: Einmaliger echter Merge**, danach normale Merges.
⚠️ **Praezisierung nach dem Test:** `--allow-unrelated-histories` allein liefert
einen ZWEI-Wege-Vergleich und damit 1757 Konflikte — gemessen. Der Graft ist kein
Gegenentwurf zu B, sondern sein Werkzeug: lokal setzen, den Merge damit rechnen
lassen (32 Konflikte), committen. Der Merge-Commit traegt danach die echten Eltern,
der Graft kann weg, und die Abstammung laeuft ueber den Merge-Commit selbst.
Die Nahtstelle wird ein sichtbarer Merge-Commit. Kein Sonderwissen, kein Zusatzschritt,
kein Klon kann sie versehentlich übersehen.
**C: So weiterarbeiten wie bisher** — Patches von Hand auftragen. Verworfen: Das ist der
Zustand, der die stille Klasse überhaupt erst erzeugt.
## Entscheidung
**Option B** (sorb, 2026-08-19).
Ausschlaggebend ist nicht der Aufwand — beide Wege sind ähnlich billig — sondern die
Sichtbarkeit. A funktioniert nur, solange alle daran denken; B trägt sich selbst. Für
ein Repo, dessen Kernproblem „Git meldet nichts" ist, wäre ein Mechanismus, der
stillschweigend unterschiedlich wirkt, die falsche Wahl.
`deadd548` bleibt trotzdem wichtig: Es ist der Stand, gegen den der Merge gefahren wird,
und ohne diese Messung wäre der Merge auf eine erfundene Grundlage gelaufen.
## Konsequenzen
- Der erste Merge ist ein einmaliger Kraftakt mit vier Quellcode-Konflikten; danach ist
ein Upstream-Update ein gewöhnlicher Merge.
- **Die stille Klasse verschwindet**: Verschiebt Upstream eine Datei, die wir angefasst
haben, meldet Git künftig einen Konflikt, statt unsere Zeilen wortlos fallen zu lassen.
- Die Nahtstelle bleibt als Merge-Commit dauerhaft sichtbar — gewollt, nicht geduldet.
- **Abnahme ist kein Build, sondern ein Funktionstest**: Die ClamAV-Patches liegen in der
Medien-Pipeline. Ohne den Test aus #0099 (verschlüsselte Datei senden, abgelehnte
empfangen) ist der Merge nicht abgenommen.
- Schritt 4 aus #0099 — ein Verfahren zum Auftragen der Patches — wird damit
gegenstandslos.
@@ -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 <noreply@github.com>` (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.
+2
View File
@@ -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
@@ -1,7 +1,7 @@
---
type: issue
id: "0031"
status: open
status: done
created: 2026-08-09
milestone: M1
priority: low
@@ -51,3 +51,20 @@ Mehr ist nicht zu tun — der Code steht, er wartet nur auf die Zugänge.
-`GITLAB_TOKEN` hinterlegt, in der CI verifiziert
- ✅ Zeitplan `Stillstandsprüfung (täglich)` angelegt, 6:17 Europe/Berlin
- ✅ Erster Lauf über den Zeitplan durchgeführt: fand in der CI **dieselben 7 Befunde** wie lokal — kein Unterschied zwischen den Umgebungen
## Erledigt 2026-08-19 — Authentik-Teil läuft
sorb hat `AUTHENTIK_URL` und `AUTHENTIK_TOKEN` als maskierte, geschützte CI-Variablen
im management-Projekt hinterlegt (dazu `GITEA_TOKEN`, der die privaten Spiegel
gegenlesbar macht). Der Token trägt genau eine Berechtigung —
`authentik_blueprints.view_blueprintinstance` —, vergeben an ein eigenes Dienstkonto;
kein Admin.
**Belegt am Lauf, nicht an der Konfiguration** (Pipeline 540): Der Vermerk
„Uebersprungen: Authentik-Blueprints … fehlen" ist verschwunden, stattdessen meldet die
Prüfung `Geprueft: 11 Projekte der Gruppe axion1337.chat` und **Keine offenen Befunde**.
Damit ist genau der blinde Fleck geschlossen, den dieses Issue als den ärgerlichsten
benannt hat: Der `matrix-recovery-flow`-Blueprint wurde tagelang bei jedem Durchlauf
verworfen, während Flux grün meldete — gefunden nur, weil jemand aus anderem Anlass in
die Datenbank sah. Dieser Fall würde jetzt auffallen.
@@ -1,7 +1,7 @@
---
type: issue
id: "0099"
status: open
status: done
created: 2026-08-06
milestone: M1
priority: medium
@@ -81,3 +81,326 @@ ohnehin eine eigene Entscheidung — bei geschlossener Föderation liegt „nein
Schritte 24 (Upstream als Remote, Graft-Versuch, Patch-Auftragsverfahren) bleiben
offen; sie sind der eigentliche Umfang dieses Issues.
## Teilmaßnahme 2026-08-19 — `disable_custom_urls` an beiden Stellen
Entscheidung sorb. Gesetzt in **zwei** Dateien, nicht in einer:
| Ort | Datei | Commit | wirksam |
|---|---|---|---|
| Web-Client | `gitops:apps/production/custom-configs/element-values.yaml` | `d809b3f` | mit dem Flux-Abgleich (Element liest `config.json` beim Laden) |
| Desktop-Client | `ThreadNet-Web:apps/desktop/axion1337/config.json` | `e1e9a19` | **erst mit dem nächsten Desktop-Build** |
Die zweite Stelle wäre fast durchgerutscht: Der Desktop-Client lädt seine **eigene**
`config.json`, nicht die des Web-Deployments — derselbe Fallstrick wie beim
Themes-Rollout. Eine Änderung nur in `element-values.yaml` hätte den Web-Client
abgesichert und genau die Builds unberührt gelassen, die verteilt werden.
### Was sie bewirkt — und was nicht
Im Code unserer Fassung nachgelesen, nicht angenommen:
- `ServerPicker.tsx`: Der **„Bearbeiten"-Knopf am Servernamen wird nicht gerendert**.
Über die Oberfläche ist der Homeserver damit nicht mehr wechselbar.
- `ErrorUtils.tsx`: Bei 401/403 benennt die Fehlermeldung den Server, statt generisch
zu bleiben — kleiner Nebengewinn für den Alltag.
⚠️ **Es ist eine Oberflächen-Sperre, keine technische.** `MatrixChat.tsx` übernimmt
`hs_url` weiterhin aus der URL — in zwei Registrierungs-Flüssen (mobile Registrierung,
Bestätigungslink) und **ohne** `disable_custom_urls` zu prüfen. Ein präparierter Link
bleibt davon unberührt.
**Für `GHSA-wrcp-5v3v-3j6v` heißt das:** Der bequeme, sichtbare Weg zu einem fremden
Homeserver ist weg, alle Wege sind es nicht. Die Maßnahme senkt die Wahrscheinlichkeit,
dass jemand versehentlich oder auf Zuruf woanders landet — sie ist **kein Ersatz** für
das Upstream-Update. Das bleibt Schritt 24 dieses Issues.
## Schritt 2 erledigt 2026-08-19 — und er widerlegt eine Annahme des Issues
`upstream` (`element-hq/element-web`) ist als zweiter Remote eingerichtet, `v1.12.17`
und `v1.12.26` sind flach geholt. Der Remote ist **lokale Konfiguration** und wird
nicht mitcommittet; die Einrichtung steht jetzt in
`ThreadNet-Web:docs/axion1337-fork.md` (Commit `fa5dcc5`).
### Der Import ist NICHT der Tag `v1.12.17`
Das Issue und die Fork-Doku behaupteten beide, „Element Web 1.12.17 kam am 2026-05-10
als kompletter Baum herein". Die erste Messung mit dem neuen Remote widerspricht dem:
| Messung | Ergebnis |
|---|---|
| `git diff --stat v1.12.17 3da3635` | **783 Dateien, +17443 / 10371** |
| nur bei uns vorhanden | **115 Dateien** |
| nur im Tag vorhanden | 62 Dateien |
Entscheidend sind zwei davon, weil sie datieren:
`apps/web/src/viewmodels/room/timeline/event-tile/body/TextualBodyViewModel.tsx` und
`packages/shared-components/src/core/roving/RovingTabIndex.tsx` — im Tag `v1.12.17`
**nicht vorhanden**, in `v1.12.26` **und in unserem Import vorhanden**. Der
`CHANGELOG.md` unseres Imports endet bei 1.12.17 (2026-04-30), weil er erst beim
Release fortgeschrieben wird.
**Die Grundlage ist also ein `develop`-Stand nach dem 1.12.17-Release** (1.12.18 kam am
2026-05-12), nicht der Tag. Ausgerechnet MVVM-Dateien belegen es — der Bereich, vor dem
dieses Issue ohnehin warnt.
### Folge für Schritt 3
**Ein Graft auf `v1.12.17` wäre falsch.** Er würde jede künftige Zusammenführung auf
eine erfundene Ahnenreihe stellen und Konflikte an Stellen erzeugen, wo keine sind —
oder schlimmer: keine erzeugen, wo welche gehören. Wer den gemeinsamen Vorfahren
nachträglich herstellen will, muss den passenden **`develop`-Commit** finden. Das
braucht die **volle** Upstream-Historie; ein flacher Tag-Fetch reicht dafür nicht.
Schritt 3 bleibt damit offen, aber er hat jetzt eine tragfähige Fragestellung statt
einer falschen Zielmarke.
### Unverändert: die Advisory-Bewertung
Der Basisstand liegt zwischen 1.12.17 und 1.12.18 und damit klar unter 1.12.22 —
`GHSA-wrcp-5v3v-3j6v` trifft uns weiterhin. Die Korrektur ändert die Dringlichkeit
nicht, nur den Weg dorthin.
## Schritt 3 beantwortet 2026-08-19 — der Graft trägt, und er halbiert das Problem
Volle Upstream-Historie geholt (70.330 Commits, `.git` wächst von 87 MB auf 603 MB).
Damit ließ sich der gesuchte gemeinsame Vorfahre **suchen statt raten**.
### Die Basis ist `deadd548` vom 2026-05-08
Verfahren: für jeden `develop`-Commit im Fenster 25.04.16.05. die Zahl der gegen
unseren Import abweichenden Dateien messen — der Basis-Commit ist das Minimum. Gemessen
wurde **der Baum, nicht das Datum**.
Ergebnis: `deadd548` („Update storybook", #33437) mit **43 abweichenden Dateien**
gegenüber **783** beim fälschlich angenommenen Tag `v1.12.17`. Und diese 43 zerfallen
sauber:
| Art | Anzahl | Was es ist |
|---|---|---|
| nur Modus (755 → 644) | **31** | der Import-Bug, den die Fork-Doku als historisch beschreibt |
| echte Inhaltsänderung | 12 | davon 5 + 1 Test = **unser Discord-Feature**, dazu `LICENSE` und `CHANGELOG.md` |
| Hinzufügungen | 2 | unsere Feature-Dateien |
Der inhaltliche Rest ist also **genau das, was wir damals selbst geändert haben**. Damit
ist `deadd548` der Stand, aus dem der Fork genommen wurde.
### Der Graft wurde getestet, nicht behauptet
In einem **Wegwerf-Klon** (Produktions-Repo unberührt, danach entfernt):
| | |
|---|---|
| vor dem Graft | `git merge-base main upstream/develop`**leer** |
| nach `git replace --graft 3da3635 deadd548` | gemeinsamer Vorfahre **`deadd548`** |
| `git merge upstream/develop` | läuft durch, **32 konfliktbehaftete Dateien** |
⚠️ Ein Zwischenergebnis war wertlos und wäre fast als Erfolg durchgegangen: Der erste
Merge-Versuch gegen `v1.12.26` meldete „0 Konflikte" — er war aber **gar nicht
gelaufen** („refusing to merge unrelated histories"), weil der Tag flach geholt war und
nur einen einzigen Commit trägt. Erst die Gegenprobe auf `MERGE_HEAD` deckte das auf.
### Was die 32 Konflikte sind
**Nur vier sind Quellcode** — und es sind genau unsere Patches:
`MImageBody.tsx`, `MAudioBody.tsx` (ClamAV), `SdkConfig.ts` (Branding),
`RoomListItemViewModel.ts` (Discord-Feature). Der Rest sind
`.github/workflows/*` (die Fork-Doku führt sie als „gering — eigene Strecke") und
`pnpm-lock.yaml`, das ohnehin regeneriert wird.
### Was das ändert
Aus „neuen Upstream-Baum beschaffen und **zwölf Patches von Hand neu auftragen**" wird
„**vier Quellcode-Konflikte in einem normalen Drei-Wege-Merge** lösen".
Wichtiger noch ist die stille Gefahr, die verschwindet. Das Issue warnt: *„Verschiebt
Element beim MVVM-Umbau eine der `viewmodels/`-Dateien, entsteht kein Konflikt — unsere
Zeilen sind schlicht weg, und Git meldet nichts."* Mit echtem gemeinsamem Vorfahren
**meldet Git es**. Das ist der eigentliche Gewinn, nicht die Zahl.
### Entscheidung, die noch aussteht
Der Graft ist eine **lokale** Ersetzung (`refs/replace/*`). Damit alle davon haben,
müsste er mitgeliefert werden — `git push origin 'refs/replace/*'` und ein Hinweis in
der Doku, dass Klone `git fetch origin 'refs/replace/*:refs/replace/*'` brauchen.
Alternative: kein Graft, sondern beim nächsten Update einmalig einen echten
Merge-Commit mit `--allow-unrelated-histories` bauen und ab dann normal weitermergen.
Beides ändert die Historie-Wahrnehmung des Repos dauerhaft und ist damit
**ADR-pflichtig**. Entscheidung sorb steht aus; Schritt 4 (Auftragsverfahren für die
Patches) wird bei Weg 1 oder 2 weitgehend gegenstandslos.
## Weg B belegt 2026-08-19 — mit einer wichtigen Präzisierung
Entscheidung sorb: **Weg B** ([ADR-0022](../adr/0022-upstream-anschluss-durch-einmaligen-merge.md)).
### `--allow-unrelated-histories` allein genügt NICHT
Gemessen gegen `v1.12.26`, im selben Klon, nacheinander:
| Vorgehen | Konflikte |
|---|---|
| nur `--allow-unrelated-histories`, ohne Vorfahren | **1757** |
| mit lokal gesetztem Graft auf `deadd548` | **32** |
Ohne gemeinsamen Vorfahren macht Git einen Zwei-Wege-Vergleich — das ist die „praktisch
jede Datei konfliktet"-Lage aus der Fork-Doku. **Der Graft ist also kein Gegenentwurf zu
Weg B, sondern sein Werkzeug:** lokal setzen, den Merge damit rechnen lassen, committen —
der Merge-Commit trägt danach die echten Eltern, und der Graft kann weg. Ab dann läuft
die Abstammung über den Merge-Commit selbst. Das steht so nicht in ADR-0022s
Optionsbeschreibung und ist hier nachgetragen.
⚠️ **Stolperstein auf dem Weg dahin:** Die mit `--depth=1` geholten Tags tragen eine
`.git/shallow`-Grenze. `v1.12.26` war dadurch auf **einen** Commit abgemauert, obwohl
derselbe Commit über `develop` vollständig vorlag — jeder Merge-Versuch scheiterte mit
„refusing to merge unrelated histories", was wie ein Grundproblem aussah und keines war.
`git fetch --unshallow upstream` löst es.
### Die 32 Konflikte, vollständig aufgeschlüsselt
| Menge | Was | Auflösung |
|---|---|---|
| 24 | `.github/workflows/*` | unsere Fassung behalten — eigene CI-Strecke |
| 1 | `pnpm-lock.yaml` | regenerieren |
| 1 | `apps/web/package.json` | **Produktentscheidung, siehe unten** |
| 6 | Quellcode, je 12 Konfliktblöcke | von Hand |
**Der Fund, der die ganze Übung rechtfertigt:** Upstream hat
`RoomListItemAccessibilityWrapper` in `RoomListItemWrapper` **umbenannt**. Weil es jetzt
einen echten Vorfahren gibt, **meldet Git den Konflikt** — genau der Fall, den dieses
Issue als stille Gefahr beschreibt („unsere Zeilen sind schlicht weg, und Git meldet
nichts").
### Warum ich hier gestoppt habe
`apps/web/package.json` enthält zwei Zeilen, die keine Konfliktauflösung sind, sondern
Entscheidungen:
```
ours: "@sorb/threadnet-call-embedded": "0.19.2-threadnet.12"
upstream: "@element-hq/element-call-embedded": "0.22.0"
ours: "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#d19cb751..."
upstream: "matrix-js-sdk": "42.2.0"
```
Die erste falsch aufgelöst, und die **gesamte KI-Geräuschunterdrückung (#0054) ist
stillschweigend weg**. Die zweite betrifft den Git-Ref-Pin, der seinerzeit ein Build-Fix
war (Abschnitt 3 der Fork-Doku) — ob Upstreams 42.2.0 ihn erübrigt, zeigt nur ein Build.
Beides ist ohne Build und ohne den ClamAV-Funktionstest nicht absicherbar. Der Merge ist
damit **vorbereitet und vermessen, aber nicht ausgeführt**; das Experiment wurde
abgeräumt (kein Zweig, kein Replace-Ref, Arbeitsverzeichnis sauber). Die Upstream-Historie
bleibt im Klon liegen, damit der nächste Anlauf nicht wieder 600 MB holen muss.
**Nächster Schritt:** den Merge als eigenes Vorhaben fahren, mit Build und
ClamAV-Abnahme als Voraussetzung — nicht als Nebenschritt.
## Ausgeführt und abgenommen 2026-08-19 — `v0.6.0` läuft in Produktion
Der Merge ist vollzogen. `ThreadNet-Web:main` steht auf `8ca03fe`; der Merge-Commit
`88c4e15` trägt beide echten Eltern (`fa5dcc5` = unser bisheriger `main`,
`c43ef70b` = `v1.12.26`). Damit ist die Abstammung hergestellt, der Graft ist weg,
und `GHSA-wrcp-5v3v-3j6v` ist mit dem Versionssprung erledigt.
### Die beiden Produktentscheidungen aus dem Abschnitt davor
| Zeile | Auflösung | Beleg |
|---|---|---|
| `@sorb/threadnet-call-embedded` | **unsere** behalten, `0.19.2-threadnet.12` | auf `main` und im Zweig identisch — die KI-Geräuschunterdrückung (#0054) ist unberührt |
| `matrix-js-sdk` | **Upstreams** `42.2.0` genommen, Git-Ref-Pin fällt weg | Build läuft; der seinerzeitige Build-Fix hat sich erübrigt |
### Drei Anläufe, zwei davon gescheitert
| | |
|---|---|
| `v0.6.0-rc.1` | **kein Image.** `docker_web` scheiterte: `.npmrc` stand nie in der `COPY`-Zeile des Dockerfiles. Unter pnpm 10 folgenlos, weil `--frozen-lockfile` die gepinnte Tarball-URL nahm; pnpm 11 prüft mit `minimumReleaseAgeStrict` das Alter jedes Eintrags, löst den Scope wieder auf und landet ohne `.npmrc` bei npmjs → 404. Genau der Ablauf, den die `.npmrc` selbst vorhersagt (#0055). |
| `v0.6.0-rc.2` | **ging live und brach die Raumliste.** Nach wenigen Minuten auf `v0.5.4` zurückgenommen. Siehe unten. |
| `v0.6.0-rc.3` | Abnahme bestanden, als `v0.6.0` freigegeben. |
### Der rc.2-Vorfall — eine stille Leiche der anderen Sorte
`RoomListItemViewModel.ts` rief `SettingsStore.getValue("feature_room_list_sections")`
auf einen Labs-Schalter, den Upstream **entfernt** hat; Sektionen laufen dort über
`RoomList.showSections`. Die Auflösung hatte überall Upstreams Seite genommen — Menü,
View, Snapshot, Typen — und nur diese eine `const`-Zeile aus unserer Seite stehen
lassen. Sie wurde tree-weit von niemandem gelesen und warf trotzdem: bei **jedem**
Raumlisteneintrag, als `react-soft-crash`.
Bemerkenswert ist die Richtung: Dieses Issue warnt vor Zeilen, die *verschwinden*.
Hier ist eine Zeile **übrig geblieben**, die verschwinden musste. Der Merge meldet
Konflikte, wo Dateien wandern — er merkt aber nicht, wenn beide Seiten überleben und
nur eine davon noch Sinn ergibt.
Abgesichert statt gehofft: alle **135** im Quellbaum abgefragten Einstellungen gegen
die **152** in `Settings.tsx` registrierten verglichen — genau diese eine Leiche,
keine weitere. Ein zweiter Rest derselben Art (ungenutzter Import
`ElementDesktopLogoSvg` in `SdkConfig.ts`) war harmlos; geprüft wurde dabei
ausdrücklich, ob unser Rebrand gelitten hat — hat er nicht, `desktopBuilds` trägt
weiter eigenes Logo und eigenen Release-Pfad.
### Warum kein Build das fangen konnte — und was daraus folgt
Der CI-Job `web` führt ausschließlich `pnpm --dir apps/web build` aus. webpack
entfernt Typen, ohne sie zu prüfen; ein unbekannter Einstellungsschlüssel ist zur
Bauzeit bloß ein String. `tsc` dagegen meldete den Fehler die ganze Zeit — **zweimal**
(`TS2345` unbekannter Schlüssel, `TS6133` ungenutzte Konstante). Gefragt hatte ihn
niemand.
Konsequenz, umgesetzt in `8ca03fe`: neuer Job `typecheck`, den `docker_web` als
`needs` führt. **Kein Image mehr ohne bestandene Typprüfung.** Maßstab ist „kein
Fehler außerhalb von `node_modules`", weil Upstream v1.12.26 selbst nicht typrein ist
`matrix-js-sdk@42.2.0` wirft drei Fehler in der eigenen Quelle, in einem sauberen
v1.12.26-Checkout gegengeprüft.
⚠️ Das Tor wäre beim Bau selbst fast wertlos geworden: Das erste `grep "error TS"`
hätte nie gegriffen, weil nx auch in der Pipe färbt und zwischen `error` und `TS` eine
Escape-Sequenz steht. Es ist jetzt in **beide** Richtungen belegt — mit wieder
eingesetzter Zeile scheitert es und benennt beide Fehler, ohne sie besteht es — und
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
laufenden System, nicht am Build:
| Prüfpunkt | Ergebnis |
|---|---|
| Raumliste lädt | ✅ mit konfigurierten Sektionen, also im kritischen Pfad |
| ClamAV Sendepfad | ✅ blockiert vor dem Upload — **ein** Scan-Aufruf, kein zweiter |
| ClamAV Empfangspfad (Datei) | ✅ EICAR erkannt, Abweisung wird angezeigt |
| ClamAV Bildpfad (`.png`) | ✅ zugestellt, beim Herunterladen abgewiesen, **Meldung gerendert** |
| Call-Teilnehmerliste | ✅ |
Der `.png`-Fall ist der wichtigste: Er ist der einzige, der den portierten Code
`ImageBodyViewModel.computeErrorLabel()` tatsächlich durchläuft. Wäre die Datei schon
beim Senden geblockt worden, hätte der Test den Sendepfad ein zweites Mal geprüft und
den Bildpfad gar nicht — beides sieht im Scanner-Log gleich aus, weil die Meldung
`flagged an upload/download` nicht unterscheidet.
### Stand
`v0.6.0` ist in Produktion (`gitops:d87c432`), `/version` liefert `0.6.0`.
Rückhebel bleibt der Tag-Revert auf `v0.5.4`.
**Alle vier Schritte dieses Issues sind beantwortet**; Schritt 4 ist wie in ADR-0022
vorhergesagt gegenstandslos geworden. Das nächste Upstream-Update ist ein gewöhnlicher
Merge.
@@ -1,7 +1,7 @@
---
type: issue
id: "0104"
status: open
status: done
created: 2026-08-18
milestone: M1
priority: high
@@ -125,7 +125,7 @@ Spalte `pruefung`.
| Kriterium | Stand |
|---|---|
| Alle drei Prüfungen laufen grün durch | ⏳ canonize ✅; die beiden management-Prüfungen erst nach dem Nachzug unten |
| Alle drei Prüfungen laufen grün durch | ✅ Pipeline 540 |
| Ein *neu* eingeführter Befund färbt nachweislich rot | ✅ am Beispiel gezeigt, nicht abgeleitet |
| Quittiertes bleibt sichtbar, mit Grund und Datum | ✅ |
| Bedingung in AGENTS.md ergänzen | ✅ mit sorbs Zustimmung 2026-08-19; im Projektabschnitt, die neckbeard-Baseline bleibt byte-treu |
@@ -153,3 +153,32 @@ startet, weil der Spiegel ein paar Minuten nachhinkt. Verlockend zu quittieren
und genau falsch: Dieselbe Meldung ist der einzige Hinweis, wenn ein Spiegel
*wirklich* stehenbleibt (MIRROR-01, #0028). Sie bleibt scharf; ein Lauf unmittelbar
nach einem Push ist eben kurz rot.
## Erledigt 2026-08-19 — alle drei Prüfungen grün
| Prüfung | Stand |
|---|---|
| `canonize_rotation` (gitops) | ✅ grün seit dem 2026-08-18 |
| `gruppenpruefung` (management) | ✅ 0 offene Befunde, 20 quittiert |
| `stillstandspruefung` (management) | ✅ „Keine offenen Befunde", 6 quittiert |
Pipeline 540, beide Jobs `success`. **Grün ist wieder der Normalzustand** — womit die
Regel aus AGENTS.md („die rote Pipeline ist der Alarm") wieder trägt.
**Der Weg dahin ging zweimal über die Ursache statt über eine Quittung**, und das ist
der eigentliche Ertrag:
- `gitops` hatte **keinen `workflow`-Block** und legte deshalb Pipelines auch dann an,
wenn kein Job auf sie passte — rot ohne Fehler (Pipeline 518). Behoben in `1e65f5b`;
`management` hatte dieselbe Lücke für API-Trigger und wurde in `cc3c430` vorbeugend
mitgeschlossen.
- Nur **eine** Sache ist quittiert, weil sie sich nicht beheben lässt: Pipeline 518
existiert in der Historie, und die Prüfung schaut acht Tage zurück. Frist
**2026-08-28**, läuft also mit dem Prüffenster aus. Färbt es danach weiter rot, war
der Fix unvollständig — und die Prüfung sagt es von selbst.
Von 25 offenen Befunden am Morgen auf **null**, ohne dass ein einziger davon
verschwiegen wurde: 26 stehen als Quittung mit Grund und Frist im Log.
**Alle vier Abnahmekriterien erfüllt** (siehe Tabelle oben, plus ADR-0020 und der
AGENTS.md-Zusatz).
+5
View File
@@ -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.
+1
View File
@@ -46,3 +46,4 @@ gruppe Projekt threadnet-wiki-deletion_scheduled-43 2026-09-30 GitLab hat das Pr
gruppe threadnet-wiki: keine CLAUDE.md-Pointer-Datei 2026-10-31 Bekannt, Rollout-Issue vorhanden (Pointer-Serie #0035-#0039). Bis zur Frist nachziehen.
gruppe Projekt wiki existiert in der Gruppe 2026-12-31 Geparkt bis unmittelbar vor Projektabschluss (sorb 2026-08-18, #0105). Der falsch herum laufende Push-Mirror ist bereits aus; offen ist nur noch der Verbleib des Projekts. Bewusst datiert statt dauerhaft: eine dauerhafte Quittung braeuchte einen ADR, und der waere die vorweggenommene Entscheidung.
stillstand wiki: kein aktiver Push-Mirror 2026-12-31 Der Mirror ist am 2026-08-18 bewusst abgeschaltet worden: er lief entgegen ADR-0015 und haette die Wiki-Inhalte ueberschrieben. Der Verbleib des Projekts ist bis unmittelbar vor Projektabschluss geparkt (#0105).
stillstand axion1337.chat-gitops: Pipeline 518 (main) ist rot, hat aber NULL Jobs 2026-08-28 Altlast vom 2026-08-19: entstand, weil gitops keinen workflow-Block hatte. Ursache behoben (Commit 1e65f5b, leere Pipelines entstehen nicht mehr); die vorhandene Pipeline bleibt in der Historie. Die Pruefung schaut 8 Tage zurueck, die Frist laeuft also mit ihr aus - faerbt es danach weiter rot, war der Fix unvollstaendig.
Can't render this file because it contains an unexpected character in line 20 and column 271.
+24
View File
@@ -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 <klonverzeichnis> [--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 "