• v1.1.1 20c2d206f8

    v1.1.1 - Sicherheits- und Robustheitskorrekturen
    Docker-Image bauen / build (push) Successful in 1m53s
    Stable

    Stefan released this 2026-09-14 17:32:00 +02:00 | 0 commits to main since this release

    Sicherheit

    • X-Forwarded-For wird nur noch dem eingetragenen Reverse-Proxy geglaubt
      (vorher jedem Absender). Damit liess sich pro erfundener IP ein
      frischer Rate-Limit-Zaehler holen - und die Limits sind das Einzige
      vor dem frei zugaenglichen Reservieren-Endpunkt.

    WICHTIG BEIM UPDATE: In docker-compose.betrieb.yml die neue Variable
    FORWARDED_ALLOW_IPS auf die Adresse des Proxys setzen (Kommentar dort
    erklaert, welche das ist). Ohne den Wert laeuft alles weiter, aber alle
    Besucher teilen sich die Rate-Limits ueber die Proxy-IP.

    Korrekturen

    • Reservieren ist jetzt atomar: Bei zwei gleichzeitigen Anfragen aufs
      selbe Stueck gewinnt genau eine Person - vorher konnte die zweite
      Name und Token der ersten stillschweigend ueberschreiben.
    • /?limit=abc lieferte einen internen Serverfehler; jetzt faellt der
      Wert auf die Seitengroesse zurueck.
    • Erfassen/Bearbeiten: unsinnige Eingaben ergeben eine Fehlermeldung
      statt eines 500ers, und Bilder werden erst nach bestandener Pruefung
      gespeichert (keine verwaisten Dateien mehr).

    Vier neue Tests decken genau diese Faelle ab (Suite: 85 Tests).

    Downloads
  • v1.1.0 f3ac3d526e

    v1.1.0 - Komprimierung, Cache und Sicherung
    Docker-Image bauen / build (push) Successful in 1m44s
    Stable

    Stefan released this 2026-09-14 04:36:16 +02:00 | 4 commits to main since this release

    Schnellere Seiten

    Die Seiten werden jetzt komprimiert ausgeliefert. Die Startseite schrumpft
    von 9725 auf 1900 Byte — rund 80 % weniger, spürbar vor allem über
    Mobilfunk.

    Dazu bekommen die mitgelieferten Dateien wie htmx.js eine Cache-Dauer,
    statt bei jedem Aufruf neu angefragt zu werden.

    Sicherung von Datenbank und Fotos

    Neu liegt ein sicherung.sh bei. Es sichert die Datenbank zusammen mit
    den Fotos
    — eine Datenbank ohne die Bilder wäre wertlos, und Bilder ohne
    Datenbank wären ein Haufen Dateien mit zufälligen Namen.

    Der erzeugte Stand wird gleich nachgeprüft: Lässt sich die Kopie öffnen, und
    ist zu jedem Eintrag das zugehörige Foto vorhanden? Voreingestellt bleiben
    sieben Stände erhalten.

    Das ist bei dieser App wichtiger als bei anderen: Was hier verloren geht,
    lässt sich nicht neu importieren.

    Unverändert

    81 automatische Tests, alle grün.

    Downloads
  • v1.0.0 e0212cfa2c

    Version 1.0.0 – Kinderkleider-Börse
    Docker-Image bauen / build (push) Successful in 1m7s
    Stable

    Stefan released this 2026-08-30 15:00:54 +02:00 | 7 commits to main since this release

    Zu klein gewordene Kinderkleidung fotografieren, in einer Galerie zeigen und an Familie, Freunde und Nachbarn weitergeben. Wer etwas brauchen kann, reserviert es mit einem Klick – ohne Konto, ohne Anmeldung.

    Erfassen

    Fürs Smartphone gedacht. Der schnelle Weg für den Erstbestand: zuerst alles mit der gewohnten Kamera-App fotografieren, dann alle Fotos auf einmal hochladen. Pro Foto entsteht ein Entwurf, die Angaben trägst du danach in Ruhe nach – auch am Rechner mit richtiger Tastatur.

    Beim Abarbeiten einer Kiste werden Grösse, Kategorie, Saison und Zustand vom zuletzt gespeicherten Teil übernommen. Meist bleibt nur der Titel zu ändern – und der ist freiwillig: ohne ihn steht dort automatisch Kategorie und Grösse, also zum Beispiel „Jacken 98/104". Wird die Grösse später korrigiert, ändert sich der Titel mit.

    Mitgeliefert sind 10 Kategorien und 53 Grössen, von Babygrössen über Konfektionsgrössen bis zu Schuhnummern.

    Reservieren

    Besucher brauchen kein Konto. Nach dem Reservieren erscheint ein Link, mit dem sich die eigene Reservierung wieder aufheben lässt – dieser Link sollte aufbewahrt werden. Ohne ihn kann nur der Betreiber sie lösen; so kann niemand fremde Reservierungen löschen.

    Der Name der reservierenden Person erscheint nicht in der Galerie, dort steht nur „reserviert". Sichtbar ist er ausschliesslich nach der Anmeldung.

    Fotos

    Beim Hochladen wird geprüft, ob es sich überhaupt um ein Bild handelt – die Endung entscheidet nicht. Anschliessend wird auf 1200 Pixel Breite verkleinert und nach WebP gewandelt.

    Dabei fallen die EXIF-Daten weg. Bei Handyfotos stehen dort oft die GPS-Koordinaten der Wohnung. Die Drehung wird vorher auf das Bild angewendet, damit Hochkant-Aufnahmen nicht quer liegen. Aufnahmen von iPhones (HEIC) werden unterstützt.

    Darstellung

    Mobile zuerst, mit Tippflächen von mindestens 44 Pixeln. Helle und dunkle Darstellung folgen der Systemeinstellung und lassen sich über einen Knopf umschalten.

    Betrieb

    Die Anwendung ist für den Betrieb hinter einem Reverse-Proxy mit HTTPS gedacht.

    Ohne gesetztes ADMIN_PASSWORD bleibt der Erfassungsbereich gesperrt – die Galerie funktioniert trotzdem. Absichtlich wird kein Passwort mitgeliefert: ein solches stünde in der Anleitung und wäre damit allgemein bekannt.

    Reservieren ist ohne Anmeldung möglich, deshalb ist es auf 5 Vorgänge pro Stunde und IP begrenzt; Anmeldeversuche auf 10. Die Galerie ist frei zugänglich, wird aber per noindex und robots.txt von Suchmaschinen ferngehalten – sonst wären Fotos und Texte noch auffindbar, wenn die Börse längst abgeräumt ist.

    Alles, was nicht im Code steht, liegt in zwei Volumes: /data (Datenbank) und /uploads (Fotos).

    Einrichten

    Eine Datei docker-compose.yml anlegen mit dem Inhalt von docker-compose.betrieb.yml, darin ein eigenes Passwort und einen SECRET_KEY eintragen:

    docker run --rm python:3.11-slim python -c "import secrets; print(secrets.token_urlsafe(48))"
    

    Dann:

    docker compose up -d
    

    Erreichbar unter http://localhost:8090. Einzelheiten stehen in der README.

    Noch nicht enthalten

    • Keine Benachrichtigung, wenn jemand etwas reserviert – man muss selbst nachsehen.
    • Keine Zuordnung zu einzelnen Kindern oder Jahrgängen.

    Technisch

    FastAPI mit SQLite, Jinja2 und HTMX, Tailwind wird beim Bauen über die Standalone-Binärdatei übersetzt – kein Node.js nötig. Ein Dienst, eine Datenbankdatei.

    Fremde Bestandteile (HTMX, Swagger) liegen im Image statt von einem CDN geladen zu werden: die Content-Security-Policy erlaubt nur eigene Skripte, und ein CDN-Aufruf gäbe die IP-Adresse jedes Besuchers an einen Dritten weiter.

    81 automatische Tests; das fertige Image wird vor der Veröffentlichung geprüft.

    Downloads