From 2d33bf7cdf9160a2ba2d44194a264c3660831978 Mon Sep 17 00:00:00 2001
From: Matthias Andreas Benkard <code@mail.matthias.benkard.de>
Date: Sun, 16 Aug 2026 06:40:07 +0200
Subject: =?UTF-8?q?Die=20Web-Version=20wird=20=C3=B6ffentlich=20betreibbar?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Die Browserfassung war für den öffentlichen Betrieb gesperrt, und zwar
ausdrücklich: Impressum und Datenschutzerklärung trugen TODO-Blöcke statt
Angaben, der Quelltextverweis im Fuß zeigte auf
https://TODO-QUELLCODE-URL-EINTRAGEN, und der README führte beides als „vor dem
produktiven Betrieb zwingend zu erledigen“. Beide Sperren fallen; die
Auslieferung wird zugleich auf das tatsächliche Ziel eingerichtet — einen
Unterpfad einer bestehenden Domain (/aendggner/), nicht einen eigenen Server.

Impressum und Datenschutz führen nun die wirklichen Angaben: § 5 DDG (nicht mehr
§ 5 TMG) samt § 18 Abs. 2 MStV, Verantwortlicher nach Art. 4 Nr. 7 DSGVO,
Rechtsgrundlage Art. 6 Abs. 1 lit. f für die Zugriffsprotokolle, deren Frist mit
vierzehn Tagen benannt ist, sowie die Betroffenenrechte samt Aufsichtsbehörde.
Die Aussage über die Dateien der Nutzer:innen bleibt, wie sie war; sie trifft zu,
weil die Verarbeitung den Rechner nicht verlässt.

Der Quelltext wird beigelegt statt verlinkt. deploy/webpaket.sh tritt in der
Phase „package“ hinter den Übersetzer und macht aus dessen Ergebnis ein
auslieferbares Verzeichnis: Es wirft den .wat-Zwischenschritt fort (368 MB, der
bislang von Hand zu übergehen war), legt den Quelltext der gebauten Fassung als
aendggner-quelltext.tar.gz nebst Fassungskennung daneben und komprimiert nach
.gz und .br vor. Ein veränderter Arbeitsbaum bricht den Bau ab: Der beigelegte
Quelltext wäre alsdann nicht der ausgelieferte, und die Auflage des § 13 AGPLv3
wäre gerade verfehlt. Der Fuß verweist primär auf den Tarball, kompakt daneben
auf Gerrit als fortlaufende Quelle.

Die nginx-Vorlage wird vom server-Block zum location-Schnipsel. Vier Punkte sind
dabei mehr als Umschrift:

* Die Dateien werden über root statt über alias zugeordnet. In einer
  Präfix-Location löst try_files gegen den root auf, nicht gegen den alias, und
  lieferte sonst 404 für alles.

* Die Haltefrist von sieben Tagen entfällt zugunsten der Revalidierung. Die
  Dateinamen tragen keine Fassungskennung; ein Wiederkehrer mit altem app.js und
  neuem .wasm bekäme sonst eine Mischfassung, die es nie gegeben hat. Ein 304
  für das unveränderte Modul kostet nichts.

* Vorkomprimiertes wird ausgeliefert (gzip_static/brotli_static), statt 24 MB je
  Abruf neu zu packen — brotli drückt sie auf 7,1 MB.

* Hinzu treten die Sicherheitskopfzeilen samt Inhaltsrichtlinie. Zwei ihrer
  Freigaben sind unvermeidlich, beide in der Vorlage begründet: 'wasm-unsafe-eval'
  für die Instanziierung des Moduls (echtes eval kommt in der erzeugten
  aendggner.js nicht vor), und 'unsafe-inline' für Stile, weil die Synopse als
  blob:-Dokument die Richtlinie der erzeugenden Seite erbt, ihr Stylesheet aber
  eingebettet trägt. Die Notwendigkeit ist gemessen, nicht vermutet: ohne die
  Freigabe meldet das Synopse-Dokument null aktive Stylesheets und
  Standardschrift, mit ihr eines mit dreiundzwanzig Regeln.

Dazu drei Kleinigkeiten, die erst unter einem Unterpfad auffallen: ein Hinweis
für abgeschaltetes JavaScript (bislang blieb das Formular wortlos wirkungslos),
ein relativ verwiesenes favicon.svg (der Abruf der Domainwurzel ginge ins Leere)
sowie Kurzbeschreibung und kanonische Adresse. Eine robots.txt unterbleibt
bewusst: Unter einem Unterpfad ist sie wirkungslos, maßgeblich ist allein die der
Domainwurzel; die Vorlage vermerkt, was dort einzutragen wäre.

Geprüft ist beides, Bau und Lauf: 304 Prüfungen laufen durch, -Pwasm package
hinterlässt ein Verzeichnis ohne .wat und mit vollständigem Tarball, und der
IfSG-Fall ergibt im Browser unter der Inhaltsrichtlinie 48 angewandte Befehle,
27 zur manuellen Prüfung und 21 geänderte Normen — dasselbe wie die
Befehlszeile, ohne eine einzige Beanstandung in der Konsole.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I004490ddaa7c424a60fb0ebac63fc9fc098736e3
---
 README.adoc | 67 ++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 49 insertions(+), 18 deletions(-)

(limited to 'README.adoc')

diff --git a/README.adoc b/README.adoc
index 586b17f..b2329b7 100644
--- a/README.adoc
+++ b/README.adoc
@@ -325,9 +325,15 @@ JAVA_HOME=/pfad/zu/oracle-graalvm ./mvnw -Pwasm package
 ----
 
 Ergebnis ist `target/web/` mit `index.html`, `app.js`, `worker.js`,
