Commit Graph
9 Commits
Author SHA1 Message Date
mhoennigandClaude Opus 5 0f3bd8f5b8 feat(backend): Zeilen-Diff als reine Funktionen (Live-Editing, Schritt 1)
Anwenden, Berechnen, Rebasen und Pruefsumme in de.werkbaum.diff — ohne
Spring, damit die Regeln ohne Kontext pruefbar sind. Grundlage fuer
PATCH /content und den Aenderungsfeed (D76).

Beim Bauen entschieden, was das Konzept offenliess: Eine Einfuegung ist ein
Punkt ZWISCHEN den Zeilen und kollidiert nur mit dem Inneren eines fremden
Bereichs (start < index < end). Beide im Konzept genannten Folgen gelten
damit weiter — zwei Einfuegungen an derselben Stelle vertragen sich, eine
Einfuegung in einen geloeschten Bereich nicht —, aber die Raender bleiben
konfliktfrei: Wer eine Zeile ueber einer gerade geaenderten einfuegt,
bekommt keinen 409.

49 Tests. Gegenprobe: Rand-Regel auf halboffen mutiert -> genau die zwei
danach benannten Zusicherungen fallen; fremde Einfuegung an gleicher Stelle
nicht mitgezaehlt -> genau die eine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 16:41:33 +02:00
mhoennigandClaude Opus 5 9e5f546d76 docs: Speicherzahlen der Zielumgebung berichtigt (D76-Nachtrag 3)
Nachtrag 2 nannte "832 MB frei" - ein Schnappschuss, und dazu mehrdeutig
zwischen `free` und `available`. Nachgemessen: 326-358 MB free, 978-1004 MB
available von 3915 MB, dazu ~1 GB Swap belegt.

Falsch war ausserdem die Annahme, ein Managed Webspace koenne den Verbrauch
nicht zuordnen. `hidepid=invisible` verbirgt zwar fremde Prozesse, aber das
systemd-cgroup-Accounting (`systemctl status pacs-<paket>.slice`, so auch im
Hostsharing-Wiki) und die world-readable atop-Aufzeichnungen unter
/var/log/atop/ geben sie her.

Befund: nicht die Datenbanken. clamav-daemon 988 MB gegen mariadb 150 MB und
postgresql 111 MB; alle zwoelf Webspaces zusammen 100 MB. MariaDB haelt
602 MB im Swap - die DBs sind auf je 25 % des RAM provisioniert und verlieren
gegen den Virenscanner.

Fuers Deployment: pacs-mih00.slice hat MemoryMax=3147M - eine Erlaubnis, keine
Reservierung. `-Xmx` gehoert gegen das Freie bemessen; die JVM-Voreinstellung
(~980 MB) ist genau die Groesse, die MariaDBs Puffer verdraengt hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:57:06 +02:00
mhoennigandClaude Opus 5 af8a7b74b3 docs: Feed nur im sichtbaren Tab (D76-Nachtrag 1)
Der Zielserver bietet kein HTTP/2, also gilt das Browser-Limit von sechs
Verbindungen je Herkunft - ein dauerhaft offener Long-Poll je Tab engt bei
mehreren Tabs alles andere ein. Der Feed schliesst deshalb bei
visibilitychange und holt beim Zurueckkommen mit dem eigenen since nach.
Ein Hintergrund-Tab braucht keinen Live-Feed; das spart nebenbei
Server-Worker und Akku. Ein SharedWorker waere sauberer, ist aber eine eigene
Baustelle fuer ein Problem, das die einfache Loesung praktisch beseitigt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:30:03 +02:00
mhoennigandClaude Opus 5 b6509ae537 test(backend): Kotest-Assertions statt JUnit, CLAUDE.md berichtigt
backend/CLAUDE.md sah Kotest-Assertions vor, der Code benutzte aber die
JUnit-Assertions. Umgestellt bei 25 Aufrufen in zwei Dateien - jetzt billig,
und Test-Abhaengigkeiten sind unkritisch, weil sie in keinem Artefakt landen.
Wo Kotest spezifischer ist, ersetzt es die handgeschriebenen Meldungen:
shouldContain statt assertTrue(contains, "..."), withClue nur noch dort, wo
der Kontext wirklich hilft.

Gegenprobe per Mutation: eine falsche Erwartung im Service-Test und eine im
BDD-Schritt lassen genau die danach benannten Tests fallen.

CLAUDE.md berichtigt: Das Backend ist nicht mehr "noch nicht bootstrapped",
die Konfiguration heisst application.yaml, die Schichten entsprechen dem
tatsaechlichen Aufbau, und die drei Spring-Boot-4-Fallen von heute sind
festgehalten, damit sie niemanden erneut treffen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:29:24 +02:00
mhoennigandClaude Opus 5 f3afc8dfa8 refactor(backend): Paketwurzel de.werkbaum, Tests auf RestTestClient
Das Backend-Geruest kam unter der Platzhalter-Wurzel com.example.editor
herein und widersprach backend/CLAUDE.md. Umgezogen nach de.werkbaum: 17
Kotlin-Dateien, Gradle-group, apiPackage/modelPackage der OpenAPI-Generierung,
die jacoco-Ausschluesse und das Cucumber-glue-Paket. Jetzt war es billig, mit
jeder Woche Entwicklung waere es teurer geworden.

