Version 1.7.0: Doku durchgesehen und Roadmap angeglichen

Sechs Erweiterungen sind zusammengekommen — Logo im Code, Freigabe je
Gruppe, Domain-Check, Dublettenpruefung, Filter nach Art und die
Kurzhilfe zu den Domains. Dafuer eine neue Minor-Version.

Zwei Stellen waren schlicht falsch und wiegen schwerer als jede Luecke:
Anleitung und Funktionsuebersicht behaupteten beide noch, statische Codes
wuerden "nicht gespeichert" — ueberholt seit 1.5.0. Ebenso die Aussage,
nur "Website" sei ausprogrammiert; das gilt seit 1.1.0 fuer alle fuenfzehn.

Danach die Luecken: Jedes der sechs Features steht jetzt in allen drei
Dokumenten, die es betrifft. Die Bedienungsanleitung hatte keines davon.

Die Roadmap verliert die zwei gebauten Punkte und bekommt einen neuen aus
der Umsetzung: Die Gestaltung eines gespeicherten Codes laesst sich
ueberhaupt nicht aendern, ein Logo also nur ueber die Schnittstelle
nachruesten.

Die Kurzhilfe verwies unter "Nachpruefen" noch auf curl, obwohl seit #7
der Pruefen-Knopf danebensteht.
This commit is contained in:
Florian Wilde
2026-08-21 11:27:15 +02:00
parent c6891f66ff
commit cdda7df17a
9 changed files with 228 additions and 61 deletions
+92 -3
View File
@@ -112,12 +112,40 @@ gescannt zu werden.
das Scannen erschweren, weil der Scanner den Code nicht mehr vom Hintergrund
trennen kann.
### Ein Logo in die Mitte setzen
Ganz unten in der Gestaltung steht **Logo in der Mitte**. Ein Haken genügt,
dann fragt die Anwendung, woher das Bild kommen soll:
- **Logo dieser Installation** — das, was unter Verwaltung → Erscheinungsbild
hinterlegt ist. Kein Upload je Code nötig. Die Wahl erscheint nur, wenn dort
überhaupt eines liegt.
- **Eigenes Logo** — je Code hochgeladen, für Kundenprojekte mit fremdem
Zeichen. PNG, JPEG, WebP oder AVIF, bis 2 MB.
Die **Größe** liegt zwischen 10 und 25 % der Kantenlänge; voreingestellt sind
20 %, das verdeckt rund 4 % der Fläche. Hinter dem Bild liegt eine Fläche in
der Hintergrundfarbe, damit es sich absetzt.
**Die Fehlerkorrektur springt dabei auf H** und lässt sich nicht mehr ändern —
was das Bild verdeckt, muss sie ausgleichen. Das steht auch so unter der
Auswahl; heimlich geschieht es nicht.
Ab 22 % erscheint eine Warnung. Die Fehlerkorrektur trägt das zwar, aber
manche Scanner-Apps suchen in der Mitte nach Ausrichtungsmustern.
> **Einmal selbst scannen, bevor etwas in den Druck geht.** Ein Code mit Logo
> ist die einzige Stelle, an der die Anwendung etwas ausliefern kann, das auf
> dem einen Gerät geht und auf dem anderen nicht. Zwei verschiedene Apps
> kosten eine halbe Minute und ersparen eine Neuauflage.
---
## Meine Codes
Hier stehen alle **dynamischen** Codes. Statische erscheinen nicht — sie
werden nicht gespeichert.
Hier stehen die **dynamischen** Codes und die statischen, die du abgelegt
hast. Beide Arten stehen nebeneinander in derselben Liste — ein statischer
trägt statt einer Kurz-URL das Abzeichen „statisch“ und zählt keine Scans.
![Meine Codes als Liste](bilder/04-meine-codes-liste.png)
@@ -128,6 +156,10 @@ Projekte nebeneinander.
- Die **Sortierung** kennt neueste, älteste, Name und Scan-Anzahl.
- Ein **Gruppenfilter** erscheint, sobald Codes in mehr als einer Gruppe
liegen.
- Ein **Filter nach Art** erscheint, sobald dynamische und statische Codes
nebeneinander liegen: *Alle Arten*, *Nur dynamische*, *Nur statische*.
Steht er auf „Nur statische“, fällt die Scan-Spalte weg und die Sortierung
nach Scans mit ihr — bei einer Liste aus lauter Strichen sagt sie nichts.
- Das Symbol neben der Kurz-URL kopiert sie in die Zwischenablage.
Über die beiden Schalter rechts geht es zur **Kartenansicht** mit großer
@@ -135,6 +167,21 @@ Vorschau. Die Wahl merkt sich der Browser.
![Meine Codes als Karten](bilder/05-meine-codes-karten.png)
### Statische Codes ablegen
Ein statischer Code ist mit dem Download eigentlich fertig — sein Inhalt
steckt in ihm. Der Knopf **In „Meine Codes“ ablegen** legt ihn trotzdem in die
Liste, damit du ihn wiederfindest und erneut herunterladen kannst.
Liegt dort schon ein statischer Code mit **identischem Inhalt**, hält das
Ablegen an und zeigt, welcher das ist und wann er entstand. Der Knopf heißt
dann **Trotzdem ablegen** — es ist eine Warnung, keine Sperre. Verglichen wird
nur der Inhalt, nicht die Gestaltung: Derselbe Code in Schwarz-Weiß und in
Hausfarben gilt hier als Dublette.
Bei **dynamischen** Codes fragt niemand nach. Zwei Kurz-Links auf dasselbe
Ziel sind der Normalfall, sobald zwei Kampagnen getrennt gezählt werden.
### Ziel ändern
![Dialog zum Ändern des Ziels](bilder/06-ziel-bearbeiten.png)
@@ -247,6 +294,25 @@ sich Typen abschalten; sie verschwinden dann aus der Auswahl.
unverändert weiter** — sie leiten weiter, zählen Scans und lassen sich
bearbeiten. Nur neue lassen sich nicht mehr anlegen.
**Freigabe je Gruppe.** Über der Liste steht die Auswahl **Freigabe für**:
| Auswahl | Wirkung |
| --- | --- |
| Alle Gruppen (Grundeinstellung) | gilt für die ganze Installation |
| Nur: *eine Gruppe* | weicht für diese eine Gruppe ab |
So bekommt die Marketingabteilung Social Media und die Werkstatt nur Website
und PDF. Fehlt eine Abweichung, folgt die Gruppe der Grundeinstellung.
**Die Grundeinstellung gewinnt immer.** Ein Typ, der dort abgeschaltet ist,
lässt sich in keiner Gruppe einschalten — der Schalter steht dann ausgegraut
und nennt den Grund. Andersherum wäre „hier abgeschaltet“ keine verlässliche
Aussage mehr.
Wer in mehreren Gruppen ist, sieht auf der Startseite die **Vereinigung**.
Welche Freigabe zählt, entscheidet sich beim Anlegen anhand der gewählten
Gruppe.
### Gruppen
![Gruppen verwalten](bilder/13-verwaltung-gruppen.png)
@@ -275,7 +341,30 @@ mehreren Gruppen dienen; die Codes bleiben trotzdem strikt nach Gruppe
getrennt.
Damit das funktioniert, muss der Reverse Proxy jede dieser Domains auf diese
Anwendung leiten — siehe README, Abschnitt „Mehrere Domains“.
Anwendung leiten. Was dafür einzurichten ist, steht nicht nur im README: Der
Knopf **Kurzhilfe** über der Liste führt es in sechs Schritten auf — DNS,
Weiterleitung im Proxy samt der drei nötigen Kopfzeilen, Zertifikat,
Registrieren, Gruppenzuteilung, Nachprüfen.
**Prüfen, ob eine Domain wirklich hierher führt.** Bei jedem Eintrag steht ein
Knopf **Prüfen**. Er geht den Weg der Scanner nach und meldet vier Dinge:
| Schritt | Was er sagt |
| --- | --- |
| DNS | ob der Name auflöst, und auf welche Adressen |
| Zertifikat | gültig bis wann, von wem ausgestellt |
| Erreichbar | ob dort ein Webserver antwortet, und wie schnell |
| Ziel | ob dahinter **diese** Installation steht |
Der letzte Schritt ist der eigentliche Wert. Dass irgendwo etwas antwortet,
sagt wenig; die Prüfung lässt sich beweisen, dass es diese Anwendung ist.
Scheitert schon DNS, fallen die drei Folgeschritte aus — dreimal dieselbe
Meldung würde die eine wichtige verdecken.
> **Der Aufruf startet dort, wo der Container läuft.** Bei internem DNS oder
> Hairpin-NAT kann er scheitern, obwohl von außen alles stimmt. Und
> umgekehrt: Ein Erfolg von innen beweist noch nicht, dass die Domain von
> außen erreichbar ist. Dafür bleibt der Blick von einem fremden Netz aus.
---
+54 -2
View File
@@ -315,8 +315,9 @@ Die **Vorschau** wird serverseitig gerendert und aktualisiert sich bei jeder
## Meine Codes
Zeigt alle dynamischen Codes — statische erscheinen nicht, weil sie nicht
gespeichert werden.
Zeigt die dynamischen Codes und die statischen, die abgelegt wurden. Ein
abgelegter statischer Code trägt statt einer Kurz-URL das Abzeichen
„statisch“ und zählt keine Scans.
- **Zwei Ansichten:** Liste (Voreinstellung, eine Zeile je Code) und Karten
mit großer Vorschau. Die Wahl merkt sich der Browser.
@@ -324,6 +325,10 @@ gespeichert werden.
- **Sortierung** nach neueste, älteste, Name oder Scan-Anzahl.
- **Gruppenfilter**, sobald Codes in mehr als einer Gruppe liegen; dann gibt
es auch eine Gruppenspalte.
- **Filter nach Art** (*Alle Arten*, *Nur dynamische*, *Nur statische*),
sobald beide Arten vorkommen. Bei „Nur statische“ verschwindet die
Scan-Spalte und mit ihr die Sortierung danach: Statische zählen keine
Scans, die Spalte wäre eine Reihe aus Strichen.
- **Kurz-URL kopieren** mit einem Klick.
- **Ziel ändern** — die Kurz-URL und damit der gedruckte Code bleiben gültig.
- **Löschen** mit Rückfrage, die den betroffenen Code nennt.
@@ -426,6 +431,53 @@ Domains werden in der Verwaltung angelegt und Gruppen zugeteilt.
Damit das funktioniert, muss der Reverse Proxy jede dieser Domains auf diese
Anwendung leiten.
### Kurzhilfe zur Einrichtung
Was außerhalb der Anwendung einzurichten ist, steht nicht nur im README: Auf
der Domain-Seite öffnet der Knopf **Kurzhilfe** eine Erklärung in sechs
Schritten — DNS-Eintrag, Weiterleitung im Reverse Proxy samt der drei nötigen
Kopfzeilen zum Abtippen, Zertifikat, Registrieren, Gruppenzuteilung,
Nachprüfen. Der Hostname aus `BASE_URL` wird als Beispiel eingesetzt.
Bewusst ein Dialog und kein Dauertext: Die Erklärung braucht man einmal beim
Einrichten und danach nie wieder.
### Prüfen, ob eine Domain hierher führt
Bei jedem Eintrag steht ein Knopf **Prüfen**. Er geht den Weg der Scanner nach
und meldet vier Dinge:
| Schritt | Was geprüft wird |
| --- | --- |
| DNS | Löst der Name auf? Auf welche Adressen? |
| Zertifikat | Gültig, von wem ausgestellt, wie lange noch? |
| Erreichbar | Antwortet dort ein Webserver, und wie schnell? |
| Ziel | Steht dahinter **diese** Installation? |
Der letzte Schritt ist der eigentliche Wert. Dass irgendwo etwas antwortet,
sagt wenig — es könnte die Parkseite des Registrars sein oder eine andere
Installation dieser Anwendung. Deshalb ruft die Prüfung unter der Domain eine
eigene Route auf und lässt sich einen HMAC über eine frische Zufallszahl
zurückgeben. Das Geheimnis dafür entsteht beim ersten Check, liegt in der
Datenbank und verlässt den Server nie.
Die Meldungen sind im Klartext: abgelaufen, selbst ausgestellt, gilt für einen
anderen Namen, Zwischenzertifikat fehlt, Port 443 nimmt nichts an, „es
antwortet etwas, aber nicht diese Anwendung“. Läuft ein Zertifikat in
höchstens 14 Tagen ab, gilt der Schritt als Warnung statt als Erfolg.
Scheitert schon DNS, fallen die drei Folgeschritte aus — dreimal dieselbe
Meldung würde die eine wichtige verdecken.
**Die Grenze der Aussage** steht unter jedem Bericht: Der Aufruf startet dort,
wo der Container läuft. Bei internem DNS oder Hairpin-NAT kann er scheitern,
obwohl von außen alles stimmt; umgekehrt beweist ein Erfolg von innen nicht,
dass die Domain von außen erreichbar ist.
Geprüft wird ausschließlich ein Hostname **aus der Datenbank**, nie einer aus
der Anfrage — sonst wäre die Route ein Werkzeug, mit dem sich vom Server aus
beliebige Adressen abklopfen ließen. Näheres in
[sicherheit.md](sicherheit.md).
---
## Erscheinungsbild
+24 -38
View File
@@ -15,8 +15,13 @@ Fußzeile.
Kurz gefasst: Version 1.0.0 (13.08.2026) brachte das Grundgerüst mit dem Typ
Website, 1.1.0 alle fünfzehn Typen samt Anmeldung, Gruppen und Domains,
1.2.0 Single Sign-on und die Sicherheitsdurchsicht, 1.3.0 Erscheinungsbild
und Dark Mode, 1.4.0 sprechende Kurz-Links, 1.5.0 benennbare statische Codes
und 1.6.0 diesen Versionshinweis.
und Dark Mode, 1.4.0 sprechende Kurz-Links, 1.5.0 benennbare statische Codes,
1.6.0 den Versionshinweis und 1.7.0 sechs Erweiterungen auf einmal — Logo im
Code, Freigabe je Gruppe, Domain-Check, Dublettenprüfung, Filter nach Art und
die Kurzhilfe zu den Domains.
Damit sind zwei Punkte erledigt, die hier lange unter „Als Nächstes“ standen:
**QR-Typen je Gruppe freigeben** und **Logo im QR-Code**.
---
@@ -25,27 +30,7 @@ und 1.6.0 diesen Versionshinweis.
In dieser Reihenfolge. Die Einschätzungen sind grobe Hausnummern für eine
Person, die den Code kennt.
### 1. QR-Typen je Gruppe freigeben · mittel
Heute gilt die Freigabe eines Typs für die ganze Installation: Was
abgeschaltet ist, ist für alle weg. Bei mehreren Gruppen ist das zu grob — die
Marketingabteilung braucht Social Media, die Werkstatt nur Website und PDF.
Geplant: Die Freigabe bekommt eine zweite Dimension. Es bleibt eine globale
Einstellung als Grundlage, und je Gruppe lässt sich davon abweichen. Wer in
mehreren Gruppen ist, sieht auf der Startseite die Vereinigung; beim Anlegen
entscheidet die gewählte Gruppe.
Zu klären ist der Fall, in dem ein Typ global aus, in einer Gruppe aber an
ist — entweder die Gruppe darf das überstimmen, oder die globale Abschaltung
gewinnt immer. Die zweite Lesart ist die weniger überraschende und
wahrscheinlich die richtige.
Berührt: `QrTypeSetting` (zusammengesetzter Schlüssel aus Typ und Gruppe),
`src/lib/qr/availability.ts`, die Startseite und die Typ-Verwaltung, die dann
eine Gruppenauswahl bekommt.
### 2. Statistik über die Zeit · mittel
### 1. Statistik über die Zeit · mittel
Der Zähler weiß heute nur, wie oft und wann zuletzt. Gebraucht wird der
Verlauf: Wie lief die Kampagne in den ersten Tagen, wann ist Ruhe
@@ -59,7 +44,7 @@ sagt nichts über einzelne Menschen aus und braucht deshalb weder Einwilligung
noch Löschfristen. Wer mehr will, muss sich mit beidem befassen — das ist eine
andere Entscheidung als „ein Diagramm wäre schön“.
### 3. Papierkorb statt Löschen · klein
### 2. Papierkorb statt Löschen · klein
Heute ist ein gedruckter Code nach einem Fehlklick unwiederbringlich tot,
samt seiner Dateien und Rückmeldungen.
@@ -69,20 +54,7 @@ Geplant: Gelöschte Codes 30 Tage aufheben und dann endgültig entfernen. In
im Papierkorb liegt, bleibt sein Slug belegt — sonst könnte ihn ein neuer Code
bekommen und die gedruckten Codes zeigten plötzlich woandershin.
### 4. Logo im QR-Code · mittel
Ein kleines Bild in die Mitte setzen, wie man es von Firmen-Codes kennt.
Geplant: Upload eines Logos je Code, mittig eingesetzt, mit erzwungener
Fehlerkorrektur **H** und einer Warnung, sobald zu viel Fläche verdeckt wird.
Das ist der Punkt mit dem größten Risiko, etwas Kaputtes auszuliefern: Ein
Code, der auf dem eigenen Handy noch funktioniert, kann bei anderen
Scanner-Apps durchfallen. Gehört deshalb nicht ohne eine ehrliche Prüfung mit
mehreren Geräten und Apps ausgeliefert — und mit einer klaren Obergrenze für
die verdeckte Fläche.
### 5. Ablaufdatum und Zeitsteuerung · mittel
### 3. Ablaufdatum und Zeitsteuerung · mittel
Ein Code, der ab einem Datum woandershin führt oder abläuft — für
Veranstaltungen, Aktionen und Aushänge mit Verfallsdatum.
@@ -99,6 +71,20 @@ Geplant, in zwei Stufen:
Zu bedenken: Zeitzonen und die Frage, was beim Bearbeiten mit vergangenen
Fenstern geschieht.
### 4. Gestaltung eines gespeicherten Codes ändern · klein
Aufgefallen beim Einbau des Logos: In „Meine Codes“ lässt sich die Gestaltung
eines abgelegten Codes gar nicht mehr anfassen — weder Farben noch Größe noch
Logo. Wer ein Logo nachrüsten will, kommt nur über die Schnittstelle daran.
Bei einem **dynamischen** Code ist das unnötig streng: Das gedruckte Bild
bleibt zwar, wie es ist, aber der erneute Download soll ja gerade die neue
Gestaltung tragen. Geplant: derselbe Gestaltungsbereich wie im Generator, im
Bearbeiten-Dialog.
Bei einem **statischen** Code bleibt es beim Nein — er ist ein Schnappschuss,
und eine geänderte Gestaltung ergäbe ein anderes Bild als das gedruckte.
---
## Später denkbar