Reviewer-facing document derived from ADR 0019: per base function (encryption, media protection, network termination, authentication, integrity) what the application does, what it deliberately does not, and which party provides it — every claim traceable to code via the ist-aufnahme. Includes the operator-duty handover (with the IndexedDB endpoint copy named explicitly, I-25) and the delta list mapping every divergence from the target state to its closing issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Ph5uBmHm8X28CSVpbpnJ
20 KiB
Abgrenzungserklärung nach §52 VSA — Dorfteich
Liefergegenstand zu Issue #226 (Meilenstein
M30, compliance documentation). Grundlage: ADR 0019 (Entwurfsfassung dieser Erklärung); bei inhaltlicher Abweichung wird zuerst das ADR geändert, dann diese Erklärung nachgezogen — nie umgekehrt. Code-Stand der Belege:main=fd07f71(Prod v0.12.0); Fundorte in der Formdatei:zeilebeziehen sich auf diesen Stand und sind indocs/vs-nfd/10-ist-aufnahme.mdausführlich hergeleitet. Status: Entwurf zur Prüfung. Die juristische Prüfung durch einen Rechtsbeistand steht aus und ist nicht Teil dieses Dokuments.
1. Zweck und Adressat
Dorfteich soll in einer nach der Verschlusssachenanweisung (VSA) freigegebenen IT-Umgebung einer Behörde betrieben werden können, für Inhalte bis einschließlich VS-NUR FÜR DEN DIENSTGEBRAUCH (VS-NfD). Eine BSI-Zulassung von Dorfteich selbst wird nicht angestrebt.
§51 VSA unterwirft IT-Produkte, die eine Sicherheitsgrundfunktion erbringen, der Zulassungspflicht. §52 VSA benennt diese Grundfunktionen: Verschlüsselung, Datenträgerschutz, Netzabschluss und Authentisierung. Diese Erklärung legt dar, dass Dorfteich keine dieser Grundfunktionen selbst erbringt, welche Partei sie stattdessen erbringt, und wo der heutige Code-Stand dieser Erklärung noch nicht entspricht (Abschnitt 7).
Adressat sind Geheimschutzbeauftragte und IT-Sicherheitsbeauftragte der betreibenden Behörde sowie prüfende Stellen. Die Erklärung ist zugleich die schriftliche Übergabe der Betreiberpflichten (Abschnitt 6): was die Anwendung bewusst nicht leistet, muss die Plattform der Behörde leisten — das ist die Arbeitsteilung, die §52 VSA vorzeichnet, keine Lücke der Anwendung.
2. Geltungsbereich und Betriebsmodell
Die Erklärung gilt für die Anwendung Dorfteich in der
Referenz-Zusammensetzung aus deploy/compose/docker-compose.yml: die
vier eigenen Dienste web, api, collab und backup sowie die Sidecars
PostgreSQL, pandoc und Gotenberg (Caddy optional als Compose-Profil).
Vorausgesetzt wird das Betriebsmodell aus ADR 0019:
- Eine Instanz je Einstufungsniveau. Die Anwendung trennt Einstufungsniveaus nicht selbst; die Trennung geschieht außerhalb der Anwendung durch getrennte Instanzen. Innerhalb einer Instanz kennzeichnet die Anwendung eingestufte Inhalte lediglich (ADR 0022).
- Die Instanz ist Single-Tenant (33 Prisma-Modelle, kein Mandanten-Modell; Ist-Aufnahme I-35) — Teiche sind Container innerhalb einer Instanz, keine Sicherheitsgrenze zwischen Einstufungsniveaus.
- Betrieb in der VS-NfD-Referenzkonfiguration des Härtungsleitfadens (#227): lokale Anmeldung aus, Public-API aus, MCP aus, Feeds aus, Plugins aus, Backup nur lokal.
3. Grundsatz
Dorfteich erbringt keine Sicherheitsgrundfunktion im Sinne von §52 VSA. Verschlüsselung, Datenträgerschutz, Netzabschluss und Authentisierung fallen der Plattform des Betreibers zu (ADR 0019).
Das ist Architektur, nicht Unterlassung: Jede dieser Funktionen in der Anwendung selbst würde Dorfteich zum Träger einer Grundfunktion machen und in die Zulassungspflicht nach §51 VSA ziehen. Die Anwendung hält sich deshalb bewusst frei von Inhaltsverschlüsselung, Backup-Verschlüsselung, eigenem MFA und eigenen Krypto-Primitiven — und jeder künftige Funktionsvorschlag wird an ADR 0019 gemessen, bevor er gebaut wird.
Was die Anwendung an Sicherheit selbst beiträgt, ist ein anderer, ihr zufallender Satz von Eigenschaften (Abschnitt 5): zentrales default-closed-Berechtigungsmodell, vollständige Abwesenheit ausgehender Verbindungen, Kennzeichnung eingestufter Inhalte in jedem Ausgabekanal und ein Audit-Trail.
4. Die Grundfunktionen im Einzelnen
Je Grundfunktion: was die Anwendung tut, was sie bewusst nicht tut, und wer die Funktion erbringt. Jede Aussage ist am Code belegt.
4.1 Verschlüsselung
Was die Anwendung tut. Die vollständige Inventur eigener Krypto-Aufrufe (Ist-Aufnahme, Abschnitt 3.1):
| Zweck | Verfahren | Fundort |
|---|---|---|
| Passwörter | Argon2id (Bibliothek argon2) |
apps/api/src/users/password.ts:9–25 |
| Session-Ids | SHA-256 über das Token | apps/api/src/auth/sessions.service.ts:84 |
| Auth-Tokens (Mail-Flows) | SHA-256 | apps/api/src/auth/auth-tokens.service.ts:55 |
| PATs | SHA-256 | apps/api/src/public-api/api-tokens.service.ts:149 |
| Feed-Tokens | SHA-256 | apps/api/src/public/feed-tokens.service.ts:73 |
| Collab-Tokens (TTL 60 s) | HS256-JWT | packages/shared/src/token-crypto.ts |
| Unsubscribe-Tokens | HMAC-SHA-256 | apps/api/src/notifications/unsubscribe-token.ts |
Sämtliche Verfahren dienen der Absicherung von Zugangsdaten und kurzlebigen Tokens — nirgends im Code werden Inhalte ver- oder entschlüsselt.
Was die Anwendung bewusst nicht tut. Keine Verschlüsselung von
Inhalten in Datenbank oder Dateisystem (Anhänge liegen unverschlüsselt
unter UPLOADS_DIR/<pondId>/<fileId>,
apps/api/src/files/file-storage.service.ts:21,25). Keine
Backup-Verschlüsselung (apps/backup/, ADR 0015, ADR 0026). Keine
TLS-Implementierung. Keine eigenen kryptographischen Primitive über die
obige Tabelle hinaus; die vorhandene Token-Signatur wird auf eine
geprüfte Bibliothek mit zweckgebundenen Schlüsseln umgestellt (ADR 0020,
#188) — eine Verengung bestehender Krypto, keine neue Grundfunktion.
Wer die Funktion erbringt. Die Plattform des Betreibers: Vertraulichkeit ruhender Daten durch Volume- bzw. Festplattenverschlüsselung der Hosts (Datenbank, Upload-Verzeichnis, Backup-Ablage), Transportverschlüsselung durch die vom Betreiber betriebene TLS-Terminierung (Abschnitt 4.3).
4.2 Datenträgerschutz
Was die Anwendung tut. Sie hält die Zahl und Lebensdauer der
Datenkopien klein und benennt sie vollständig (Ist-Aufnahme,
Abschnitt 3.2): Inhalte liegen ausschließlich in PostgreSQL (fünf
Repräsentationen je Seite), Anhänge im Dateisystem, Backups in der
konfigurierten Ablage mit konfigurierbarer Retention. Löschung ist
zweistufig (Papierkorb → Purge-Job), der Seiten-Purge erfasst Anhänge,
Content-Cache, Update-Log und abhängige Tabellen (Ist-Aufnahme I-42).
Der PWA-Service-Worker cached keine Inhalte, nur Build-Assets
(apps/web/vite.config.ts:12–20). Künftig beschränkt die Anwendung,
wohin Backups gehen dürfen (Deploy-Allowlist, leere Liste = nur lokal;
ADR 0026, #192) — mehr nicht.
Was die Anwendung bewusst nicht tut. Keine Verschlüsselung ruhender Daten (s. 4.1), keine sichere Vernichtung physischer Datenträger, kein Schutz der Endgeräte.
Wer die Funktion erbringt. Der Betreiber: Festplatten-/ Volume-Verschlüsselung der Server, Behandlung und Vernichtung von Datenträgern (einschließlich Backup-Medien) nach den Regeln der Behörde, und — ausdrücklich — der Schutz der Endgeräte:
Inhaltskopie auf dem Endgerät (Betreiberpflicht). Jede im Editor geöffnete Seite wird als Yjs-Dokument in die IndexedDB des Browsers gespiegelt (
apps/web/src/editor/use-collab-provider.ts:76, Datenbankdorfteich-page-<pageId>; Ist-Aufnahme I-25). Beim Verlassen der Seite wird die Kopie gelöscht, sobald der Server synchronisiert hat; bei unsynchronisierten Offline-Änderungen bleibt sie absichtlich stehen, und bei einem Browser-Abbruch läuft die Aufräum-Routine nicht. Die Vertraulichkeit dieser Kopie ist Datenträgerschutz des Endgeräts — eine Funktion der Plattform (Endgeräteverschlüsselung, Gerätehärtung nach den VS-NfD-Regeln der Behörde), nicht der Anwendung. Die Anwendung behauptet ausdrücklich nicht, keine Spuren auf Endgeräten zu hinterlassen.
4.3 Netzabschluss
Was die Anwendung tut. Nichts — und das belegbar auch in der
Gegenrichtung: Die Anwendung baut keine Verbindungen nach außen auf.
Jeder ausgehende Aufruf im Code geht an einen internen Sidecar
(PANDOC_URL, GOTENBERG_URL), an den konfigurierten SMTP-Server oder
an das konfigurierte Backup-Ziel (Ist-Aufnahme I-31, mit vollständiger
Fundortliste). Keine Telemetrie, keine Update-Checks, kein Analytics,
kein Crash-Reporting, keine Link-Vorschauen, kein oEmbed, keine externen
Schriften, Karten oder Skripte; drawio ist vendored, Mermaid und
Excalidraw sind gebündelte Workspace-Pakete, und die CSP
default-src 'self' des Web-Tiers würde Nachlader ohnehin blocken.
Was die Anwendung bewusst nicht tut. Keine TLS-Terminierung, keine Netzsegmentierung, keine Firewall-Funktion, kein VPN. Die Dienste bieten unverschlüsseltes HTTP/WebSocket auf ihren Compose-internen Ports an.
Wer die Funktion erbringt. Der Betreiber: Netzabschluss, Zonierung und Zugangskontrolle seines Netzes; TLS-Terminierung am Reverse-Proxy der Behörde. Der Netzplan mit allen Ports und Vertrauensgrenzen ist Gegenstand der Sicherheitsdokumentation (#228); die Vertrauensstellung zum Reverse-Proxy wird in #215 ausgestaltet.
4.4 Authentisierung
Zielbild (das diese Erklärung beschreibt). Authentisierung ist an
den Identity-Provider des Betreibers delegiert (ADR 0021): Anmeldung per
OIDC Authorization Code mit PKCE gegen den IdP der Behörde (#214),
lokale Anmeldung einschließlich Registrierung, Passwort-Reset, PATs und
Feed-Tokens per hartem Schalter auth.local.enabled = false vollständig
abgeschaltet (#216), Gruppen-/Rollen-Mapping aus dem IdP (#217). MFA,
Passwort-Richtlinien und Konto-Lebenszyklus sind damit Sache des IdP.
Was die Anwendung heute tut — und der heutige Stand entspricht dem
Zielbild noch nicht (Ist-Aufnahme I-01/I-02, dort als BLOCKIEREND
bewertet): Es existiert nur die lokale Anmeldung
(Benutzername/Passwort, Argon2id) mit eigener serverseitiger
Session-Verwaltung (Session-Id = SHA-256-Hash des Tokens,
httpOnly/sameSite: lax/secure-Cookie,
apps/api/src/auth/sessions.service.ts, auth.guard.ts:52–58). Eine
OIDC-Anbindung ist vorbereitet (UserIdentity.provider,
apps/api/prisma/schema.prisma:562–577), aber nicht implementiert; die
lokale Anmeldung ist nicht abschaltbar. Bis #214/#216 umgesetzt sind,
ist Dorfteich faktisch Träger der Grundfunktion Authentisierung — die
Delta-Liste (Abschnitt 7) weist das als die wichtigste offene Position
aus.
Was die Anwendung dauerhaft behält. Die Autorisierung (wer darf
welche Inhalte sehen und ändern) bleibt anwendungsseitig — sie ist keine
Grundfunktion nach §52 VSA, sondern Fachlogik: zentrales
default-closed-Berechtigungsmodell mit deny-wins, durchgesetzt über
Guards und abgesichert durch einen Route-Enumeration-Test
(apps/api/src/permissions/; Ist-Aufnahme I-33). Die serverseitige
Session-Haltung bleibt als Sitzungsverwaltung nach erfolgter
Authentisierung ebenfalls bestehen (konfigurierbare Lebensdauer und
Idle-Timeout: #190).
Wer die Funktion erbringt. Der Identity-Provider des Betreibers, einschließlich MFA und aller Credential-Richtlinien. Für Umgebungen mit Client-Zertifikaten oder vorgelagerter Proxy-Authentisierung ist #215 der vorgesehene Pfad.
4.5 Integrität (soweit anwendbar)
Integrität ist in §52 VSA keine eigene Grundfunktion, wird hier aber der Vollständigkeit halber abgegrenzt, weil sie zwischen Plattform und Anwendung geteilt ist:
Bei der Anwendung liegt, was nur sie leisten kann (ADR 0019):
- Kennzeichnung eingestufter Inhalte — nur die Anwendung kennt die Einstufung einer Seite (ADR 0022; Einführung des Metadatums #204/#205, Aufdruck in allen Ausgabekanälen #206–#212).
- Integrität der eigenen Nutzdaten: SHA-256-Prüfsummen auf Anhängen (#199, heute nicht vorhanden — Ist-Aufnahme I-18) und Hash-Pinning für Plugin-Bundles statt Code-Signierung (ADR 0025, #232).
Bei der Plattform liegt die Integrität von Betriebssystem, Container-Runtime, Netz und Datenträgern. Die Reproduzierbarkeit der Auslieferung (Image-Digests #203, Node-Pin #236, Offline-Build #219) ist Zulieferung der Anwendung an die Integritätskette des Betreibers, keine eigene Grundfunktion.
5. Was die Anwendung selbst beiträgt
Die Sicherheitsleistung der Anwendung besteht — neben der Abwesenheit der Grundfunktionen — aus vier Eigenschaften, die sie selbst trägt und belegt:
- Zentrales Berechtigungsmodell, default-closed, deny-wins, mit
Route-Enumeration-Test; auch Export, Suche, MCP und die Collab-Ebene
laufen über den zentralen
PermissionService(Ist-Aufnahme I-33, I-41; unautorisierte Reads antworten 404, Existenz wird versteckt). - Keine ausgehenden Verbindungen außer Sidecars, SMTP und Backup-Ziel (Ist-Aufnahme I-31) — die Grundlage der Airgap-Tauglichkeit, deren empirischer Nachweis als Testlauf #220 geführt wird.
- Kennzeichnung eingestufter Inhalte in jedem Ausgabekanal (ADR 0022, #204–#212 — geplant, s. Delta-Liste).
- Audit-Trail für Authentisierungs- und Administrations-Ereignisse
(
audit_log,apps/api/src/audit/audit.service.ts), künftig mit konfigurierbarer Retention (#196), stabilem Ereigniskatalog für SIEM-Anbindung (#201) und einem zuschaltbaren Lesetrail für eingestufte Inhalte (ADR 0023, #222–#225). Logs gehen als pino-JSON auf stdout mit Redaction vonauthorization/cookie(apps/api/src/app.module.ts:84–93); die Weiterleitung ins SIEM ist bewusst Sache der Container-Runtime des Betreibers.
6. Betreiberpflichten (Übergabe)
Aus der Arbeitsteilung folgt, was der Betreiber leisten muss. Diese Liste ist die schriftliche Übergabe; die Referenzkonfiguration und die Prüf-Checkliste dazu liefert der Härtungsleitfaden (#227):
| Nr. | Pflicht | Grundfunktion |
|---|---|---|
| B1 | Volume-/Festplattenverschlüsselung der Hosts für Datenbank, Upload-Verzeichnis und Backup-Ablage | Verschlüsselung |
| B2 | TLS-Terminierung vor der Anwendung; kein unverschlüsselter Zugriff außerhalb der Compose-internen Netze | Verschlüsselung |
| B3 | Netzabschluss, Zonierung und Zugangskontrolle; Egress-Blockade bis auf SMTP und ggf. Backup-Ziel | Netzabschluss |
| B4 | Identity-Provider einschließlich MFA, Passwort-Richtlinien und Konto-Lebenszyklus (sobald #214/#216 umgesetzt; bis dahin s. Delta-Liste) | Authentisierung |
| B5 | Endgeräteschutz einschließlich Geräteverschlüsselung — Seiteninhalte liegen als IndexedDB-Kopie auf jedem Endgerät, das sie geöffnet hat (s. 4.2) | Datenträgerschutz |
| B6 | Behandlung und Vernichtung von Datenträgern und Backup-Medien nach den Regeln der Behörde | Datenträgerschutz |
| B7 | Betrieb einer Instanz je Einstufungsniveau; keine Mischinstanz | (Betriebsmodell) |
| B8 | Log-Weiterleitung und -Aufbewahrung (stdout → SIEM/Syslog der Behörde) | (Protokollierung) |
| B9 | Betrieb in der VS-NfD-Referenzkonfiguration (#227) und Nachvollzug von Abweichungen | (Konfiguration) |
7. Delta-Liste — wo der heutige Stand dieser Erklärung noch nicht entspricht
Diese Erklärung beschreibt das Zielbild. Am Code-Stand fd07f71 bestehen
folgende Abweichungen; jede ist einem Issue zugeordnet, das sie schließt
(Meilensteine M24–M31, Herleitung docs/vs-nfd/10-ist-aufnahme.md):
| Abweichung vom Zielbild | Befund | Issue |
|---|---|---|
| Lokale Anmeldung ist der einzige und nicht abschaltbare Auth-Pfad — Grundfunktion liegt noch in der Anwendung | I-01, I-02 | #214, #216 |
| IdP-Gruppen-/Rollen-Mapping fehlt | I-01 | #217 |
| Kein Einstufungsmetadatum, kein Aufdruck in irgendeinem Ausgabekanal | I-03, I-04 | #204–#212 |
| Backup-Ziel frei wählbar (keine Allowlist, kein Deploy-Kill-Switch) | I-11 | #192 |
| Ein Secret signiert zwei Token-Zwecke; JWT handgeschrieben statt Bibliothek | I-06, I-07 | #188 |
| CSRF-Origin-Prüfung fail-open bei fehlenden Headern | I-08 | #189 |
| Session 30 Tage gleitend, hart kodiert, ohne Idle-Timeout | I-09 | #190 |
| Feed-Token im Query-Parameter; Feeds nicht abschaltbar | I-10 | #191 |
| Plugins nicht instanzweit abschaltbar | I-19 | #200 |
| Keine Security-Response-Header, CORS-Haltung nicht als Entscheidung dokumentiert | I-16 | #197 |
| Keine Integritäts-Prüfsummen auf Anhängen | I-18 | #199 |
| Kein Plugin-Hash-Pinning | — | #232 |
audit_log ohne Retention; Ereigniskatalog nicht stabil; kein Lesetrail |
I-15, I-20, I-21 | #196, #201, #222–#225 |
| Teich-Papierkorb ohne endgültiges Löschen; Papierkorb-Inhalte im Suchindex | I-12, I-14 | #193, #195 |
| Rohdokument-Bytes und Mail-Outbox unbefristet; Slug-Residuum nach Purge | I-22–I-24 | #233–#235 |
| Container-Images nicht per Digest gepinnt, Node-Version nicht gepinnt, Airgap unverifiziert | I-05, I-26, I-28 | #203, #218–#221, #236 |
Bewusst offene Punkte, die keine Abweichung, sondern akzeptierte Restrisiken sind (z. B. Seitentitel in Logs und Digest-Mails, Slug-Residuum falls in #235 so entschieden), führt die Restrisikoliste (#231) — nicht diese Erklärung.
8. Pflege dieser Erklärung
- Maßgeblich ist ADR 0019; Abweichungen werden dort aufgelöst, diese Erklärung folgt dem ADR.
- Jedes Feature, das die Anwendung zum Träger einer Grundfunktion machen würde, erfordert zuerst eine Änderung von ADR 0019 — und damit dieser Erklärung.
- Die Delta-Liste (Abschnitt 7) wird mit jedem geschlossenen Issue gekürzt; die Erklärung ist erst dann uneingeschränkt gültig, wenn die Delta-Liste leer ist oder alle Restpositionen in der Restrisikoliste (#231) vom Betreiber gebilligt sind.
- Querbezüge: Härtungsleitfaden (#227), Sicherheitsdokumentation (#228), Betriebshandbuch (#229), IT-Grundschutz-Zuarbeit (#230).