# 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 Form `datei:zeile` beziehen sich auf diesen Stand und sind in > `docs/vs-nfd/10-ist-aufnahme.md` ausfü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//`, `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`, Datenbank > `dorfteich-page-`; 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: 1. **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). 2. **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. 3. **Kennzeichnung** eingestufter Inhalte in jedem Ausgabekanal (ADR 0022, #204–#212 — geplant, s. Delta-Liste). 4. **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 von `authorization`/`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).