diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c7de80..d6c173b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ Versionsnummer in der Fußzeile. > Diese Datei wird erzeugt: `npm run changelog`. > Gepflegt wird der Verlauf in `src/lib/changelog.ts`. +## 1.7.0 — 21.08.2026 + +Logo im Code, Freigabe je Gruppe und ein Domain-Check. + +- Ein Logo in der Mitte des Codes — das der Installation oder ein eigenes je Code, 10 bis 25 % der Kantenlänge. Die Fehlerkorrektur springt dabei auf H. +- QR-Typen lassen sich je Gruppe freigeben. Die Grundeinstellung bleibt die Grundlage; eine globale Abschaltung gewinnt immer. +- Der Knopf „Prüfen“ bei jeder Domain meldet DNS, Zertifikat, Erreichbarkeit — und ob dahinter wirklich diese Installation steht. +- Eine Kurzhilfe auf der Domain-Seite führt in sechs Schritten auf, was für eine neue Domain einzurichten ist. +- „Meine Codes“ lässt sich nach Art filtern: alle, nur dynamische, nur statische. +- Beim Ablegen eines statischen Codes wird gewarnt, wenn derselbe Inhalt schon in der Gruppe liegt. + ## 1.6.0 — 21.08.2026 Sichtbare Version mit Änderungsverlauf. diff --git a/README.md b/README.md index 32a6d5d..70032ce 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,18 @@ entscheidet die Verwaltung — nicht gebrauchte lassen sich ausblenden. Fehlerkorrektur L/M/Q/H, einstellbarer Rand. Download als PNG und SVG. - **Logo in der Mitte:** das Logo der Installation oder ein eigenes je Code, 10–25 % der Kantenlänge, mit erzwungener Fehlerkorrektur H. -- **Meine Codes:** Liste oder Karten, Suche, Sortierung, Gruppenfilter, - Ziel ändern, löschen. Statische Codes lassen sich auf Wunsch mit Namen - ablegen, um sie wiederzufinden. +- **Meine Codes:** Liste oder Karten, Suche, Sortierung, Filter nach Gruppe + und nach Art, Ziel ändern, löschen. Statische Codes lassen sich auf Wunsch + mit Namen ablegen; liegt derselbe Inhalt schon dort, wird gewarnt. - **Feedback auswerten:** Durchschnitt, Verteilung und Kommentare — anonym erhoben, ohne Name und IP-Adresse. - **Anmeldung abschaltbar.** Mit Anmeldung: Benutzer, Gruppen und die Rollen Administrator, Bearbeiter und Betrachter. -- **Mehrere Domains** für Kurz-URLs, den Gruppen zugeteilt. +- **Mehrere Domains** für Kurz-URLs, den Gruppen zugeteilt — mit Kurzhilfe + zur Einrichtung und einer Prüfung, ob eine Domain wirklich hierher führt. - **Single Sign-on** über Authentik oder einen anderen OIDC-Anbieter. -- **Typen abschaltbar:** Was ihr nicht braucht, erscheint gar nicht erst. +- **Typen abschaltbar:** Was ihr nicht braucht, erscheint gar nicht erst — + für die ganze Installation oder je Gruppe. - **Eigenes Erscheinungsbild:** Name, Logo, Favicon und Akzentfarbe im Admin-Bereich einstellbar. - **Hell und dunkel:** folgt dem Betriebssystem, mit Umschalter für eine @@ -609,7 +611,7 @@ Zwei Eigenschaften sind dabei zu unterscheiden: | | Bedeutung | Woher | | --- | --- | --- | -| **umgesetzt** | Der Typ ist ausprogrammiert. In Version 1 gilt das nur für „Website“. | Registry im Code | +| **umgesetzt** | Der Typ ist ausprogrammiert. Seit 1.1.0 gilt das für alle fünfzehn. | Registry im Code | | **freigegeben** | Die Verwaltung zeigt den Typ an. | Datenbank, jederzeit änderbar | Nur umgesetzt **und** freigegeben heißt benutzbar. Freigegeben, aber nicht @@ -673,7 +675,10 @@ Kurz-URL rückt dann unter den Namen. Zum Herunterladen dient dort die Kartenansicht. Abgelegte **statische Codes** stehen mit in der Liste, tragen aber ein -Abzeichen „statisch“ statt einer Kurz-URL und zählen keine Scans. Steht der +Abzeichen „statisch“ statt einer Kurz-URL und zählen keine Scans. Beim +Ablegen läuft eine **Dublettenprüfung**: Liegt in derselben Gruppe schon ein +statischer Code mit identischem Inhalt, hält das Ablegen an und nennt ihn — +eine Rückfrage mit dem Knopf „Trotzdem ablegen“, keine Sperre. Verglichen wird nur der Inhalt, nicht die Gestaltung. Steht der Filter auf „Nur statische“, fällt die Scan-Spalte weg und die Sortierung nach Scans mit ihr — bei einer Liste aus lauter Nullen sagt sie nichts. @@ -1017,6 +1022,8 @@ deutschen Meldung. | `GET` | `/r/{slug}` | Weiterleitung, erhöht den Scan-Zähler | | `GET` | `/api/admin/types` | Zustand aller QR-Typen (`?group={id}` je Gruppe) | | `PATCH` | `/api/admin/types` | Typ freigeben oder abschalten (`groupId` optional) | +| `POST` | `/api/admin/domains/{id}/check` | Domain prüfen: DNS, Zertifikat, Erreichbarkeit, Ziel | +| `GET` | `/api/domain-check` | Beweis für die Domain-Prüfung (`?nonce=…`, ohne Anmeldung) | Beispiel: diff --git a/docs/anleitung.md b/docs/anleitung.md index 7354a98..e6f8319 100644 --- a/docs/anleitung.md +++ b/docs/anleitung.md @@ -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. --- diff --git a/docs/funktionen.md b/docs/funktionen.md index 88387e5..95a03ed 100644 --- a/docs/funktionen.md +++ b/docs/funktionen.md @@ -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 diff --git a/docs/roadmap.md b/docs/roadmap.md index 85d1092..99516f0 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -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 diff --git a/package.json b/package.json index e840a46..6950f1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qrcode-generator", - "version": "1.6.0", + "version": "1.7.0", "private": true, "scripts": { "dev": "next dev", diff --git a/src/components/domain-hilfe.tsx b/src/components/domain-hilfe.tsx index 11c19e7..ea4832f 100644 --- a/src/components/domain-hilfe.tsx +++ b/src/components/domain-hilfe.tsx @@ -98,13 +98,21 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;`} -

