Anhang: Bewertungen halten den Stand zu einem Stichtag fest
Die Kapitel 1 bis 12 beschreiben die Architektur, wie sie heute gilt. Dieser Anhang hält fest, was Bewertungen an einem Stichtag gefunden haben. Drei Arten gibt es: die ATAM-Bewertung prüft die Architekturansätze gegen den Utility Tree, das Security-Review prüft den ganzen Bestand nach OWASP Top 10, und das Harness-Audit prüft, ob die Prüfschichten des Harness-Rads wirklich laufen. Ein Bericht ist wie ein Protokoll: Er bleibt, wie er am Stichtag war. Was sich danach ändert, steht in den Kapiteln und im nächsten Bericht.
Jedes Quartal kommt ein datierter Abschnitt dazu
Die drei Bewertungen laufen jedes Quartal gemeinsam, das nächste Mal im Dezember 2026
(ADR-030). Jede Runde bekommt einen eigenen Abschnitt am Ende
dieses Anhangs; ältere Runden bleiben unverändert stehen, damit die Geschichte lesbar bleibt. Jeder Bericht
liegt in einer eigenen Datei mit Datum im Namen: _atam-JJJJ-MM-TT.adoc, _security-JJJJ-MM-TT.adoc und
_harness-audit-JJJJ-MM-TT.adoc. Die Befund-IDs laufen über alle Runden fort (AA, SP, TP, AR und NR für
ATAM, S für Security); ein neuer Befund bekommt die nächste freie ID, ein erledigter bleibt mit Datum stehen.
Die Übersichtsseite zeigt das Datum des jüngsten ATAM-Berichts und des jüngsten Audits. Ein neuer
ATAM-Bericht verlangt im KI-Review den Abschnitt „Architektur (ATAM)“, die anderen beiden nicht.
Die Ergebnisse wandern in die Kapitel 8, 10 und 11
Ein Bericht erklärt, woher ein Befund kommt; gepflegt wird der Befund in den Kapiteln. Neue Bedrohungen (T) und Maßnahmen (M) stehen in 8.1 und 8.2 und verlinken den Bericht. Neue oder anders benotete Qualitätsszenarien ändern den Utility Tree in Kapitel 10. Risiken ®, Risikothemen (RT) und technische Schulden (TD) stehen in Kapitel 11, der Stand der Prüfschichten im Harness-Rad in 8.16.
September 2026: Die erste Runde legt die Baseline
Die erste Runde fand am 24. und 25.09.2026 statt. Sie setzt die IDs, an denen sich alle späteren Runden messen.
Harness-Audit vom 24.09.2026: Jede vorhandene Schicht hat jetzt einen prüfbaren Beleg
Das Audit prüft, ob jede Schicht, die das Harness-Rad
(8.16) als „vorhanden“ zählt, wirklich läuft. Am 24.09.2026 hat
Claude Code es zum ersten Mal durchgeführt. Seitdem nennt jede vorhandene Schicht in
scripts/harness-belege.js maschinenprüfbare Belege, und test/build/harness-rad.test.js bricht, wenn
einer fehlt. Repo-Einstellungen sieht kein Test: Secret Scanning mit Push Protection, Dependabot-Warnungen
und -Updates, CodeQL Default Setup und die Branch Protection auf main (Belege github:). Sie hat das
Audit über die GitHub-API bestätigt.
Die Befunde betrafen den Text, nicht die Schichten, und sind behoben (Commit c48e4c5). Zahlen, die mit
jedem PR veralten, etwa die Anzahl der Unit-Tests und Properties, sind aus 8.16 entfernt. Falsch
beschrieben waren drei Details: JSON-Schemas werden nicht validiert, doku.yml läuft nur bei PRs mit
Doku-Änderungen, und der Umfang des Link-Prüfers stimmte nicht. Seit dem Audit beschreibt 8.16, wie der
Stand geprüft wird.
Ergebnisse der ATAM-Bewertung vom 25.09.2026: Das größte Risiko ist ein Kern-Fehler, den jede App sofort erbt
Die Architecture Tradeoff Analysis Method (ATAM) prüft, ob die Architekturansätze die wichtigsten Qualitätsszenarien tragen. Grundlage sind der Utility Tree in Kapitel 10, die Ansätze aus Kapitel 4 und die ADRs aus Kapitel 9. Die Bewertung hat Claude Code am 25.09.2026 aus Doku und Code abgeleitet; der Product Owner hat die Wichtigkeit im Utility Tree bestätigt und die Ladezeit (QS-26) als Nicht-Risiko eingestuft. Die Befunde tragen feste IDs, damit spätere Bewertungen sie fortschreiben können: SP für Sensitivity Points, TP für Tradeoff Points, AR für Risiken und NR für Non-Risks.
Neun Architekturansätze tragen die Szenarien
| ID | Ansatz | ADR | Szenarien |
|---|---|---|---|
AA-1 |
Statische Site ohne Backend; alles läuft im Build oder im Browser |
ADR-001 |
QS-1, QS-13, QS-26 |
AA-2 |
Monorepo, Kern einmal unter |
ADR-012, ADR-013 |
QS-6, QS-9, QS-25 |
AA-3 |
Der Build als Prüfstand: Regelverstöße sind Build-Fehler |
ADR-008, ADR-017, ADR-023 |
QS-2, QS-5, QS-10 |
AA-4 |
Deterministischer Zufall aus der Aufgabennummer, |
ADR-004, ADR-007 |
QS-3, QS-4, QS-5 |
AA-5 |
Zwei-Klick-Video mit lokalem Platzhalter |
ADR-005, ADR-019 |
QS-1 |
AA-6 |
Eigene Parser ohne |
ADR-006, ADR-009 |
QS-6, QS-7, QS-8, QS-19 |
AA-7 |
Eine Zeichenfunktion für Build (Mini-DOM) und Browser |
ADR-016 |
QS-13 |
AA-8 |
Inhalts-Hash an jeder Referenz, Basis-URL an einer Stelle |
ADR-014, ADR-015 |
QS-20, QS-21, QS-23 |
AA-9 |
Harness: Pflicht-Checks, Property-Tests, Browser-Tests, KI-Review |
ADR-026, ADR-027, ADR-029 |
QS-27, QS-28, alle |
Sechs Stellen reagieren empfindlich, an sechs Stellen ziehen Ziele gegeneinander
| ID | Befund | Szenario | ADR | Risiko |
|---|---|---|---|---|
SP-1 |
|
QS-6, QS-7, QS-19 |
ADR-013, ADR-006 |
R-004 |
SP-2 |
Termprüfung: 8 Prüfstellen, mindestens 5 gültig, Toleranz 1e-9. Weniger Stellen lassen falsche Terme durch, eine engere Toleranz weist richtige ab. |
QS-19 |
ADR-009 |
R-012 |
SP-3 |
Die Reihenfolge, in der ein Generator Zufallszahlen zieht. Ein neuer |
QS-3 |
ADR-004 |
R-003 |
SP-4 |
|
QS-1, QS-2 |
ADR-008, ADR-026 |
R-031 |
SP-5 |
Der Term-Auswerter begrenzt Exponenten auf 64 und kennt nur seine eigenen Tokens. Jede neue Funktion im Parser erweitert die Eingabefläche. |
QS-8 |
ADR-006 |
R-025 |
SP-6 |
axe-core prüfte je App nur eine Kompetenzseite ( |
QS-27 |
ADR-026 |
R-030 |
TP-1 |
Ein Kern für alle Apps: Eine Korrektur erreicht jede App mit einem Commit (QZ-4, QS-25), ein Fehler ebenso (QZ-3, QS-6, QS-19). |
QS-25, QS-6 |
ADR-012, ADR-013 |
R-004, R-025 |
TP-2 |
Stabile Aufgabennummern (QZ-2) gegen bessere Generatoren (QZ-3, QZ-4). Der Product Owner hat einen Einfrier-Test am 23.09.2026 verworfen. |
QS-3 |
ADR-004 |
R-003 |
TP-3 |
Eigene Parser ohne |
QS-8, QS-19 |
ADR-006, ADR-009 |
R-012, R-025 |
TP-4 |
Zwei-Klick-Video (QZ-1, QS-1) gegen einen Klick mehr für das Kind (QZ-5). |
QS-1 |
ADR-005, ADR-019 |
R-009 |
TP-5 |
Pflicht-Review je Kopf-Commit (QZ-3) gegen Tempo beim Bauen neuer Apps (QZ-4): Jeder neue Commit braucht ein neues Review. |
QS-28 |
ADR-027 |
R-026 |
TP-6 |
Statisches Bild im Build (QZ-5, QS-13) gegen eine Zeichenfunktion mit zwei Laufzeiten (QZ-4). |
QS-13 |
ADR-016 |
R-019 |
AR-1 |
Ein Fehler im Kern-Prüfer meldet in allen Apps zugleich eine richtige Antwort als falsch oder eine falsche als richtig. Den zweiten Fall bemerkt niemand. |
QS-6, QS-7, QS-19 |
ADR-013 |
R-004, R-025 |
AR-2 |
Ein falscher Term, der an allen Prüfstellen zufällig mit dem richtigen übereinstimmt, gilt als richtig. |
QS-19 |
ADR-009 |
R-012 |
AR-3 |
Eine fremde Anfrage, die erst nach einer Eingabe entsteht (außer dem Video), fängt kein automatischer Test. |
QS-1 |
ADR-001, ADR-026 |
R-031 |
AR-4 |
Eine Generator-Änderung lässt alte Tutor-Links auf eine andere Aufgabe zeigen. |
QS-3 |
ADR-004 |
R-003 |
AR-5 |
Der Tutor hängt an claude.ai; ändert sich |
QS-3, QS-4 |
ADR-004 |
R-002 |
AR-6 |
Barrierefreiheit prüfte die Automatik nur stichprobenartig; eine neue Seitenform konnte WCAG verletzen, ohne dass ein Check rot wurde. Gemildert 25.09.2026: axe prüft jede Seite; der erste Lauf fand einen Verstoß im Pfadbaum (R-030). |
QS-27 |
ADR-026 |
R-030 |
AR-7 |
Autor und Reviewer posten über dasselbe Konto, oft mit demselben Modell; blinde Flecken teilen beide. |
alle |
ADR-027 |
R-026 |
NR-1 |
Ohne Backend gibt es keinen Server zum Angreifen und keine personenbezogenen Daten zum Verlieren. |
QS-1 |
ADR-001 |
– |
NR-2 |
Eine externe Ressource in der Ausgabe bricht den Build; beim Laden prüft |
QS-2 |
ADR-008, ADR-026 |
– |
NR-3 |
Brüche rechnen exakt; gerundet wird erst beim Vergleich und nur nach den getippten Stellen. Property-Tests decken die Regel ab. |
QS-6, QS-7 |
ADR-006 |
– |
NR-4 |
Kein |
QS-8 |
ADR-006, ADR-023 |
– |
NR-5 |
Die Ladezeit ist kein Risiko: statische Seiten ohne Framework, Web-Fonts und Tracking. Der Product Owner schätzt sie am 25.09.2026 als weit unter 2 Sekunden ein. |
QS-26 |
ADR-001 |
– |
NR-6 |
Inhalts-Hash und eine Basis-URL: Nach einem Deployment mischen sich keine Modulversionen, ein Umzug ist eine Zeile. |
QS-20, QS-21, QS-23 |
ADR-014, ADR-015 |
– |
NR-7 |
Die CI-Läufe dauern 13 bis 92 Sekunden bei einem Ziel unter 5 Minuten; Platz für weitere Prüfungen ist da. |
QS-28 |
ADR-026 |
– |
Die Befunde bündeln sich zu drei Risikothemen
Die Befunde fassen drei Risikothemen zusammen: RT-1 „Ein Fehler trifft alle Apps zugleich“, RT-2 „Der Vertrag mit dem Tutor bewegt sich“ und RT-3 „Die Prüfer sehen nur Stichproben“. Den laufenden Stand der Themen und die daraus entstandenen Risiken R-030 und R-031 führt Kapitel 11.
Security-Review vom 25.09.2026: Kein XSS-Pfad, aber Lücken in der Tutor-Allowlist und in der CI-Lieferkette
Das KI-Review jedes PRs prüft OWASP nur am Diff. Am 25.09.2026 hat Claude Code erstmals den ganzen
Bestand geprüft: jeden URL-Parameter und jeden localStorage-Wert bis zu jeder DOM-Senke in
src/kern/js/ und src/*/js/, die vendorte talkitover.js, die Nunjucks-Vorlagen, den Tutor-Vertrag
(T-015), die Workflows unter .github/workflows/ und den Datenschutz. Payloads liefen gegen die gebaute
Site im Browser (Playwright). Grundlage ist die OWASP Top 10 (2021), angepasst an eine statische Site mit
CI-Lieferkette. Der Product Owner hat S-008 bis S-010 am 25.09.2026 bewusst akzeptiert.
Das Ergebnis: Kein Weg führt von außen zu fremdem Markup oder Skript. Jeder Parameter läuft durch eine
Allowlist oder ein Muster und landet nur über textContent, setAttribute oder value im DOM;
innerHTML steht nur in TalkItOver, dort mit festen Zeichenketten. Schwach waren zwei Prüfungen, die
Angreifer nicht von außen erreichen, sondern nur über einen gemergten PR: die Link-Allowlist für
Tutor-Dateien und die Pins der GitHub Actions. Beide sind in diesem Review behoben.
| ID | OWASP | Ort | Befund und Nachweis | Schwere | Stand |
|---|---|---|---|---|---|
S-001 |
A03 |
|
|
niedrig |
Behoben: |
S-002 |
A08 |
|
16 |
mittel |
Behoben: SHA-Pins, Dependabot für Actions (M-27) |
S-003 |
A03 / T-015 |
|
Die Tutor-Allowlist ließ durch: |
mittel |
Behoben: erweiterte Muster, Pfad-Tricks verboten, Repository nur |
S-004 |
Datenschutz |
|
Die Referrer-Policy hing an der Browser-Vorgabe. Ein Browser mit anderer Vorgabe schickte YouTube Pfad, |
niedrig |
Behoben: |
S-005 |
A05 |
alle Seiten |
Keine Content Security Policy. Pages setzt keine Header; ein Meta-Tag geht, braucht aber Hashes für 27 Inline-Module und zwei Stile. Zweite Verteidigungslinie, kein offener Angriff. |
niedrig |
Issue #58 (R-033) |
S-006 |
A03 |
|
|
info |
Issue #59 |
S-007 |
A03 |
|
|
info |
Issue #59 |
S-008 |
T-015 |
|
Ein präparierter Link trägt Freitext aus |
niedrig |
Akzeptiert: Das Kind kann ohnehin alles in den Chat schreiben (R-034) |
S-009 |
T-015 |
|
|
info |
Akzeptiert (R-034) |
S-010 |
A08 |
|
Ein PR kann den Check |
niedrig |
Akzeptiert: Der Product Owner liest jeden PR (R-026) |
S-011 |
A06 |
|
v1.1.0, MIT. |
info |
Keine Aktion (R-007 bleibt) |
S-012 |
A05 |
docToolchain-Theme |
Der Link „Create an issue“ hat |
info |
Keine Aktion |
Geprüft und in Ordnung (A08): Kein Workflow nutzt pull_request_target, workflow_run oder
issue_comment; ${{ github.event.* }} steht nur in env:, nie in run:. Jeder Workflow hat
contents: read, nur pages.yml darf pages: write und id-token: write, und nur auf main. Das
Standard-Token des Repositorys ist lesend und darf keine PRs freigeben. Secrets nutzt kein Workflow außer
dem automatischen GITHUB_TOKEN. Caches aus PRs sieht main nicht (Cache-Scope je Ref);
docToolchain und asciidoc-linter hängen an Commits (M-13, ADR-028).
Nicht anwendbar oder abgedeckt: A01 (Zugriffskontrolle) und A07 (Authentifizierung) – keine Konten,
kein Backend (M-01); A02 (Kryptografie) – nur HTTPS über Pages, keine Geheimnisse im Browser; A06
(Komponenten) – npm audit, Dependency Review und Dependabot (M-20, M-24); A09 (Logging) – die Apps
messen bewusst nichts (8.4), Änderungen zeigt die
Git-Historie (M-08); A10 (SSRF) – kein Server, die Karte lädt nur ihre eigene data.json.
Datenschutz: localStorage hält nur Stufen je Kompetenz, den letzten Test (Nummer, Modus, Datum, Stufen),
den Video-Merker und den TalkItOver-Provider, keine Namen und keinen Freitext. Nach einer Eingabe geht
keine Anfrage an fremde Hosts; YouTube lädt erst nach dem Klick. Der Deploy liefert nur _site/ und die
Doku, ohne Quelltext-Maps. R-031 bleibt offen, weil der Build fremde Hosts nur an Mustern erkennt.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.