chore: session checkpoint 2026-05-19 — AGENTS.md + CLAUDE-Symlink
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
32
AGENTS.md
Normal file
32
AGENTS.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Kanban
|
||||||
|
|
||||||
|
Self-contained HTML-Kanban als operative Single Source of Truth für alle laufenden Projekte. Visualisiert Robins Ringsystem (Ring 0–3) über 4 Gruppen × 16 Boards.
|
||||||
|
|
||||||
|
**Stack:** Vanilla HTML/CSS/JS, localStorage, kein Build, kein Backend
|
||||||
|
**Server:** `./server.sh` (Python http.server auf Port 8765, started aus `~/`)
|
||||||
|
**URL:** `http://localhost:8765/dev/kanban/index.html`
|
||||||
|
**Spec:** `SPEC.md` (Architektur + Test-Checkliste)
|
||||||
|
|
||||||
|
## Aktueller Stand
|
||||||
|
|
||||||
|
<!-- Zuletzt aktualisiert: 2026-05-19 via /save -->
|
||||||
|
|
||||||
|
**Sprint / Phase:** Initial-Release — produktionsreif für tägliche Nutzung, vor Tester-Agent-Validierung
|
||||||
|
|
||||||
|
**Zuletzt implementiert:**
|
||||||
|
- Migration `~/.kanban → ~/dev/kanban` + Backwards-Compat-Symlink, Git-Repo initialisiert
|
||||||
|
- 3 Views (Overview/Board/Analytics), Overview komplett editierbar inkl. Drag-Reorder von Gruppen/Boards
|
||||||
|
- Auto-Aging + Throughput-History (echter Throughput aus Done-Cards der letzten 14 Tage)
|
||||||
|
- WIP-Limit/Throughput/SLE per Pill editierbar pro Board
|
||||||
|
- Tool-Agnostik: globale CLAUDE.md → AGENTS.md, kanban-mcp aus MCP-Config entfernt
|
||||||
|
- Local-Server-Setup für MD-Viewer (löst file://-CORS-Sackgasse)
|
||||||
|
|
||||||
|
**Als nächstes:**
|
||||||
|
- Tester-Agent auf SPEC.md + index.html ansetzen
|
||||||
|
- Overview-Daten für die 13 restlichen Boards füllen (Pilot war Döner-App)
|
||||||
|
- AGENTS.md `## Aktueller Stand` in den Code-Repos auf Kurz-Snapshot schrumpfen
|
||||||
|
|
||||||
|
**Offene Punkte:**
|
||||||
|
- PWA-Manifest für iPad-Home-Screen (geplant, Stufe 1)
|
||||||
|
- CFD (Cumulative Flow Diagram) — Throughput-History wird dafür bereits gesammelt
|
||||||
|
- Sync-Layer für Multi-Device (Stufe 3, später)
|
||||||
15
REPO-AUDIT.md
Normal file
15
REPO-AUDIT.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Repo Audit Pointer
|
||||||
|
|
||||||
|
Aktueller Audit:
|
||||||
|
|
||||||
|
- `docs/audits/2026-05-19-repo-audit.md`
|
||||||
|
|
||||||
|
Reproduzierbare Checks:
|
||||||
|
|
||||||
|
- `./scripts/verify-repo.sh`
|
||||||
|
|
||||||
|
Konvention:
|
||||||
|
|
||||||
|
- Neue Audits unter `docs/audits/YYYY-MM-DD-repo-audit.md`
|
||||||
|
- Verify-/Smoke-Checks in `scripts/`
|
||||||
|
- Dieses File bleibt nur ein kurzer Einstiegspunkt
|
||||||
67
docs/audits/2026-05-19-repo-audit.md
Normal file
67
docs/audits/2026-05-19-repo-audit.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Repo-Audit
|
||||||
|
|
||||||
|
Datum: 2026-05-19
|
||||||
|
Scope: vollstaendiges Repo
|
||||||
|
Status: solide mit Risiken
|
||||||
|
|
||||||
|
## Kurzfazit
|
||||||
|
|
||||||
|
- Kritischste Themen: persistente HTML-/Script-Injection ueber `innerHTML`, unsichere Markdown-Link-Behandlung, Funktionsabweichungen bei Reset und Task-Erzeugung
|
||||||
|
|
||||||
|
## Reproduzierbarkeit
|
||||||
|
|
||||||
|
Vor dem Audit wurden die verfuegbaren automatisierten Checks ueber `./scripts/verify-repo.sh` ausgefuehrt.
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
1. [High] Persistente HTML-/Script-Injection ueber unescaped User-State
|
||||||
|
Datei: `index.html:1505-1513`, `index.html:1621-1627`, `index.html:2084-2120`, `index.html:2298-2313`
|
||||||
|
Problem: Mehrere Renderer schreiben benutzerkontrollierte Werte direkt per `innerHTML` ins DOM, ohne sie vorher zu escapen, z. B. `task.t`, `idea.text`, Board-Namen und Gruppennamen. Diese Werte kommen aus Inputs, `contenteditable`, `prompt()` und `localStorage`.
|
||||||
|
Warum es zaehlt: Ein Eintrag wie `<img src=x onerror=...>` wird persistent gespeichert und bei jedem Render erneut ausgefuehrt.
|
||||||
|
Empfehlung: Alle benutzerkontrollierten Texte konsequent mit `escapeHtml()` behandeln oder DOM-Knoten per `textContent`/`createElement` aufbauen statt HTML-Strings zu interpolieren.
|
||||||
|
|
||||||
|
2. [High] Markdown-Renderer erlaubt `javascript:`-Links
|
||||||
|
Datei: `index.html:1953-2017`, insbesondere `index.html:2007`
|
||||||
|
Problem: Der Markdown-Parser escaped zwar HTML, uebernimmt aber Link-Ziele ungeprueft in `<a href="$2" target="_blank">`. Ein Markdown-Link wie `[x](javascript:alert(1))` bleibt klickbar.
|
||||||
|
Warum es zaehlt: Jede geladene `.md`-Datei kann so aktiven Script-Code hinter einem scheinbar normalen Link verstecken.
|
||||||
|
Empfehlung: Link-Protokolle whitelisten (`http:`, `https:`, ggf. `file:`) und alles andere verwerfen oder als reinen Text rendern. Zusaetzlich `rel="noopener noreferrer"` setzen.
|
||||||
|
|
||||||
|
3. [High] `Reset` setzt nicht auf `DEFAULTS` zurueck, sondern nur die Spalten
|
||||||
|
Datei: `SPEC.md:112`, `index.html:1012-1023`
|
||||||
|
Problem: Laut Spec soll `↺ Reset` das aktuelle Board auf `DEFAULTS` zuruecksetzen. Implementiert wird aber nur `cols = deepClone(DEFAULTS[curId].cols)`. Name, Goal, WIP-Limit, Throughput, SLE, Focus und `overview` bleiben erhalten.
|
||||||
|
Warum es zaehlt: Der sichtbare UX-Vertrag stimmt nicht mit dem Verhalten ueberein; ein Reset hinterlaesst versteckte Altzustaende.
|
||||||
|
Empfehlung: Das gesamte Default-Board zurueckkopieren und danach nur `group/color/ring` aus `BOARD_META` wieder anwenden.
|
||||||
|
|
||||||
|
4. [Medium] Aus Ideen erzeugte Tasks bekommen kein `movedAt`
|
||||||
|
Datei: `SPEC.md:137-138`, `index.html:1343-1349`, `index.html:2252-2260`
|
||||||
|
Problem: Beim Droppen einer Idee auf ein Board oder beim Promote-Dialog wird nur `{ t: idea.text }` angelegt. `movedAt` fehlt, obwohl es laut Datenmodell Grundlage fuer Aging ist.
|
||||||
|
Warum es zaehlt: Diese Tasks altern nie sichtbar und verfaelschen die Board-Signale gegenueber regulaer angelegten Karten.
|
||||||
|
Empfehlung: Beim Erzeugen aus Ideen dieselbe Initialisierung wie in `addCard()` verwenden, inklusive `movedAt = Date.now()`.
|
||||||
|
|
||||||
|
5. [Medium] "Maskierte" Secrets liegen im Klartext in `localStorage` und im DOM
|
||||||
|
Datei: `SPEC.md:52`, `index.html:906-964`, `index.html:1740-1746`
|
||||||
|
Problem: Der Secrets-Bereich ist nur optisch maskiert. Die Werte werden vollstaendig in `kanban_v2` gespeichert und zusaetzlich als `data-value`/`data-copy` ins DOM geschrieben.
|
||||||
|
Warum es zaehlt: Bei XSS, gemeinsam genutztem Browser-Profil oder lokalem Zugriff sind die Daten sofort auslesbar; die UI suggeriert mehr Schutz als tatsaechlich vorhanden ist.
|
||||||
|
Empfehlung: Keine echten Secrets in App-State speichern. Stattdessen nur Env-Referenzen/Keys-Namen anzeigen oder Secrets separat ausserhalb des Boards halten.
|
||||||
|
|
||||||
|
6. [Medium] State-Laden ist unvalidiert und schluckt Fehler vollstaendig
|
||||||
|
Datei: `index.html:855-856`, `index.html:863-864`, `index.html:905-939`, `index.html:2202-2203`
|
||||||
|
Problem: `localStorage`-Payloads werden ohne Shape-Validierung uebernommen, und Exceptions werden mit leeren `catch {}`/`catch(e) {}` verschluckt. Schon eine kaputte Struktur kann das Laden teilweise abbrechen, ohne Hinweis fuer den Nutzer.
|
||||||
|
Warum es zaehlt: Beschaedigter oder zukuenftiger inkompatibler State fuehrt zu stillen Datenverlusten oder schwer erklaerbaren Resets.
|
||||||
|
Empfehlung: Geladene Daten vor der Uebernahme validieren, defekte Teile gezielt verwerfen und einen sichtbaren Recovery-Hinweis anzeigen.
|
||||||
|
|
||||||
|
## Test- und Pruefstand
|
||||||
|
|
||||||
|
- Tests: nicht ausgefuehrt, kein Test-Setup im Repo vorhanden
|
||||||
|
- Lint/Typecheck/Build: nicht ausgefuehrt, kein entsprechendes Setup vorhanden
|
||||||
|
- Shell-Syntax: `bash -n server.sh` erfolgreich
|
||||||
|
- Nicht verifiziert: echtes Browser-Laufzeitverhalten, Drag-and-drop im UI, Verhalten unter beschaedigtem `localStorage`
|
||||||
|
|
||||||
|
## Empfohlene Reihenfolge
|
||||||
|
|
||||||
|
1. XSS-Pfade in Renderern schliessen
|
||||||
|
2. Markdown-Link-Whitelist ergaenzen
|
||||||
|
3. `resetCurrentBoard()` auf echten Default-Reset umstellen
|
||||||
|
4. Task-Erzeugung vereinheitlichen (`addCard`, Idea-Drop, Promote)
|
||||||
|
5. Secrets-Handling entschaerfen
|
||||||
|
6. `localStorage`-Load validieren und Fehler sichtbar machen
|
||||||
20
docs/audits/README.md
Normal file
20
docs/audits/README.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Audit-Konvention
|
||||||
|
|
||||||
|
Diese Struktur trennt kuratierte Audit-Ergebnisse von reproduzierbaren Checks.
|
||||||
|
|
||||||
|
## Ablage
|
||||||
|
|
||||||
|
- Audit-Berichte: `docs/audits/YYYY-MM-DD-repo-audit.md`
|
||||||
|
- Reproduzierbare Checks: `scripts/verify-repo.sh`
|
||||||
|
- Root-Einstiegspunkt: `REPO-AUDIT.md`
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. `./scripts/verify-repo.sh` ausfuehren
|
||||||
|
2. Repo risikobasiert pruefen
|
||||||
|
3. Findings mit Datei- und Zeilenbezug in ein neues Audit schreiben
|
||||||
|
4. Audit-Datei im Root-Pointer aktualisieren
|
||||||
|
|
||||||
|
## Hinweis
|
||||||
|
|
||||||
|
Dieses Repo hat aktuell kein Test-, Lint-, Typecheck- oder Build-Setup. `verify-repo.sh` dokumentiert deshalb nur die verfuegbaren automatisierbaren Checks und markiert fehlende Check-Arten explizit.
|
||||||
57
scripts/verify-repo.sh
Executable file
57
scripts/verify-repo.sh
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
EXIT_CODE=0
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
printf '[OK] %s\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
printf '[WARN] %s\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf '[FAIL] %s\n' "$1"
|
||||||
|
EXIT_CODE=1
|
||||||
|
}
|
||||||
|
|
||||||
|
printf 'Repo verify: %s\n' "$ROOT_DIR"
|
||||||
|
|
||||||
|
if [ -f "$ROOT_DIR/server.sh" ]; then
|
||||||
|
if bash -n "$ROOT_DIR/server.sh"; then
|
||||||
|
ok 'server.sh shell syntax valid'
|
||||||
|
else
|
||||||
|
fail 'server.sh shell syntax invalid'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fail 'server.sh missing'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ROOT_DIR/package.json" ]; then
|
||||||
|
warn 'package.json gefunden, aber kein JS-Verify-Schritt definiert'
|
||||||
|
else
|
||||||
|
warn 'kein package.json vorhanden; kein test/lint/build setup erkannt'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ROOT_DIR/index.html" ]; then
|
||||||
|
ok 'index.html vorhanden'
|
||||||
|
else
|
||||||
|
fail 'index.html missing'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ROOT_DIR/SPEC.md" ]; then
|
||||||
|
ok 'SPEC.md vorhanden'
|
||||||
|
else
|
||||||
|
warn 'SPEC.md fehlt'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$ROOT_DIR/docs/audits" ]; then
|
||||||
|
ok 'docs/audits vorhanden'
|
||||||
|
else
|
||||||
|
warn 'docs/audits fehlt'
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$EXIT_CODE"
|
||||||
Reference in New Issue
Block a user