-`style.css`, `aendggner.js` und `aendggner.js.wasm` (rund 20 MB, komprimiert
-etwa 6 MB). Die daneben liegende `aendggner.js.wat` ist ein Zwischenschritt des
-Übersetzers und gehört nicht auf den Server.
+`style.css`, `favicon.svg`, `aendggner.js` und `aendggner.js.wasm` (rund 24 MB,
+komprimiert etwa 7 MB). Das Verzeichnis ist so, wie es dasteht, auslieferbar:
+`deploy/webpaket.sh` läuft am Ende desselben Befehls, wirft den mehrere hundert
+Megabyte großen Textzwischenschritt `aendggner.js.wat` fort, legt den Quelltext
+der gebauten Fassung als `aendggner-quelltext.tar.gz` samt
+`quelltext-fassung.txt` bei und komprimiert die großen Dateien nach `.gz` und
+`.br` vor. Trägt der Arbeitsbaum uneingecheckte Änderungen, bricht der Bau ab —
+der beigelegte Quelltext wäre dann nicht der gebaute; für einen Probelauf hilft
+`QUELLTEXT_UNGEPRUEFT=1`.
 
 Lokal ansehen — `file://` genügt nicht, Browser laden Wasm-Module und Worker
 nur über HTTP (http://localhost:8000/):
@@ -337,11 +343,48 @@ nur über HTTP (http://localhost:8000/):
 jwebserver -d target/web
 ----
 
-Der öffentliche Betrieb braucht nur einen Webserver für statische Dateien;
-eine `nginx`-Vorlage liegt unter `deploy/nginx-aendggner.conf`. Die
-Befehlszeilenfassung bleibt davon unberührt und ist weiterhin der Weg für
+Die Befehlszeilenfassung bleibt davon unberührt und ist weiterhin der Weg für
 Massenläufe.
 
+=== Ausrollen
+
+Betrieben wird die Fassung unter einem Unterpfad einer bestehenden Domain,
+https://matthias.benkard.de/aendggner/ — ein eigener Server und ein eigenes
+Zertifikat sind dafür nicht nötig. Nötig ist nur ein Webserver für statische
+Dateien.
+
+[source,shell script]
+----
+JAVA_HOME=/pfad/zu/oracle-graalvm ./mvnw -Pwasm package
+rsync -av --delete target/web/ server:/var/www/aendggner/
+----
+
+`deploy/nginx-aendggner.conf` ist dafür kein eigener `server`-Block, sondern ein
+Schnipsel zum Einfügen in den vorhandenen (`include`). Er bringt mit:
+
+* die Weiterleitung von `/aendggner` auf `/aendggner/`, ohne die alle relativen
+  Verweise der Seite auf die Domainwurzel zielten;
+* den MIME-Typ `application/wasm`, ohne den der Browser die Instanziierung des
+  Moduls verweigert;
+* `gzip_static`/`brotli_static` für die vorkomprimierten Dateien, statt 24 MB je
+  Abruf neu zu packen;
+* `Cache-Control: no-cache` statt einer Haltefrist: Die Dateinamen tragen keine
+  Fassungskennung, und ein Browser mit altem `app.js` und neuem `.wasm` bekäme
+  sonst eine Mischfassung, die es nie gegeben hat. Revalidiert wird per ETag, das
+  unveränderte Modul kostet dann ein 304 ohne Rumpf;
+* die Sicherheitskopfzeilen samt einer Content-Security-Policy. Zwei ihrer
+  Freigaben sind unvermeidlich und in der Datei begründet: `'wasm-unsafe-eval'`
+  für die Instanziierung des Moduls und `'unsafe-inline'` für Stile, weil die
+  Synopse als `blob:`-Dokument die Richtlinie der erzeugenden Seite erbt, ihr
+  Stylesheet aber eingebettet trägt.
+
+Der Footer der Startseite verweist auf den beigelegten Quelltext-Tarball; das
+verlangt AGPLv3 §13 für den Netzwerkbetrieb. Als fortlaufende Zweitquelle ist
+https://gerrit.benkard.de/plugins/gitiles/aendggner genannt. `impressum.html`
+und `datenschutz.html` tragen die Angaben nach § 5 DDG und Art. 13 DSGVO; die
+dort genannte Aufbewahrungsfrist der Zugriffsprotokolle (14 Tage) muss zu der
+des Servers passen.
+
 === Warum WebAssembly und nicht ein Java-Server
 
 Der Kern ist reines Java ohne Dateisystem- oder Netzzugriff; nur vier Stellen
@@ -360,18 +403,6 @@ vermerkt:
   Dateiinhalt wandert deshalb als Base64-Text über die JS-Grenze.
 
 
-Vor dem produktiven, öffentlichen Betrieb sind zwingend zu erledigen:
-
-* `impressum.html` und `datenschutz.html`
-  (`src/main/resources/eu/mulk/aendggner/web/`) mit den tatsächlich
-  zutreffenden Angaben statt der `TODO`-Platzhalter füllen (Pflicht
-  nach § 5 DDG bzw. DSGVO für öffentlich erreichbare Dienste).
-* Den Quellcode-Link im Footer von `index.html` auf das tatsächlich
-  öffentlich erreichbare Repository setzen — das Projekt steht unter
-  AGPLv3 (`COPYING`), dessen §13 bei Netzwerkbetrieb einen
-  Quellcode-Zugriff für Nutzer:innen verlangt.
-
-
 == Running the Tests
 
 To build and run the tests:
-- 
cgit v1.2.1

