feat(backend): Master-Passwort fuer die Dokumentenliste (Schritt 5)

GET /documents listet alle Dokumente und machte damit jede UUID auffindbar —
das Zugriffsmodell "unerratbarer Link" waere hinfaellig. Der Endpunkt
verlangt jetzt HTTP Basic; alles andere bleibt bewusst offen.

Ohne konfigurierten Hash ist die Liste ausdruecklich gesperrt (denyAll),
nicht offen: Ein vergessener Umgebungswert gaebe sonst jede UUID preis, und
niemandem fiele es auf, weil alles funktioniert. Bewusst als Regel und nicht
bloss als zufaelliges Passwort, das niemand kennt — der Unterschied ist
pruefbar: Mit dem Zufallspasswort blieb die Gegenprobe stumm, mit denyAll
faellt genau die danach benannte Zusicherung.

Die Sperre nach Fehlversuchen ist global statt je Adresse: Es gibt genau ein
Passwort, und hinter dem Reverse Proxy der Zielumgebung saehe der Server
ohnehin fuer alle dieselbe Adresse. Preis benannt (D76-Nachtrag 6).

135 Tests. Gegenproben: Schutz entfernt, Sperre entfernt, Voreinstellung
geoeffnet -> es faellt jeweils genau die danach benannte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-26 17:30:10 +02:00
co-authored by Claude Opus 5
parent 741b41ef11
commit bc8850a518
16 changed files with 544 additions and 18 deletions
@@ -27,6 +27,13 @@ paths:
tags: [Documents]
operationId: listDocuments
summary: Alle Dokumente auflisten
description: >
Verlangt das Master-Passwort (HTTP Basic, Benutzer `werkbaum`).
Ohne diesen Schutz waere jede Dokument-UUID auflistbar - und das
Zugriffsmodell "unerratbare UUID" damit hinfaellig. Nach mehreren
Fehlversuchen wird der Endpunkt fuer eine Weile gesperrt (429).
security:
- masterPassword: []
responses:
"200":
description: Liste aller Dokumente
@@ -36,6 +43,10 @@ paths:
type: array
items:
$ref: "#/components/schemas/Document"
"401":
description: Master-Passwort fehlt oder ist falsch
"429":
description: Zu viele Fehlversuche; `Retry-After` nennt die Restdauer
post:
tags: [Documents]
operationId: createDocument
@@ -570,6 +581,14 @@ components:
type: string
securitySchemes:
masterPassword:
type: http
scheme: basic
description: >
Master-Passwort fuer die Dokumentenliste. Der Hash liegt serverseitig
in einer Umgebungsvariable (`werkbaum.master-password.hash`); ist er
nicht gesetzt, bleibt die Liste gesperrt.
bearerAuth:
type: http
scheme: bearer