Files
werkbaum/backend/CLAUDE.md
T
mhoennigandClaude Opus 5 bc8850a518 feat(backend): Master-Passwort fuer die Dokumentenliste (Schritt 5)
GET /documents listet alle Dokumente und machte damit jede UUID auffindbar —
das Zugriffsmodell "unerratbarer Link" waere hinfaellig. Der Endpunkt
verlangt jetzt HTTP Basic; alles andere bleibt bewusst offen.

Ohne konfigurierten Hash ist die Liste ausdruecklich gesperrt (denyAll),
nicht offen: Ein vergessener Umgebungswert gaebe sonst jede UUID preis, und
niemandem fiele es auf, weil alles funktioniert. Bewusst als Regel und nicht
bloss als zufaelliges Passwort, das niemand kennt — der Unterschied ist
pruefbar: Mit dem Zufallspasswort blieb die Gegenprobe stumm, mit denyAll
faellt genau die danach benannte Zusicherung.

Die Sperre nach Fehlversuchen ist global statt je Adresse: Es gibt genau ein
Passwort, und hinter dem Reverse Proxy der Zielumgebung saehe der Server
ohnehin fuer alle dieselbe Adresse. Preis benannt (D76-Nachtrag 6).

135 Tests. Gegenproben: Schutz entfernt, Sperre entfernt, Voreinstellung
geoeffnet -> es faellt jeweils genau die danach benannte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 17:30:10 +02:00

3.0 KiB
Raw Blame History

Werkbaum · Backend

Kotlin/Spring-Boot-Anwendung. Aufgaben: Persistenz der Notationstexte, Live-Editing (D76), Taiga-Integration (REST-API, #ref-Auflösung, Status-Sync), später Tenzu-Adapter.

Stand: Gerüst steht — Dokumenten-CRUD mit Historie und Wiederherstellung, API-First aus src/main/resources/openapi/api.yaml, H2 mit Liquibase. Kommandos in README.md hier. Live-Editing (D76, docs/live-editing-proposal.md) ist in Arbeit: Schritte 15 der Reihenfolge dort sind gebaut (Zeilen-Diff in de.werkbaum.diff, Historie in zwei Ebenen, PATCH /content und der Änderungsfeed im LiveEditingService, Master-Passwort für die Dokumentenliste); offen sind PATCH /title und der Client im Frontend.

Konventionen

  • Kotlin, Spring Boot 4, Gradle (Kotlin DSL), JDK 21.
  • Paketwurzel de.werkbaum; Schichten: api (Controller), domain, service, repository (Interfaces), persistence (JPA), später integration.taiga (Client, Mapping).
  • API First: Interfaces und Modelle werden aus der OpenAPI-Spezifikation generiert; der Controller implementiert sie. Ändert sich die Spec, schlägt der Compile fehl — genau so ist es gewollt.
  • Tests mit JUnit 5 als Runner + Kotest-Assertions (shouldBe, shouldContain, shouldThrow) und MockK; Verhalten per Cucumber gegen die laufende Anwendung (RestTestClient, nicht TestRestTemplate — das ist in Boot 4 Auslaufmodell). Taiga-Client gegen aufgezeichnete Antworten (WireMock), nie gegen Live-Instanzen.
  • Konfiguration über application.yaml + Umgebungsvariablen; keine Zugangsdaten im Repository.
  • Keine neuen Laufzeit-Abhängigkeiten ohne Rückfrage (Wurzel-CLAUDE.md); Test-Abhängigkeiten sind unkritisch, sie landen in keinem Artefakt.

Spring Boot 4 — drei Fallen (D13-Nachtrag)

Vieles ist aus dem Kern in eigene Module gewandert. Was uns getroffen hat:

  • spring-boot-starter-test bringt kein TestRestTemplate/RestTestClient mit — dafür spring-boot-resttestclient.
  • @SpringBootTest stellt die Test-Client-Bean nicht mehr von selbst bereit: @AutoConfigureRestTestClient gehört an die Testkonfiguration.
  • org.liquibase:liquibase-core allein bringt die Autokonfiguration nicht mehr mit; ohne spring-boot-starter-liquibase läuft keine Migration, und der Fehler zeigt sich erst spät als „Schema validation: missing table".

Wichtig (D14 — Parser-Hoheit)

Das Backend parst die Notation nicht. Es speichert den Text als Ganzes und arbeitet mit expliziten Metadaten. Sollte Backend-Parsen doch nötig werden: zuerst DECISIONS ergänzen, dann gegen die gemeinsamen Fixtures aus docs/SPEC.md §10 testen — niemals eine zweite, abweichende Grammatik pflegen.

Taiga-Mapping (Vorgabe aus docs/ROADMAP.md)

  • #123 referenziert Epic/User Story/Task/Issue; Auflösung liefert Titel, URL, Status. Status-Mapping Taiga-Workflow → Notation konfigurierbar (Default: „New"→[ ], „In progress"→[~], „Ready for test"→[/], „Done"→[x], „Archived"→[^]).