docs/anleitung.md fuehrt vom ersten Code bis zur Auswertung von
Rueckmeldungen: statisch gegen dynamisch, Gestaltung, Meine Codes, die fuenf
Typen mit eigener Seite, Verwaltung, Konto und haeufige Fragen.
Die Bilder erzeugt docs/screenshots.mjs. Von Hand aufgenommene Bilder
veralten beim ersten Umbau — so sind sie in einer Minute neu erzeugt, samt
Beispieldaten, die das Skript hinterher wieder entfernt.
Anmeldefluss mit PKCE (S256), State und Nonce. Das ID-Token wird gegen den
JWKS des Anbieters geprueft — Signatur, Aussteller, Empfaenger, Ablauf und
Nonce; alles Noetige kommt aus dem Discovery-Dokument, damit die Anbindung
nicht auf Authentik festgelegt ist.
Wiedererkannt wird jemand an der Kennung des Anbieters (sub), nicht an der
E-Mail-Adresse — Adressen aendern sich. Ein bestehendes Konto mit derselben
Adresse wird verknuepft statt verdoppelt, aber nur bei bestaetigter Adresse:
sonst koennte sich beim Anbieter jemand eine fremde Adresse eintragen und
damit ein hiesiges Konto uebernehmen.
Uebernommen wird bewusst nur, wer jemand ist — plus die Instanz-Administration,
wenn OIDC_ADMIN_GROUP gesetzt ist. Gruppen und Rollen bleiben Sache dieser
Anwendung: die Gruppen im Verzeichnis bedeuten etwas anderes als die hier.
Konten aus dem Verzeichnis haben kein Passwort mehr (passwordHash ist jetzt
optional); Konto-Bereich und Passwort-Anmeldung sagen das statt an einer
leeren Pruefung zu scheitern.
Anleitung mit allen Feldern in Authentik: docs/authentik.md
E-Mail, SMS, WhatsApp, WLAN, Standort, vCard, Zahlung und App-Link sind
umgesetzt. Damit sind 9 der 15 Typen nutzbar.
Erweiterungen am Typ-Vertrag, die dafuer noetig waren:
- supportsStatic: nicht jeder Typ kann statisch. Beim App-Link steht das
Ziel erst beim Scannen fest, also gibt es ihn nur dynamisch.
- RedirectContext: die Weiterleitung reicht den User-Agent durch, damit der
App-Link iOS, Android und alles Uebrige unterscheiden kann.
- assertDynamicPossible(): supportsDynamic ist eine Eigenschaft des Typs,
aber nicht jede Eingabe taugt dafuer. Ein GiroCode ist kein Web-Ziel,
obwohl der Typ 'Zahlung' als Zahlungslink sehr wohl dynamisch sein kann.
Ohne diese Probe liess sich ein Code speichern, der erst beim Scannen
aufgefallen waere - also nach dem Drucken. Greift beim Anlegen und beim
Bearbeiten.
Sorgfalt bei den Formaten, gesammelt in src/lib/qr/encoding.ts:
- WLAN maskiert ; , : \\ und setzt rein hexadezimale Werte in
Anfuehrungszeichen, sonst deuten Geraete sie als Hexzahl.
- vCard 3.0 mit CRLF, Maskierung und Faltung nach 75 Oktetten, oktettweise
gezaehlt, damit kein mehrbytiges Zeichen zerrissen wird.
- GiroCode nach EPC069-12 mit fester Feldreihenfolge, IBAN-Pruefsumme nach
Modulo 97 und der 331-Byte-Grenze.
- Rufnummern werden nach E.164 normalisiert, '(0)' faellt weg.
- Standort nimmt Koordinaten auch aus einem Google-Maps- oder Apple-Link an.
Formular-Bausteine (Select, Textarea, Checkbox, FieldRow, FieldSet) fuer die
mehrfeldrigen Typen ergaenzt.
Geprueft: 225 Pruefungen, davon 80 neu - Dekodierung je Typ aus dem fertigen
PNG, Validierung, Betriebsarten, geraeteabhaengige Weiterleitung und die
Formulare im Browser.
- Dockerfile (4 Stufen) und docker-compose.yml mit Postgres-Healthcheck,
Volume und direktem Port-Mapping 3000:3000, ohne Reverse Proxy.
- Entrypoint wendet beim Start "prisma migrate deploy" an; die Prisma-CLI
bekommt eine eigene Build-Stufe, weil sie mehr als nur @prisma/* braucht.
- prisma.config.ts durch prisma.config.js ersetzt: laedt ohne TypeScript und
ohne dotenv, damit sie im Laufzeit-Image funktioniert.
- Prisma-Client wird erst beim ersten Zugriff erzeugt. Vorher scheiterte
"next build" beim Einsammeln der Routen-Konfiguration ohne DATABASE_URL.
- Postgres-18-Volume auf /var/lib/postgresql gemountet (neues Datenlayout).
- npm 11 blockiert Installationsskripte: erlaubte Pakete stehen jetzt im
Feld "allowScripts" der package.json.
- Lokale Variable "module" ueberall in "qrType" umbenannt (verdeckte sonst
die CommonJS-Variable) und Vorschau-Effekt ohne synchrones setState.
- README.md auf Deutsch: Setup, Konfiguration, Bedienung, Aufbau, API und
Ausblick auf Version 2.
- Erweiterbare Registry aller 15 QR-Typen; nur "Website" ist aktiv, die
uebrigen erscheinen als Platzhalter mit Badge "Bald verfuegbar".
- defineQrType() kapselt Zod-Schema, Kodierung und Redirect-Ziel je Typ,
sodass ein V2-Typ nur aus einem Registry-Eintrag plus Formular besteht.
- Serverseitige QR-Erzeugung (PNG/SVG) mit Farben, Groesse, Fehlerkorrektur
und Rand; Live-Vorschau ueber /api/qr/preview.
- Dynamische Codes: Kurz-URL {BASE_URL}/r/{slug}, 302-Redirect mit
Scan-Zaehler, CRUD unter /api/codes.
- Prisma 7 mit pg-Driver-Adapter und Initial-Migration fuer PostgreSQL.
- Deutsche Oberflaeche mit Tailwind CSS, helles Theme, responsiv.