Von außerhalb des eigenen Netzes:

+

+ Dafür gibt es den Knopf Prüfen bei jedem Eintrag + in der Liste. Er meldet DNS, Zertifikat, Erreichbarkeit — und ob + hinter der Domain wirklich diese Installation steht. +

+

+ Der Aufruf startet dort, wo dieser Container läuft. Bei internem + DNS oder Hairpin-NAT kann er scheitern, obwohl von außen alles + stimmt. Von einem fremden Netz aus hilft dann: +

{`curl -I https://${beispiel}/`}

- Kommt eine Antwort dieser Anwendung, stimmen DNS, Proxy und - Zertifikat. Danach einen Code der zugeteilten Gruppe anlegen, die - Domain auswählen und den fertigen Code einmal mit dem Handy - scannen — das ist die einzige Prüfung, die wirklich zählt. + Zum Schluss einen Code der zugeteilten Gruppe anlegen, die Domain + auswählen und den fertigen Code einmal mit dem Handy scannen — das + ist die einzige Prüfung, die wirklich zählt.

diff --git a/src/lib/changelog.ts b/src/lib/changelog.ts index d6d8c5e..047544e 100644 --- a/src/lib/changelog.ts +++ b/src/lib/changelog.ts @@ -8,10 +8,10 @@ import pkg from "../../package.json"; * unweigerlich auseinander; eine Prüfung wacht darüber, dass die erzeugte * Datei zu dieser Quelle passt. * - * Die Einträge sind aus dem Abschnitt „Gebaut“ der Roadmap und der - * Git-Historie zusammengetragen. Versionsnummern gab es dabei nie — es - * existieren keine Tags —, deshalb ist je **Erscheinungstag** eine Version - * gebildet. Das ist nachträglich vergeben, aber die Daten selbst stimmen. + * Die Einträge bis 1.5.0 sind aus dem Abschnitt „Gebaut“ der Roadmap und der + * Git-Historie zusammengetragen: Versionsnummern gab es damals nicht, deshalb + * ist je **Erscheinungstag** eine gebildet. Nachträglich vergeben, aber die + * Daten selbst stimmen. Ab 1.6.0 trägt jede Fassung einen Git-Tag. */ export type ChangelogEntry = { version: string; @@ -23,6 +23,19 @@ export type ChangelogEntry = { }; export const CHANGELOG: readonly ChangelogEntry[] = [ + { + version: "1.7.0", + date: "2026-08-21", + summary: "Logo im Code, Freigabe je Gruppe und ein Domain-Check.", + changes: [ + "Ein Logo in der Mitte des Codes — das der Installation oder ein eigenes je Code, 10 bis 25 % der Kantenlänge. Die Fehlerkorrektur springt dabei auf H.", + "QR-Typen lassen sich je Gruppe freigeben. Die Grundeinstellung bleibt die Grundlage; eine globale Abschaltung gewinnt immer.", + "Der Knopf „Prüfen“ bei jeder Domain meldet DNS, Zertifikat, Erreichbarkeit — und ob dahinter wirklich diese Installation steht.", + "Eine Kurzhilfe auf der Domain-Seite führt in sechs Schritten auf, was für eine neue Domain einzurichten ist.", + "„Meine Codes“ lässt sich nach Art filtern: alle, nur dynamische, nur statische.", + "Beim Ablegen eines statischen Codes wird gewarnt, wenn derselbe Inhalt schon in der Gruppe liegt.", + ], + }, { version: "1.6.0", date: "2026-08-21", diff --git a/src/lib/qr/availability.ts b/src/lib/qr/availability.ts index f0e40a3..422aacf 100644 --- a/src/lib/qr/availability.ts +++ b/src/lib/qr/availability.ts @@ -17,7 +17,8 @@ import { * Zwei voneinander unabhängige Eigenschaften bestimmen, was ein Typ kann: * * - `implemented` — steht in der Registry und sagt, ob der Typ überhaupt - * ausprogrammiert ist. In V1 gilt das nur für „Website“. + * ausprogrammiert ist. Seit 1.1.0 gilt das für alle fünfzehn; die + * Unterscheidung bleibt für Typen, die später dazukommen. * - `enabled` — kommt aus der Datenbank und sagt, ob die Verwaltung den Typ * freigegeben hat. Fehlt der Eintrag, ist der Typ freigegeben. *