deleteLogo löschte zuerst die Datei und zuletzt die Zeile. Brach es dazwischen ab, blieb eine öffentliche Zeile mit gelöschter Datei stehen: unter
dieser Datei-ID kann jedes Konto im Bucket eine neue Datei anlegen, und alle gespeicherten Karten mit diesem Logo zeigten bis zur Wiederholung deren Bild.
- logos.js: Vor dem Löschen der Datei wird das Logo ausgeblendet wie bei der Admin-Sichtbarkeit (hideLogo: Datei, dann Zeile auf genau die ausgeblendeten
Rechte mit hidden: true; die Rechte der Zeile bleiben die des Hochladers, auch wenn ein Admin löscht). Ein schon ausgeblendetes Logo überspringt das.
Danach wie bisher Datei, Herzen, Meldungen, die Zeile zuletzt. Wer nicht löschen darf (403), ändert nichts. Das Zurückziehen von Karten bleibt unverändert.
- Tests: Reihenfolge (Datei und Zeile ausblenden, Datei, Herzen, Meldungen, Zeile); Abbruch nach dem Löschen der Datei bei „Herzen lesen“, „Meldungen lesen“
und „Zeile löschen“ (Hochlader und Admin): die Zeile bleibt mit genau den ausgeblendeten Rechten, kein Gast liest sie, die Wiederholung vollendet das
Löschen ohne erneutes Ausblenden; scheitert schon das Ausblenden, ist nichts gelöscht; Fremde und schon ausgeblendete Logos lösen kein Ausblenden aus.
- README und Spec: Reihenfolge beim Löschen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Zeilen-ID eines gelöschten Logos steht öffentlich in der Liste und in gespeicherten Karten. War sie die Datei-ID, konnte jeder eine Datei
mit genau dieser ID anlegen, als Logo hochladen und so die alte ID neu belegen: gespeicherte Karten anderer zeigten dann sein Bild.
- logos.js: Zeilen-ID = hash32("<ownerId>|<fileId>") (logoRowId); die Antwort 201 {id} trägt sie. Dieselbe Datei desselben Kontos ergibt dieselbe ID
(409 logoTaken, bei einem Altlogo über die fileId der Zeile); alle anderen Regeln bleiben. Die Logzeilen nennen die Zeilen-ID, die Fehlerzeilen
zusätzlich die Datei-ID (sie folgt nicht mehr aus der Zeilen-ID, und die Zeile ist beim Aufräumen vielleicht schon weg).
- Altlogos (Zeilen-ID = Datei-ID, eines ist live) gehen weiter: Herz, Melden, Löschen und Sichtbarkeit adressieren nur die Zeile und lesen die Datei aus fileId.
- Tests: seedLogo legt Zeile und Datei mit verschiedenen IDs an; neu: logoRowId, die ID eines gelöschten Logos lässt sich nicht neu belegen, anderes Konto
bekommt eine verwendete Datei nicht (403), Altlogo (Herz, Meldung, Ausblenden/Einblenden, Löschen, erneutes Hochladen 409).
- README und Spec: ID-Regel. Der Client (upload-logo.ts) folgt im nächsten Commit; beide gehen zusammen live.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schlussreview F8. Die Dokumentation kannte die Community-Logos, die Herzen, die zweite Sprache und den GitHub-Link noch nicht.
- README.md: Einleitung ohne „Netzwerk-Logo“, neuer Abschnitt „Funktionen“ (Editor, Community-Logos mit Herzen und Moderation,
Galerie, Deutsch/Englisch mit GitHub-Link), Modulübersicht um logos/, community/, i18n/ und shell/ ergänzt und die Routen vervollständigt,
Tabellen und Buckets (cards, gallery, reports, logos, logo_likes, logo_reports; card-images, gallery-images, logo-images), Testbefehle
(API-Tests, Build mit tsconfig.build.json), Hinweis auf die Reihenfolge beim Einführen.
- docs/appwrite-console.md: Schema-Liste (oben, Schritt 5, Abschnitt 7 und 8) mit den Tabellen und dem Bucket der Logos, das Label
`admin` gilt auch für die Logos, die Scopes des Keys `aircard-api` genügen für die Logo-Endpunkte.
- deploy/README.md: neuer Abschnitt „Reihenfolge bei Änderungen an Schema, API und Seite“: 1. Schema (--check, anlegen, noch einmal
prüfen), 2. API (fünf Dateien, Neustart, Prüfung: POST /api/logos/herz ohne JWT ergibt 401 mit code unauthorized, 404 hieße alte
API), 3. erst dann main pushen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Der Key aircard-api braucht in der Console documents.read/documents.write (entspricht rows.* der API) sowie files.read/files.write.
- Der Befehl zum Eintragen des Keys nutzt read -rs, schreibt bei leerer Eingabe nichts und beginnt mit einem Zeilenumbruch
(klebt nie an einer letzten .env-Zeile ohne Umbruch); Hinweis zum Zeilenumbruch auch bei der Eingabe mit nano.
- deploy/README.md: nginx-503 bei fehlendem Dienst, up -d nach .env-Änderung, X-Real-Ip im Docker-Netz als akzeptiertes Risiko.
- Kommentare in server.js und compose-snippet.yml angepasst.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Setup-Skript um Tabellen gallery und reports (Spalten boolean/integer/enum,
Volltext- und Key-Indizes) sowie den Bucket gallery-images erweitert.
DESIRED auf tables/buckets umgebaut, Vergleich je Spaltentyp und Index,
Indizes erst nach available-Spalten. Console-Anleitung um Abschnitt
Community (JWT an, Label admin, Key aircard-api) ergänzt.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Endpoint-Standard ${origin}/v1, echte Projekt-ID im Traefik-Header, Console-
Einstellungen als Soll-Stand statt Tatsache, Test-Befehle je mit Verzeichnis;
Projekt-ID nicht mehr "aircard", Auth-/Dienste-Schritte als optionale Härtung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
web/scripts/appwrite-setup.mjs legt Datenbank aircard, Tabelle cards
(4 Spalten) und Bucket card-images idempotent per fetch an, wartet auf
Spalten-Status available und meldet Abweichungen, ohne sie zu ändern
(--check: nichts anlegen, Exit 1 bei Fehlendem/Abweichendem).
docs/appwrite-console.md ist die Klickliste für Projekt, Plattformen,
Auth, Dienste und API-Key. Tests laufen mit node --test gegen einen
Fake-Appwrite; Vitest nimmt nur src/**/*.test.ts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>