Technisch-organisatorische Maßnahmen (TOMs) gemäß Art. 32 DSGVO
Stand: 5. August 2026 | Version: 1.4 | Verantwortlicher: KYTH. Systems UG (haftungsbeschränkt)
1. Vertraulichkeit (Art. 32 Abs. 1 lit. b DSGVO)
1.1 Zutrittskontrolle (physisch)
Maßnahmen, die geeignet sind, Unbefugten den Zutritt zu Datenverarbeitungsanlagen zu verwehren, mit denen personenbezogene Daten verarbeitet oder genutzt werden.
- Hosting in einem nach ISO 27001 zertifizierten Rechenzentrum der IONOS SE in Berlin (Deutschland) — kein eigener Server-Standort des Auftragsverarbeiters.
- Die physische Zutrittskontrolle zum Rechenzentrum liegt bei IONOS. Mit IONOS besteht ein Auftragsverarbeitungsvertrag nach Art. 28 DSGVO; IONOS ist nach ISO 27001 zertifiziert und weist die Einhaltung der Art.-28-Pflichten über diese Zertifizierung nach. Die technisch-organisatorischen Maßnahmen von IONOS werden von IONOS selbst dokumentiert und sind dort einsehbar.
- Es werden keine Datenträger an Mitarbeiter oder Dritte übergeben. Die Serververwaltung erfolgt remote: die Betriebssystem-Ebene über schlüsselbasiertes SSH, die Plattformverwaltung (Coolify) über eine passwortgeschützte Weboberfläche.
1.2 Zugangskontrolle (logisch)
Maßnahmen, die verhindern, dass Datenverarbeitungssysteme von Unbefugten genutzt werden können.
- Shopify-Händler-Zugang: OAuth 2.0 (Shopify-Standard) + Shopify Session Token (JWT HS256) — Multi-Tenant-Isolation pro Shop;
- Admin-Zugang: E-Mail/Passwort-Authentifizierung mit PBKDF2-SHA256 (310.000 Iterationen) für Passwort-Hashing;
- Intranet-/Verwaltungszugang: Benutzername und Passwort,
Sitzungsverwaltung über HMAC-signierte Cookies (
KARL_INTRANET_SECRET), Sperre nach zu vielen Fehlversuchen je IP-Adresse. Zusätzlich ist ein zweiter Faktor (zeitbasiertes Einmalpasswort mit Wiederherstellungscodes) eingerichtet; ist er aktiv, genügt für maschinelle Zugriffe das Passwort nicht mehr, sondern es wird ein eigenes Zugangstoken verlangt; - Programmierschnittstelle: Zugriffe über die Programmierschnittstelle laufen über je Shop erzeugte Schlüssel, die ausschließlich als Hashwert gespeichert werden;
- Datenbank-Zugang: kein Direktzugang aus dem Internet — der Datenbank-Port ist nicht nach außen veröffentlicht, die Verbindung läuft ausschließlich innerhalb des Container-Netzwerks (Coolify); Zugang zum Host nur schlüsselbasiert per SSH;
- SSH-Zugang zum Server: ausschließlich Schlüssel-basiert (kein Passwort-Login), nur Geschäftsführung;
- HMAC-Verifizierung auf allen Shopify-OAuth-Callbacks und GDPR-Webhook-Endpoints (Schutz vor unauthorisierten Webhook-Calls).
1.3 Zugriffskontrolle (Daten)
Maßnahmen, die gewährleisten, dass die zur Benutzung eines Datenverarbeitungssystems Berechtigten ausschließlich auf die ihrer Zugriffsberechtigung unterliegenden Daten zugreifen können.
- Multi-Tenant-Isolation: Jede Tabelle mit personenbezogenen Daten führt
eine
shop_id-Spalte, und die zugehörigen Abfragen filtern darauf. Carrier-Stammdaten, Preistabellen, Zuschlagszonen und Tarifdefinitionen enthalten keine personenbezogenen Daten und werden zentral für alle Shops gepflegt; plattformweite Verwaltungs- und Protokollzeilen tragen bewusst keinen Shop-Bezug; - Per-Request ContextVar: der aktuelle Shop-Kontext wird über Python
contextvars.ContextVarisoliert pro Request gehalten — keine globalen Zustandsvariablen; - Tabellen-Whitelist (
_ALLOWED_TABLES): dynamische Tabellennamen sind ausschließlich gegen eine Whitelist zulässig (Schutz gegen SQL-Injection bei generischer GDPR-Löschung); - Parametrisierte SQL-Queries: ausschließlich
%s-Placeholder, niemals f-string-Interpolation für User-Input; - Zugriffsbeschränkung der Händler-Mitarbeiter: Wer die App im
Shopify-Adminbereich öffnen darf, bestimmt der Händler über die Mitarbeiter-Berechtigungen
seines Shopify-Kontos; jede Anfrage an KARL wird gegen den von Shopify signierten
Session-Token geprüft. Innerhalb dieses Rahmens führt KARL zusätzlich Nutzer-Rollen in
admin_users.role(„admin", „user") — sie steuern den Funktionsumfang der Oberfläche (etwa das Ausblenden von Preisen) und ersetzen nicht die Rechtevergabe in Shopify. Daneben existiert genau eine mandantenübergreifende Betreiber-Rolle (superadmin) ohne Shop-Bindung. Sie wird ausschließlich beim Start der Anwendung aus Umgebungsvariablen angelegt und kann über die Oberfläche nicht vergeben werden. Zugriffe auf Shop-Detaildaten und Löschvorgänge im internen Verwaltungsportal werden inaudit_logmit Aktion, Rolle, Zeitstempel und IP-Adresse protokolliert; - Verschlüsselte Suchfelder: Admin-E-Mail-Adressen liegen verschlüsselt
in der Datenbank; gesucht wird über einen deterministischen HMAC-SHA256-Hash
(
email_lookup_hash) — der Klartext wird dafür nicht zusätzlich gespeichert.
1.4 Trennungskontrolle (separate Verarbeitung)
Maßnahmen, die gewährleisten, dass zu unterschiedlichen Zwecken erhobene Daten getrennt verarbeitet werden können.
- Logische Trennung der Mandanten (Shopify-Händler) auf Datenbankebene über
shop_id; - Sandbox-Modus pro Shop (
shop_settings.sandbox_mode): produktive und Sandbox-Aufträge werden auf Anwendungsebene strikt getrennt — Sandbox erzeugt weder echte Versandetiketten noch echte Carrier-API-Calls;
1.5 Pseudonymisierung (Art. 32 Abs. 1 lit. a DSGVO)
- Empfänger-Name, Firma, Straße, Adresszusatz, E-Mail und Telefon werden mit AES-256-GCM verschlüsselt gespeichert. Land, Postleitzahl, Ort und Region bleiben im Klartext, weil Routing, Zuschlagsprüfung und Carrier-Auswahl auf diesen Feldern filtern;
- Carrier-API-Request-/Response-Logs (
api_request_json,api_response_json) werden ebenfalls verschlüsselt — Klartext-Adressen sind in diesen Logs nicht zugänglich; - Lookups erfolgen für ausgewählte Felder über deterministischen HMAC-Hash
(z. B.
email_lookup_hash) — kein Reverse-Lookup von Pseudonym auf Klartext außerhalb des AES-Keys möglich; - Anwendungs-Logs durchlaufen vor der Ausgabe einen Filter am Root-Logger, der E-Mail-Adressen, Telefonnummern, Zugangstoken und Portal-Links durch Platzhalter ersetzt. Derselbe Filter greift beim Fehler-Protokoll in der Datenbank und beim Fehler-Tracking. Ergänzend gilt die interne Regel, keine personenbezogenen Daten zu protokollieren.
1.6 Verschlüsselung (Art. 32 Abs. 1 lit. a DSGVO)
| Datenart | Methode | Schutzrichtung |
|---|---|---|
| Empfänger-Name, Firma, Straße, Adresszusatz, Telefon, E-Mail | AES-256-GCM (Python cryptography) |
at-rest |
| API-Logs (Carrier-Request/Response) | AES-256-GCM | at-rest |
| Shop-Settings (Absender-PII) | AES-256-GCM auf JSONB-Feld | at-rest |
| Label-PDFs (Base64) | AES-256-GCM | at-rest |
| Shopify OAuth-Tokens | AES-256-GCM | at-rest |
| Carrier-API-Credentials (BYOAK) | AES-256-GCM | at-rest |
| Carrier-Account-Passwörter | AES-256-GCM | at-rest |
| Portokasse OAuth-Tokens | AES-256-GCM | at-rest |
| eBay OAuth-Tokens | AES-256-GCM | at-rest |
| UPS OAuth-Tokens („Mit UPS verbinden") | AES-256-GCM | at-rest |
| Admin-E-Mail + Name | AES-256-GCM (+HMAC-Lookup-Hash) | at-rest |
| Admin-Passwörter | PBKDF2-SHA256, 310.000 Iter., zufälliger Salt pro User | at-rest (one-way) |
| Backups (pg_dump) | GPG AES-256 (symmetrisch, Passphrase-basiert) | at-rest (Backup-Storage) |
| Backups (wal-g WAL) | libsodium AES-256 + lz4-Kompression | at-rest (Backup-Storage) |
| Alle Verbindungen zur Anwendung karl.kyth.systems | TLS 1.2+ (Let's Encrypt via Traefik) | in-transit |
| Database-Connection | Nicht nach außen veröffentlicht; ausschließlich innerhalb des Container-Netzwerks erreichbar. Personenbezogene Felder sind zusätzlich bereits auf Feldebene AES-256-GCM verschlüsselt (siehe Zeilen oben), verlassen die Anwendung also nicht im Klartext. | Netzwerk-Isolation + Feldverschlüsselung |
Schlüsselverwaltung: Der AES-Schlüssel wird ausschließlich als Umgebungsvariable der Deployment-Plattform gehalten und liegt weder im Quellcode noch in der Datenbank. Im Produktivbetrieb ist er zwingend: fehlt er, bricht der Anwendungsserver den Start mit einem Fehler ab (Fail-Closed). Die Schlüsselrotation erfolgt über ein dediziertes Skript mit Alt-/Neu-Schlüssel-Übergangsphase. Ein rotierter Altschlüssel bleibt mindestens so lange verfügbar wie die längste Backup-Aufbewahrung, damit ältere Sicherungen entschlüsselbar bleiben.
2. Integrität (Art. 32 Abs. 1 lit. b DSGVO)
2.1 Eingabekontrolle
Maßnahmen, die gewährleisten, dass nachträglich überprüft und festgestellt werden kann, ob und von wem personenbezogene Daten in Datenverarbeitungssysteme eingegeben, verändert oder entfernt worden sind.
- Audit-Log (
audit_log-Tabelle): jede datenschutzrelevante Aktion (gdpr.shop_redact,gdpr.customer_redact,gdpr.customer_data_request, Löschläufe sowie Eingriffe über das interne Verwaltungsportal) wird mit Zeitstempel, Aktion, betroffenem Shop, handelnder Person (E-Mail verschlüsselt), Rolle, IP-Adresse und Browserkennung protokolliert (Art. 30 Abs. 2 DSGVO); - Sub-Processor-Änderungs-Historie: Änderungen der Sub-Processor-Liste
werden über die versionierte, datierte Sub-Processor-Übersicht
(
/sub-processors+ maschinenlesbarer/api/sub-processors.json-Feed) sowie die Versionshistorie des Dokuments nachvollziehbar dokumentiert; - Versand-Audit-Trail: jedes erstellte Versandetikett wird mit über
50 Feldern protokolliert (
shipments-Tabelle), inklusive vollständiger Carrier-API-Request- und Response-JSONs (verschlüsselt); - Application-Logs: Server-Anwendungs-Logs (Uvicorn) enthalten Timestamp, Request-ID und Endpoint, jedoch keine PII (siehe 1.5);
- Error-Tracking (GlitchTip): automatisches Logging von
Anwendungs-Exceptions inklusive Stack-Trace; PII-Scrubbing über
before_send-Hook inapp.py.
2.2 Schutz vor SQL-Injection und XSS
- Die kundenseitig gerenderten HTML-Seiten (Retouren-Portal, Tracking-Seite, Dokumente,
E-Mails) werden mit Jinja2 bei aktiviertem Autoescape erzeugt; an den wenigen Stellen mit
direkt zusammengesetztem HTML wird
html.escape()eingesetzt; - Content-Security-Policy mit
default-src 'self'und eingeschränkten Skriptquellen (keinunsafe-inlineim Skript-Kontext); zusätzlich HTTP Strict Transport Security,X-Content-Type-Options: nosniff, eine restriktive Referrer-Policy und eine Permissions-Policy.frame-ancestorssteuert die Einbettung im Shopify-Adminbereich; - Regelmäßige interne Security-Reviews (siehe
docs/audit/im Repository).
2.3 Transaktionssicherheit
autocommit=Falsein der Datenbankverbindung — atomare Transaktionen mit explizitem Commit (Pflicht für Multi-Statement-DSGVO-Löschung);- Zeilensperren (
SELECT … FOR UPDATE) bei gleichzeitigen Schreibzugriffen auf Shop-Einstellungen, Druck- und Label-Warteschlange.
3. Verfügbarkeit und Belastbarkeit (Art. 32 Abs. 1 lit. b DSGVO)
3.1 Verfügbarkeit
- Hosting: IONOS VPS L+ (6 vCores, 8 GB RAM, 240 GB NVMe), Berlin, Deutschland — Multi-Tenant-Coolify-Plattform mit Health-Checks;
- HEALTHCHECK: Docker-Healthcheck via curl auf
/health-Endpoint — Coolify überwacht die Verfügbarkeit kontinuierlich; - Hintergrundjobs: APScheduler (Zeitzone UTC) für die DSGVO-Bereinigung täglich um 03:00 und den stündlichen Abrechnungsabgleich. Sendungsstatus werden nicht periodisch abgefragt, sondern beim Aufruf der Tracking-Seite bedarfsgesteuert aktualisiert.
3.2 Belastbarkeit gegen Angriffe
- Rate-Limiting auf API-Ebene;
- Container-Härtung: die Anwendung läuft im Docker-Container als nicht-privilegierter Benutzer;
- Die Qualitäts- und Sicherheitsprüfungen sind in der Build-Konfiguration hinterlegt: Lint (ruff), TypeScript-Baseline, automatisierte Tests (pytest, vitest) sowie statische Sicherheitsanalyse (bandit; Befunde mit hoher Schwere und hoher Konfidenz sind blockierend). Python-Abhängigkeiten werden zusätzlich per CVE-Scan (pip-audit) ausgewertet.
3.3 Wiederherstellbarkeit (Art. 32 Abs. 1 lit. c DSGVO)
- wal-g WAL-Streaming: fortlaufende, bereits auf dem Server verschlüsselte Übertragung der Transaktionsprotokolle nach IONOS S3 (libsodium AES-256, lz4-Kompression). Sie erlaubt die Wiederherstellung auf einen frei wählbaren Zeitpunkt; die Dauer dieser Wiederherstellung ist noch nicht gemessen;
- wal-g daily base backup: 03:00 UTC, 35-Tage-Retention via
wal-g delete retain FULL 35; - Objektsperre (WORM): Der Backup-Bucket ist mit Object Lock im Modus COMPLIANCE (30 Tage) und Versionierung konfiguriert — Schutz gegen Ransomware und nachträgliche Manipulation. Im Modus COMPLIANCE kann die Sperre von niemandem aufgehoben werden, auch nicht vom Kontoinhaber; ein Angreifer mit vollständigem Serverzugriff kann die Sicherungen daher nicht vernichten;
- pg_dump GPG-encrypted Cron:
/opt/karl-backup/backup.sh:pg_dump | gzip | gpg AES256auf IONOS S3, stündlich; - Coolify built-in pg_dump-Backup ist deaktiviert (war nicht client-side encrypted) — Reduktion der Angriffsfläche;
- Wiederherstellungs-Tests: Verfahren, Szenarien und Erfolgskriterien sind in einem
Wiederherstellungsplan dokumentiert (Restore aus letztem Base-Backup + WAL-Replay auf
separater Instanz). Tests sind mindestens halbjährlich vorgesehen und werden mit Datum
und Ergebnis protokolliert. Der erste vollständige Durchlauf wurde am
27.07.2026 durchgeführt: Wiederherstellung aus dem verschlüsselten
Datenbank-Abzug auf eine separate Instanz, anschließend Stichprobenprüfung der
verschlüsselten Felder mit dem produktiven Schlüssel — fehlerfrei, mit protokollierter
Wiederherstellungszeit. Am 04.08.2026 wurde der Test gegen eine 15 Tage alte Sicherung
wiederholt: 94 Tabellen fehlerfrei eingespielt, Einspieldauer 4 Sekunden, 79 von 79
Stichproben mit dem produktiven Schlüssel entschlüsselbar. Die Protokolle liegen im
Repository unter
docs/restore-tests/. Der Wiederherstellungsweg über fortlaufende Transaktionsprotokolle (WAL-Replay) ist eingerichtet, aber noch nicht separat durchgespielt; er ist für den nächsten Turnus vorgesehen.
4. Verfahren zur regelmäßigen Überprüfung (Art. 32 Abs. 1 lit. d DSGVO)
4.1 Regelmäßige Überprüfung der TOMs
- Jährliche oder anlassbezogene Überprüfung der TOMs auf Wirksamkeit und Anpassung an den Stand der Technik;
- Wesentliche Änderungen werden im Audit-Log und im Versions-Header dieses Dokuments dokumentiert;
- Auftraggeber werden über wesentliche Änderungen mit angemessener Vorlauffrist informiert.
4.2 Interne Security-Audits
- Regelmäßige interne Security-Audits (Code-Review, Dependency-Audits, GDPR-Sweep);
- Erkenntnisse werden in
docs/audit/als zeitstempelbenannte Audit-Berichte abgelegt (z. B.2026-04-19-security-gdpr-shopify-audit.md); - Befunde werden nach Schwere klassifiziert und priorisiert behandelt; kritische Befunde werden vorrangig behoben.
4.3 Auftragskontrolle (Art. 28 DSGVO)
- Mit jedem Unterauftragsverarbeiter wird ein eigener AVV nach Art. 28 DSGVO geschlossen. Nicht erfasst sind Empfänger, die die Daten als eigene Verantwortliche verarbeiten — insbesondere die Carrier (siehe AVV, Anlage 1);
- Sub-Processor-Liste (Sub-Processor-Liste) wird öffentlich geführt;
- Änderungen werden mit 30-Tage-Vorlauffrist und Widerspruchsrecht des Auftraggebers kommuniziert (siehe AVV § 6).
4.4 Datenschutz durch Technikgestaltung und durch datenschutzfreundliche Voreinstellungen (Art. 25 DSGVO)
- Datenminimierung: KARL liest aus Shopify ausschließlich die für den Versandprozess erforderlichen Felder (Bestellinhalte, Adressen) — keine Profilbildung, kein Tracking, keine Weitergabe an Dritte zu Werbezwecken;
- Privacy by Design: Pseudonymisierung (Verschlüsselung) ist Default für alle PII-Spalten; ein Opt-out gibt es nicht;
- Privacy by Default: Branded Tracking ist bei Neuinstallation abgeschaltet und muss vom Händler bewusst eingeschaltet werden.
5. Datenträgerverwaltung und Datenträgervernichtung
- Keine physischen Datenträger beim Auftragsverarbeiter — sämtliche Datenhaltung erfolgt auf gemieteten Cloud-Servern (IONOS).
- Bei Außerbetriebnahme der IONOS-Hardware übernimmt IONOS die DSGVO-konforme Datenträgervernichtung (siehe IONOS-AVV).
- Backups im S3-Object-Storage laufen durch die Retention-Policy automatisch aus: die stündlichen verschlüsselten Datenbank-Abzüge nach 30 Tagen; eine zusätzliche lokale Kopie auf dem Server wird nach 7 Tagen gelöscht. Von den täglichen wal-g-Basis-Sicherungen werden die letzten 35 vorgehalten, was bei täglichem Lauf rund 35 Tagen entspricht. Der Bucket ist mit Objektsperre (WORM, Modus COMPLIANCE, 30 Tage) und Versionierung konfiguriert — ein geschriebenes Backup ist in dieser Zeit weder überschreibbar noch löschbar, auch nicht mit gültigen Zugangsdaten und auch nicht durch den Kontoinhaber.
6. Datenpannen-Meldeprozess (Art. 33, 34 DSGVO)
- Bei Bekanntwerden einer Datenpanne wird der betroffene Auftraggeber unverzüglich per E-Mail an die hinterlegte Kontakt-Adresse benachrichtigt (Art. 33 Abs. 2 DSGVO, siehe AVV § 8);
- Parallel wird das Ereignis im internen Incident-Response-Plan
(
docs/incident-response.html) dokumentiert; - Die Meldung an die Aufsichtsbehörde gemäß Art. 33 Abs. 1 DSGVO erfolgt in der Verantwortung des betroffenen Auftraggebers — der Auftragsverarbeiter unterstützt mit allen nötigen Informationen.
7. Verantwortliche Stellen und Aufsichtsbehörde
- Auftragsverarbeiter: KYTH. Systems UG (haftungsbeschränkt), Prof.-Mederer-Str. 4, 92348 Berg, Deutschland;
- Datenschutz-Kontakt: datenschutz@kyth.systems;
- Zuständige Aufsichtsbehörde: Bayerisches Landesamt für Datenschutzaufsicht (BayLDA), Promenade 18, 91522 Ansbach, www.lda.bayern.de;
- Datenschutzbeauftragter: Aufgrund der Unternehmensgröße besteht keine Pflicht zur Bestellung eines DSB nach § 38 BDSG. Datenschutz-Anfragen werden zentral durch die Geschäftsführung beantwortet.