Die BDD-Tests nutzen jetzt RestTestClient statt TestRestTemplate, das in
Spring Boot 4 als Auslaufmodell gilt. Weil Cucumber Senden und Pruefen
trennt, wird die fluent API nicht fuer Zusicherungen genutzt, sondern ueber
returnResult das Ergebnis festgehalten.

Nachgemessen: 22 Tests gruen, check inklusive Coverage-Verifikation besteht,
91,7 % Zeilenabdeckung, generierter Code weiterhin ausgeschlossen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:21:34 +02:00
mhoennigandClaude Opus 5 7684872a42 docs: Proxy-Weg gemessen, JDK entschieden (D76-Nachtrag 2)
RewriteRule [P] ist in der .htaccess erlaubt - gemessen mit einer temporaeren
Regel auf einen lokalen Testprozess, danach vollstaendig zurueckgebaut.
Sofortige Antwort HTTP 200 nach 0,13 s, absichtlich um 30 s verzoegerte
Antwort HTTP 200 nach 30,1 s: Apache haelt die Verbindung durch und puffert
nichts weg. Long Polling mit wait=25 ist damit gemessen tragfaehig, nicht nur
rechnerisch. Die Regel gehoert nach scripts/prod.htaccess, weil deploy-prod.sh
die Datei mit rsync --delete spiegelt.

JDK: eigenes 21 ins Home statt Toolchain auf die installierte 17 senken.
GraalVM Native Image ist vorgemerkt statt verworfen - es spart den Grossteil
des knappen RAM (nur 832 MB frei auf einem geteilten Server), scheitert aber
vorerst an der glibc-Differenz, an Liquibase/Hibernate-Metadaten und an einem
offenen Boot-4-Fehler fuer genau diese Kombination. Kotlin/Native scheidet
grundsaetzlich aus: Spring, Hibernate und JDBC sind JVM-Bibliotheken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:13:56 +02:00
mhoennigandClaude Opus 5 2540bbf0a7 docs: Live-Editing-Konzept entschieden und eingearbeitet (D76)
Die offenen Punkte der beiden Entwuerfe sind beantwortet und in beide
Dokumente eingearbeitet. Die wichtigsten Aenderungen am Protokoll:

- Der Server rebased selbst; 409 nur noch bei echter Ueberlappung. Reines
  Ablehnen fuehrt zu Starvation - ein Client mit hoeherer Latenz kommt bei
  fleissigen Mitschreibern womoeglich nie durch.
- Der Feed arbeitet auf der Historie statt am Dokument, sonst koennte er
  ausgerechnet das Loeschen nicht melden, das er melden soll.
- Historie in zwei Ebenen: kurzlebige Sync-Versionen und nutzersichtbare
  Meilensteine (nach Schreibpause und auf Knopfdruck, wie D54).
- Pruefsumme als Pflichtfeld, clientId + seq gegen doppelt angewendete
  Patches, Volltext im Feed fuer zu alte Staende, eigener Aenderungstyp fuer
  den Rollback, Titel im Feed-Ereignis.
- Zugriff ueber die unerratbare UUID; GET /documents bekommt ein
  Master-Passwort (Spring Security).

Die Client-Instruktion war fuer ein anderes Frontend geschrieben: Sie nannte
CodeMirror, TypeScript, jsdiff und MSW. Werkbaum hat eine rohe textarea,
Vanilla JS und keine Laufzeit-Abhaengigkeiten - CodeMirror bleibt eine eigene
Entscheidung (gemessen: 120 kB gzip Einstieg, danach nur 18 kB fuer alles
Weitere).

Zielumgebung vermessen: Apache 2.4.68 mit MPM event, 1024 Worker,
Timeout 300 - Long Polling traegt dort. Offen bleiben fehlendes HTTP/2,
nur Java 17 statt 21 und der ungeklaerte Weg vom Apache zum Backend.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:04:00 +02:00
mhoennig 0446e3d81e initial backend: Dokumente, Historie, API und Persistenz (D76)
- Liquibase-Schema (`document`, `document_history`) + Rollback-scripts
- Spring Boot with JPA-repositories, entities and services
- REST-API (`/documents`, `/documents/{id}`, `/documents/{id}/history`)
- OpenAPI-specifikation for CRUD-Operationen and history
- config files (`application.yaml`, `Liquibase`, H2 im PostgreSQL-Modus)
- preps for future live-editing/delta-updates
- Exceptions for conflikt- and not-found cases (409/404)
- keeping document hostory even after `delete` for RESTORE functionality
2026-08-26 12:56:27 +02:00
Michael Hoennig ded894a4da initial, vibe-coded version, mostly frontend 2026-07-21 09:55:30 +02:00