Files
werkbaum/backend/CLAUDE.md
T
mhoennigandClaude Opus 5 ae85503b79 feat(backend): PATCH /content — Diffs einreichen, rebasen, wiederholen (Schritt 3)
Der Server rebased selbst: Ist die Basis veraltet, ueberschneiden sich die
Operationen aber nicht mit den zwischenzeitlichen, verschiebt er sie und
akzeptiert. Reines Ablehnen fuehrte zu Starvation — ein Client mit hoher
Latenz kaeme bei fleissigen Mitschreibern womoeglich nie durch. 409 gibt es
nur bei echter Ueberschneidung, mit allem, was der Client zum Weiterarbeiten
braucht, ohne neu zu laden.

Pruefsumme ist Pflicht (422 bei Abweichung): Die Versionsnummer bestaetigt
nur, dass die Basis dieselbe Version ist, nicht dass beide Seiten sie gleich
lesen. clientId + seq machen den Aufruf wiederholbar — im Mobilnetz ist die
verlorene Antwort der Normalfall.

Die Sperre je Dokument liegt ausserhalb der Transaktion: innen gaebe der
Proxy sie vor dem Commit frei, und der naechste Schreiber laese einen Stand,
der noch nicht steht. Deshalb ist LiveEditingService nicht transaktional und
schreibt ueber DocumentService.

Was das Konzept offenliess, ist jetzt entschieden und in D76-Nachtrag 4
begruendet: die Randfaelle der Einfuege-Ueberschneidung, die Trennung von
400 und 422, die gedeckelte Idempotenz im Speicher.

104 Tests, davon 8 Cucumber-Szenarien fuer das Live-Editing. Gegenprobe:
Pruefsumme nicht geprueft, Idempotenz entfernt, veraltete Basis abgelehnt
statt verschoben -> es fallen jeweils genau die danach benannten.

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

55 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 13 der Reihenfolge
dort sind gebaut (Zeilen-Diff in `de.werkbaum.diff`, Historie in zwei Ebenen,
`PATCH /content` im `LiveEditingService`), ab Schritt 4 (`GET /changes` per
Long Polling) steht es aus.
## 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"→`[^]`).