Vertrag über die Auftragsverarbeitung (AVV)
nach Art. 28 DSGVO — für die Shopify-App Kartuu
| Fassung | 1.1 |
| Stand | 26.07.2026 |
| Kennung des Zustimmungsnachweises | 1.1-2026-07-26 |
| Gilt für | Kartuu, Shopify-App, https://kartuu.kyth.systems |
| Abgebildeter Entwicklungsstand | Bestellablauf (Quelltextstand 27.07.2026) |
Dieser Entwurf ist nicht anwaltlich geprüft. Der Schlusshinweis am Ende des Dokuments gehört zum Text dazu.
Warum der abgebildete Quelltextstand jünger ist als die Fassung: Fassung 1.1 ist nie ausgeliefert worden und hat deshalb keinen einzigen Zustimmenden — die Begründung steht im Schlusshinweis. Die Kennung bleibt darum unverändert, während der Inhalt dem heutigen Programm nachgeführt wird.
Vertragsparteien
Verantwortlicher
Der Händler, der Kartuu in seinem Shopify-Shop installiert. Er entscheidet über Zwecke und Mittel der Verarbeitung der Daten, die in seinem Shop anfallen.
Der Händler wird gegenüber dem Auftragsverarbeiter durch zwei Angaben identifiziert, die beide beim Vertragsschluss nach § 0 festgehalten werden:
- seine myshopify-Domain — sie bezeichnet den Shop eindeutig und stammt aus dem von Shopify signierten Sitzungsnachweis, ist also nicht frei behauptbar;
- eine E-Mail-Adresse als Kontaktadresse, die der Händler im Zustimmungsschritt selbst angibt (Pflichtfeld, § 2a Nr. 4).
Damit sind Name und Kontaktdaten des Verantwortlichen im Sinne von Art. 30 Abs. 2 lit. a DSGVO führbar. Die vollständigen Firmendaten (Firmierung, Anschrift, Vertretung) erhebt KYTH nicht selbst; sie ergeben sich aus dem Shopify-Konto des Händlers und werden bei Bedarf über die genannte Kontaktadresse erfragt.
Auftragsverarbeiter
KYTH. Systems UG (haftungsbeschränkt) Prof.-Mederer-Straße 4 92348 Berg Deutschland
| Sitz | Berg bei Neumarkt in der Oberpfalz |
| Registergericht | Amtsgericht Nürnberg |
| Registernummer | HRB 46313 |
| Vertreten durch | Stefan Grasse und Stephan Wittmann, jeweils einzelvertretungsberechtigt |
| Kontakt Datenschutz | datenschutz@kyth.systems |
| Kontakt allgemein | hello@kyth.systems · 0157 51603446 |
Datenschutzbeauftragter: Ein Datenschutzbeauftragter ist nicht bestellt. Nach § 38 BDSG besteht dazu bei der derzeitigen Unternehmensgröße keine Pflicht. Zuständige Anlaufstelle für Datenschutzfragen ist datenschutz@kyth.systems; das ist kein Datenschutzbeauftragter im Sinne von Art. 37 DSGVO.
Im Folgenden „KYTH“.
§ 0 Zustandekommen des Vertrages
0.1 Zustimmung im Installationsablauf
Dieser Vertrag kommt dadurch zustande, dass der Händler ihm im Installationsablauf der App zustimmt. Der Ablauf ist folgender:
- Der Händler öffnet Kartuu in seinem Shopify-Adminbereich und löst das Verbinden aus.
- Liegt für die aktuelle Fassung keine Zustimmung vor, führt die App den Vorgang nicht aus, sondern zeigt den Zustimmungsschritt: Verweise auf diesen Vertrag und auf die Datenschutzerklärung, ein Feld für die Kontaktadresse (Pflichtfeld) und ein Zustimmungshäkchen, das nicht vorbelegt ist.
- Erst wenn der Händler beides ausfüllt, wird der Vorgang ausgeführt.
Ohne Zustimmung geschieht nichts. Vor der Zustimmung wird weder ein Datensatz zum Shop angelegt noch ein Zugangstoken bei Shopify abgeholt. Das ist keine Zusage über gute Absichten, sondern die Reihenfolge, in der die App arbeitet: Die Prüfung, ob eine Zustimmung zur aktuellen Fassung vorliegt, steht vor jedem Schreibzugriff und vor jedem Aufruf bei Shopify.
Eine Ausnahme, und zwar eine, die außerhalb der Kontrolle von KYTH liegt. Bei der von
Shopify verwalteten Installation ist die App bereits installiert und sind die Webhooks
bereits abonniert, bevor der Händler die eingebettete Seite überhaupt zum ersten Mal
öffnet. Klickt er den Zustimmungsschritt weg und deinstalliert wieder, sendet Shopify
gleichwohl app/uninstalled; verkauft er in der Zwischenzeit etwas, sendet Shopify auch
orders/paid. Diese signierten Webhooks nimmt KYTH entgegen: Die Shop-Domain wird zum
Suchhash verrechnet, in der Datenbank nachgeschlagen und — wenn kein Shop zu ihr gehört —
für 14 Tage im Anwendungsprotokoll vermerkt. Ein Datensatz zum Shop entsteht dabei nicht,
und auch keine Gutscheinzeile: Ohne Shop-Datensatz gibt es keinen Mandanten, in dem
eine entstehen könnte, und der Inhalt der Bestellung wird nach der Signaturprüfung nicht
weiter ausgewertet. Gespeichert wird lediglich die technische Webhook-Kennung im
Duplikatschutz. Diese Verarbeitung findet also ohne geschlossenen Vertrag statt, und
sie steht deshalb als eigener Fall in Anlage 1 Abschnitt A. Rechtsgrundlage ist Art. 6
Abs. 1 lit. f DSGVO — berechtigtes Interesse daran, einen von Shopify verpflichtend
abonnierten Webhook signaturgeprüft entgegenzunehmen und einen unbekannten Shop nicht
lautlos zu verschlucken —, ergänzend Art. 6 Abs. 1 lit. c DSGVO, soweit die Entgegennahme
der Datenschutz-Webhooks der Erfüllung der Pflichten aus Art. 12 ff. DSGVO dient.
Eine gesonderte Unterschrift ist nicht erforderlich (Art. 28 Abs. 9 DSGVO lässt das elektronische Format ausdrücklich zu).
0.2 Nachweis
KYTH hält den Vertragsschluss in der Datenbank fest — drei Angaben, entweder alle oder keine:
| Angabe | Inhalt |
|---|---|
| wann | Zeitpunkt der Zustimmung, zeitzonenbewusst |
| welche Fassung | die Kennung des Textes, der dem Händler angezeigt wurde, z. B. 1.1-2026-07-26 |
| wer | die vom Händler angegebene Kontaktadresse, verschlüsselt gespeichert |
Die Fassungskennung setzt ausschließlich der Server; eine vom Browser mitgeschickte Angabe bleibt wirkungslos. Andernfalls ließe sich eine Zustimmung zu einer Fassung protokollieren, die dem Händler nie angezeigt wurde — ein Nachweis, der eine Genauigkeit behauptet, die er nicht hat, ist im Streitfall schlechter als keiner.
Der Nachweis überdauert eine Deinstallation. Installiert der Händler die App innerhalb der Frist nach § 9.3 Nr. 1 erneut, muss er nicht erneut zustimmen — seine Zustimmung zu genau dieser Fassung liegt vor. Mit der Löschung des Shops verschwindet auch der Nachweis.
Grenze, offen benannt: Gespeichert wird nur die zuletzt erteilte Zustimmung, keine Historie. Erforderlich wird eine eigene Verlaufstabelle, bevor eine Fassung erhöht wird, zu der bereits ein Händler zugestimmt hat — dann ginge der Nachweis der älteren Zustimmung verloren. Beim Schritt von Fassung 1.0 auf 1.1 war das nicht der Fall: Zu 1.0 lag keine einzige Zustimmung vor, weil die Produktions-App nie ausgerollt war. Bei der nächsten Erhöhung wird es sehr wahrscheinlich zutreffen.
0.3 Geltende Fassung und Änderungen
Der Vertrag gilt in der Fassung, deren Kennung beim Zustimmen festgehalten wurde. Ändert KYTH den Text inhaltlich, erhöht KYTH die Fassungskennung; beim nächsten Öffnen der App wird der Händler erneut um Zustimmung gebeten. Eine reine Berichtigung von Schreibfehlern führt nicht zu einer neuen Kennung — ein Zustimmungsfenster ohne Anlass entwertet die Zustimmung.
Unabhängig davon informiert KYTH den Händler über eine Änderung dieses Vertrages mindestens 30 Tage vor dem Wirksamwerden in Textform an die nach § 2a Nr. 4 hinterlegte Kontaktadresse. Widerspricht der Händler nicht innerhalb von 30 Tagen ab Zugang der Mitteilung in Textform, gilt die neue Fassung als angenommen; widerspricht er, kann jede Partei die Nutzung der App beenden — der Händler durch Deinstallation.
0.4 Veröffentlichung
Beide Dokumente liefert die App unter https://kartuu.kyth.systems/rechtliches/ aus
(/rechtliches/auftragsverarbeitung und /rechtliches/datenschutz), ohne Anmeldung und
aus derselben Quelle, aus der die Fassungskennung stammt. Unabhängig davon stellt KYTH
sie auf Anfrage an datenschutz@kyth.systems bereit.
Bis zum 03.08.2026 war die Auslieferung auf die Testumgebungen beschränkt, weil dieser Vertrag offene Stellen trug: In der Produktivumgebung verweigert die App den Start, statt einen Entwurf wie einen fertigen Vertragstext auszuliefern. Eine Zustimmung zu einem Text, den der Zustimmende nicht lesen kann, ist unwirksam.
Die offenen Stellen sind geschlossen. Der Riegel bleibt als Mechanismus bestehen - er greift wieder, sobald jemand eine neue Stelle öffnet, und das ist seine Aufgabe.
§ 1 Gegenstand, Dauer, Art und Zweck der Verarbeitung
1.1 Gegenstand
KYTH stellt dem Händler die Shopify-App Kartuu zur Verfügung. Kartuu ist dafür bestimmt, aus Bestellungen des Händler-Shops personalisierte Geschenkgutscheine als PDF zu erzeugen und zuzustellen.
Wichtig für das Verständnis dieses Vertrages, und an dieser Stelle grundlegend geändert: Frühere Fassungen sagten hier, von dieser Funktion sei erst der Teil ohne Bezug zu den Daten des Händler-Shops umgesetzt — ein PDF-Erzeuger für Angaben, die der Händler selbst eintippt, ohne Zugriff auf Bestelldaten. Das traf zu, als der Satz geschrieben wurde. Mit dem Bestellablauf trifft es nicht mehr zu.
Umgesetzt ist heute:
- Der Gutschein-Editor im Adminbereich, unverändert: Der Händler tippt Angaben ein und bekommt eine Vorschau und ein PDF zurück. Nichts davon wird gespeichert.
- Die Einrichtung des Gutscheinprodukts im Shop des Händlers, auf seinen Klick hin.
- Der Bestellablauf: Kartuu ist auf den Webhook
orders/paidabonniert. Aus einer bezahlten Bestellung mit einer Gutscheinposition entsteht je gekauftem Stück eine Zeile in der Datenbank — mit den Angaben, die der Kunde im Bestellformular gemacht hat (Empfängername, E-Mail-Adresse des Beschenkten, Absendername, Grußtext), mit der Shopify-Kundennummer des Käufers und mit einem von Kartuu erzeugten Gutscheincode. Bei einem Wertgutschein legt Kartuu damit über die Admin-API eine echte Shopify-Geschenkkarte an. Anschließend wird die Karte gerendert.
Die Zustellung ist umgesetzt — über den Mailserver DES HÄNDLERS. Der Händler hinterlegt in der App unter „Zustellung" seinen eigenen SMTP-Zugang; Kartuu liefert die Mail über diesen Zugang ein. Sie trägt das gerenderte PDF im Anhang und einen Abruflink. Hinterlegt der Händler nichts, verschickt Kartuu für ihn nichts: Der Gutschein wird erzeugt, ist abrufbar und herunterladbar, und der Händler übergibt ihn selbst.
KYTH ist an dieser Stelle kein Verarbeiter. Die Mail an den Beschenkten geht nicht
über einen Versandweg von KYTH und nicht über einen Unterauftragsverarbeiter von KYTH,
sondern über den Mailanbieter, den der Händler selbst gewählt und selbst beauftragt hat.
Ein einziges Konto für alle Händler wäre das Gegenteil und ist im Quelltext ausgeschlossen
(kaspar/config.py führt keine SMTP-Einstellung mehr; kaspar/zustellung/versender.py
kennt keinen Rückfall auf ein Konto der Installation).
Das gerenderte PDF wird nicht gespeichert; es entsteht bei jedem Versand neu. Was Kartuu heute tatsächlich verarbeitet, ist abschließend in Anlage 1 aufgeführt.
Zur Speicherung, die schon vorher neu war. Der Händler kann Bildmotive hochladen — sein Logo, sein Produktfoto —, damit eine Kartenvorlage sie zeichnen kann. Diese Bilder werden dauerhaft aufbewahrt: die Bytes in einem Objektspeicher, die Angaben darüber (Schlüssel, Typ, Maße, Größe, Prüfsumme) in einer Tabelle der Datenbank. Anlage 1 Abschnitt A führt sie mit Zweck, Rechtsgrundlage und Löschung; die Prüfung beim Hochladen steht in Anlage 2 Abschnitt 2.6.
Frühere Fassungen dieses Vertrages sagten für alles, was der Händler eingibt, „keine Speicherung" und führten den Objektspeicher ausschließlich als Ablage der Datenbanksicherungen. Beides ist für die Bildmotive überholt.
Dieser Vertrag beschreibt daher den heutigen Stand. Mit jeder Erweiterung des Funktionsumfangs — insbesondere sobald die Zustellung an Käufer und Beschenkte gebaut ist — sind dieser Vertrag und seine Anlagen gegen den dann tatsächlichen Quelltext neu zu führen und dem Händler in der neuen Fassung vorzulegen.
1.2 Art der Verarbeitung
Erheben, Erfassen, Speichern, Verwenden, Abfragen, Verschlüsseln, Übermitteln an den in § 6 genannten Empfängerkreis, Löschen und Einschränken der Verarbeitung — jeweils im Umfang der Anlage 1.
1.3 Zweck der Verarbeitung
Ausschließlich:
- Installation und Betrieb der App im Shop des Händlers: Zuordnung des Shops, Beschaffung und Erneuerung der Shopify-Zugangstoken, Authentifizierung von Aufrufen aus der eingebetteten Oberfläche.
- Erfüllung der von Shopify vorgeschriebenen Datenschutz-Webhooks (Auskunft, Löschung einer Person, Löschung eines Shops).
- Nachweis über Zugriffe auf geschützte Kundendaten (Protokoll über Zugriffe auf geschützte Kundendaten): Auflage aus der Shopify-Freigabe für geschützte Kundendaten und eigene Rechenschaftsfähigkeit nach Art. 5 Abs. 2 DSGVO. Art. 5 Abs. 2 DSGVO ist dabei der Zweck, nicht die Rechtsgrundlage; zur Rechtsgrundlage siehe Abschnitt 5.1 der Datenschutzerklärung.
- Feststellung des Abonnementstands des Händler-Shops bei Shopify und dessen Durchsetzung am PDF-Abruf. Die Tarife verwaltet Shopify; KYTH liest ausschließlich, ob ein aktives Abonnement besteht, und speichert diese Antwort zwischen.
- Erzeugung der Gutscheinkarte als Vorschau und als PDF aus Angaben, die der Händler im Adminbereich selbst eingibt — ohne Speicherung dieser Angaben und ohne Zugriff auf Bestell- oder Kundendaten des Shops.
- Aufbewahrung der vom Händler hochgeladenen Bildmotive, damit eine Kartenvorlage sie zeichnen kann. Anders als die Textangaben aus Nummer 5 werden diese Bilder gespeichert: Ohne Aufbewahrung müsste der Händler sein Logo vor jeder einzelnen Vorschau erneut hochladen, und ein bereits gestaltetes Kartenmotiv wäre nach dem Schließen des Tabs verloren.
- Einrichtung des Gutscheinprodukts im Shop des Händlers auf dessen Klick hin, und Festhalten, welches Produkt das ist. Ohne diese Angabe ließe sich eine Gutscheinbestellung, die über einen Express-Bezahlweg hereinkommt, nicht als solche erkennen — sie wäre bezahlt und bekäme lautlos keinen Gutschein.
- Abwicklung einer bezahlten Gutscheinbestellung. Das ist der Zweck, um den dieser Vertrag mit dem Bestellablauf gewachsen ist, und er zerfällt in vier Schritte: a) die bezahlte Bestellung entgegennehmen und je gekauftem Stück einen Datensatz anlegen; b) die Angaben des Kunden zur beschenkten Person übernehmen und verschlüsselt ablegen; c) bei einem Wertgutschein einen Gutscheincode erzeugen, ihn verschlüsselt speichern und damit bei Shopify eine Geschenkkarte anlegen; d) die Karte rendern und den Vorgang als abgeschlossen vermerken. Die Zustellung an Käufer oder Beschenkte gehört heute nicht dazu — sie ist vorgesehen und nicht gebaut.
- Betriebsdiagnose und Sicherheit in dem in Anlage 1 beschriebenen, sehr engen Umfang.
Eine Verarbeitung zu eigenen Zwecken von KYTH — insbesondere zu Werbung, Profiling, Weiterverkauf, Training von Modellen oder Auswertung über Händler hinweg — findet nicht statt.
1.4 Dauer
Die Verarbeitung beginnt mit der Zustimmung nach § 0 und dem darauf folgenden Verbinden der App. Der Vertrag läuft auf unbestimmte Zeit, solange die App installiert ist.
Der Vertrag endet, ohne dass es einer Kündigung bedarf, mit der Deinstallation der App. Für Daten, die zu diesem Zeitpunkt noch vorhanden sind, gelten die Pflichten dieses Vertrages bis zu deren Löschung nach § 9 fort.
Höchstdauer dieses Nachlaufens. Die in der Datenbank verbliebenen Daten werden
spätestens 30 Tage nach der Deinstallation gelöscht — im Regelfall früher, nämlich
mit dem Webhook shop/redact, den Shopify regelmäßig 48 Stunden nach der Deinstallation
sendet. Bleibt dieser Webhook aus, greift der Aufräumlauf nach § 9.3 Nr. 1. Die
Nachwirkung dieses Vertrages ist damit auf 30 Tage begrenzt, mit zwei Einschränkungen,
die hier stehen müssen, damit die Frist nicht mehr behauptet als sie trägt:
- In den Sicherungen bestehen gelöschte Daten fort, bis die dortigen Fristen ablaufen (§ 9.3 Nr. 2).
§ 2 Art der personenbezogenen Daten und Kategorien betroffener Personen
2.1 Kategorien betroffener Personen
| Kategorie | Heutiger Stand |
|---|---|
| Händler und die für ihn im Shopify-Adminbereich handelnden Personen | betroffen — über die Shop-Domain, den kurzlebigen Sitzungstoken und die im Zustimmungsschritt angegebene Kontaktadresse. Letztere ist regelmäßig die Adresse einer natürlichen Person und deshalb verschlüsselt gespeichert |
| Endkundschaft des Händlers (Käuferinnen und Käufer) | betroffen, mit Speicherung: Kauft eine Kundin einen Gutschein, werden Name und E-Mail-Adresse verschlüsselt in der Gutscheinzeile abgelegt (seit 01.08.2026) — der Händler sieht beides in der Einzelansicht SEINER eigenen Bestellung, weil das im Supportfall die erste Frage ist. In der Liste der Bestellungen stehen sie ausdrücklich nicht, damit nicht jedes Laden der Übersicht einen Protokolleintrag erzeugt und den Nachweis entwertet. Zusätzlich wird ihre Shopify-Kundennummer in der Gutscheinzeile abgelegt — im Klartext, weil sie der Suchschlüssel der beiden Datenschutz-Webhooks ist und ein verschlüsselter Wert sich nicht durchsuchen ließe. Bei einem Gastkauf fehlt sie. Zusätzlich wird sie beim Anlegen der Shopify-Geschenkkarte an Shopify zurückgegeben, damit der Händler im Supportfall sieht, wer die Karte gekauft hat. Flüchtig hinzu kommt die Kundennummer aus den Datenschutz-Webhooks |
| Beschenkte / Empfänger von Gutscheinen | betroffen, mit Speicherung, und in zwei Rollen zugleich. Als betroffene Person: Empfängername, E-Mail-Adresse und der an sie gerichtete Grußtext werden aus der Bestellung übernommen und verschlüsselt gespeichert; über einen nicht umkehrbaren Suchwert der Adresse ist sie auffindbar. Als Empfängerin des Gutscheins: Genau dafür wird die Adresse erhoben — die Karte wird ihr über den Mailzugang des Händlers zugestellt und trägt Grußtext und Absendernamen (§ 1.1). Hat der Händler keinen Zugang hinterlegt, wird nichts zugestellt und er übergibt die Karte selbst. Sie hat nie bestellt, hat deshalb keine Kundennummer, und Shopify kennt sie nicht — die Folge daraus für ihre Betroffenenrechte steht in § 7.2 |
| Schenkende Personen | betroffen, mit Speicherung, soweit ein Absendername angegeben wurde: verschlüsselt in derselben Zeile. Sie ist regelmäßig, aber nicht zwingend die Käuferin |
| Personen, die auf einem hochgeladenen Bild zu sehen sind oder in dessen Metadaten stehen | betroffen, und hier mit Speicherung. Was ein hochgeladenes Motiv zeigt, entscheidet allein der Händler; KYTH sieht es nicht durch und wertet es nicht aus. Bei einem Bild aus einem Mobiltelefon können die eingebetteten Aufnahmedaten (EXIF) unter anderem Aufnahmezeitpunkt, Gerät und Standort enthalten. Diese Angaben werden nicht entfernt — die Begründung und die Folge stehen in Anlage 2 Abschnitt 7.2 |
2.2 Art der Daten
Abschließend aufgeführt in Anlage 1. In Kurzform:
- Gespeichert werden zum Shop: die myshopify-Domain des Shops im Klartext, ein nicht umkehrbarer HMAC-Hash derselben Domain als Suchindex, der Shopify-Access-Token und der Shopify-Refresh-Token (beide verschlüsselt), die Kontaktadresse des Händlers (verschlüsselt), Zeitpunkt und Fassungskennung seiner Zustimmung, der zuletzt bei Shopify gelesene Abonnementstand, technische Zeitstempel und der Berechtigungsumfang (Scopes), Einträge im Protokoll über Zugriffe auf geschützte Kundendaten, technische Kennungen eingehender Webhooks, die vom Händler hochgeladenen Bildmotive — deren Bytes im Objektspeicher, deren Schlüssel, MIME-Typ, Größe, Maße und Prüfsumme in einer Tabelle der Datenbank — sowie die Angaben zu seinem Gutscheinprodukt (Art, Shopify-Produktkennung, Handle, gewählte Vorlage, Zeitpunkt des Anlegens).
- Gespeichert werden je gekauftem Gutschein — und das ist die Kategorie, die dieser Vertrag zuletzt nicht hatte: Empfängername, E-Mail-Adresse des Beschenkten, Absendername, Grußtext und der Gutscheincode, sämtlich verschlüsselt; ein Abruf- Token, ebenfalls verschlüsselt; nicht umkehrbare Suchwerte über Gutscheincode, Abruf-Token und Empfängeradresse; die Shopify-Kundennummer des Käufers im Klartext; Bestellkennung, Positionskennung und die laufende Nummer des Stücks; die Art des Gutscheins, die Kennung der Kartenvorlage und ein eingefrorenes Abbild dieser Vorlage mit Platzhaltern statt Werten; Nennwert und Währung, der gedruckte Betrag als Text, der Shopname und ein Gültigkeitsdatum; die Kennung der Shopify-Geschenkkarte; Zustand, Zeitpunkt des letzten Zustandswechsels, Fehlerzähler und Fehlergrund als kurze eigene Kennung; sowie die Schlüssel der Bildmotive, die in dieser Karte stecken.
- Nur flüchtig im Arbeitsspeicher berührt und nirgends abgelegt: der Shopify-Sitzungstoken des eingeloggten Händler-Nutzers, Kundennummer und E-Mail-Adresse aus den Datenschutz-Webhooks, der übrige Inhalt einer eingehenden Bestellung, die Angaben, die der Händler in den Gutschein-Editor eintippt (Empfänger- und Absendername, Grußtext, Gutscheincode, Betrag, Shopname, Gültigkeitsdatum), sowie jedes erzeugte PDF — auch das aus einer Bestellung.
- Nicht verarbeitet: Anschriften, Telefonnummern und Zahlungsdaten der Kundschaft des Händlers, der Bestellinhalt jenseits der Gutscheinpositionen, das im Bestellformular angebbare Wunschversanddatum und der Guthabenstand einer Shopify-Geschenkkarte. Für keines davon gibt es eine Spalte. Bis zu dieser Fassung stand an dieser Stelle auch „Bestellinhalte" und „E-Mail-Adressen der Kundschaft des Händlers" — beides ist mit dem Bestellablauf falsch geworden und steht jetzt zwei Punkte weiter oben.
Zu den Bildmotiven, weil die Aufzählung sonst mehr verspricht als sie halten kann: Was ein hochgeladenes Bild zeigt und welche Aufnahmedaten darin stehen, bestimmt der Händler. Ein Bild kann Personen abbilden, und die eingebetteten Aufnahmedaten (EXIF) eines Mobiltelefons können einen Standort tragen. KYTH prüft das Bild auf Format, Maße und Ungefährlichkeit (Anlage 2 Abschnitt 2.6), wertet den Inhalt aber nicht aus und entfernt die Aufnahmedaten nicht. Die Angabe „nicht verarbeitet" oben bezieht sich auf Daten, die KYTH aus dem Shop des Händlers entnimmt — sie ist keine Zusage darüber, was ein Händler von sich aus in ein Bild hineinlädt.
2.3 Erteilte Berechtigungen und ihre Ausübung
Dieser Abschnitt trennt zwei Dinge, die leicht verwechselt werden: was KYTH darf und
was KYTH tut. Bis zu dieser Fassung trug er die Überschrift „Erteilte Berechtigung
ohne Ausübung" und sagte in einem Satz: „Was KYTH damit tut: nichts." Das war richtig,
solange es den Bestellablauf nicht gab. Es ist heute falsch, und zwar in beide
Richtungen: Die App übt read_orders aus, und sie hat zwei Berechtigungen mehr, als
der Abschnitt kannte.
Was der Händler erteilt. In der Shopify-App-Konfiguration sind angefordert:
| Berechtigung | Zweck laut Konfiguration | Ausübung |
|---|---|---|
read_orders |
Gutscheinbestellungen erkennen und die Angaben lesen, die der Kunde als Zusatzangaben zur Bestellposition mitgibt | ausgeübt — über den Webhook orders/paid. Ohne diesen Berechtigungsumfang käme der Webhook ohne verwertbaren Inhalt an. read_all_orders ist ausdrücklich nicht angefordert |
write_gift_cards |
den Wertgutschein als echte Shopify-Geschenkkarte anlegen, mit einem von Kartuu erzeugten Code — ein von Shopify vergebener Code wäre nie auslesbar und damit nicht druckbar | ausgeübt, bei jedem Wertgutschein. Heute ausschließlich zum Anlegen; das Deaktivieren einer Karte beim Storno ist vorgesehen und nicht gebaut. Guthabenstände liest und speichert die App nicht |
write_products |
das Gutscheinprodukt im Shop des Händlers anlegen: Produkt, eine Option, je Betrag oder Leistung eine Variante und die Metafelder, an denen der Bestellablauf die Gutscheinpositionen wiedererkennt | ausgeübt, aber nur auf einen Klick des Händlers. Nichts entsteht bei der Installation und nichts im Hintergrund. Ein vorhandenes Produkt wird nicht geändert und keines gelöscht; ändert der Händler Titel, Preis oder Bilder, bleibt es so. write_publications ist ausdrücklich nicht angefordert — ob das Produkt im Onlineshop sichtbar wird, entscheidet der Händler |
geschütztes Kundendatenfeld name |
Empfängername und Name der schenkenden Person werden auf den Gutschein gedruckt | ausgeübt — die Namen stammen aus der Bestellposition und werden verschlüsselt gespeichert |
geschütztes Kundendatenfeld email |
der fertige Gutschein soll als PDF an Käufer und wahlweise an die beschenkte Person zugestellt werden | ausgeübt. Die Adresse des Beschenkten wird entgegengenommen, verschlüsselt gespeichert und als Suchwert abgelegt. Zugestellt wird über den vom Händler hinterlegten Mailzugang; ohne hinterlegten Zugang wird nichts zugestellt |
Was KYTH weiterhin nicht tut. Über die Admin-API fragt Kartuu keine Bestellung und kein Kundendatenfeld ab. Die Bestelldaten kommen ausschließlich aus dem Webhook, den Shopify zustellt. Der gespeicherte Access-Token würde einen Abruf erlauben; keine Funktion der App nutzt ihn dafür. Die vollständige Liste der sechs Aufrufe an die Admin-API steht in § 3.4.
Drei Herkünfte, und sie sind auseinanderzuhalten. Personenbezogene Daten erreichen Kartuu heute auf drei Wegen, und jeder hat eine andere Folge:
- Aus dem Shop des Händlers — über den Bestellwebhook. Diese Daten werden gespeichert (Anlage 1 Abschnitt A). Für sie ist der Händler Verantwortlicher und KYTH Auftragsverarbeiter; die Weisung dazu ist dieser Vertrag samt der Einrichtung des Gutscheinprodukts.
- Aus der Eingabe des Händlers im Gutschein-Editor — sie werden nicht gespeichert (Anlage 1 Abschnitt B).
- Aus einem Upload des Händlers — die Bilder werden gespeichert (Anlage 1 Abschnitt A).
Wenn sich das ändert. Vor der ersten Zustellung an Käufer oder Beschenkte sind Anlage 1 und Anlage 2 neu zu erheben, dieser Vertrag ist in neuer Fassung vorzulegen und die Fassungskennung zu erhöhen — der Händler wird dann erneut um Zustimmung gebeten (§ 0.3, § 11 Nr. 6).
2.4 Besondere Datenkategorien
Daten besonderer Kategorien nach Art. 9 DSGVO und Daten nach Art. 10 DSGVO sind nicht Gegenstand der Verarbeitung. KYTH wird sie auch künftig nicht anfordern.
§ 2a Pflichten und Rechte des Verantwortlichen
Art. 28 Abs. 3 Satz 1 DSGVO verlangt, dass ein Auftragsverarbeitungsvertrag auch die Pflichten und Rechte des Verantwortlichen festlegt. Das geschieht hier.
- Rechtmäßigkeit der Verarbeitung. Der Händler ist allein dafür verantwortlich, dass die von ihm angewiesene Verarbeitung rechtmäßig ist und dass eine Rechtsgrundlage nach Art. 6 DSGVO vorliegt. Er entscheidet über Zwecke und Mittel. KYTH prüft die Rechtsgrundlage nicht und kann sie nicht prüfen.
- Informationspflichten. Die Informationspflichten nach Art. 13 und Art. 14 DSGVO gegenüber der Kundschaft des Händlers und gegenüber Beschenkten treffen den Händler. Beschenkte geben ihre Daten typischerweise nicht selbst, sondern die schenkende Person gibt sie — dafür gilt Art. 14 DSGVO.
- Weisungen. Der Händler ist berechtigt und verpflichtet, Weisungen nach § 3 zu erteilen; seine Weisungen müssen rechtmäßig sein. Er benennt KYTH die Personen, die für ihn weisungsberechtigt sind, und hält diese Angabe aktuell. Benennt er niemanden, gelten die vertretungsberechtigten Organe des Händlers als weisungsberechtigt.
- Kontaktadresse. Der Händler gibt beim Zustimmungsschritt nach § 0 eine E-Mail-Adresse an, unter der KYTH ihn erreichen kann. Die Angabe ist Pflicht; ohne sie wird die App nicht verbunden. An diese Adresse gehen die Mitteilungen nach § 0.3, § 6.6 und § 8.2. Der Händler hält die Adresse aktuell und teilt eine Änderung in Textform an datenschutz@kyth.systems mit. Eine Änderung in der App ist nicht vorgesehen. Wird die Adresse unzustellbar, kann KYTH den Händler nicht mehr unmittelbar erreichen — auch nicht bei einer Verletzung des Schutzes personenbezogener Daten, für deren Meldung dem Händler nach Art. 33 Abs. 1 DSGVO nur 72 Stunden bleiben. Die Aktualität liegt deshalb in seinem eigenen Interesse.
- Nachweise und Prüfungen. Der Händler hat die Rechte auf Nachweise und Überprüfungen nach § 10.
- Meldung von Datenpannen. Die Meldung einer Verletzung des Schutzes personenbezogener Daten an die Aufsichtsbehörde (Art. 33 DSGVO) und die Benachrichtigung der betroffenen Personen (Art. 34 DSGVO) obliegen dem Händler. KYTH unterstützt ihn dabei nach § 8.2.
- Eigene Kontrolle. Der Händler überzeugt sich vor Beginn der Verarbeitung und danach regelmäßig von den technischen und organisatorischen Maßnahmen nach Anlage 2. Anlage 2 benennt in Abschnitt 7 ausdrücklich die bekannten Lücken.
Zum Umgang mit der Kontaktadresse. KYTH speichert sie verschlüsselt, verwendet sie ausschließlich für die in Nummer 4 genannten Mitteilungen und für die Weiterleitung von Anfragen betroffener Personen nach § 7.1, gibt sie nicht weiter und wirbt darüber nicht. Sie wird mit der Shop-Zeile gelöscht (§ 9).
§ 3 Verarbeitung nur auf dokumentierte Weisung
3.1 Grundsatz
KYTH verarbeitet personenbezogene Daten ausschließlich auf dokumentierte Weisung des Händlers. Das gilt auch für die Übermittlung in ein Drittland.
3.2 Was als Weisung gilt
Weisungen sind:
- dieser Vertrag einschließlich seiner Anlagen — er ist die Grunderklärung der Weisungen; die Zustimmung nach § 0 ist die Erteilung dieser Grunderklärung,
- die Installation der App und die Erteilung der Berechtigungen im Shopify-Adminbereich,
- Einstellungen, die der Händler in der App vornimmt. Die App hat zwei Seiten, die Installationsseite mit dem Zustimmungsschritt und den Gutschein-Editor. Der Editor nimmt Werte für einen einzelnen Renderlauf entgegen (Angaben der Karte, Wahl der Vorlage, Wahl eines bereits hochgeladenen Bildmotivs); davon wird nichts gespeichert — die Wahl des Motivs benennt nur ein Bild, das ohnehin schon liegt, und sie gilt für diesen einen Renderlauf. Eine dauerhaft wirkende Handlung kennt er inzwischen aber doch, nämlich das Hochladen eines Bildmotivs: Das Bild bleibt liegen, bis der Shop gelöscht wird. Es ist damit die einzige Handlung in der App, mit der der Händler von sich aus einen Speichervorgang auslöst — und die Weisung dazu ist der Upload selbst,
- Einzelweisungen in Textform an datenschutz@kyth.systems.
Mündlich erteilte Weisungen bestätigt der Händler unverzüglich in Textform. KYTH dokumentiert Einzelweisungen und bewahrt sie für die Dauer des Vertrages auf.
3.3 Grenzen der Weisung
KYTH informiert den Händler unverzüglich, wenn eine Weisung nach Auffassung von KYTH gegen die DSGVO oder gegen andere Datenschutzvorschriften verstößt. KYTH darf die Ausführung einer solchen Weisung aussetzen, bis der Händler sie bestätigt oder ändert.
Ist KYTH gesetzlich zu einer Verarbeitung verpflichtet, teilt KYTH dem Händler die rechtliche Anforderung vor der Verarbeitung mit, sofern das Gesetz die Mitteilung nicht wegen eines wichtigen öffentlichen Interesses verbietet.
3.4 Verarbeitungsort und Drittlandtransfer
Die Verarbeitung durch KYTH selbst findet in Deutschland statt: Anwendung und
Datenbank laufen auf einem einzigen virtuellen Server bei der IONOS SE am Standort
Berlin. Die täglichen Datenbanksicherungen und die vom Händler hochgeladenen
Bildmotive liegen im Objektspeicher der IONOS in der Region eu-central-3, ebenfalls
Berlin — in getrennten Eimern und zu getrennten Zwecken, siehe § 6.3. Es gibt keine
weitere Verarbeitungsumgebung. Der Objektspeicher begründet keinen Drittlandbezug.
Übermittlungen an Stellen außerhalb von KYTH ergeben sich ausschließlich aus dem in § 6 genannten Kreis:
- Shopify: Kartuu ruft ausgehend genau zwei fremde Endpunkte auf, beide beim
Händler-Shop selbst: den Token-Endpunkt
(
https://{shop-domain}/admin/oauth/access_token) und die Admin-API (https://{shop-domain}/admin/api/{version}/graphql.json). Übertragen werden dabei die Zugangsdaten der App und der jeweilige Token. Über die Admin-API laufen sechs verschiedene Aufrufe, und sie tragen Unterschiedliches:
| Aufruf | Was dabei übertragen wird |
|---|---|
| Abfrage des Abonnementstands | nichts außer dem Token — die Abfrage trägt keine Angaben |
| Anlegen einer Geschenkkarte | der Gutscheincode, der Nennwert, eine Notiz zur Zuordnung und die Shopify-Kundennummer des Käufers. Die Notiz enthält keine Personendaten: Wer beschenkt wird, steht in der verschlüsselten Spalte bei KYTH und nicht in einem Freitextfeld bei Shopify |
| Nachsehen, ob es den Produkt-Handle im Shop schon gibt | der Handle und die Namen zweier Metafelder |
| Nachsehen, ob eine hinterlegte Produktkennung noch existiert | die Produktkennung |
| Anlegen des Gutscheinprodukts | Produkttitel, Beschreibung, Optionen, Varianten mit Preisen und die Metafelder — Angaben über Ware, keine über Personen |
| Nachziehen der beiden Bestandsfelder einer Variante | Produkt- und Variantenkennung |
Bestell- und Kundendaten werden über die Admin-API nicht abgefragt; sie kommen
eingehend über den Webhook orders/paid, den Shopify zustellt. Shopify
ist zugleich die Plattform, auf der der Shop des Händlers ohnehin betrieben wird;
der Händler unterhält hierzu ein eigenes Vertragsverhältnis mit Shopify.
Vertragspartner für Händler im Europäischen Wirtschaftsraum ist regelmäßig die
Shopify International Ltd. mit Sitz in Irland; eine Verarbeitung durch verbundene
Unternehmen außerhalb des EWR, insbesondere die Shopify Inc. in Kanada, ist nicht
ausgeschlossen.
Weisung. Mit Abschluss dieses Vertrages weist der Händler KYTH an, den Token-Endpunkt und die Admin-API seines eigenen Shops bei Shopify aufzurufen und die eingehenden Webhooks von Shopify entgegenzunehmen, auch soweit dabei eine Übermittlung an Shopify-Stellen außerhalb des EWR stattfindet (Art. 28 Abs. 3 lit. a DSGVO). Ohne diesen Datenfluss lässt sich die App nicht betreiben.
Kanada. Für Kanada besteht ein Angemessenheitsbeschluss der Europäischen Kommission (Entscheidung 2002/2/EG) für privatwirtschaftliche Organisationen, die dem kanadischen Datenschutzgesetz PIPEDA unterliegen.
Übrige Drittländer, insbesondere die USA: Standardvertragsklauseln. Shopify
bezieht in sein Data Processing Addendum in der Fassung vom 07.07.2026 die
EU-Standardvertragsklauseln ein — die Klauseln aus dem Durchführungsbeschluss (EU)
2021/914 der Europäischen Kommission vom 4. Juni 2021. Auf sie stützen sich
Übermittlungen an Shopify-Stellen außerhalb des Europäischen Wirtschaftsraums, also
auch an Stellen in den USA. Das Addendum ist unter
https://www.shopify.com/legal/dpa öffentlich abrufbar; eine Kopie der Klauseln
erhält der Händler auf Anfrage an datenschutz@kyth.systems (Art. 13 Abs. 1
lit. f DSGVO). Festgestellt am 01.08.2026; dieselbe Grundlage steht in Abschnitt 8
der Datenschutzerklärung und mit Quelle und Prüfdatum in deren Belegtabelle 12.4.
Zwei Dinge, die hier bewusst NICHT stehen.
Keine Zertifizierung unter dem EU-US Data Privacy Framework. Das Addendum nennt keine, und ohne Beleg gehört sie nicht in einen Vertrag. Die Standardvertragsklauseln tragen die Übermittlung auch ohne sie.
Welches Modul der Klauseln greift, ist nicht gesondert festgestellt. Für das Verhältnis KYTH → Shopify wäre Modul 3 (Auftragsverarbeiter an Auftragsverarbeiter) einschlägig; belegt ist bislang nur, DASS das Addendum die Klauseln nach 2021/914 einbezieht. Eine Modulangabe ohne Beleg wäre geraten, und geraten wird hier nichts. Wer das Addendum daraufhin liest, trägt die Angabe hier nach.
- Cloudflare: keine Übermittlung. Die DNS-Zone
kyth.systemswird bei Cloudflare geführt. Für Kartuu ist Cloudflare damit ausschließlich autoritativer DNS-Dienst; die App-Namen lösen unmittelbar auf die IP-Adresse des Servers in Berlin auf, der Datenverkehr läuft nicht über Cloudflare. Cloudflare erhält weder Händler- noch Kundendaten und ist deshalb kein Unterauftragsverarbeiter dieses Vertrages. Siehe § 6.4.
Andere Übermittlungen in Drittländer finden nicht statt. Insbesondere liegen die Sicherungen in Deutschland (§ 6.3).
§ 4 Vertraulichkeit der eingesetzten Personen
KYTH setzt zur Verarbeitung nur Personen ein, die zur Vertraulichkeit verpflichtet sind oder einer angemessenen gesetzlichen Verschwiegenheitspflicht unterliegen (Art. 28 Abs. 3 lit. b DSGVO). Die Verpflichtung wirkt über das Ende der Tätigkeit hinaus.
KYTH stellt sicher, dass diese Personen personenbezogene Daten ausschließlich auf Weisung des Händlers verarbeiten und mit den für sie maßgeblichen Datenschutzvorgaben vertraut sind.
Der Kreis der Zugriffsberechtigten, festgestellt am 03.08.2026. Zugriff auf die Produktionsumgebung — Server, Coolify, Datenbank und das Shopify Partner Dashboard — haben ausschließlich die beiden Geschäftsführer von KYTH, Stefan Grasse und Stephan Wittmann. Stefan Grasse führt daneben die technische Leitung; die Betriebsdokumentation weist ausdrücklich aus, dass diese bei einer einzelnen Person liegt („Bus-Faktor 1").
Darüber hinaus hat niemand Zugriff. Es gibt keine Beschäftigten, keine freie Mitarbeit und keine Dienstleister mit Zugang zur Produktionsumgebung. Die Unterauftragsverarbeiter aus § 6.3 sind davon nicht berührt: Sie stellen Infrastruktur und haben keinen Zugriff auf die Anwendung.
Warum keine gesonderten Verpflichtungserklärungen vorliegen. Art. 28 Abs. 3 lit. b DSGVO verlangt eine Verpflichtung zur Vertraulichkeit oder eine angemessene gesetzliche Verschwiegenheitspflicht. KYTH stützt sich auf die zweite Alternative: Für Geschäftsführer einer Unternehmergesellschaft folgt die Verschwiegenheitspflicht aus ihrer organschaftlichen Treuepflicht (§ 43 GmbHG, für die UG über § 5a Abs. 1 GmbHG). Eine zusätzliche Erklärung, mit der sich jemand sich selbst gegenüber verpflichtet, brächte keinen Nachweis, den es nicht schon gibt.
Das ist eine Bewertung von KYTH und kein geprüftes Gutachten. Ob die organschaftliche Treuepflicht im Sinne von Art. 28 Abs. 3 lit. b DSGVO „angemessen" ist, ist eine Rechtsfrage; keiner der drei Texte dieses Vertragswerks ist anwaltlich geprüft (siehe den Hinweis am Anfang). Der Sachverhalt darunter — zwei Geschäftsführer, sonst niemand — ist dagegen eine Feststellung und keine Auslegung.
Sobald eine dritte Person Zugriff bekommt, trägt diese Begründung nicht mehr: Für Beschäftigte, freie Mitarbeit und Dienstleister braucht es eine unterschriebene Vertraulichkeitsverpflichtung, und dieser Abschnitt ist vorher zu ändern.
§ 5 Technische und organisatorische Maßnahmen (Art. 32 DSGVO)
KYTH trifft die in Anlage 2 beschriebenen technischen und organisatorischen Maßnahmen. Anlage 2 enthält ausschließlich Maßnahmen, die im Quelltext oder in der Betriebsdokumentation belegt sind, und benennt in einem eigenen Abschnitt die bekannten Lücken.
Die Maßnahmen unterliegen dem technischen Fortschritt. KYTH darf sie anpassen, solange das Schutzniveau nicht unterschritten wird. Wesentliche Änderungen werden dokumentiert und dem Händler auf Anfrage mitgeteilt.
KYTH verfügt über keine Datenschutz- oder Sicherheitszertifizierung (weder ISO/IEC 27001 noch SOC 2 noch eine Zertifizierung nach Art. 42 DSGVO) und behauptet auch keine. Anlage 2 ist eine Selbstauskunft, kein Prüfbericht.
§ 6 Unterauftragsverarbeiter
6.1 Zustimmung
Der Händler stimmt mit Abschluss dieses Vertrages der Beauftragung der unter 6.3 genannten Unterauftragsverarbeiter zu (allgemeine schriftliche Genehmigung nach Art. 28 Abs. 2 Satz 2 DSGVO).
6.2 Bedingungen
KYTH verpflichtet jeden Unterauftragsverarbeiter vertraglich auf Datenschutzpflichten, die den Pflichten aus diesem Vertrag entsprechen, insbesondere auf hinreichende Garantien nach Art. 28 Abs. 4 DSGVO. Kommt der Unterauftragsverarbeiter seinen Datenschutzpflichten nicht nach, haftet KYTH gegenüber dem Händler für dessen Einhaltung nach Maßgabe von Art. 28 Abs. 4 Satz 2 DSGVO.
Ehrliche Angabe zum heutigen Stand: Für welche der unter 6.3 genannten Stellen ein solcher Vertrag tatsächlich vorliegt, ist nicht belegt. Der vorstehende Absatz beschreibt die Pflicht, die KYTH übernimmt — nicht einen bereits geführten Nachweis. Siehe die Klärungsmarkierung unter 6.3.
6.3 Liste der Unterauftragsverarbeiter
Stand 29.07.2026:
| Unternehmen | Sitz / Verarbeitungsort | Zweck | Welche Daten |
|---|---|---|---|
| IONOS SE | Elgendorfer Straße 57, 56410 Montabaur, Deutschland (AG Montabaur, HRB 24498); Verarbeitungsort Rechenzentrum Berlin | Hosting: ein virtueller Server (VPS), darauf die Anwendungscontainer und die PostgreSQL-Datenbanken für Test- und Produktivbetrieb | Alle in Anlage 1 als gespeichert bezeichneten Daten sowie die Anwendungsprotokolle |
| IONOS Cloud GmbH (Objektspeicher) | Elgendorfer Straße 57, 56410 Montabaur, Deutschland (AG Montabaur, HRB 31110); Verarbeitungsort Region eu-central-3, Rechenzentrum Berlin; Endpunkt s3.eu-central-3.ionoscloud.com |
Zwei getrennte Zwecke in zwei getrennten Eimern. (a) Ablage der täglichen Datenbanksicherungen im Eimer kaspar-kyth-db-backup. (b) Produktive Ablage der vom Händler hochgeladenen Bildmotive in einem eigenen Eimer je Umgebung — für den Testbetrieb kaspar-kyth-bilder-staging (angelegt am 29.07.2026, Region eu-central-3), für den Produktivbetrieb ist noch keiner angelegt. Ausdrücklich nicht im Sicherungseimer, weil dort eine völlig andere Aufbewahrungs- und Zugriffsregel gilt |
Zu (a): die vollständige Datenbanksicherung, also alle in Anlage 1 als gespeichert bezeichneten Daten in dem Zustand, in dem sie in der Datenbank stehen — die feldweise verschlüsselten Werte verschlüsselt; Fristen in § 9.3 Nr. 2. Zu (b): die Bytes der hochgeladenen Bilder, unverändert und einschließlich ihrer Aufnahmedaten; Schlüssel <Shop-Kennung>/<Prüfsumme>.<Endung>, nicht öffentlich lesbar; Fristen in § 9.3 Nr. 6 |
Änderung gegenüber früheren Entwürfen: Ein früherer Entwurf dieses Vertrages führte aus, die Sicherungen lägen lokal auf demselben Server und ein externer Objektspeicher sei kein Unterauftragsverarbeiter. Das ist seit dem 26.07.2026 überholt. Die Sicherungen gehen zusätzlich in den oben genannten Eimer; IONOS ist damit Unterauftragsverarbeiter auch für die Sicherungen. Cloudflare wurde umgekehrt aus dieser Liste entfernt und steht nun unter 6.4 — siehe die dortige Begründung.
Zweite Änderung, und die weiter reichende: Bis zu dieser Fassung war der Objektspeicher ausschließlich Sicherungsablage — ein Ort, an dem nur ein Abbild von Daten liegt, die ohnehin schon in der Datenbank stehen. Mit den hochgeladenen Bildmotiven ist er zusätzlich ein produktiver Speicherort für Inhalte, die es sonst nirgends gibt. Der Unterschied ist kein formaler: Eine Sicherung kann man verlieren, ohne dass Daten verschwinden; ein produktiver Speicher nicht. Deshalb steht der Objektspeicher oben mit zwei Zwecken und nicht mehr mit einem, deshalb trennt § 9.3 Nr. 6 die Löschung der Objekte von der Löschung der Zeilen, und deshalb ist die Prüfung beim Hochladen eine eigene Maßnahme in Anlage 2 Abschnitt 2.6.
Getrennte Eimer je Umgebung. Test- und Produktivbetrieb schreiben in verschiedene Eimer. Der Grund ist die Bauart des Schlüssels: Er beginnt mit der internen Kennung des Shops, und diese Kennungen werden je Datenbank vergeben. Ein Testshop könnte im gemeinsamen Eimer denselben Namensraum treffen wie ein echter Händler — und eine Löschung im Testbetrieb nähme einem zahlenden Händler seine Motive.
Was heute eingerichtet ist, und was diese Zeile deshalb bedeutet. Die App kennt zwei Ablagen: ein Verzeichnis im Dateisystem und den Objektspeicher. Welche gilt, entscheidet die Konfiguration der jeweiligen Umgebung; ohne Angabe gilt das Verzeichnis, und das ist die Voreinstellung für Entwicklung und Tests. Für den Betrieb ist es keine Wahl: Ein Verzeichnis im Container überlebt kein Neuaufsetzen und wird von einem zweiten Container nicht geteilt — hochgeladene Motive wären nach dem nächsten Aufspielen weg, ohne dass irgendetwas meldet. Jede Umgebung, in der ein fremder Händler ein Bild hochladen kann, läuft deshalb auf dem Objektspeicher. Die Oberfläche bietet den Upload inzwischen an; bis zu dieser Fassung stand hier, sie tue das nicht, und das traf zu, als der Satz geschrieben wurde. Welche Umgebung auf den Objektspeicher umgestellt ist, steht nicht im Quelltext und ist diesem Vertrag deshalb nicht zu entnehmen — ohne Angabe gilt das Verzeichnis. Diese Zeile beschreibt damit die Ablage, für die dieser Vertrag die Grundlage schafft. Die Reihenfolge ist Absicht: Erst der Vertrag, dann die Umstellung — umgekehrt läge ein Händlerbild in einem Eimer, den kein Vertrag nennt.
Zu den Verträgen nach Art. 28 Abs. 4 DSGVO:
IONOS: der Auftragsverarbeitungsvertrag, benannt am 03.08.2026. Es gilt die
„Vereinbarung zur Auftragsverarbeitung nach Art. 28 Abs. 3 DSGVO" der IONOS,
Version 1.2, Stand 06/2023, öffentlich abrufbar unter
https://www.ionos.de/terms-gtc/avv/. KYTH hält eine Ausfertigung in seinen
Vertragsunterlagen.
Sie deckt den Objektspeicher mit ab, und zwar über ihren Geltungsbereich und nicht über eine Aufzählung. Ihr § 1.1 lautet: Gegenstand sind die Rechte und Pflichten der Parteien „im Rahmen der Leistungserbringung gemäß Leistungsbeschreibung und AGB (nachfolgend Hauptvertrag), soweit eine Verarbeitung von personenbezogenen Daten durch IONOS … erfolgt", und weiter: „Dies umfasst alle Tätigkeiten, die der Auftragnehmer zur Erfüllung des Auftrags erbringt und die eine Auftragsverarbeitung darstellen. Dies gilt auch, sofern der Auftrag nicht ausdrücklich auf diese Vereinbarung zur Auftragsverarbeitung verweist." Die Vereinbarung ist damit leistungsunabhängig und erfasst Server und Objektspeicher, soweit beide unter demselben Hauptvertrag bezogen werden — für beide Zwecke: den Sicherungseimer und die Eimer mit den hochgeladenen Bildmotiven.
Was daran Auslegung ist und was Beleg. Belegt ist der Wortlaut oben. Dass er den Objektspeicher erfasst, folgt aus der allgemeinen Geltungsklausel — das Dokument zählt keine Einzelleistungen auf und nennt den Objektspeicher an keiner Stelle beim Namen. Wer eine ausdrückliche Nennung braucht, muss sie bei IONOS erfragen.
Das Dokument benennt auch keine Gesellschaft. Es spricht durchgehend vom „Auftragnehmer". Welche Gesellschaft der IONOS-Gruppe Vertragspartnerin ist, bleibt deshalb offen — siehe die Marke direkt darunter.
Folge für die Bildablage: Der Vertragsvorbehalt, der ABLAGE_ART=s3 gesperrt hat,
ist damit gefallen. Was der Umstellung im Produktivbetrieb noch fehlt, ist der Eimer
selbst — für den Testbetrieb heißt er kaspar-kyth-bilder-staging (angelegt am
29.07.2026), für den Produktivbetrieb ist keiner angelegt und deshalb auch keiner
benannt.
Shopify: am 03.08.2026 entschieden — kein Unterauftragsverarbeiter. Das geltende Data Processing Addendum (Fassung vom 07.07.2026) liegt als Ausfertigung in den Vertragsunterlagen von KYTH; seine Parteien sind der Händler und Shopify, nicht KYTH. Der Vertrag, der KYTH bindet — das Shopify Partner Program Agreement, Stand 27.02.2026 —, enthält kein Data Processing Addendum. Shopify ist damit eigener Auftragsverarbeiter des Händlers; die Zeile steht in 6.4, mit der vollständigen Begründung und den Fundstellen.
Damit nennt diese Liste nur noch Stellen, die KYTH selbst beauftragt hat.
Die Anschriften stehen seit dem 03.08.2026 vollständig in der Tabelle oben und in 6.4. Sie waren nicht neu zu ermitteln: Abschnitt 7 der Datenschutzerklärung führt sie seit dem 01.08.2026, mit Fundstellen in deren Belegtabelle 12.3 — dieser Vertrag hatte sie nur nie übernommen.
Den Objektspeicher stellt die IONOS Cloud GmbH (AG Montabaur, HRB 31110); die
Anbieterkennzeichnung des Dienstes unter s3.eu-central-3.ionoscloud.com nennt sie.
Server, Datenbank und Sicherungen laufen bei der IONOS SE (HRB 24498). Beide sind
unter derselben Anschrift erreichbar; welche Gesellschaft im Einzelfall
Vertragspartnerin ist, ergibt sich aus dem jeweiligen Vertrag.
Genau das ist die Drift, vor der Abschnitt 7 der Datenschutzerklärung warnt: Dort steht seit dem 01.08.2026 der Satz, die Tabelle und § 6.3 dieses Vertrages beschrieben denselben Empfängerkreis, und wer einen ändere, müsse den anderen mitändern — „sonst laufen sie auseinander, und die ältere Fassung wird stillschweigend zur falschen Auskunft". Sie sind zwei Tage lang auseinandergelaufen.
6.4 Weitere Empfänger, die keine Unterauftragsverarbeiter sind
Der Vollständigkeit halber, weil ein Datenfluss oder eine Beteiligung besteht:
- Shopify International Limited, The Sidings, 4th Floor, Grand Canal Quay, Dublin D02 E7K8, Irland (Vertragspartnerin für Händler im EWR), verbunden mit Shopify Inc., 151 O'Connor Street, Ground floor, Ottawa, Ontario K2P 2L8, Kanada — eigener Auftragsverarbeiter des Händlers, nicht Unterauftragsverarbeiter von KYTH. Bis zum 03.08.2026 stand Shopify in der Liste unter 6.3; die Einordnung war offen und ist an diesem Tag anhand der Verträge entschieden worden.
Was tatsächlich fließt: Plattform: Bezug und Erneuerung der Zugangstoken über den Token-Endpunkt des Shops; sechs Aufrufe an die Admin-API des Shops (§ 3.4); Zustellung der eingehenden Webhooks an Kartuu, darunter die bezahlten Bestellungen; Verwaltung und Abrechnung der App-Tarife
Welche Daten: Zugangsdaten der App, Sitzungstoken bzw. Refresh-Token, Access-Token, Shop-Domain — und seit dem Bestellablauf zusätzlich der Gutscheincode, der Nennwert und die Kundennummer des Käufers beim Anlegen einer Geschenkkarte sowie die Angaben des Gutscheinprodukts. Empfängername, Empfängeradresse und Grußtext gehen nicht an Shopify zurück; sie kommen von dort und bleiben verschlüsselt bei KYTH
Warum das keine Unterauftragsverarbeitung von KYTH ist. Eine solche setzt voraus, dass KYTH den Dienstleister beauftragt. Hier ist es umgekehrt: Der Händler hat Shopify längst beauftragt — Shopify betreibt seinen Shop. Wenn Kartuu eine Geschenkkarte über die Admin-API anlegt, schreibt es Daten in den Shop des Händlers, und Shopify verarbeitet sie dort als dessen Auftragsverarbeiter, unter dessen eigenem Vertrag.
Belegt ist das an zwei Stellen:
- Shopifys Data Processing Addendum (Fassung vom 07.07.2026,
https://www.shopify.com/legal/dpa) benennt seine Parteien selbst: „by and between You (or »Merchant«), and the Shopify Contracting Entity" und weiter: „You shall act as a Data Controller and Shopify shall act as a Data Processor with respect to the processing of Your Customer Personal Data." KYTH ist dort nicht Partei. - Das Shopify Partner Program Agreement (Stand 27.02.2026,
https://www.shopify.com/partners/terms) — der Vertrag, der KYTH bindet — enthält kein Data Processing Addendum. Es beschränkt in 9.14.2 die Verwendung der Händlerdaten durch den Partner („Partner will only use or store such information for the purpose of providing the Partner's services to the Merchant"), begründet aber keine Auftragsverarbeitung Shopifys für KYTH.
Getrennt davon zu sehen ist die Abrechnung der App-Tarife. Dort ist KYTH selbst Kunde von Shopify; das ist eine eigene Vertragsbeziehung von KYTH und keine Verarbeitung im Auftrag des Händlers.
Das ist eine Einordnung und kein Gutachten. Die zitierten Stellen sind belegt, die Schlussfolgerung daraus ist die Bewertung von KYTH; keiner der drei Texte ist anwaltlich geprüft. Wer sie anders trifft, stellt die Zeile zurück nach 6.3 — dann braucht es einen Vertrag nach Art. 28 Abs. 4 DSGVO zwischen KYTH und Shopify, und den gibt es nach heutigem Stand nicht.
- Cloudflare (Cloudflare, Inc., San Francisco, USA; in der EU Cloudflare Germany
GmbH, München) — autoritativer DNS-Dienst für die Zone
kyth.systems, mehr nicht. Nachgemessen am 26.07.2026: Die Namen der App lösen unmittelbar auf die IP-Adresse des Servers in Berlin auf. Der Datenverkehr zwischen dem Browser des Händlers und Kartuu läuft nicht über Cloudflare; ein Proxy-Modus ist für die App nicht eingeschaltet. Cloudflare beantwortet lediglich Namensauflösungen und verarbeitet dabei weder Verbindungs- noch Inhaltsdaten der Händler oder ihrer Kundschaft. Cloudflare ist deshalb kein Unterauftragsverarbeiter dieses Vertrages, und es entsteht über Cloudflare kein Drittlandbezug.
Anders liegt es bei der Unternehmenswebsite von KYTH unter kyth.systems und
www.kyth.systems: Diese Namen laufen im Proxy-Modus, dort verarbeitet Cloudflare
Verbindungsdaten. Das betrifft Kartuu nicht und ist Gegenstand der
Datenschutzerklärung jener Website, nicht dieses Vertrages.
Wird die App künftig auf den Proxy-Modus umgestellt, wird Cloudflare damit
Unterauftragsverarbeiter mit allen Folgen (Drittlandbetrachtung, Vertrag nach Art. 28
Abs. 4 DSGVO). Die Umstellung ist eine Einstellung, kein Umbau — sie darf deshalb erst
erfolgen, nachdem die Liste unter 6.3 ergänzt und der Händler nach 6.6 informiert
wurde.
- GitHub, Inc. (San Francisco, USA; Tochter der Microsoft Corporation) — privates
Quellcode-Repository und Bereitstellungsschlüssel. GitHub verarbeitet keine
Händler-, Kunden- oder Gutscheindaten. Zugangsgeheimnisse liegen ausschließlich in
der Bereitstellungsumgebung und sind von Repository und Container-Abbild
ausgeschlossen.
- cdn.shopify.com — die eingebettete Oberfläche lädt die Shopify-Bibliothek
„App Bridge“ direkt vom Shopify-CDN. Dieser Aufruf erfolgt aus dem Browser des
Händlers, nicht vom Server von KYTH. Übertragen werden dabei die Verbindungsdaten des
Händler-Browsers (IP-Adresse, Browserkennung) und die Herkunftsangabe. Übertragen
werden keine Kunden-, Bestell- oder Gutscheindaten und kein Token; das einzige
mitgegebene Attribut ist die öffentliche Anwendungskennung. Die Herkunftsangabe ist
durch die Richtlinie Referrer-Policy: strict-origin-when-cross-origin auf
https://kartuu.kyth.systems beschränkt, der Parameter ?shop= wird also nicht
mitübertragen. Empfänger ist Shopify — dieselbe Stelle, die die umgebende
Adminoberfläche ausliefert. Ein zusätzlicher Empfängerkreis entsteht dadurch nicht.
6.5 Ausdrücklich nicht beteiligt
Gesucht und nicht vorhanden: kein Versanddienstleister für E-Mail, kein externer Schrift- oder Symboldienst, kein Analyse- oder Tag-Dienst, kein externer Fehlererfassungsdienst. Die einzige HTTP-Bibliothek im Anwendungscode wird an genau zwei Stellen verwendet, und beide sprechen denselben Empfänger an: den Token-Endpunkt und die Admin-API des Händler-Shops.
Objektspeicher wird ausschließlich bei IONOS benutzt (6.3), in zwei getrennten Eimern. Mit dem Sicherungseimer spricht die Anwendung nicht; die Übertragung dorthin besorgt ein eigenes Sicherungsskript auf dem Server, das den Abzug verschlüsselt, bevor er den Server verlässt (§ 9.3 Nr. 2). Mit dem Eimer für die hochgeladenen Bildmotive spricht sie sehr wohl — sie legt dort ab, liest wieder und löscht beim Löschen eines Shops. Bis zu dieser Fassung stand hier, die Anwendung spreche mit keinem Objektspeicher; das trifft seit der Bildablage nicht mehr zu.
6.6 Änderungen und Widerspruchsrecht
KYTH informiert den Händler über die beabsichtigte Hinzuziehung eines weiteren oder
den Austausch eines bestehenden Unterauftragsverarbeiters mindestens 30 Tage vorher
in Textform an die vom Händler nach § 2a Nr. 4 hinterlegte Kontaktadresse. Ist diese
Adresse unzustellbar geworden, erfolgt die Information zusätzlich durch Veröffentlichung
unter https://kartuu.kyth.systems/rechtliches/auftragsverarbeitung; die Frist läuft
dann ab der Veröffentlichung.
Der Händler kann der Änderung innerhalb von 30 Tagen ab Zugang der Mitteilung aus einem sachlichen, datenschutzbezogenen Grund in Textform widersprechen. Einigen sich die Parteien nicht, kann der Händler die Nutzung der App beenden, indem er sie deinstalliert; die Löschung richtet sich dann nach § 9. Widerspricht der Händler nicht, gilt die Änderung als genehmigt.
Erfordert eine Änderung wegen einer unmittelbaren Gefahr für die Sicherheit oder Verfügbarkeit ein sofortiges Handeln, informiert KYTH den Händler gleichzeitig mit der Maßnahme, spätestens innerhalb von 24 Stunden. Der Händler kann der Maßnahme innerhalb von 14 Tagen ab Zugang der Mitteilung widersprechen. Im Fall des Widerspruchs beendet KYTH die Einbindung des Unterauftragsverarbeiters unverzüglich, oder der Händler kann den Vertrag mit sofortiger Wirkung beenden; die Löschung richtet sich dann nach § 9. Das Einspruchsrecht nach Art. 28 Abs. 2 Satz 2 DSGVO bleibt damit erhalten.
§ 7 Unterstützung bei den Rechten betroffener Personen
7.1 Grundsatz
Anträge betroffener Personen richten sich an den Händler als Verantwortlichen. Wendet sich eine betroffene Person unmittelbar an KYTH, leitet KYTH den Antrag unverzüglich an den Händler weiter und beantwortet ihn nicht selbst.
KYTH unterstützt den Händler mit geeigneten technischen und organisatorischen Maßnahmen dabei, seiner Pflicht zur Beantwortung nachzukommen (Art. 12 bis 23 DSGVO), soweit dem Händler das nicht bereits über seinen eigenen Shopify-Zugang möglich ist.
7.2 Was technisch bereitsteht
Kartuu ist an die von Shopify vorgeschriebenen Datenschutz-Webhooks angebunden:
| Webhook | Wirkung heute |
|---|---|
customers/data_request (Art. 15 DSGVO) |
Aus dem signaturgeprüften Inhalt werden zwei Angaben gelesen: die Kundenkennung und die E-Mail-Adresse. Die Auskunftsfunktion durchsucht damit die Gutscheintabelle — über die Kundenkennung den Käufer, über den Suchwert der Adresse die beschenkte Person. Zusammengestellt werden Empfängername, Adresse, Absendername und Grußtext, entschlüsselt; eine Auskunft in Base64 erfüllt Art. 15 nicht. Ausdrücklich nicht enthalten sind Gutscheincode und Abruf-Token: Beides sind Schlüssel zur Ware, und eine Auskunft, die ein Zahlungsmittel aushändigt, wäre ein Weg um jede Authentifizierung herum. Es wird ein Eintrag im Protokoll über Zugriffe auf geschützte Kundendaten erzeugt. Was der Webhook nicht tut — und das ist die wichtigste Zeile dieses Feldes: Er stellt die Auskunft niemandem zu. In der App gibt es keine Seite, auf der der Händler sie abrufen könnte, und es geht keine Nachricht an seine Kontaktadresse. Festgehalten wird die Tatsache der Anfrage und die Anzahl der gefundenen Datensätze; der Inhalt wird mit dem Aufruf verworfen. Die Herausgabe erfolgt auf Anforderung des Händlers in Textform an datenschutz@kyth.systems und von Hand, aus denselben Zeilen und mit derselben Funktion (§ 7.1, § 7.4). Bis zum 27.07.2026 stand hier, die Angaben würden „ausgegeben". Das war unzutreffend: Die Auskunft wurde berechnet und verworfen. Die Lücke steht in Anlage 2 Abschnitt 7.2. |
customers/redact (Art. 17 DSGVO) |
Gleicher Suchweg. Die gefundenen Zeilen werden anonymisiert und nicht gelöscht: Empfängername, E-Mail-Adresse samt Suchwert, Absendername und Grußtext werden geleert, die Kundennummer nur dann, wenn sie zu der gesuchten Person gehört. Der Gutschein selbst bleibt — Code, Zustand, Wert und Vorlagenabbild. Er ist bezahlt, und die beschenkte Person kann ihn morgen einlösen wollen; ein gelöschter Code wäre kein Datenschutz, sondern ein Vermögensschaden bei einem Dritten. Ein Nachdruck trägt danach keinen Empfängernamen mehr, und das ist die gewollte Folge. |
shop/redact |
Löscht sämtliche Daten des Shops, siehe § 9. |
Bis zu dieser Fassung stand hier, die Liste der Tabellen mit personenbezogenen Kundenfeldern sei leer und das Ergebnis folglich „nachweislich leer". Das war die zutreffende Antwort für den damaligen Funktionsumfang. Mit dem Bestellablauf ist die Liste nicht mehr leer, und beide Webhooks treffen Zeilen.
Eine Grenze, die hierher gehört, weil sie eine betroffene Person betrifft und nicht
eine Tabelle. Shopifys customers/redact und customers/data_request tragen
Kundenkennung und Adresse genau einer Person — der Person, die Shopify kennt. Eine
beschenkte Person hat nie bestellt und taucht dort nie auf; ihre Zeilen werden über diese
Webhooks nur dann getroffen, wenn ihre Adresse zufällig dieselbe ist. Der Suchweg über
die Adresse ist gebaut, sein Auslöser für eine dritte Person ist es nicht. Verlangt
eine beschenkte Person Auskunft oder Löschung, führt KYTH sie auf Weisung des Händlers
von Hand aus (§ 7.1). Das ist eine benannte Lücke und keine Zusage; sie steht auch in
Anlage 2 Abschnitt 7.2.
7.3 Berichtigung, Einschränkung, Übertragbarkeit
Zu den technischen Daten des Shops (Shop-Domain, Token, Zeitstempel) gibt es keine Angaben, die inhaltlich unrichtig sein könnten und die der Händler nicht selbst über Shopify korrigieren kann. Verlangt der Händler eine Einschränkung der Verarbeitung, setzt KYTH sie nach Absprache um; das praktisch wirksame Mittel ist die Deinstallation der App.
Anders liegt es seit dem Bestellablauf bei den Angaben zu einer bestellten Karte. Empfängername, Empfängeradresse, Absendername und Grußtext können unrichtig sein — sie stammen aus einem Formular, das ein Kunde ausgefüllt hat. In der App gibt es dafür keine Änderungsmöglichkeit, und zwar auch keine für den Händler: Die Anwendungsrolle darf diese Spalten zwar schreiben, eine Oberfläche dafür ist nicht gebaut. Eine Berichtigung erfolgt deshalb heute auf Nachricht in Textform an datenschutz@kyth.systems und von Hand. Bis eine Bearbeitungsmöglichkeit in der App besteht, ist das der einzige Weg — er steht deshalb hier und nicht nur in Anlage 2 Abschnitt 7.2.
Ausnahme: die hochgeladenen Bildmotive. Sie sind der einzige gespeicherte Bestand mit frei bestimmbarem Inhalt, und für sie gibt es in der App keine Löschmöglichkeit — weder für ein einzelnes Bild noch für alle. Verlangt der Händler die Entfernung eines Motivs, etwa weil darauf eine Person zu sehen ist, die widersprochen hat, genügt eine Nachricht in Textform an datenschutz@kyth.systems; KYTH entfernt das Objekt und seine Zeile von Hand und bestätigt das. Bis eine Löschfunktion in der App besteht, ist das der einzige Weg — er steht deshalb hier und nicht nur in § 9.3 Nr. 6.
7.4 Aufwand
Die Unterstützung nach diesem Paragraphen erbringt KYTH unentgeltlich, im Rahmen dessen, was Art. 28 Abs. 3 lit. e DSGVO verlangt. Eine Vergütung für darüber hinausgehenden Aufwand ist nicht vereinbart und wird nicht verlangt.
§ 8 Unterstützung bei Sicherheit, Datenpannen und Datenschutz-Folgenabschätzung
8.1 Sicherheit der Verarbeitung (Art. 32 DSGVO)
KYTH unterhält die in Anlage 2 beschriebenen Maßnahmen und überprüft sie anlassbezogen, insbesondere bei jeder Erweiterung des Funktionsumfangs.
8.2 Verletzungen des Schutzes personenbezogener Daten (Art. 33, 34 DSGVO)
KYTH meldet dem Händler jede Verletzung des Schutzes personenbezogener Daten, die Daten aus dessen Shop betrifft, unverzüglich nach Bekanntwerden in Textform an die vom Händler nach § 2a Nr. 4 hinterlegte Kontaktadresse. Die Meldung enthält, soweit bekannt:
- Beschreibung der Art der Verletzung, die Kategorien und die ungefähre Zahl der betroffenen Personen und Datensätze,
- Kontaktstelle für weitere Auskünfte (datenschutz@kyth.systems),
- die wahrscheinlichen Folgen,
- die ergriffenen und die vorgeschlagenen Gegenmaßnahmen.
Sind noch nicht alle Angaben verfügbar, meldet KYTH zunächst den bekannten Sachverhalt und liefert das Übrige unverzüglich nach. Die Meldung an die Aufsichtsbehörde und die Benachrichtigung betroffener Personen obliegen dem Händler (§ 2a Nr. 6); KYTH unterstützt ihn dabei mit den vorliegenden Informationen.
Grenze dieser Zusage. Der Kanal zum Händler steht, weil die Kontaktadresse beim
Vertragsschluss erhoben wird (§ 0.2, § 2a Nr. 4). Er hängt aber daran, dass der Händler
sie aktuell hält. Ist die hinterlegte Adresse unzustellbar geworden, kann KYTH ihn nicht
mehr unmittelbar erreichen; KYTH veröffentlicht die Meldung dann unter
https://kartuu.kyth.systems/rechtliches/auftragsverarbeitung und weist in der
eingebetteten Oberfläche darauf hin. Das ersetzt eine unmittelbare Benachrichtigung
nicht — die 72-Stunden-Frist des Händlers nach Art. 33 Abs. 1 DSGVO lässt sich auf
diesem Weg nicht zuverlässig wahren.
KYTH unterhält einen dokumentierten Ablaufplan für Sicherheitsvorfälle mit Eskalationsstufen, benannten Zuständigkeiten, der 72-Stunden-Frist des Art. 33 DSGVO und der zuständigen Aufsichtsbehörde (Bayerisches Landesamt für Datenschutzaufsicht, BayLDA).
8.3 Datenschutz-Folgenabschätzung und vorherige Konsultation (Art. 35, 36 DSGVO)
Führt der Händler eine Datenschutz-Folgenabschätzung durch oder konsultiert er die Aufsichtsbehörde, stellt KYTH auf Anfrage die dafür erforderlichen Informationen über die Verarbeitung durch Kartuu zur Verfügung — insbesondere die Anlagen 1 und 2 dieses Vertrages sowie Auskunft über die eingesetzten Unterauftragsverarbeiter.
§ 9 Löschung oder Rückgabe nach Ende der Verarbeitung
9.1 Was wann geschieht
| Ereignis | Wirkung |
|---|---|
Deinstallation der App (Webhook app/uninstalled) |
Access-Token und Refresh-Token werden sofort auf NULL gesetzt, der Zeitpunkt der Deinstallation wird vermerkt. Der Zugriff auf den Shop ist damit beendet. Die Datenzeile des Shops bleibt zunächst bestehen — samt Kontaktadresse und Zustimmungsnachweis, damit eine Neuinstallation innerhalb der Frist nach 9.3 Nr. 1 keine erneute Zustimmung erfordert. |
Löschung des Shops (Webhook shop/redact, den Shopify regelmäßig 48 Stunden nach der Deinstallation sendet) |
Zuerst die hochgeladenen Bildmotive im Objektspeicher, danach die Daten in der Datenbank. Letztere in einer Transaktion: zunächst alle Zeilen jeder Tabelle mit einer Shop-Zuordnung, danach die Datenzeile des Shops selbst — entweder verschwindet der Shop vollständig oder gar nicht. Die Reihenfolge ist zwingend, siehe 9.3 Nr. 6. |
Ausbleiben von shop/redact |
Ein Aufräumlauf löscht die Shop-Zeile 30 Tage nach der Deinstallation über denselben Löschpfad — einschließlich der Bildmotive im Objektspeicher und in derselben Reihenfolge: zuerst die Objekte, dann die Zeilen. Er läuft seit dem 01.08.2026 täglich, siehe § 9.3 Nr. 1. |
| Verbindung kam nie zustande (Zustimmung erteilt, Token-Abruf gescheitert — es gibt deshalb keinen Deinstallationszeitpunkt) | Derselbe Aufräumlauf löscht die Shop-Zeile 90 Tage nach dem letzten Lebenszeichen, sofern weder Access- noch Refresh-Token hinterlegt sind. Siehe 9.3 Nr. 1. |
| Abgeschlossene Webhook-Kennungen | werden 30 Tage nach Abschluss entfernt, unabhängig vom Shop. Siehe 9.3 Nr. 3. |
Löschung einer einzelnen Person (Webhook customers/redact) |
Die Gutscheinzeilen dieser Person werden anonymisiert, nicht gelöscht: Empfängername, E-Mail-Adresse samt Suchwert, Absendername und Grußtext werden geleert, die Kundennummer nur dann, wenn sie zu dieser Person gehört. Der bezahlte Gutschein bleibt bestehen. Einzelheiten und die Begründung in § 7.2. |
| Einlösung, Ablauf oder Storno eines einzelnen Gutscheins | Nichts. Es gibt keinen Lauf, der Gutscheine nach Zweckfortfall entfernt. Sie liegen, bis der Shop verschwindet — siehe § 9.3 Nr. 7. |
Die zu leerenden Tabellen werden dabei nicht aus einer gepflegten Liste, sondern zur
Laufzeit aus dem Datenbankkatalog ermittelt. Erfasst werden alle Tabellen im Schema
public, die eine Spalte mit dem Namen shop_id tragen. Innerhalb dieser Grenze
verhindert das, dass eine neu hinzugekommene Tabelle beim Löschen vergessen wird. Der
Aufräumlauf nach 9.3 Nr. 1 benutzt genau denselben Pfad: Es gibt eine Löschlogik, nicht
zwei, weil zwei mit der Zeit auseinanderlaufen.
Die drei Tabellen des Bestellablaufs sind auf genau diesem Weg mitgekommen — die
Gutscheine, die Zuordnung ihrer Bildmotive und die Gutscheinprodukte tragen alle eine
shop_id, es musste nichts nachgetragen werden. Genau dafür ist der Mechanismus da. Eine
Besonderheit bringt der Bestellablauf trotzdem mit: Die Zuordnungstabelle der Bildmotive
zeigt per Fremdschlüssel auf die Bildtabelle, damit sich ein Motiv, das ein ausgestellter
Gutschein benutzt, nicht löschen lässt. Die Tabellen werden alphabetisch geleert, die
Bildtabelle also vor ihr — bei sofortiger Prüfung scheiterte damit die Löschung jedes
Shops, der je einen Gutschein mit einem Motiv ausgestellt hat, und zwar ausgerechnet bei
den aktivsten Händlern. Die Prüfung ist deshalb bis zum Abschluss der Transaktion
aufgeschoben; dann sind beide Seiten weg. Die eine Transaktion aus dem Absatz oben ist
damit nicht mehr nur eine Annehmlichkeit, sondern Voraussetzung.
Was der Mechanismus nicht erfasst — diese Grenzen sind im Quelltext ausdrücklich festgehalten:
- Tabellen in einem anderen Schema als
public, - Tabellen, deren Shop-Spalte anders heißt als
shop_id, - Views mit einer
shop_id-Spalte, auf denen ein Löschbefehl scheitert oder ungewollt auf die Basistabelle durchschlägt, - Tabellen ohne eigene
shop_id, die nur über einen Fremdschlüssel an einer Shop-Tabelle hängen — sie verschwinden nur mit, wenn dieser Fremdschlüssel eine Löschweitergabe trägt.
Für diese vier Fälle muss die Löschung gesondert sichergestellt werden. Der heutige Datenbestand fällt vollständig in den erfassten Bereich; die Einschränkung wird mit jeder neuen Tabelle wichtiger.
Fünfter Fall, und er betrifft keine Tabelle: Der Mechanismus erfasst ausschließlich Zeilen in der Datenbank. Die Bytes der hochgeladenen Bildmotive liegen nicht dort, sondern im Objektspeicher; sie werden deshalb auf einem eigenen Weg gelöscht — über den Namensraum des Shops und nicht über die Liste seiner Zeilen. Was das leistet und was nicht, steht in 9.3 Nr. 6.
9.2 Löschung oder Rückgabe — der Händler wählt
Nach Beendigung der Verarbeitung löscht KYTH sämtliche Daten des Händlers oder gibt sie nach Wahl des Händlers heraus (Art. 28 Abs. 3 lit. g DSGVO).
Der Händler teilt seine Wahl vor der Deinstallation oder innerhalb von 14 Tagen danach in Textform an datenschutz@kyth.systems mit. Ohne Mitteilung löscht KYTH.
Verlangt der Händler die Herausgabe, stellt KYTH die zu seinem Shop gespeicherten Daten innerhalb von 14 Tagen nach Zugang der Mitteilung in einem gängigen maschinenlesbaren Format (JSON) bereit. Eine automatische Ausleitung ist nicht umgesetzt; KYTH stellt die Daten in diesem Fall von Hand zusammen. Beim heutigen Umfang ist das eine überschaubare Menge.
Zur Einordnung: Zu den technischen Daten des Shops — Shop-Domain, deren Hash, verschlüsselte Zugangstoken, verschlüsselte Kontaktadresse, Zustimmungsnachweis, zuletzt gelesener Abonnementstand, technische Zeitstempel und die Einträge des Protokolls über Zugriffe auf geschützte Kundendaten — gilt: Für den Händler haben sie außerhalb von Kartuu voraussichtlich wenig Nutzen, und die Zugangstoken sind nach der Deinstallation ohnehin ungültig. Das ist eine Einschätzung — die Wahl bleibt beim Händler.
Anders bei den Gutscheindaten, und hier ist die Wahl praktisch relevant. Sie sind Belege über eingegangene Verpflichtungen: Wer welchen Gutschein über welchen Betrag bekommen hat und ob er eingelöst ist. Verlangt der Händler die Herausgabe, gibt KYTH sie in JSON heraus, mit den verschlüsselten Feldern entschlüsselt — ein Chiffrat wäre keine Herausgabe. Der Gutscheincode gehört ausdrücklich dazu, denn ohne ihn wäre die Aufstellung für den Händler wertlos: Er kann ihn bei Shopify nicht mehr auslesen. Die Herausgabe geht ausschließlich an den Händler als Verantwortlichen und ausschließlich an die nach § 2a Nr. 4 hinterlegte Kontaktadresse.
Anders bei den hochgeladenen Bildmotiven: Sie sind der eine gespeicherte Bestand, der außerhalb von Kartuu einen Wert hat, denn es sind die Dateien des Händlers. Verlangt er die Herausgabe, gibt KYTH sie als Dateien heraus — im hochgeladenen Format, also nicht in JSON verpackt. Eine Ausnahme gilt für SVG-Motive: Herausgegeben wird die bereinigte Fassung, denn nur die ist gespeichert (Anlage 2 Abschnitt 2.6). Die Ausgangsdatei liegt beim Händler und ist bei KYTH zu keinem Zeitpunkt aufbewahrt worden.
9.3 Vernichtung vorhandener Kopien — verbindliche Fristen
Art. 28 Abs. 3 lit. g DSGVO verlangt, dass KYTH nach Beendigung der Verarbeitung auch die vorhandenen Kopien vernichtet, soweit keine gesetzliche Aufbewahrungspflicht besteht. KYTH sagt dafür die folgenden Fristen zu.
Übersicht:
| Was | Frist | Wodurch |
|---|---|---|
| Shop-Zeile samt allen Daten mit Shop-Zuordnung | mit shop/redact, spätestens 30 Tage nach der Deinstallation |
Webhook, ersatzweise Aufräumlauf (Nr. 1) |
| Shop-Zeile ohne je zustande gekommene Verbindung (kein Deinstallationszeitpunkt, kein Token) | 90 Tage nach dem letzten Lebenszeichen | derselbe Aufräumlauf, zweite Regel (Nr. 1) |
| Gutscheine samt Empfänger- und Absenderangaben, Grußtext und Code | keine eigene Frist — sie verschwinden mit dem Shop nach der ersten Zeile dieser Tabelle | Löschpfad (Nr. 7) |
| Empfänger- und Absenderangaben einer einzelnen Person | mit dem Eingang eines Löschverlangens nach Art. 17 | Anonymisierung über customers/redact bzw. von Hand (Nr. 7, § 7.2) |
| Hochgeladene Bildmotive im Objektspeicher | mit shop/redact; bleibt der Webhook aus, mit dem Aufräumlauf nach Nr. 1, der seit dem 01.08.2026 täglich läuft |
eigener Löschschritt über den Namensraum des Shops, in beiden Fällen derselbe (Nr. 6) |
| Sicherung auf dem Server | 30 Tage | Aufräumschritt im Sicherungsskript (Nr. 2) |
| Sicherung im Objektspeicher | 90 Tage | Aufräumschritt im Sicherungsskript und Lebenszyklusregel im Eimer (Nr. 2) |
| Kennungen eingehender Webhooks | 30 Tage nach Abschluss | eigener Aufräumlauf (Nr. 3) |
| Anwendungs- und Containerprotokolle | 14 Tage | Einstellung im Betriebswerkzeug (Nr. 4) |
- Wenn
shop/redactausbleibt: 30 Tage. Bleibt der Webhook aus — die Zustellung geht verloren, der Endpunkt ist vorübergehend nicht erreichbar, Shopify meldet ihn nie —, löscht ein Aufräumlauf die Shop-Zeile 30 Tage nach dem Deinstallationszeitpunkt vollständig, über denselben Löschpfad wieshop/redact. Die Frist ist bewusst deutlich länger als die 48 Stunden des Regelwegs: Wer die App versehentlich deinstalliert und in derselben Woche neu installiert, soll seine Zustimmung und seine Kontaktadresse nicht verloren haben. Zweiter Fall desselben Aufräumlaufs: nie zustande gekommene Verbindungen — 90 Tage. Die Frist oben rechnet ab dem Deinstallationszeitpunkt. Es gibt eine Lage, in der es diesen Zeitpunkt nie gibt: Der Händler stimmt zu, KYTH legt den Datensatz zum Shop an, und der unmittelbar folgende Abruf des Zugangstokens bei Shopify scheitert — etwa weil der Händler zwischenzeitlich deinstalliert hat oder das Netz ausfiel. Eine Deinstallationsmeldung kommt für diesen Datensatz nie, weil die App gar nicht (mehr) installiert ist. Damit er nicht dauerhaft stehen bleibt, löscht derselbe Aufräumlauf über denselben Löschpfad einen Datensatz, der keinen Deinstallationszeitpunkt trägt, kein Zugangs- und kein Erneuerungstoken hat und dessen letztes Lebenszeichen länger als 90 Tage zurückliegt. Ohne beide Token ist belegt, dass kein Zugriff auf den Shop mehr möglich ist. Die Frist ist bewusst länger als die 30 Tage oben: Sie rechnet ab einem schwächeren Anhaltspunkt als einer gemeldeten Deinstallation.
Was auch diese Regel nicht erfasst: einen Datensatz, dessen Token noch stehen, obwohl der Shop längst deinstalliert ist — möglich, wenn die Deinstallationsmeldung den Shop wegen eines nach einem Schlüsselwechsel veralteten Suchhashes nicht auflösen konnte. Ein solcher Datensatz ist von dem eines arbeitenden Shops nicht zu unterscheiden; eine Regel, die ihn träfe, träfe auch arbeitende Shops. Dieser Fall wird dort behoben, wo er entsteht (Neuberechnen der Suchhashes nach einem Schlüsselwechsel), und steht in der Liste offener Punkte.
Der Auslöser ist seit dem 01.08.2026 eingerichtet. Ein Aufräumlauf startet mit dem Anwendungsprozess und ruft beide Regeln alle 24 Stunden auf (
kaspar/aufraeumlauf.py, gestartet im Lebenszyklus der Anwendung). Bis dahin war die Löschung gebaut und geprüft, wurde aber von nichts aufgerufen — die Frist war eine Absicht und keine Wirklichkeit. Dasselbe gilt jetzt auch für Nr. 3, die denselben Lauf benutzt. 2. Sicherungen: 30 Tage lokal, 90 Tage im Objektspeicher. Es wird täglich nachts eine vollständige Sicherung der Datenbank erstellt und mit AES-256 verschlüsselt, bevor sie den Server verlässt. Sie liegt auf dem Server (Aufbewahrung 30 Tage) und im Objektspeicher der IONOS in Berlin (Aufbewahrung 90 Tage). Im Eimer wirkt zusätzlich eine Lebenszyklusregel (sicherungen-nach-90-tagen-loeschen, gesamter Eimer, Ablauf 90 Tage nach Erstellung), die auf Speicherebene löscht — unabhängig davon, ob der Aufräumschritt des Sicherungsskripts läuft. Aufräumjobs fallen still aus; eine Lebenszyklusregel nicht.
Der Abzug ist verschlüsselt, seit dem 01.08.2026. Er wird symmetrisch mit AES-256 verschlüsselt, bevor er den Server verlässt; das Kennwort liegt auf dem Server und nicht im Objektspeicher. Zuvor lag er dort im Klartext — die feldweise verschlüsselten Werte darin verschlüsselt, alles Übrige offen. Die damals abgelegten Sicherungen sind nachträglich verschlüsselt und in ihrer offenen Fassung gelöscht worden. Dass sich eine Sicherung einspielen lässt, ist am selben Tag durch eine tatsächliche Wiederherstellung geprüft worden, und ein täglicher Prüflauf meldet ausgebliebene Sicherungen.
Ausdrücklich, weil es für den Händler zählt: Wird ein Shop gelöscht — durch
shop/redact, durch den Aufräumlauf nach Nr. 1 oder auf Verlangen des Händlers —,
bleiben seine Daten in bereits erstellten Sicherungen enthalten und verschwinden
von dort erst mit dem Ablauf der genannten Fristen: spätestens 30 Tage später auf dem
Server, spätestens 90 Tage später im Objektspeicher. Ein gezieltes Herausschneiden
einzelner Datensätze aus vorhandenen Sicherungen findet nicht statt; es würde die
Sicherung als Wiederherstellungspunkt entwerten. Solange die Daten dort liegen, werden
sie ausschließlich zur Wiederherstellung im Störungsfall verwendet.
Zur Verschlüsselung — was KYTH zusagt und was nicht. Die Übertragung zum Objektspeicher erfolgt mit TLS 1.3. IONOS verschlüsselt ruhende Objekte mit AES-256; KYTH sagt das nicht als eigene Maßnahme zu, weil die Dokumentation von IONOS die Standardverschlüsselung für Uploads über die Weboberfläche beschreibt und nicht belegt ist, ob der Sicherungslauf über die S3-Schnittstelle dieselbe Verschlüsselung anfordert; eine Standardverschlüsselung auf Ebene des Eimers bietet IONOS nicht an. Was KYTH zusagt und was tatsächlich trägt: Die schutzbedürftigen Felder — die Zugangstoken und die Kontaktadresse des Händlers — liegen innerhalb der Sicherung feldweise mit AES-256-GCM verschlüsselt, und der Schlüssel steht in der Umgebung der Anwendung, nicht in der Sicherung und nicht bei IONOS. Wer die Sicherungsdatei erlangt, erhält für diese Felder kein Klartextergebnis. Nicht verschlüsselt sind die übrigen Felder, insbesondere die Shop-Domain im Klartext, die Zeitstempel und die Fassungskennung der Zustimmung; die Sicherungsdatei als Ganzes ist von KYTH nicht verschlüsselt. 3. Technische Webhook-Kennungen: 30 Tage nach Abschluss. Die Tabelle mit den Kennungen eingehender Webhooks (Duplikatschutz) trägt keine Shop-Zuordnung und wird vom Löschvorgang des Shops nicht erfasst. Ein eigener Aufräumlauf entfernt einen abgeschlossenen Eintrag 30 Tage nach seinem Abschluss. Shopify wiederholt einen Webhook über höchstens 48 Stunden; die 30 Tage sind Puffer für die Frage, ob ein Webhook je angekommen ist. Inhaltlich sind das ausschließlich von Shopify vergebene technische Kennungen ohne Personenbezug.
Benannte Ausnahme: Einträge, deren Verarbeitung nie abgeschlossen wurde — etwa
weil ein Prozess abgebrochen ist —, werden von diesem Lauf nicht entfernt. Sie zu
löschen hieße, eine Wiederholung desselben Webhooks ein zweites Mal durchlaufen zu
lassen. Personenbezug haben sie nicht.
4. Anwendungs- und Containerprotokolle: 14 Tage. Sie enthalten die Shop-Domain, die
interne Shop-Kennung, im Bestellablauf zusätzlich Bestell-, Positions- und
Gutscheinkennung sowie den Fehlergrund als kurze eigene Kennung, und den Typ
aufgetretener Ausnahmen — keine Token, keine Kontaktadresse, keinen Gutscheincode,
keinen Empfänger- oder Absendernamen, keinen Grußtext und keine Kundenadresse. Nach
14 Tagen werden sie verworfen. Die Frist wird im Betriebswerkzeug eingestellt, nicht
im Programm; sie steht hier, weil sie gilt.
5. Protokoll über Zugriffe auf geschützte Kundendaten. Es trägt eine Shop-Zuordnung
und verschwindet deshalb vollständig mit dem Shop — über shop/redact und über den
Aufräumlauf nach Nr. 1. Eine eigene Frist ist dafür weder nötig noch zulässig: Ein
früheres Löschen würde die Nachweisauflage aus der Shopify-Freigabe verletzen, ein
späteres wäre eine Aufbewahrung ohne Shop und ohne Zweck.
6. Hochgeladene Bildmotive: mit shop/redact, und zwar vor allem anderen. Die
Bildmotive haben keine eigene Frist. Sie werden aufbewahrt, solange der Händler die
App benutzt — ein Logo, das nach 30 Tagen verschwindet, wäre eine Karte, die von
selbst kaputtgeht —, und mit dem Shop gelöscht.
Wie gelöscht wird: über den Namensraum, nicht über die Liste. Jedes Objekt eines Shops liegt unter einem Schlüssel, der mit der Kennung dieses Shops beginnt. Gelöscht wird alles unter diesem Anfang. Der Weg über die Tabellenzeilen wäre der naheliegende und der schlechtere: Bricht ein Upload zwischen dem Ablegen des Objekts und dem Schreiben seiner Zeile ab, gibt es ein Objekt ohne Zeile — es stünde in keiner Liste und bliebe genau deshalb liegen. Über den Namensraum wird es mitgelöscht.
Warum die Objekte zuerst gelöscht werden und die Zeilen danach. Die umgekehrte Reihenfolge ließe sich nicht heilen: Verschwänden die Zeilen zuerst und scheiterte danach der Objektspeicher, meldete KYTH einen Fehlschlag, Shopify wiederholte den Webhook — und die Wiederholung fände den Shop nicht mehr, meldete „nichts zu löschen" und ließe die Bilder für immer liegen. Ein Foto, das nach einer gemeldeten Löschung noch da ist, ist genau der Befund, den dieser Vertrag ausschließt.
Zwei benannte Grenzen, und beide gehören hierher:
a) Der Aufräumlauf nach Nr. 1 geht denselben Weg und läuft seit dem 01.08.2026.
Er löscht einen verwaisten Shop in genau der Reihenfolge dieses Abschnitts: zuerst
die Objekte über den Namensraum, dann die Datenbankzeilen. Bis zur Fassung 1.1
stand hier das Gegenteil, und es traf zu: Der Lauf entfernte nur die Zeilen und
ließ die Bilder liegen — dauerhaft, denn er greift ja gerade dann, wenn
shop/redact ausgeblieben ist, es also niemanden mehr gibt, der es nachholte.
Diese Lücke ist geschlossen. Scheitert der Objektspeicher, bleibt die Shop-Zeile
stehen und der Shop bleibt Kandidat für den nächsten Lauf; auch das ist dieselbe
Entscheidung wie beim Webhook. Was bleibt: Der Aufräumlauf hat weiterhin keinen
Auslöser (Nr. 1). Solange das so ist, hängt die Löschzusage für die Bilder an der
tatsächlichen Zustellung von shop/redact — nicht mehr am fehlenden Löschschritt,
sondern am fehlenden Zeitplan.
b) Verwaiste Objekte werden nicht aufgeräumt. Lädt ein Händler ein Motiv hoch und
benutzt es nie oder nicht mehr, bleibt es liegen, solange sein Shop besteht. Es
gibt keinen Lauf, der ungenutzte Objekte sucht und entfernt, und es gibt auch
keine Stelle in der App, an der ein Händler ein einzelnes Bild löschen kann. Wer
das verlangt, wendet sich an datenschutz@kyth.systems (§ 7.3); die Löschung
erfolgt dann von Hand. Auch das ist eine benannte Grenze und keine Zusage.
7. Gutscheine, Empfänger- und Absenderangaben: keine eigene Frist — und das ist eine
offene Stelle, keine Zusage. Die Zeilen des Bestellablaufs tragen eine
Shop-Zuordnung und verschwinden deshalb vollständig mit dem Shop, über shop/redact
wie über den Aufräumlauf nach Nr. 1. Darüber hinaus gilt heute:
a) Zweckfortfall löst nichts aus. Ein eingelöster, ein abgelaufener und ein stornierter Gutschein bleiben stehen, solange der Shop besteht. Es gibt keinen Lauf, der sie sucht und entfernt. Das ist bei einem Gutschein nicht selbstredend falsch — er ist der Beleg über eine eingegangene Verpflichtung, und Belege sind aufzubewahren —, aber wie lange, ist nicht festgelegt. Die Frist folgt nicht aus dem Quelltext, sondern aus handels- und steuerrechtlichen Aufbewahrungspflichten und aus der Verjährung des Anspruchs. Solange sie fehlt, ist dieser Abschnitt für die größte neue Datenkategorie ohne Frist, und das benennen wir, statt eine zu erfinden.
b) Die Löschung einer einzelnen Person löscht die Zeile nicht. Sie leert die personenbezogenen Felder und lässt Code, Zustand, Wert und Vorlagenabbild stehen (§ 7.2). Das ist Absicht: Der Gutschein ist bezahlt, und ein gelöschter Code wäre ein Vermögensschaden bei einem Dritten.
c) Für die beschenkte Person fehlt der Auslöser. Der Suchweg über den Suchwert ihrer Adresse ist gebaut; ein Weg, über den der Händler eine Löschung für sie auslösen könnte, ist es nicht. Bis dahin führt KYTH sie auf Weisung von Hand aus.
Die drei Punkte stehen auch in Anlage 2 Abschnitt 7.2.
Nach dem Zweckfortfall: drei Jahre, dann anonym. Ist ein Gutschein eingelöst, abgelaufen oder storniert, werden seine personenbezogenen Angaben drei Jahre nach diesem Zustandswechsel geleert: Empfänger, dessen Adresse und deren Suchwert, Absender, Grußtext, Käufer, dessen Adresse und die Kundennummer. Der Gutschein selbst bleibt bestehen - Code, Zustand und Wert -, denn er ist der Beleg über eine eingegangene Verpflichtung.
Maßgeblich ist die Verjährung, nicht die Buchführung. Drei Jahre sind die Regelverjährung des Anspruchs aus dem Gutschein (§ 195 BGB). Die handels- und steuerrechtlichen Fristen von sechs und zehn Jahren gelten für Buchungsbelege; die liegen beim Händler in seinem Shopify-Konto. Was KYTH hält, sind Namen, Adressen und ein Grußtext - dafür wären zehn Jahre nicht zu begründen.
Gerechnet ab dem Zustandswechsel und nicht ab dem Kauf. Ein Gutschein, der zwei Jahre in der Schublade lag und dann eingelöst wurde, hat danach noch drei.
Ausgeführt wird das täglich vom selben Aufräumlauf wie Nr. 1 und Nr. 3
(kaspar/db/aufraeumen.py::anonymisiere_alte_gutscheine). Am 03.08.2026 auf der
Testumgebung nachgemessen: Ein vier Jahre altes Stück wurde vollständig
anonymisiert, ein ein Jahr altes blieb unberührt, der Code beider blieb
erhalten, und ein zweiter Lauf fand nichts mehr.
9.4 Gesetzliche Aufbewahrung
Besteht ausnahmsweise eine gesetzliche Pflicht zur weiteren Aufbewahrung, unterbleibt insoweit die Löschung; die Daten werden in ihrer Verarbeitung eingeschränkt und ausschließlich zu diesem Zweck verwendet. KYTH teilt dem Händler eine solche Aufbewahrung mit.
§ 10 Nachweise und Prüfrechte des Verantwortlichen
10.1 Nachweise
KYTH stellt dem Händler auf Anfrage an datenschutz@kyth.systems alle Informationen zur Verfügung, die zum Nachweis der Einhaltung der Pflichten aus Art. 28 DSGVO erforderlich sind. Regelmäßig genügen dafür:
- dieser Vertrag mit Anlage 1 (Verarbeitungsübersicht) und Anlage 2 (technische und organisatorische Maßnahmen),
- die aktuelle Liste der Unterauftragsverarbeiter,
- der Ablaufplan für Sicherheitsvorfälle,
- Auskunft über die zum Shop des Händlers gespeicherten Daten.
10.2 Prüfungen
Reichen diese Nachweise im Einzelfall nicht aus, ermöglicht KYTH Überprüfungen einschließlich Inspektionen und trägt zu ihnen bei (Art. 28 Abs. 3 lit. h DSGVO). Der Händler kann die Prüfung selbst durchführen oder einen von ihm beauftragten Prüfer einsetzen, der nicht in Wettbewerb zu KYTH steht und zur Verschwiegenheit verpflichtet ist.
Prüfungen erfolgen nach Ankündigung mit angemessenem Vorlauf — in der Regel 30 Tage —, zu üblichen Geschäftszeiten, ohne Störung des Betriebsablaufs und höchstens einmal je Kalenderjahr; bei einem konkreten Anlass, insbesondere nach einer Verletzung des Schutzes personenbezogener Daten oder auf Verlangen einer Aufsichtsbehörde, auch darüber hinaus und kurzfristig.
10.3 Was eine Prüfung nicht umfassen kann
- Zertifikate: KYTH hält keine. Es kann kein Prüfbericht vorgelegt werden, den es nicht gibt (siehe § 5).
- Rechenzentrum: Die Serverinfrastruktur ist bei der IONOS SE angemietet. Eine Prüfung vor Ort im Rechenzentrum kann KYTH nicht gewähren; hierfür ist auf die Nachweise und Zertifizierungen von IONOS zu verweisen.
- Daten anderer Händler: Eine Prüfung darf nicht dazu führen, dass der Prüfer Zugang zu Daten anderer Händler erhält. KYTH wird Zugriffe entsprechend beschränken.
10.4 Behörden
KYTH unterstützt den Händler bei Prüfungen durch die zuständige Aufsichtsbehörde und erteilt dieser auf Verlangen unmittelbar Auskunft (Art. 31 DSGVO). KYTH informiert den Händler unverzüglich über behördliche Maßnahmen, die dessen Daten betreffen, soweit das rechtlich zulässig ist.
§ 11 Rangfolge und Schlussbestimmungen
- Dieser Vertrag geht den übrigen Vertragsbedingungen zwischen den Parteien vor, soweit es um die Verarbeitung personenbezogener Daten im Auftrag geht.
- Die Anlagen 1 und 2 sind Bestandteil dieses Vertrages.
- Änderungen und Ergänzungen bedürfen der Textform. Das gilt auch für die Aufhebung dieses Formerfordernisses.
- Ist eine Bestimmung unwirksam, bleibt der übrige Vertrag wirksam. Die Parteien ersetzen die unwirksame Bestimmung durch eine wirksame, die dem verfolgten Zweck am nächsten kommt.
- Es gilt deutsches Recht. Gerichtsstand ist, soweit gesetzlich zulässig, der Sitz von KYTH.
- Fortschreibungspflicht: Vertrag und Anlagen bilden den Quelltextstand vom 27.07.2026 ab. Vor jeder Erweiterung, die den Kreis der verarbeiteten Daten verändert — insbesondere der Versand von E-Mail, die Entgegennahme von Zugangsdaten des Händlers für dessen Versandinfrastruktur, die Route hinter dem Abruflink und die Übernahme eines Wunschversanddatums — sind Anlage 1 und Anlage 2 gegen den dann geltenden Quelltext neu zu erheben.
Diese Pflicht ist bereits einmal verletzt worden, und der Vorgang gehört hierher, weil er die Regel begründet: Der Bestellablauf wurde in vier Schritten gebaut, ohne dass Vertrag und Anlagen mitgeführt wurden. Anlage 1 Abschnitt C führte Bestell- und Kundendaten in dieser Zeit weiterhin als „beantragt, nicht verarbeitet", während sie bereits verarbeitet und gespeichert wurden. Nachgeführt ist das mit dieser Fassung; ausgeliefert wurde der falsche Text nie (Schlusshinweis).
§ 12 Was Sie als Händler tun müssen
Die Pflichten aus § 2a stehen dort im Vertragston. Hier stehen sie noch einmal kurz und im Klartext, damit Sie nach dem Lesen wissen, was Sie übernommen haben.
- Halten Sie Ihre Kontaktadresse aktuell. Die E-Mail-Adresse, die Sie beim Verbinden der App angegeben haben, ist unser einziger Weg zu Ihnen — bei einer Datenpanne, bei einer Vertragsänderung, bei einem Wechsel eines Unterauftragsverarbeiters. Ändert sie sich, schreiben Sie uns an datenschutz@kyth.systems. Wird sie unzustellbar, erreichen wir Sie nicht mehr, und die 72 Stunden aus Art. 33 Abs. 1 DSGVO laufen trotzdem (§ 2a Nr. 4, § 8.2).
- Sorgen Sie für die Rechtsgrundlage. Für die Verarbeitung der Daten Ihrer Kundschaft brauchen Sie eine Rechtsgrundlage nach Art. 6 DSGVO. Wir prüfen sie nicht und können sie nicht prüfen.
- Informieren Sie Ihre Kundschaft und die Beschenkten. Die Informationspflichten nach Art. 13 und Art. 14 DSGVO treffen Sie, nicht uns. Beschenkte geben ihre Daten nicht selbst — dafür gilt Art. 14 DSGVO. Nehmen Sie Kartuu in Ihre eigene Datenschutzerklärung auf.
- Beantworten Sie Anfragen betroffener Personen selbst. Wendet sich jemand an uns, leiten wir die Anfrage an Sie weiter und beantworten sie nicht (§ 7.1).
- Melden Sie Datenpannen selbst an Ihre Aufsichtsbehörde. Wir melden Ihnen den Vorfall; die Meldung nach Art. 33 DSGVO und die Benachrichtigung der Betroffenen nach Art. 34 DSGVO machen Sie (§ 8.2).
- Erteilen Sie Weisungen in Textform. Einzelweisungen gehen an datenschutz@kyth.systems. Was Sie mündlich sagen, bestätigen Sie uns bitte unverzüglich in Textform (§ 3.2).
Anlage 1 — Verarbeitungsübersicht
Quelltextstand 27.07.2026. Grundlage ist eine Erhebung am Quelltext.
Warum hier keine Belegstellen stehen. Frühere Entwürfe dieser Anlage führten je Zeile eine Datei- und Zeilenangabe aus dem Quellcode-Repository mit. Diese Angaben sind entfernt, und zwar aus zwei Gründen: Das Repository ist privat (§ 6.4) — der Händler kann dort ohnehin nichts einsehen —, und Zeilennummern veralten mit jeder Änderung. Ein Vertrag, der auf Zeilennummern verweist, wird mit jedem Programmierschritt ein Stück unrichtiger, ohne dass es jemandem auffällt.
Die Belegführung findet weiterhin statt, nur an ihrem Platz: in der internen Spezifikation, die der Erhebung zugrunde liegt. Der für den Händler offene Weg zur Nachprüfung ist § 10: Auskunft und Nachweise auf Anfrage an datenschutz@kyth.systems, im Bedarfsfall eine Prüfung nach § 10.2. Einer Aufsichtsbehörde legt KYTH die Belegzuordnung auf Verlangen vor (Art. 31 DSGVO).
Angaben nach Art. 30 Abs. 2 DSGVO
| Angabe | Inhalt |
|---|---|
| Auftragsverarbeiter | KYTH. Systems UG (haftungsbeschränkt), Prof.-Mederer-Straße 4, 92348 Berg, datenschutz@kyth.systems |
| Verantwortliche, in deren Auftrag verarbeitet wird | die Händler, die Kartuu verbunden haben — je Shop geführt über die myshopify-Domain (Name) und die beim Vertragsschluss hinterlegte E-Mail-Adresse (Kontaktdaten), Art. 30 Abs. 2 lit. a DSGVO |
| Kategorien der Verarbeitungen | Installation und Betrieb der App, Erfüllung der Datenschutz-Webhooks, Nachweis über Zugriffe auf geschützte Kundendaten, Feststellung des Abonnementstands, Erzeugung der Gutscheinkarte aus Eingaben des Händlers, Aufbewahrung der vom Händler hochgeladenen Bildmotive, Einrichtung des Gutscheinprodukts, Abwicklung einer bezahlten Gutscheinbestellung, Betriebsdiagnose (§ 1.3) |
| Kategorien betroffener Personen | Händler und die für ihn handelnden Personen, Käuferinnen und Käufer, beschenkte Personen, schenkende Personen, Personen auf einem hochgeladenen Bildmotiv (§ 2.1) |
| Übermittlungen in Drittländer | an Shopify-Stellen außerhalb des EWR, siehe § 3.4 |
| Maßnahmen nach Art. 32 Abs. 1 DSGVO | Anlage 2 |
Die vollständigen Firmendaten des Händlers (Firmierung, Anschrift, Vertretung) erhebt KYTH nicht; sie ergeben sich aus dem Shopify-Konto des Händlers und werden bei einer Anfrage nach Art. 31 DSGVO über die hinterlegte Kontaktadresse erfragt.
Garantien nach Art. 30 Abs. 2 lit. c DSGVO. Für Übermittlungen an Shopify-Stellen außerhalb des EWR: die EU-Standardvertragsklauseln nach Durchführungsbeschluss (EU) 2021/914, einbezogen über Shopifys Data Processing Addendum in der Fassung vom 07.07.2026. Für Kanada daneben der Angemessenheitsbeschluss 2002/2/EG. Einzelheiten und die beiden ausdrücklichen Nichtaussagen stehen in § 3.4.
A. Tatsächlich gespeicherte Daten
Die genannten Daten liegen in der PostgreSQL-Datenbank auf dem Server in Berlin und gehen in die Sicherungen nach § 9.3 Nr. 2 ein — mit einer Ausnahme: Von den hochgeladenen Bildmotiven steht nur die Beschreibung in der Datenbank. Die Bytes liegen im Objektspeicher (§ 6.3) und sind nicht Teil der Datenbanksicherung. Für sie gibt es keine Sicherung; geht der Eimer verloren, sind sie weg. Das ist eine Verfügbarkeits- und keine Vertraulichkeitsfrage, es steht trotzdem hier, weil eine Aufzählung, die alle Daten in der Sicherung wähnt, an dieser Zeile falsch wäre.
| Datenkategorie | Betroffene Personen | Zweck | Speicherform | Dauer / Löschung |
|---|---|---|---|---|
Shop-Domain im Klartext (z. B. beispielshop.myshopify.com) |
Händler (mittelbar) | Zuordnung des Mandanten, Adressierung des Shopify-Token-Endpunkts, Zuordnung eingehender Webhooks | Tabelle shops, unverschlüsselt |
Nicht bei Deinstallation. Mit shop/redact, spätestens 30 Tage nach Deinstallation — über den Aufräumlauf nach § 9.3 Nr. 1, der seit dem 01.08.2026 täglich läuft — die Frist trägt damit auch dann, wenn Shopify den Webhook nicht zustellt |
| Shop-Domain als HMAC-Hash | Händler (mittelbar) | Suchindex: jede Abfrage im Produktivbetrieb läuft über den Hash statt über den Klartext | Tabelle shops, nicht umkehrbar |
wie Shop-Domain |
| Shopify Access-Token (Zugangsdatum; kein Personendatum im engeren Sinn, aber Schlüssel zu personenbezogenen Daten im Shop) | — | Zugriff auf die Shopify Admin API im Namen des Händlers. Wird für genau einen Aufruf verwendet: die Abfrage des Abonnementstands (§ 2.3; siehe die Zeile Abonnementstand des Shops) — nicht für Bestell- oder Kundendaten | Tabelle shops, AES-256-GCM verschlüsselt |
Bei Deinstallation sofort auf NULL; Ablauf ohnehin nach 1 Stunde; endgültig mit der Zeile |
| Shopify Refresh-Token (Zugangsdatum) | — | Erneuerung des einstündigen Access-Tokens ohne erneute Anmeldung des Händlers | Tabelle shops, AES-256-GCM verschlüsselt |
Bei Deinstallation auf NULL; bei Verwerfen durch Shopify sofort; regulärer Ablauf nach 90 Tagen; endgültig mit der Zeile |
| Auftritt des Shops: frei gewählter Anzeigename für die Gutscheinkarte und der Schlüssel des als Logo gewählten Bildes | Händler (unmittelbar — er trägt beides selbst ein) | Den Namen des Ladens statt der technischen Shop-Adresse auf die Karte setzen und sein Logo darauf zeigen. Ohne Eintrag steht dort weiterhin die aus der Shop-Adresse abgeleitete Bezeichnung, und die Karte trägt kein Logo | Tabelle shops, unverschlüsselt — beides steht auf jeder gedruckten Karte, die der Händler selbst verteilt, und ist damit kein Geheimnis. Als Kategorie trotzdem benannt: Bei einem Einzelunternehmen kann der Anzeigename der Name einer Person sein. Datenbankseitig erzwungen: höchstens 60 Zeichen und nicht leer, und der Logoschlüssel muss im Namensraum genau dieses Shops liegen |
wie Shop-Domain |
| Abonnementstand des Shops: ob ein aktives Abonnement besteht, Tarifname, Kennzeichen „von Shopify ausgestelltes Testabonnement“, Zeitpunkt der letzten Abfrage | Händler (mittelbar) | Durchsetzung der Bezahlschranke am PDF-Abruf und Anzeige des Tarifs im Adminbereich. Zwischengespeichert, damit nicht jeder PDF-Abruf einen Aufruf bei Shopify auslöst | Tabelle shops, unverschlüsselt. Datenbankseitig erzwungen: „aktiv“ nur mit Prüfzeitpunkt |
wie Shop-Domain |
| Kontaktadresse des Händlers (E-Mail) | Händler bzw. die von ihm benannte natürliche Person | Mitteilungen nach § 0.3, § 6.6 und § 8.2; Weiterleitung von Anfragen betroffener Personen nach § 7.1; Angabe nach Art. 30 Abs. 2 lit. a DSGVO | Tabelle shops, AES-256-GCM verschlüsselt. Ohne Suchhash — nach der Adresse sucht niemand, sie wird über die Shop-Domain gefunden |
wie Shop-Domain |
| Nachweis der Zustimmung: Zeitpunkt und Fassungskennung | Händler (mittelbar) | Nachweis des Vertragsschlusses nach § 0.2 | Tabelle shops, unverschlüsselt. Datenbankseitig erzwungen: entweder alle drei Zustimmungsangaben oder keine |
wie Shop-Domain |
| Technische Metadaten des Shops: Ablauf- und Rotationszeitpunkte der Token, Token-Version, Zeitpunkt der Installation und der Deinstallation, Berechtigungsumfang (Scopes) | Händler (mittelbar) | Steuerung des Token-Lebenszyklus, Auflösen von Wettläufen bei gleichzeitigen Installationen, Erkennen verspäteter Deinstallations-Webhooks | Tabelle shops, unverschlüsselt |
wie Shop-Domain |
| Protokoll über Zugriffe auf geschützte Kundendaten: Shop-Zuordnung, Zeitpunkt, Akteur, Zweck, berührte Feldkategorien, Anzahl der Datensätze | Händler (mittelbar) | Auflage aus der Shopify-Freigabe für geschützte Kundendaten; Nachweis nach Art. 5 Abs. 2 DSGVO. Belegt, dass zugegriffen wurde, nicht welche Inhalte | Eigene Tabelle, bewusst ohne jede Spalte, die einen Namen, eine Anschrift, eine E-Mail-Adresse oder eine Gutscheinnummer aufnehmen könnte | Vollständig mit dem Shop — Fremdschlüssel mit Löschweitergabe und zusätzliches ausdrückliches Löschen. Siehe § 9.3 Nr. 5 |
| Hochgeladene Bildmotive — die Bytes. Das Bild in der Form, in der es abgelegt wurde: bei Rastern (JPEG, PNG, WebP) unverändert wie hochgeladen, einschließlich der eingebetteten Aufnahmedaten (EXIF); bei SVG die um alles Ausführbare bereinigte Fassung (Anlage 2 Abschnitt 2.6) | Händler (mittelbar). Zusätzlich jede Person, die auf dem Bild zu sehen ist oder in dessen Aufnahmedaten steht — was das ist, bestimmt allein der Händler | Zeichnen des Motivs auf der Gutscheinkarte, in der Vorschau und im PDF (§ 1.3 Nr. 6). KYTH sieht den Inhalt nicht durch und wertet ihn nicht aus | Objektspeicher bei IONOS in Berlin, eigener Eimer je Umgebung, nicht öffentlich lesbar. Schlüssel <Shop-Kennung>/<Prüfsumme>.<Endung>, serverseitig aus der Kennung des hochladenden Shops gebildet und nie aus einer Angabe der Anfrage — der Anfang gehört damit genau einem Shop. Nicht in der Datenbanksicherung |
Mit shop/redact, über den Namensraum des Shops und vor den Zeilen. Kein Aufräumlauf und keine Löschfunktion in der App — die beiden Grenzen stehen in § 9.3 Nr. 6 |
| Hochgeladene Bildmotive — die Angaben darüber: Schlüssel, MIME-Typ, Größe in Byte, Breite und Höhe in Pixeln, Prüfsumme (SHA-256 der gespeicherten Bytes), Zeitpunkt des Hochladens | Händler (mittelbar) | Auflisten der Bilder eines Shops und Anzeigen ihres Seitenverhältnisses, ohne jedes Bild dafür aus dem Objektspeicher holen zu müssen | Eigene Tabelle mit Shop-Zuordnung, unverschlüsselt. Zeilenschutz auf Datenbankebene. Datenbankseitig erzwungen: Schlüsselform, Prüfsummenform, ein festes Vokabular für den MIME-Typ, positive Maße, Eindeutigkeit je Shop und Schlüssel. Kein Änderungsrecht — ein Schlüssel beschreibt den Inhalt, unter dem er liegt | wie Shop-Domain (Fremdschlüssel mit Löschweitergabe und ausdrückliches Löschen) |
| Gutschein — die Angaben zur beschenkten und zur schenkenden Person: Empfängername, E-Mail-Adresse des Beschenkten, Absendername, Grußtext | Beschenkte (zugleich als betroffene Person und als Empfängerin des Gutscheins, § 2.1), schenkende Person | Die Karte drucken; die Adresse für die vorgesehene Zustellung. Herkunft ist die bezahlte Bestellung, nicht die Eingabe des Händlers | Tabelle gutscheine, jedes Feld einzeln AES-256-GCM verschlüsselt. Daneben ein nicht umkehrbarer Suchwert über die E-Mail-Adresse — der einzige Weg, eine beschenkte Person wiederzufinden, denn sie hat keine Kundennummer. Datenbankseitig erzwungen: Chiffratform je verschlüsselter Spalte, 64 Hexzeichen je Suchwert. Zeilenschutz auf Datenbankebene |
Mit dem Shop (§ 9.3 Nr. 7). Auf ein Löschverlangen nach Art. 17 werden diese Felder geleert, die Zeile bleibt (§ 7.2). Keine Frist nach Zweckfortfall — offene Stelle in § 9.3 Nr. 7 |
| Gutschein — die Angaben zum Käufer: Shopify-Kundennummer | Käuferin bzw. Käufer | Suchschlüssel der beiden Datenschutz-Webhooks; Zuordnung der Geschenkkarte bei Shopify für den Supportfall des Händlers | Tabelle gutscheine, Klartext. Verschlüsselt wäre sie nicht durchsuchbar, und ohne Durchsuchbarkeit wäre eine Anfrage nach Art. 15 oder 17 nicht erfüllbar. Bei einem Gastkauf fehlt sie |
wie oben. Sie wird bei einer Löschung nach Art. 17 nur dann geleert, wenn sie zu der gesuchten Person gehört — sonst wäre es eine Löschung, die niemand beantragt hat |
| Gutschein — der Code und der Abruf-Token | kein unmittelbarer Personenbezug; beides sind Schlüssel zu einem Vermögenswert einer betroffenen Person | Der Code steht auf der Karte und wird an der Kasse eingelöst; Shopify gibt ihn genau einmal heraus und danach nie wieder. Der Abruf-Token adressiert den späteren Abruf des PDF | Tabelle gutscheine, beide AES-256-GCM verschlüsselt, daneben je ein nicht umkehrbarer Suchwert. Der Suchwert des Codes ist zugleich der Riegel dagegen, denselben Code zweimal zu vergeben. Datenbankseitig erzwungen: Chiffrat- und Hashform, Code und Suchwert nur paarweise, kein Änderungsrecht auf dem Abruf-Token — der Link steht in Shopifys Bestellbestätigung und ist dort nicht mehr änderbar |
wie oben. Bei einer Löschung nach Art. 17 bleiben beide stehen (§ 7.2, § 9.3 Nr. 7 b) |
| Gutschein — die Angaben über die Bestellung und den Vorgang: Bestellkennung, Positionskennung, laufende Nummer des Stücks, Art, Nennwert und Währung, gedruckter Betrag als Text, Shopname, Gültigkeitsdatum, Kennung der Shopify-Geschenkkarte, Zustand, Zeitpunkt des letzten Zustandswechsels, Kennzeichen „Angaben unvollständig" und „nach Versand geändert", Fehlerzähler, Fehlergrund als kurze Kennung, Kennung der gewählten Kartenvorlage | Käuferin bzw. Käufer (mittelbar) | Die Bestellung dem Gutschein zuordnen, den Ablauf steuern und die Karte ohne den Webhook-Körper fertigstellen können. Ein Guthabenstand steht hier nicht und bekommt keine Spalte — den führt allein Shopify | Tabelle gutscheine, unverschlüsselt. Datenbankseitig erzwungen: ein festes Vokabular für Art und Zustand, positive Kennungen, laufende Nummer ab 1, Fehlergrund nur als [a-z0-9_]-Kennung — niemals eine durchgereichte Fremdmeldung, die Empfängername und Code zitieren könnte, Nennwert nur bei Wertgutscheinen und nur zusammen mit einer Währung, sowie Vollständigkeit ab dem Zustand „bereit" |
wie oben |
| Gutschein — das eingefrorene Abbild der Kartenvorlage | kein Personenbezug | Ein Nachdruck soll dieselbe Karte ergeben, auch wenn der Händler seine Vorlage geändert hat | Tabelle gutscheine, JSONB. Es trägt Platzhalter statt Werten, und das ist die tragende Entscheidung: In einem JSON-Feld ließen sich die personenbezogenen Werte weder einzeln verschlüsseln noch einzeln löschen. Sie stehen deshalb daneben in eigenen Spalten |
wie oben |
| Zuordnung der Bildmotive zu einem Gutschein: Schlüssel des benutzten Bildes | mittelbar über das Bild (siehe die Zeile zu den Bildmotiven) | Ein Motiv, das ein ausgestellter Gutschein benutzt, darf nicht gelöscht werden — und der Händler soll erfahren, wie viele Gutscheine betroffen sind | Eigene Tabelle mit Shop-Zuordnung, Zeilenschutz auf Datenbankebene, kein Änderungsrecht: Welche Bilder in einer ausgestellten Karte stecken, ist eine Tatsache über die Vergangenheit. Fremdschlüssel auf Gutschein und Bild, letzterer erst beim Abschluss der Transaktion geprüft — sonst scheiterte shop/redact bei jedem Shop, der je einen Gutschein mit Motiv ausgestellt hat |
wie oben |
| Gutscheinprodukt des Shops: Art, Shopify-Produktkennung, Handle, gewählte Kartenvorlage, Zeitpunkt des Anlegens | kein Personenbezug — eine Produktkennung, ein Handle und zwei Kennungen aus eigenem Vokabular | Zweimaliges Anlegen verhindern; den eingerichteten Stand anzeigen, ohne Shopify zu fragen; eine Gutscheinposition auch dann erkennen, wenn ein Theme keine Zusatzangaben mitschickt | Eigene Tabelle mit Shop-Zuordnung, unverschlüsselt, Zeilenschutz auf Datenbankebene. Eindeutig je Shop und Art — dieser Index ist die Idempotenz. Kein Änderungsrecht auf keiner Spalte: KYTH legt an, danach gehört das Produkt dem Händler | wie Shop-Domain |
| Kennungen eingehender Webhooks: von Shopify vergebene Webhook-Kennung, Status, Zeitpunkte | kein Personenbezug | Duplikatschutz — verhindert, dass Wiederholungen von Shopify denselben Webhook mehrfach verarbeiten | Eigene Tabelle ohne Shop-Zuordnung | 30 Tage nach Abschluss, siehe § 9.3 Nr. 3 |
| Anwendungsprotokolle: Shop-Domain, interne Shop-Kennung, beim Zugriffsprotokoll zusätzlich Akteur und Zweck, ob ein Abonnement aktiv bzw. ein Testabonnement ist, bei einer abgelehnten Eingabe im Gutschein-Editor der Name des beanstandeten Feldes — nie dessen Inhalt —, beim Hochladen eines Bildes der MIME-Typ des angenommenen Bildes bzw. der Grund einer Ablehnung (Format, Maße, Ergebnis der SVG-Bereinigung) — nie der Schlüssel, nie die Prüfsumme, nie ein Dateiname und nie ein Ausschnitt des Bildes —, sowie der Typ aufgetretener Ausnahmen | Händler (mittelbar) | Betriebsdiagnose (fehlgeschlagene Anlage eines Shops, fehlgeschlagener Token-Tausch, unbekannter Shop bei Webhooks, fehlgeschlagenes Schreiben des Zugriffsprotokolls, nicht abrufbarer Abonnementstand, gescheitertes Rendern, nicht erreichbarer Objektspeicher) | Standardausgabe des Containers, eingesammelt auf dem Server. Nicht protokolliert werden Access-, Refresh- und Sitzungstoken sowie die Kontaktadresse — auch nicht gekürzt. Im Fehlerfall wird nur der Ausnahmetyp geschrieben, nie die Ausnahmemeldung — mit der einen in Anlage 2 Abschnitt 1.4 benannten Ausnahme | 14 Tage, siehe § 9.3 Nr. 4 |
| Signierte Webhooks zu Shops ohne Zustimmung: Shop-Domain aus dem signierten Inhalt, von Shopify vergebene Webhook-Kennung | Händler (mittelbar) | Entgegennahme der von Shopify verpflichtend abonnierten Webhooks, bevor oder ohne dass der Händler dem Vertrag zugestimmt hat (§ 0.1). Rechtsgrundlage Art. 6 Abs. 1 lit. f, ergänzend lit. c DSGVO | Kein Datensatz zum Shop. Die Webhook-Kennung in der Duplikatschutz-Tabelle; die Shop-Domain nur im Anwendungsprotokoll, wenn kein Shop zu ihr gehört | Webhook-Kennung 30 Tage nach Abschluss (§ 9.3 Nr. 3), Protokollzeile 14 Tage (§ 9.3 Nr. 4) |
Entfallen gegenüber früheren Fassungen: Die Hilfstabelle test_notizen, die
ausschließlich dem Nachweis der Mandantentrennung diente und dennoch im Produktivschema
angelegt wurde, ist per Migration aus dem Produktivschema entfernt. Sie entsteht nur noch
innerhalb der Testumgebung.
B. Nur flüchtig berührte Daten — keine Speicherung
| Datenkategorie | Betroffene Personen | Zweck | Warum keine Speicherung |
|---|---|---|---|
| Shopify-Sitzungstoken des eingeloggten Händler-Nutzers (JWT) | Händler und die für ihn handelnden Personen | Authentifizierung des Aufrufs, Ermittlung der Shop-Domain, Weitergabe an den Shopify-Token-Tausch | Nicht in der Datenbank, nicht im Protokoll, nicht im Browserspeicher, nicht in der Adresszeile. Der Fehlerpfad protokolliert ausdrücklich nur „Sitzungstoken abgelehnt“ ohne Grund und ohne Inhalt. Der Token selbst ist kurzlebig |
Shopify-Kundenkennung und E-Mail-Adresse aus den Webhooks customers/data_request und customers/redact |
Endkundschaft des Händlers; über die Adresse mittelbar auch eine beschenkte Person | Bearbeitung von Auskunfts- und Löschverlangen nach Art. 15 und Art. 17 DSGVO | Der Webhook-Inhalt wird zur Signaturprüfung vollständig eingelesen und danach verworfen. Shopify sendet in diesen Webhooks weitere Kundendaten (unter anderem Telefonnummer und Anschrift); ausgelesen werden ausschließlich Kundenkennung und E-Mail-Adresse. Die Adresse wird nicht gespeichert, sondern nur zum Suchwert verrechnet — ohne sie fände die Anfrage keine einzige Zeile einer beschenkten Person |
| Der Inhalt einer eingehenden Bestellung, soweit er nicht in eine Gutscheinzeile übernommen wird — insbesondere Positionen ohne Gutschein, Anschriften, Telefonnummern, Zahlungsangaben und ein angegebenes Wunschversanddatum | Endkundschaft des Händlers | Erkennen, welche Positionen einer bezahlten Bestellung Gutscheine sind | Der Körper wird zur Signaturprüfung vollständig eingelesen. Übernommen wird ausschließlich, was in Abschnitt A steht; alles Übrige wird nicht ausgewertet und im Arbeitsspeicher verworfen. Für keines davon gibt es eine Spalte |
| Das gerenderte PDF eines bestellten Gutscheins | Beschenkte, schenkende Personen | Prüfen, dass die Karte druckbar ist — „bereit" heißt „PDF gerendert" | Es entsteht im Arbeitslauf und wird danach verworfen. Migration und Datenmodell lassen die Spalte dafür bewusst weg: Das eingefrorene Vorlagenabbild und die gespeicherten Werte ergeben das Dokument jederzeit wieder |
| Eingaben des Gutschein-Editors: Empfängername, Absendername, Grußtext, Gutscheincode, Betrag, Shopname, Gültigkeitsdatum — sowie die daraus erzeugte HTML-Vorschau und das PDF | Beschenkte, schenkende Personen (soweit der Händler solche Namen einträgt) | Erzeugung der Gutscheinkarte als Vorschau und als PDF (§ 1.3 Nr. 5) | Die Werte stammen aus dem Körper der Anfrage desselben Händlers, werden in die gewählte Vorlage gesetzt und mit der Antwort zurückgegeben. Es gibt keine Tabelle und keine Datei dafür; im Protokoll steht im Fehlerfall nur der Name des beanstandeten Feldes, nie sein Inhalt. Aus dem Shop des Händlers wird für diesen Vorgang nichts abgerufen |
C. Vorgesehen, aber nicht verarbeitet
Diese Tabelle steht getrennt von A und B, weil die Unterscheidung zwischen „darf“ und „tut“ für die Beurteilung dieses Vertrages entscheidend ist (§ 2.3).
Sie ist mit dem Bestellablauf drastisch geschrumpft, und das ist die wichtigste
Änderung dieser Anlage. Bis zu dieser Fassung stand hier als erste Zeile: „Bestell-
und Kundendaten … Eine Verarbeitung findet nicht statt: Es gibt keine Tabelle für
Kunden-, Bestell- oder Empfängerdaten, kein Abonnement des Webhooks orders/paid und
keinen Mailversand." Keine dieser drei Aussagen trifft heute noch zu. Die Kategorie
ist vollständig nach Abschnitt A gewandert; den Mailversand gibt es seit dem
Zustellungsmodul, und seit dem 01.08.2026 läuft er über den Mailzugang des Händlers.
| Datenkategorie | Stand |
|---|---|
| Zugangsdaten des Händlers für den Mailversand (SMTP) | Seit 01.08.2026 vorhanden und nach Abschnitt A gewandert. Der Händler trägt Mailserver, Port, Absender- und Antwortadresse sowie wahlweise Benutzername und Passwort selbst ein. Benutzername und Passwort liegen verschlüsselt in der Datenbank (dieselbe Verschlüsselung wie die Zugangstoken), Server und Adressen im Klartext — sie sind keine Geheimnisse und stehen in jedem Mailkopf, den der Händler verschickt. Das Passwort wird nie wieder ausgeliefert. Rechtsgrundlage und Zweck: die Zustellung des Gutscheins im Auftrag des Händlers. |
| Wunsch-Versanddatum | Es kann im Bestellformular angegeben werden und reist mit der Bestellung an; gespeichert wird es nicht, es gibt keine Spalte dafür. Es steht deshalb in Abschnitt B. |
| Der Abruf über den Abruflink | Der Token wird erzeugt und verschlüsselt gespeichert (Abschnitt A), weil der Link später in einer Bestellbestätigung stehen soll, die sich nachträglich nicht ändern lässt. Die Route dahinter gibt es nicht; heute führt der Link ins Leere. Damit findet über diesen Weg auch keine Verarbeitung statt. |
| Zustellung an Käufer und Beschenkte | Seit dem Zustellungsmodul umgesetzt und nach Abschnitt A gewandert. Zugestellt wird über den Mailzugang des Händlers; die Mail trägt das PDF im Anhang und einen Abruflink. Hat der Händler keinen Zugang hinterlegt, wird nichts zugestellt — der Gutschein bleibt abrufbar, und der Händler übergibt ihn selbst. |
| Deaktivieren einer Shopify-Geschenkkarte beim Storno | Der Berechtigungsumfang write_gift_cards deckt es ab, der Zustand „storniert" ist im Datenmodell vorgesehen; gebaut ist nur das Anlegen. |
| Guthabenstand einer Shopify-Geschenkkarte | Wird nicht gelesen und nicht gespeichert, und das ist keine Auslassung, sondern eine Festlegung: Zwei Systeme, die denselben Betrag führen, laufen auseinander, und der Händler stünde vor einem Kunden, dessen Gutschein laut App noch Guthaben hat und laut Kasse nicht. |
Anlage 2 — Technische und organisatorische Maßnahmen (Art. 32 DSGVO)
Quelltextstand 27.07.2026. Aufgeführt sind ausschließlich Maßnahmen, die im Quelltext oder in der Betriebsdokumentation belegt sind. Belegstellen führt diese Anlage aus demselben Grund nicht mit wie Anlage 1. Der Abschnitt „Bekannte Lücken“ gehört zur Darstellung dazu; er ist bewusst nicht weggelassen.
1. Vertraulichkeit
1.1 Verschlüsselung gespeicherter Daten
- Mit AES-256-GCM verschlüsselt gespeichert werden: Access-Token, Refresh-Token, die Kontaktadresse des Händlers und — seit dem Bestellablauf — der Gutscheincode, der Abruf-Token, der Empfängername, die E-Mail-Adresse des Beschenkten, der Absendername und der Grußtext. Jedes Chiffrat trägt eine Schlüsselkennung, und diese Kennung ist kryptografisch an das Chiffrat gebunden — ein nachträgliches Umschreiben der Kennung fällt beim Entschlüsseln auf.
- Die Datenbank lässt Klartext in einer verschlüsselten Spalte nicht zu. Jede dieser Spalten trägt eine Prüfregel auf das Chiffratformat, jede Suchwertspalte eine auf genau 64 Hexzeichen. Der Riegel fängt den teuersten denkbaren Fehler dieser Art ab: einen Klartext in einer Spalte, deren Name „verschlüsselt" sagt. Er fiele sonst nie auf — Lesen und Schreiben funktionieren weiter.
- Suchwerte statt Klartext, wo gesucht werden muss. Gutscheincode, Abruf-Token und die E-Mail-Adresse des Beschenkten tragen je einen nicht umkehrbaren Suchwert (HMAC-SHA256) neben dem Chiffrat. Ohne ihn müsste jede Suche jede Zeile des Shops entschlüsseln — und für die beschenkte Person gäbe es überhaupt keinen Weg, sie zu finden. Die Shopify-Kundennummer des Käufers liegt aus demselben Grund im Klartext: Sie ist der Suchschlüssel der beiden Datenschutz-Webhooks.
- Was gegenüber Shopify nicht preisgegeben wird. Die Notiz, die beim Anlegen einer Geschenkkarte an ihr hinterlegt wird, enthält keine Personendaten. Wer beschenkt wird, steht in der verschlüsselten Spalte bei KYTH und nicht in einem Freitextfeld bei Shopify.
- Der Schlüssel stammt ausschließlich aus einer Umgebungsvariablen; je Umgebung ein eigener. Es gibt keinen Betriebsmodus, in dem die Verschlüsselung abschaltbar wäre.
- Der Suchhash nutzt nicht den rohen Verschlüsselungsschlüssel, sondern einen davon abgeleiteten eigenen Schlüssel (Trennung der Einsatzzwecke).
- Diese Feldverschlüsselung ist zugleich die tragende Maßnahme für die Sicherungen. Sie wirkt innerhalb des Datenbankabzugs weiter, und der Schlüssel liegt nicht im Abzug und nicht beim Speicheranbieter. Siehe § 9.3 Nr. 2 — dort steht auch, was zur Verschlüsselung der Sicherungsdatei selbst nicht zugesagt wird.
1.2 Trennung der Mandanten
- Jede Tabelle mit einer Shop-Kennung (
shop_id) ist mit Zeilenschutz auf Datenbankebene (Row-Level-Security, mitENABLEundFORCE) und genau einer Richtlinie über den gesetzten Mandanten versehen. Ohne gesetzten Mandanten liefert die Datenbank für diese Tabellen keine Zeile — kein Mandant, kein Zugriff. - Die Tabelle
shopsselbst trägt keinen Zeilenschutz. Sie hat keineshop_id-Spalte, sondern ist die Shop-Tabelle; die Anwendungsrolle hat auf ihrSELECTüber alle Zeilen undDELETE. Die Mandantentrennung wirkt dort ausschließlich über die Anwendung — jede Abfrage filtert über den Suchhash der Shop-Domain — und über spaltenweise Rechte (1.3). Der Quelltext hält das ausdrücklich fest. Damit ist die Tabelle, die heute die produktiven Händlerdaten führt, gerade nicht durch den Zeilenschutz abgesichert; siehe Abschnitt 7. - Die Anwendung verbindet sich mit einer entrechteten Datenbankrolle, die den Zeilenschutz nicht umgehen darf und ausdrücklich nicht Eigentümerin der Tabellen ist (Eigentümer und Superuser würden den Zeilenschutz immer umgehen).
- Fehlt diese Rolle im Betrieb oder ist sie mit der Verwaltungsrolle identisch, bricht die Anwendung den Start ab, statt lautlos ohne wirksame Mandantentrennung zu laufen.
- Die Datenzugriffsschicht kann ohne Mandantenangabe keine Abfrage bilden. Tabellennamen werden gegen eine Freigabeliste und ein festes Namensmuster geprüft, Werte ausschließlich als Parameter übergeben; ein rohes SQL-Fragment lässt sich nicht übergeben.
- Im Objektspeicher trennt der Namensraum selbst. Der Schlüssel eines Bildes beginnt mit der Kennung seines Shops. Zwei Händler, die dasselbe Motiv hochladen, bekommen deshalb zwei verschiedene Schlüssel und zwei getrennte Objekte — ohne diesen Anfang wären es zwangsläufig dasselbe, und das Löschen des einen Shops nähme dem anderen sein Bild weg. Die Trennung steht damit im Namen und nicht nur in einer Abfragebedingung. Jeder Schlüssel wird an jeder Stelle gegen ein vollständig verankertes Muster geprüft, bevor daraus ein Pfad oder eine Speicheradresse wird; die Dateiablage prüft zusätzlich, dass der aufgelöste Pfad unterhalb ihres Wurzelverzeichnisses liegt. Objekte sind nicht öffentlich lesbar; sie erreichen den Browser des Händlers ausschließlich eingebettet im gerenderten Dokument.
1.3 Rechte auf das Nötigste beschränkt
Datenbankrechte sind spaltenweise statt tabellenweit vergeben:
- Ändern der Shop-Tabelle nur auf den Token- und Rotationsspalten,
- Anlegen eines Shops nur mit Domain und Hash,
- Schreiben der Zustimmung nur auf den drei Zustimmungsspalten,
- Lesen der Webhook-Kennungen nur auf den tatsächlich gelesenen Spalten,
- Anlegen einer Bildzeile nur auf den sieben tatsächlich geschriebenen Spalten — nicht auf der laufenden Nummer und nicht auf dem Zeitpunkt des Hochladens, der damit festgestellt und nicht behauptet wird,
- kein Änderungsrecht auf dem Protokoll über Zugriffe auf geschützte Kundendaten, damit Einträge nachträglich nicht veränderbar sind — und aus einem anderen Grund auch keines auf den Bildzeilen: Der Schlüssel ist die Prüfsumme des Inhalts, eine geänderte Zeile beschriebe also ein anderes Objekt unter derselben Adresse.
Bei den Gutscheinen trägt dieselbe Technik zwei Zusagen, die sonst nur Vorsatz wären:
- Ein Gutschein kann gar nicht als „bereit" entstehen. Die Anwendungsrolle hat beim Anlegen kein Recht auf den Zustand und auf den Zeitpunkt des Zustandswechsels. Der Einstiegspunkt des Ablaufs steht damit im Schema und nicht in der Sorgfalt des Schreibpfads. Ebenso wenig kann sie beim Anlegen einen Code, eine Geschenkkartenkennung oder ein Vorlagenabbild setzen: Die entstehen später, und ein Recht darauf wäre die Einladung, den Ablauf abzukürzen.
- Die Identität eines Gutscheins ist unveränderlich. Auf Shop, Bestellung, Position, laufender Nummer, Art, Vorlage und Abruf-Token gibt es kein Änderungsrecht. Ohne das wäre der Idempotenzschlüssel wertlos — die Wiederholungsfestigkeit hinge daran, dass niemand dazwischen schreibt —, und der Abruflink, der in Shopifys Bestellbestätigung steht und dort nicht mehr änderbar ist, könnte ins Leere zeigen.
- Kein Änderungsrecht auf der Zuordnung der Bildmotive und keines auf den Gutscheinprodukten. Welche Bilder in einer ausgestellten Karte stecken, ist eine Tatsache über die Vergangenheit. Und ein Produkt, das der Händler in Shopify verändert hat, gehört ihm: Eine änderbare Zeile wäre die Einladung, aus dem Anlegen ein Abgleichen zu machen, und ein Abgleich nimmt dem Händler früher oder später eine Änderung weg, die er selbst gemacht hat.
1.4 Keine Geheimnisse an falscher Stelle
- Weder Access-, noch Refresh-, noch Sitzungstoken werden protokolliert — auch nicht gekürzt. Dasselbe gilt für die Kontaktadresse des Händlers und, seit dem Bestellablauf, für Gutscheincode, Abruf-Token, Empfänger- und Absendername, Grußtext und die E-Mail-Adresse der Kundschaft. Geloggt werden aus dem Bestellablauf ausschließlich Shopdomain, Bestell-, Positions- und Gutscheinkennung, die Anzahl angelegter Gutscheine, der erreichte Zustand und der Fehlergrund als kurze eigene Kennung. Im Fehlerfall wird nur der Ausnahmetyp geschrieben, nie die Ausnahmemeldung, weil diese Teile der Nutzdaten zitieren könnte. Von dieser Regel gibt es genau eine Ausnahme, und sie ist im nächsten Punkt benannt.
- Auch die Antworten von Shopify werden nicht im Wortlaut protokolliert. Lehnt Shopify das Anlegen einer Geschenkkarte oder eines Produkts ab, werden ausschließlich die Fehlerkennung und der Feldpfad übernommen — beides Namen aus dem GraphQL-Schema. Die Meldung selbst bleibt draußen: Sie ist Fließtext, in dem der abgelehnte Wert zitiert sein kann, und der abgelehnte Wert ist hier im Zweifel der Gutscheincode.
- Die eine benannte Ausnahme: Scheitert der Token-Tausch mit Shopify vorübergehend, schreibt das Protokoll zusätzlich die Meldung dieser einen Fehlerklasse. Sie ist keine von außen erhaltene Zeichenkette: KYTH setzt sie selbst zusammen, und sie besteht ausschließlich aus eigenem Text, einem HTTP-Statuscode, einem Ausnahmetyp, einer Zeilenzahl und der Shop-Domain — Letztere steht ohnehin in derselben Zeile. Weder ein Token noch ein Geheimnis noch eine Antwort von Shopify im Wortlaut kann darin auftauchen. Der Grund für die Ausnahme ist betrieblich: Ohne sie ist im Störungsfall nicht unterscheidbar, ob das Netz weg war, ob das Anwendungsgeheimnis nicht passt, ob Shopify gedrosselt hat oder ob der Datensatz zum Shop fehlte — vier verschiedene Ursachen mit vier verschiedenen Behebungen.
- Frühere zweite Ausnahme, beseitigt: Bis zum 26.07.2026 schrieb der Fehlerpfad beim Protokollieren von Zugriffen auf geschützte Kundendaten die vollständige Fehlermeldung samt Aufrufkette. Bei Datenbankfehlern konnte eine solche Meldung Angaben aus der betroffenen Zeile enthalten — anders als bei der oben benannten Ausnahme war der Inhalt dieser Meldung also nicht vorhersehbar. Dieser Pfad ist an die übrige Linie angeglichen; er schreibt nur noch den Ausnahmetyp, die Meldungsstufe bleibt unverändert.
- Ein Prüflauf gegen versehentlich eingecheckte Geheimnisse läuft automatisch vor jeder Übernahme in die Versionsverwaltung; die Umgebungsdatei ist von Repository und Container-Abbild ausgeschlossen.
- Zugangsgeheimnisse liegen ausschließlich in der Bereitstellungsumgebung.
1.5 Protokoll über Zugriffe auf geschützte Kundendaten
Wird vom ersten Tag an geführt und ist bewusst inhaltsfrei: Die zulässigen Werte für Akteur und Feldkategorie sind doppelt abgesichert (Prüfung im Code und Prüfregel in der Datenbank). Ein Fehler beim Protokollieren bringt den fachlichen Aufruf nicht zu Fall.
Seit dem Bestellablauf läuft es nicht mehr ins Leere. Bis dahin wurde es nur von den
beiden Datenschutz-Webhooks beschrieben und traf keine Zeile — es gab keine Kundendaten.
Die Entgegennahme einer bezahlten Bestellung ist die erste Stelle, an der die
beantragten Kategorien name und email tatsächlich verarbeitet werden, und sie
schreibt einen eigenen Eintrag. Zwei Feinheiten gehören dazu, weil ein Nachweis sonst
mehr behauptet, als er trägt: Vermerkt werden nur die tatsächlich berührten
Kategorien, und eine Bestellung ohne jede Personenangabe schreibt gar keinen Eintrag
— ein Nachweis über einen Zugriff, den es nicht gegeben hat, entwertet das Protokoll.
Der Eintrag entsteht beim Entgegennehmen und nicht beim Rendern, damit ein
Wiederholungslauf nicht einen zweiten Eintrag über denselben einen Zugriff erzeugt.
2. Integrität
2.1 Prüfung eingehender Aufrufe
- Webhooks: HMAC-SHA256 über den rohen Inhalt, Vergleich in konstanter Zeit, Ablehnung mit Statuscode 401 bei Fehlern — und zwar vor jeder weiteren Verarbeitung, damit niemand ohne gültige Signatur Webhook-Kennungen blockieren kann.
- Sitzungstoken: Prüfung mit erzwungenem Signaturverfahren, Vergleich in konstanter Zeit, enge Toleranz bei Gültigkeitszeitpunkten, Wiedereinspielfenster von 70 Sekunden, Prüfung des Adressaten gegen die eigene Anwendungskennung sowie Kreuzprüfung von Aussteller und Ziel einschließlich Schutz vor eingeschleusten Benutzerangaben im Hostnamen.
2.2 Absicherung der eingebetteten Oberfläche
Sicherheitskopfzeilen: Inhaltsrichtlinie (Content-Security-Policy) mit dynamischer
Einbettungsbeschränkung, deren Shop-Parameter gegen ein vollständig verankertes Muster
geprüft wird und bei mehrfacher Angabe abweisend reagiert; X-Content-Type-Options;
Referrer-Policy: strict-origin-when-cross-origin.
2.3 Angriffsfläche klein halten
Schema-Beschreibung und interaktive Dokumentation der Schnittstelle sind im Produktivbetrieb abgeschaltet (die Routen existieren dort nicht).
2.4 Prüfung der Eingaben des Zustimmungsschritts
Die im Zustimmungsschritt eingegebene Kontaktadresse wird serverseitig gegen ein vollständig verankertes Muster geprüft (keine Zeilenumbrüche, keine Trennzeichen, kein spitzklammerartiger Anhang, Domäne mit Punkt, Längenbegrenzung), Randleerzeichen werden entfernt, die Groß- und Kleinschreibung bleibt erhalten. Die Zustimmung muss als echter Wahrheitswert übermittelt werden — Zeichenketten oder Zahlen gelten nicht als Zustimmung.
Begrenzung des Anfragekörpers. Der Körper dieser Anfrage darf 4 Kilobyte nicht überschreiten; mehr braucht er nie, denn er trägt eine E-Mail-Adresse und einen Wahrheitswert. Die Grenze wirkt an zwei Stellen: vorab gegen die vom Aufrufer angekündigte Länge und — entscheidend — während des Einlesens selbst, das abgebrochen wird, sobald die Grenze überschritten ist. Ohne den zweiten Teil wäre die Zusage wirkungslos: Eine Anfrage kann ihre Länge verschweigen, und der Körper läge dann vollständig im Arbeitsspeicher, bevor irgendeine Prüfung greift. Bis zum 26.07.2026 war genau das der Fall; begrenzt war die Auswertung des Körpers, nicht seine Entgegennahme.
Derselbe Deckel an den beiden Renderaufrufen, dort 8 Kilobyte (Vorschau und PDF-Abruf; der Körper trägt sieben Textwerte und eine Vorlagenkennung). Beide Grenzen stammen aus einer Umsetzung, die alle drei Anfragen benutzen — eine kopierte Schutzmaßnahme wird an einer Stelle repariert und an der anderen vergessen. Ein Körper über dem Deckel endet ausdrücklich nicht in einer erfolgreichen Antwort mit leeren Werten, sondern in einer Ablehnung: Ein abgeschnittener Körper ergäbe sonst eine druckbare Karte ohne Gutscheincode.
2.5 Prüfung der Eingaben des Gutschein-Editors
Neben der Kontaktadresse aus 2.4 ist der Editor die Stelle, an der ein Händler frei formulierten Text an KYTH schickt — und die einzige, an der dieser Text anschließend gesetzt und gedruckt wird. Er wird serverseitig geprüft, bevor daraus ein Dokument entsteht; auf eine Prüfung im Browser verlässt sich der Server dabei nicht.
- Erlaubnislisten statt freier Werte, und Ablehnung statt stiller Ersetzung. Fest vorgegeben sind die wählbare Vorlage, das Blattformat, der Ebenentyp, die Fläche der Klappkarte, die Ausrichtung, die Schrift und die zulässigen Platzhalternamen. Ein unbekannter Wert wird abgelehnt — ein stillschweigend korrigierter Wert erzeugte eine Karte, die anders aussieht als die, die der Händler angeklickt hat, und das fiele als Entscheidung durch und nicht als Fehler. Aus demselben Grund wird auch ein unbekannter Schlüssel im übermittelten Objekt abgelehnt: Ein Feld, das gesendet wird und nirgends erscheint, wäre ein stiller Verlust.
- Die Schrift kommt nie als Name aus der Eingabe. Übermittelt wird ausschließlich eine Kennung, die serverseitig auf eine feste Formatvorlage abgebildet wird. Ein Feld, in das sich ein Schriftname schreiben ließe, wäre eine Zeichenkette mit Anführungszeichen und Kommas an genau der Stelle, an der eine Übernahme der Gestaltung beginnt.
- Farben ausschließlich als Hexwert oder „transparent“. Diese Liste ist mit Absicht winzig: Farbangaben kennen im Gestaltungsformat auch Funktionen, und jede davon wäre eine Möglichkeit, aus einem Farbfeld etwas anderes zu machen als eine Farbe — bis hin zu einem Aufruf nach draußen aus einem Renderer, der ohne Netz laufen soll.
- Längengrenzen je Feld, aus den Flächen der Vorlagen gerechnet und nicht gegriffen: Empfänger- und Absendername je 40 Zeichen, Gutscheincode 20, Betrag 18, Grußtext 240, Shopname 60, Gültigkeitsangabe 40. Dazu höchstens 2000 Zeichen je Ebenentext und höchstens 200 Ebenen je Dokument. Ein Wert, der durchgelassen wird, muss in die Fläche passen, für die er gedacht ist; sonst ist die Grenze keine Grenze.
- Zahlen nur innerhalb benannter Grenzen — Schriftgröße 4 bis 400 Punkt, Zeilenhöhe 0,5 bis 4,0, Buchstabenabstand höchstens 40 Punkt in beide Richtungen, Drehung höchstens 360 Grad, Stapelposition 0 bis 999; Position und Größe werden gegen das Blatt geprüft. „Keine Zahl“ und „unendlich“ werden abgelehnt statt zurechtgebogen. Das schützt nicht nur vor Unsinn, sondern vor Aufwand: Eine Ebene mit zehn Metern Kantenlänge ist für den Renderer teuer.
- Steuerzeichen werden entfernt. Unsichtbare Zeichen entstehen beim Kopieren aus einer Textverarbeitung; eine Fehlermeldung über ein Zeichen, das man nicht sieht, hilft niemandem. Zeilenumbrüche bleiben nur im Grußtext erhalten — in einem einzeiligen Feld sind sie entweder ein Versehen oder der Anfang einer Gewohnheit, die spätestens in einer Kopfzeile gefährlich wird.
- Eine zweite, unabhängige Schicht an der Ausgabe. Beim Erzeugen des HTML läuft jede Zahl noch einmal durch eine feste Formatvorlage, aus der kein Trennzeichen entstehen kann, und wird auf das Blattformat geklemmt; jede Farbe wird erneut gegen dieselbe Erlaubnisliste geprüft und andernfalls durch „transparent“ ersetzt. Diese Schicht ist keine Verdopplung der ersten, sondern deren Absicherung für den Fall, dass ein Dokument auf einem anderen Weg in den Renderer gelangt — aus einer Migration oder aus einem künftigen Editor —, ohne die Eingabeprüfung durchlaufen zu haben.
- Kein Auswerten von Händlereingabe als Vorlage. Die Platzhalter im Text einer Ebene werden rein textuell und in einem Durchgang ersetzt. Ein Wert, der selbst wie ein Platzhalter aussieht, wird deshalb nicht ein zweites Mal ersetzt. Alle freien Texte werden beim Einsetzen maskiert; ein Skript kann im Ergebnis nicht stehen.
- Ratenbegrenzung je Shop: zwölf Renderläufe und sechs PDF-Abrufe pro Minute, nach einem Eimermodell, das sich stetig nachfüllt. Schlüssel ist die Shop-Domain aus dem geprüften Sitzungstoken und nie eine Angabe aus Körper oder Adresszeile — sonst ließe sich durch Ändern einer Zeichenkette ein frisches Kontingent ausstellen. Ohne diese Bremse genügte eine Schleife im Browser eines einzigen Shops, um alle Arbeitsprozesse zu belegen; betroffen wären dann alle Mandanten gleichzeitig. Ehrlich dazu: Jeder der vier Arbeitsprozesse führt sein eigenes Kontingent, die tatsächliche Obergrenze liegt also beim Vierfachen. Das ist bekannt und hingenommen — eine gemeinsame Zählung bräuchte einen Netzwerkaufruf im heißesten Pfad.
- Der Dateiname des PDF ist fest und wird nicht aus den Werten gebaut. Ein Dateiname aus Händlereingabe stünde in einer Kopfzeile, und dort richtet ein Anführungszeichen oder ein Zeilenumbruch den größten Schaden an.
- Nichts davon landet im Protokoll. Wird ein Wert abgelehnt, wird der Name des Feldes vermerkt, nie sein Inhalt — der Grußtext eines Händlers ist der Text auf einem Geschenk (Anlage 1 Abschnitt A, Zeile Anwendungsprotokolle).
2.6 Prüfung hochgeladener Bilder
Ein hochgeladenes Bild ist die einzige Datei, die von außen in die App gelangt, und damit die Stelle mit der größten Angriffsfläche: Es wird dekodiert, gespeichert und später in ein Dokument gezeichnet, das im Adminbereich eines Händlers angezeigt wird. Die Prüfung läuft deshalb einmal beim Hochladen und nicht bei jedem Zeichnen — was hier durchgeht, ist ab diesem Punkt vertrauenswürdig; was nicht durchgeht, wird nie gespeichert. Eine Prüfung erst beim Zeichnen käme zu spät: Die Rohdatei läge dann bereits im Objektspeicher.
- Erlaubnisliste der Formate. Angenommen werden ausschließlich JPEG, PNG, WebP und SVG. Andere Bildformate werden abgelehnt und nicht umgewandelt. Jedes zusätzliche Format wäre ein zusätzlicher Dekoder im Pfad einer Anfrage von außen; keines der fehlenden fehlt einer Gutscheinkarte.
- Das Format wird aus dem Inhalt bestimmt, nicht aus der Behauptung des Aufrufers. Der Typ, den die Anfrage angibt, wird gar nicht erst gelesen, und einen Dateinamen kann die Anfrage nicht mitschicken. Ein Raster wird an seinen Kopfdaten erkannt und vollständig dekodiert; ein SVG daran, dass es sich als SVG lesen lässt. Eine Datei mit vorgetäuschtem Kopf scheitert damit nicht erst beim Zeichnen — also mitten in der Anfrage eines anderen Händlers —, sondern beim Hochladen.
- Deckel auf die Größe: 5 Mebibyte. Er wirkt an drei Stellen: vorab gegen die vom Aufrufer angekündigte Länge, während des Einlesens und ein drittes Mal in der Prüfung selbst, damit die Zusage auch für einen künftigen Aufrufer gilt, der nicht über diese Route kommt. Der zweite Teil ist der tragende: Eine Anfrage kann ihre Länge verschweigen, und die Nutzlast läge dann vollständig im Arbeitsspeicher, bevor irgendeine Prüfung greift.
- Riegel gegen Dekompressionsbomben. Ein Bild von wenigen Kilobyte kann beim Dekodieren mehrere Gigabyte belegen und einen Arbeitsprozess beenden — für alle Mandanten gleichzeitig, ausgelöst von einem einzigen Upload. Deshalb greifen die Pixelgrenzen (höchstens 6000 Bildpunkte je Kante, höchstens 12 Millionen insgesamt) nach dem Lesen der Kopfdaten und vor dem Dekodieren — an dieser Stelle sind Breite und Höhe bekannt und noch kein Bildpunkt belegt. Dahinter liegt als Rückfallebene die eigene Grenze der Bildbibliothek, herabgesetzt auf denselben Wert.
- SVG wird bereinigt, und gespeichert wird die bereinigte Fassung. SVG ist kein Bildformat wie die anderen: Es ist ein Dokument, das Skript, fremde Verweise und beliebiges HTML aufnehmen kann. Die Bereinigung arbeitet mit einer Erlaubnisliste für Elemente und Attribute und baut das Motiv daraus neu auf, statt Unerwünschtes herauszulöschen — beim Neuaufbau bleibt nur stehen, was jemand ausdrücklich genannt hat, auch gegenüber Bestandteilen, die es heute noch gar nicht gibt. Entfernt werden damit unter anderem Skriptelemente und Ereignisattribute, eingebettetes HTML, Formatvorlagen und das Stilattribut sowie jeder Verweis nach draußen; Verweise sind nur auf Elemente desselben Dokuments zulässig. Dokumenttypdefinitionen und Entitäten sind abgeschaltet — sonst wären ein Zugriff auf Serverdateien und eine Entitätenbombe möglich. Die Schachtelungstiefe ist auf 40 Ebenen begrenzt. Ein Motiv, das nach der Bereinigung nichts mehr zeichnen würde, wird abgelehnt und nicht leer gespeichert: Sonst bekäme der Händler eine Erfolgsmeldung und sähe nichts.
- Ratenbegrenzung je Shop: zehn Uploads pro Minute, nach demselben Eimermodell wie in 2.5, aber mit eigenem Kontingent. Getrennt, weil ein Upload teuer und selten ist, eine Vorschau billig und häufig — aus einem gemeinsamen Kontingent folgte, dass ein Händler nach dem Hochladen seines Motivs seine eigene Karte nicht mehr sehen könnte. Schlüssel ist auch hier die Shop-Domain aus dem geprüften Sitzungstoken und nie eine Angabe aus der Anfrage. Ehrlich dazu, wie in 2.5: Jeder der vier Arbeitsprozesse führt sein eigenes Kontingent, die tatsächliche Obergrenze liegt beim Vierfachen.
- Reihenfolge der Schritte. Sitzungstoken prüfen, Ratenbegrenzung ziehen, Shop auflösen — und erst danach ein Byte des Körpers lesen. Ohne gültigen Token wird nichts eingelesen; die Bremse steht vor dem Einlesen, weil auch das Einlesen kostet.
- Erst das Objekt, dann die Zeile. Bricht der Vorgang dazwischen ab, bleibt ein
Objekt ohne Zeile zurück — belegter Platz, den der nächste identische Upload von selbst
wieder einsammelt und den
shop/redactüber den Namensraum mit abräumt. Die umgekehrte Reihenfolge hinterließe eine Zeile ohne Objekt: Sie sähe wie ein vorhandenes Bild aus, die App böte es an, und das Zeichnen scheiterte später an einem Upload von vorgestern. - Nichts davon landet im Protokoll. Vermerkt werden der angenommene Typ oder der Grund einer Ablehnung — nie der Schlüssel, nie die Prüfsumme, nie ein Ausschnitt der Datei. Einen Dateinamen gibt es nicht, weil die Anfrage keinen mitschicken kann.
- Was diese Prüfung ausdrücklich nicht leistet: Sie entfernt keine Aufnahmedaten aus einem Raster. Siehe Abschnitt 7.2 — dort steht, warum, und was daraus folgt.
2.7 Maßnahmen des Bestellablaufs
Der Bestellablauf ist der erste Vorgang, in dem KYTH Daten Dritter aus dem Shop des Händlers entgegennimmt und aufbewahrt, und zugleich der erste, in dem ein Fehlschlag einen Vermögenswert betrifft. Die Maßnahmen dafür sitzen in der Datenbank und nicht in der Sorgfalt eines Aufrufers — das ist der Unterschied, auf den es hier ankommt.
- Idempotenzschlüssel je Stück. Shop, Bestellung, Bestellposition und laufende Nummer bilden zusammen einen eindeutigen Index. Shopify wiederholt einen Webhook über bis zu 48 Stunden; eine Wiederholung trifft damit dieselben Zeilen und erzeugt keine zweiten Gutscheine. Der Shop steht bewusst an erster Stelle des Schlüssels: Ohne ihn wäre die Eindeutigkeit shopübergreifend, und ein fehlgeschlagener Schreibversuch verriete, dass ein anderer Händler dieselbe Bestellnummer schon hat.
- Ein Datensatz je Stück, nicht je Bestellposition. Drei gekaufte Gutscheine über je 50 Euro ergeben drei Zeilen mit drei Codes. Das ist keine Feinheit der Ablage: Ein zusammengefasster Gutschein über 150 Euro ließe sich nicht einzeln verschenken und nicht einzeln einlösen.
- Der Zustandslauf steht an einer Stelle und wirkt an zwei. Zehn benannte Zustände, festgeschrieben als Prüfregel in der Datenbank — ein Tippfehler im Zustandsnamen erzeugte sonst einen bezahlten Gutschein, den keine Abfrage mehr findet. Welche Übergänge erlaubt sind, hängt der einzige Schreibpfad als Bedingung an die Schreibanweisung selbst: Es gibt kein Lesen-Prüfen-Schreiben und damit kein Fenster dazwischen; zwei gleichzeitig laufende Arbeiter können denselben Gutschein nicht zweimal weiterschalten.
- Vollständigkeit ab dem Zustand „bereit". Ab diesem Zustand gilt der Gutschein als geliefert. Die Datenbank lässt ihn dort nur zu, wenn Code und Vorlagenabbild vorhanden sind — bei einem Wertgutschein zusätzlich Nennwert und Geschenkkartenkennung. Ein gelieferter Gutschein ohne Code wäre ein Stück Papier ohne Gegenwert; das fällt hier auf und nicht beim Beschenkten.
- Der Code steht in der Zeile, bevor die Karte bei Shopify entsteht. Das Anlegen einer Geschenkkarte kennt bei Shopify keinen Wiederholungsschutz — jeder Aufruf legt eine neue Karte mit neuem Guthaben an. Kartuu schreibt deshalb zuerst den Code, und zwar in einer Anweisung, die nur greift, solange das Feld leer ist; erst danach ruft es Shopify. Von zwei gleichzeitigen Arbeitern ruft damit nur einer die Mutation auf, und ein Abbruch dazwischen führt beim nächsten Anlauf zu demselben Code. Weil ein Gutscheincode je Shop eindeutig ist, entsteht entweder die fehlende Karte oder Shopify lehnt den Code als vergeben ab. Am Ende existiert genau eine bezahlte Karte. Die verbleibende Lücke ist benannt: Lehnt Shopify den Code als vergeben ab, gibt es die Karte, ihre Kennung ist aber unbekannt. Das endet in einem sichtbaren Fehlzustand und nicht in einer stillen zweiten Karte.
- Der Fehlergrund ist eine eigene kurze Kennung, nie eine fremde Fehlermeldung. Die
Datenbank erzwingt das Format
[a-z0-9_]. Eine durchgereichte Meldung aus der Datenbank oder aus GraphQL zitiert die fehlgeschlagene Anweisung samt Werten — hier also Empfängername und Gutscheincode, in einer Spalte, die jeder künftige Statusbildschirm anzeigt. Dieselbe Linie wie beim Protokoll über Zugriffe auf geschützte Kundendaten, nur als Riegel statt als Vorsatz. - Der Code wird nicht geraten und nicht verwechselt. Er stammt aus einem kryptografisch sicheren Zufallsgenerator, 16 Zeichen aus einem Alphabet ohne die auf Papier verwechselbaren Paare. Der Abruf-Token stammt aus derselben Quelle, ist aber das Gegenteil: Der Code identifiziert einen Gutschein und berechtigt nicht, das Token berechtigt und darf deshalb nirgends stehen, wo der Code steht.
- Der Webhook quittiert erst, wenn die Zeilen in der Datenbank stehen. Eine Warteschlange im Arbeitsspeicher hätte bedeutet: Shopify hat die Quittung, ein Neustart wirft die Arbeit weg, und ein bezahlter Gutschein entsteht nie — ohne dass irgendetwas nach einem Fehler aussieht. Alles Teure (Shopify-Aufruf, Rendern) läuft danach; ein Neustart verzögert seither, er verliert nicht mehr.
- Was der Kunde im Bestellformular nicht ausgefüllt hat, wird nicht geraten. Eine Bestellung über einen Express-Bezahlweg kommt ohne Personalisierung an. Diese Zeilen werden als „Angaben unvollständig" gekennzeichnet, bleiben stehen und lösen keinen Aufruf bei Shopify aus — es entsteht also auch keine Geschenkkarte, auf die niemand wartet.
2.8 Nachvollziehbarkeit von Änderungen
Das Datenbankschema wird ausschließlich über Migrationen und in einem eigenen Prozess vor dem Start der Anwendung geändert; kein Arbeitsprozess sieht ein halbfertiges Schema.
3. Verfügbarkeit und Belastbarkeit
- Der Container läuft nicht mit Systemrechten (eigener Benutzer), mehrstufiger Aufbau, Zustandsprüfung.
- Sperrkonflikte in der Datenbank laufen in eine Zeitgrenze von 20 Sekunden und enden in einer sauberen Fehlermeldung statt in einem hängenden Arbeitsprozess.
- Tägliche Datenbanksicherung, mit AES-256 verschlüsselt, bevor sie den Server verlässt, abgelegt auf dem Server (Aufbewahrung 30 Tage) und im Objektspeicher der IONOS in Berlin (Aufbewahrung 90 Tage, zusätzlich abgesichert durch eine Lebenszyklusregel im Eimer). Damit liegt eine Kopie außerhalb des Servers; ein Ausfall des Datenträgers nimmt nicht mehr Datenbank und Sicherung zugleich mit. Einzelheiten in § 9.3 Nr. 2. Zu dem, was trotzdem offen ist, siehe Abschnitt 7.
- Die Sicherung prüft sich selbst. Vor dem Hochladen wird die verschlüsselte Datei wieder entschlüsselt und darauf geprüft, dass ein Datenbankabzug herauskommt; nach dem Hochladen wird beim Speicher zurückgefragt, ob das Objekt in der erwarteten Größe angekommen ist. Eine Datei, die niemand öffnen kann, und eine, die nie ankam, gelten damit nicht als Sicherung. Ein zu kleiner Abzug führt zum Abbruch — eine leere Sicherung sieht im Speicher aus wie eine echte und fällt sonst erst auf, wenn man sie braucht.
- Ein täglicher Prüflauf meldet ausgebliebene Sicherungen an die Betriebsadresse von KYTH, wenn seit mehr als 26 Stunden kein erfolgreicher Lauf vermerkt wurde. Dass sich eine Sicherung einspielen lässt, ist am 01.08.2026 durch eine tatsächliche Wiederherstellung geprüft worden.
- Für die hochgeladenen Bildmotive gibt es keine Sicherung. Sie liegen im Objektspeicher und nicht in der Datenbank; der tägliche Lauf oben erfasst sie deshalb nicht. Geht der Eimer verloren, sind die Motive weg — die Karten der Händler wären dann ohne Bild, die übrigen Angaben blieben vollständig. Das ist eine benannte Lücke, siehe Abschnitt 7.2.
4. Belastbarkeit der Konfiguration
Die Anwendung startet nicht ohne die erforderlichen Konfigurationswerte; der Verschlüsselungsschlüssel wird auf das korrekte Format geprüft. Fehlkonfiguration führt zum Abbruch, nicht zu stillem Weiterlaufen.
5. Trennung von Test und Produktion
Zwei getrennte Anwendungen mit je eigener Datenbank, eigenem Verschlüsselungsschlüssel, eigener Datenbankrolle mit eigenem Kennwort, eigener Domain und eigener Shopify-Anwendung. Die Begründung, warum der Schlüssel nicht geteilt werden darf, ist in der Betriebsdokumentation festgehalten. Auch die Adressen der beiden Rechtstexte werden je Umgebung aus der jeweils eigenen Anwendungsadresse abgeleitet, damit die Testumgebung nicht auf den Produktivtext verweist.
6. Verfahren zur Überprüfung und Bewertung
- Löschpfad ohne pflegbare Liste: Die beim Löschen zu leerenden Tabellen werden zur
Laufzeit aus dem Datenbankkatalog ermittelt — alle Tabellen im Schema
publicmit einer Spalteshop_id. Die Löschung läuft in einer Transaktion. Nicht erfasst werden Tabellen in anderen Schemata, Tabellen mit abweichend benannter Shop-Spalte, Views und Tabellen, die nur mittelbar über einen Fremdschlüssel an einer Shop-Tabelle hängen. Die vier Grenzen sind im Quelltext offen benannt und stehen ausformuliert in § 9.1. - Ein Löschpfad, zwei Auslöser. Der Aufräumlauf für verwaiste Shops (§ 9.3 Nr. 1)
benutzt genau dieselbe Löschfunktion wie
shop/redact— und seit dieser Fassung auch denselben ersten Schritt, das Entfernen der Bildmotive über den Namensraum des Shops. Eine zweite Löschroutine müsste dieselbe Tabellenermittlung, dieselbe Mandantenbehandlung und dieselbe Transaktionsgrenze nachbilden — und würde über kurz oder lang eine Tabelle vergessen, die nur in einer der beiden gepflegt wird. Genau das war bei den Bildmotiven eingetreten: Derselbe Satz stand schon hier, während der Aufräumlauf den Objektspeicher gar nicht anfasste. - Automatische Prüfungen gegen schleichende Abweichung: Jede neue Tabelle mit
Shop-Zuordnung muss über die Datenzugriffsschicht erreichbar sein oder begründet
ausgenommen werden, muss ein Löschrecht für die Anwendungsrolle tragen, und jede
Tabelle mit einer nach Namensmuster personenbezogenen Spalte muss in die Liste der
Tabellen mit personenbezogenen Feldern eingetragen sein — sonst schlägt die Prüfung
fehl. Diese Prüfung hat mit dem Bestellablauf zum ersten Mal etwas zu tun bekommen:
Die Liste war bis dahin leer, weil es keine solche Tabelle gab; heute steht die
Gutscheintabelle darin, und über sie laufen Auskunft und Löschung nach Art. 15 und
Art. 17. Die Tabelle der Gutscheinprodukte steht ausdrücklich nicht darin und muss
es nicht — sie trägt eine Produktkennung, einen Handle und zwei Kennungen aus eigenem
Vokabular, nichts davon gehört einem Menschen.
Diese Prüfungen arbeiten auf demselben Ergebnis wie der Löschpfad und tragen daher
dieselben vier Grenzen. Die Tabelle
shopsist von ihnen ausdrücklich ausgenommen, weil sie keineshop_id-Spalte hat. Eine zweite, ausdrücklich begründete Ausnahme betrifft die Kontaktadresse in derselben Tabelle: Sie trägt einen Spaltennamen, den die Prüfung sonst als Kundendatum beanstanden würde. Es sind Händlerdaten, keine Kundendaten; sie tragen keine Kundenkennung und verschwinden übershop/redactund über den Aufräumlauf nach § 9.3 Nr. 1. Die Ausnahme ist im Quelltext niedergelegt und gilt genau für diese eine Spalte, nicht für die Tabelle: Kommt eine weitere Spalte mit einem solchen Namen hinzu, schlägt die Prüfung an. Bis zum 26.07.2026 war die Ausnahme tabellenweit gefasst und hätte jede künftige Spalte dieser Tabelle mitverdeckt. - Ablaufplan für Sicherheitsvorfälle mit 72-Stunden-Frist, benannter Aufsichtsbehörde (BayLDA), Eskalationsstufen und ausdrücklichem Hinweis auf Art. 14 DSGVO für Beschenkte.
7. Bekannte Lücken — offen benannt
Diese Punkte sind heute nicht oder nicht vollständig erfüllt. Sie stehen hier, weil eine Darstellung technischer Maßnahmen, die ihre Lücken verschweigt, wertlos ist.
7.1 Seit dem vorherigen Stand geschlossen
Damit niemand einer überholten Fassung folgt, zuerst das, was nicht mehr offen ist:
| Früher benannte Lücke | Stand (Datum jeweils genannt) |
|---|---|
| Sicherungen lagen lokal auf demselben Server wie die Datenbank | geschlossen. Sie gehen zusätzlich in den Objektspeicher der IONOS in Berlin. Ein Ausfall des Datenträgers nimmt nicht mehr beides mit (§ 9.3 Nr. 2) |
| Die Sicherungsdatei als Ganzes war nicht verschlüsselt — die feldweise Verschlüsselung schützte Token und Kontaktadresse auch in der Sicherung, alles Übrige lag offen: Shop-Domains, Bestell- und Positionskennungen, Zeitpunkte, Beträge, der ganze Aufbau. Ob der Speicheranbieter bei der Ablage über die S3-Schnittstelle verschlüsselt, war nicht belegt | geschlossen am 01.08.2026. Der Abzug wird symmetrisch mit AES-256 verschlüsselt, bevor er den Server verlässt; das Kennwort liegt auf dem Server, nicht im Objektspeicher. Die bis dahin offen abgelegten Sicherungen sind nachträglich verschlüsselt und in ihrer offenen Fassung gelöscht worden (§ 9.3 Nr. 2) |
| Wiederherstellungstest nie durchgeführt — ob sich die Sicherungen einspielen lassen, war unbewiesen | geschlossen am 01.08.2026. Eine Sicherung wurde aus dem Objektspeicher geholt, entschlüsselt und in eine leere Wegwerfdatenbank eingespielt; Tabellenzahl, Datenbestand und Versionsstand wurden verglichen, die Wegwerfdatenbank danach gelöscht |
| Kein Alarm bei fehlgeschlagener Sicherung — ein Ausfall fiel erst auf, wenn die Sicherung gebraucht wurde | geschlossen am 01.08.2026. Ein täglicher Prüflauf meldet, wenn seit mehr als 26 Stunden keine erfolgreiche Sicherung vermerkt wurde. Er erfasst damit auch ausgebliebene Läufe, nicht nur gescheiterte — der Ausfall, den ein Alarm im Fehlerzweig des Sicherungsskripts gerade nicht bemerkt |
| Auslöser der beiden Aufräumläufe fehlte — die Löschung verwaister Shops und die Entfernung abgeschlossener Webhook-Kennungen waren gebaut und geprüft, aber es gab keinen Zeitplan, der sie aufruft. Die 30-Tage-Fristen aus § 9.3 Nr. 1 und Nr. 3 waren damit Absicht und nicht Wirklichkeit | geschlossen am 01.08.2026. kaspar/aufraeumlauf.py startet mit dem Anwendungsprozess und ruft beide Regeln alle 24 Stunden auf |
| Serverseitige Zugriffsprotokolle nicht geregelt — ob und wie lange ein vorgelagerter Web-Server IP-Adressen, Browserkennungen und Abfrageparameter speichert, war nicht festgelegt | geklärt am 03.08.2026, und anders als erwartet: Traefiks Zugriffsprotokollierung ist ausgeschaltet — sie ist standardmäßig aus und in dieser Installation nirgends eingeschaltet (kein --accesslog im Startbefehl). Es gibt keine IP-Adressen, keine Browserkennungen und keine Abfrageparameter, also auch keine Frist zu setzen. Nachgezogen in 9.8 der Datenschutzerklärung, die bis dahin mehr Datenerhebung behauptete als stattfindet |
| Keine Aufbewahrungsfristen festgelegt | geschlossen. Sicherungen 30/90 Tage, verwaiste Shops 30 Tage, nie verbundene Shops 90 Tage, Webhook-Kennungen 30 Tage, Protokolle 14 Tage (§ 9.3) |
| Kein Aufräumlauf für Webhook-Kennungen und für Shops ohne Löschwebhook | gebaut und seit dem 01.08.2026 auch aufgerufen — ein Lauf startet mit dem Anwendungsprozess und ruft beide Regeln alle 24 Stunden auf |
| Vollständige Fehlermeldung im Fehlerpfad des Zugriffsprotokolls | geschlossen. Nur noch der Ausnahmetyp (1.4) |
| Shop-Zeilen ohne je zustande gekommene Verbindung fielen aus jedem Aufräumlauf. Ein gescheiterter Verbindungsversuch nach einer Deinstallation hob den Deinstallationszeitpunkt auf; die Zeile war danach für die 30-Tage-Regel unsichtbar und wäre dauerhaft stehen geblieben | geschlossen. Der Zeitpunkt wird erst nach einem erfolgreichen Token-Abruf aufgehoben, und eine zweite Regel im selben Aufräumlauf erfasst Zeilen ohne Deinstallationszeitpunkt und ohne jeden Token nach 90 Tagen (§ 9.3 Nr. 1) |
| Die Größe des Anfragekörpers war erst nach dem vollständigen Einlesen begrenzt — eine Anfrage ohne Längenangabe konnte den Arbeitsspeicher eines Arbeitsprozesses füllen; ein tief verschachtelter Körper endete zudem in einem Serverfehler statt in der vorgesehenen Antwort | geschlossen. Die Grenze wirkt vor und während des Einlesens (2.4) |
| Keine Kontaktadresse des Händlers | geschlossen. Pflichtfeld im Zustimmungsschritt (§ 0.2, § 2a Nr. 4) |
| Keine Zustimmungserfassung | geschlossen. Vertragsschluss durch Zustimmung mit Nachweis (§ 0) |
Hilfstabelle test_notizen im Produktivschema |
geschlossen. Per Migration entfernt |
| Die beiden Rechtstexte wurden unter ihren Adressen nicht ausgeliefert — der Zustimmungsschritt verwies auf Seiten, die es nicht gab | gebaut. Beide Adressen liefern den Text ohne Anmeldung aus derselben Quelle aus, aus der auch die Fassungskennung stammt (§ 0.4). Offen bleibt die Auslieferung in der Produktivumgebung, siehe 7.2 |
| Dieser Vertrag deckte die Ablage hochgeladener Bilder nicht — Anlage 1 sagte für alles, was der Händler eingibt, „keine Speicherung", und § 6.3 führte den Objektspeicher ausschließlich als Sicherungsablage. Die Software konnte Bilder zu diesem Zeitpunkt bereits annehmen, prüfen und ablegen | geschlossen mit dieser Fassung. Die Bildmotive stehen in Anlage 1 Abschnitt A mit Zweck, Speicherform und Löschung, der Objektspeicher steht in § 6.3 mit zwei Zwecken, die Löschung in § 9.3 Nr. 6 und die Prüfung beim Hochladen in 2.6 |
Dieser Vertrag deckte den Bestellablauf nicht — und zwar in seinen Kernaussagen. Anlage 1 Abschnitt C sagte zu Bestell- und Kundendaten wörtlich: „Eine Verarbeitung findet nicht statt: Es gibt keine Tabelle für Kunden-, Bestell- oder Empfängerdaten, kein Abonnement des Webhooks orders/paid und keinen Mailversand." § 2.3 sagte „Was KYTH damit tut: nichts", § 7.2 sagte, das Ergebnis einer Auskunft sei „nachweislich leer", und die beiden Berechtigungsumfänge write_gift_cards und write_products kamen im ganzen Vertrag nicht vor. Die Software nahm zu diesem Zeitpunkt bereits bezahlte Bestellungen entgegen, speicherte Empfänger-, Absender- und Codedaten verschlüsselt, legte Geschenkkarten bei Shopify an und richtete Produkte im Shop des Händlers ein |
geschlossen mit dieser Fassung. Die neuen Datenkategorien stehen in Anlage 1 Abschnitt A, die drei betroffenen Personen in § 2.1, die tatsächliche Ausübung aller fünf Berechtigungen in § 2.3, die sechs Aufrufe an die Admin-API in § 3.4, die Löschung und Anonymisierung in § 7.2 und § 9.3 Nr. 7, und die Maßnahmen des Bestellablaufs in 2.7 |
| Die Auskunft nach Art. 15 hätte ein Zahlungsmittel ausgehändigt — sie liest ausgewählte Spalten und nicht die ganze Zeile. Gutscheincode und Abruf-Token sind ausdrücklich ausgenommen | so gebaut, und mit dieser Fassung auch beschrieben (§ 7.2) |
Der Aufräumlauf für verwaiste Shops löschte die Bildmotive nicht mit. Blieb shop/redact aus, entfernte er nach 30 Tagen die Datenbankzeilen und ließ die Objekte im Objektspeicher stehen — ohne Zeile, die noch auf sie zeigt, und dauerhaft, weil er gerade dann greift, wenn niemand mehr nachlöscht. Der Vertrag beschrieb den Lauf zugleich als „exakt denselben Pfad" wie shop/redact |
geschlossen mit dieser Fassung. Der Lauf führt denselben Löschschritt über den Namensraum aus wie shop/redact und in derselben Reihenfolge: zuerst die Objekte, dann die Zeilen. Scheitert der Objektspeicher, bleibt die Shop-Zeile stehen und der Shop bleibt Kandidat des nächsten Laufs (§ 9.3 Nr. 6 a). Die Löschzusage für die Bilder hängt damit nur noch am fehlenden Auslöser, siehe 7.2 |
| In der Produktivumgebung wurden die beiden Rechtstexte nicht ausgeliefert. Die Route bestand, aber solange die Texte KLÄREN-Marken trugen, verweigerte die App dort den Start — statt einen Entwurf wie einen fertigen Vertragstext auszuliefern. Eine Zustimmung zu einem unlesbaren Text ist unwirksam (§ 0.4) | geschlossen am 03.08.2026. Alle zwölf offenen Stellen dieses Vertrags sind entschieden und belegt; die Produktivumgebung startet, und Impressum wie Datenschutzerklärung sind unter https://kartuu.kyth.systems/rechtliches/ abrufbar (beide HTTP 200 nachgemessen). Der Riegel selbst bleibt scharf: Öffnet jemand eine neue Stelle, startet die Produktivumgebung wieder nicht | | Die Produktivdatenbank wurde nicht gesichert — sie trug kein Schema und keine Daten, das Sicherungsskript brach an seiner Größenprüfung ab, und im Zeitplan stand nur die Testumgebung. Mit der ersten Migration in die Produktivumgebung gilt die Zusage aus § 9.3 Nr. 2 auch dort | geschlossen am 03.08.2026. Die Produktivumgebung ist auf Alembic 0026 migriert (neun Tabellen, Zeilenschutz auf sechs davon). Der erste Lauf von Hand hat eine verschlüsselte Sicherung erzeugt, sie vor dem Hochladen probeweise entschlüsselt und ihre Ankunft im Eimer bestätigt. Der Zeitplan ruft sie täglich um 03:25 UTC, und der Wächter aus § 9.3 Nr. 2 beobachtet seit demselben Tag beide Umgebungen — er meldet, wenn länger als 26 Stunden keine Sicherung mehr angekommen ist |
7.2 Weiterhin offen
| Lücke | Stand |
|---|---|
Die Auskunft nach Art. 15 erreicht den Händler nicht von selbst. Der Webhook customers/data_request stellt sie zusammen und schreibt einen Protokolleintrag mit der Anzahl der Datensätze; danach wird der Inhalt verworfen. Es gibt keine Seite in der App, auf der der Händler sie abrufen könnte, und keinen Versand an seine Kontaktadresse. Die Herausgabe erfolgt auf Anforderung in Textform und von Hand (§ 7.2). Shopify verlangt vom App-Anbieter, die Daten binnen 30 Tagen bereitzustellen — mit dem Weg von Hand ist das erfüllbar, aber es hängt an einer Nachricht und nicht an der Software. Wer handelt: die technische Leitung von KYTH, wenn eine Abrufmöglichkeit gebaut wird |
offen, mit benanntem Ersatzweg |
| Der Herausgabeweg der Schlüssel im Vertretungsfall ist nicht geregelt. Die Zweitkopien selbst gibt es seit dem 01.08.2026 — Kennwort der Sicherungsdateien und Verschlüsselungsschlüssel beider Umgebungen, außerhalb des Servers. Ungeklärt ist, wer sie herausgeben darf, wenn die technische Leitung ausfällt. Damit ist der Bus-Faktor nicht mehr technisch, sondern organisatorisch. Getrennte Verwahrung der beiden Geheimnisse bleibt Bedingung — an einem Ort zusammengelegt heben sie die Trennung auf, die sie wirksam macht | offen |
| Kein externes Verfügbarkeitsmonitoring, keine externe Fehlererfassung angebunden. Der Prüflauf über die Sicherungen läuft auf demselben Server und deckt dessen Totalausfall nicht ab | offen |
Kein Zeilenschutz auf shops — die Tabelle mit den produktiven Händlerdaten (Shop-Domain, verschlüsselte Token, Kontaktadresse, Zustimmungsnachweis, Berechtigungen, Zeitstempel) trägt keine Richtlinie; die Anwendungsrolle kann sie vollständig lesen und löschen. Die Trennung wirkt dort nur über die Anwendung und über spaltenweise Rechte |
offen |
| Löschpfad mit vier Grenzen — anderes Schema, abweichender Spaltenname, Views, nur mittelbar verknüpfte Tabellen werden nicht erfasst. Heute ohne Auswirkung, mit jeder neuen Tabelle relevanter (§ 9.1) | offen |
| Restfenster im Aufräumlauf für verwaiste Shops — zwischen der Prüfung unmittelbar vor dem Löschen und dem Löschen selbst kann derselbe Händler die App neu installieren. Das Fenster ist verkleinert, nicht geschlossen; bewusst so, um nur eine Löschlogik zu haben. Trifft der seltene Fall ein, installiert der Händler die App erneut | offen, mit überschaubarer Folge |
| Keine Zustimmungshistorie — gespeichert wird nur die zuletzt erteilte Zustimmung. Erforderlich wird eine Verlaufstabelle, bevor eine Fassung erhöht wird, zu der bereits ein Händler zugestimmt hat. Bei der Erhöhung von 1.0 auf 1.1 traf das nicht zu: Zu 1.0 lag keine Zustimmung vor (§ 0.2) | offen vor der nächsten Erhöhung |
| Shop-Zeile mit hinterlegten Token nach einem Schlüsselwechsel — konnte die Deinstallationsmeldung den Shop wegen eines veralteten Suchhashes nicht auflösen, bleibt die Zeile mit Token stehen und ist von der eines arbeitenden Shops nicht zu unterscheiden. Beide Regeln des Aufräumlaufs greifen dann nicht. Zu beheben durch Neuberechnen der Suchhashes nach jedem Schlüsselwechsel; ein Verfahren dafür ist nicht festgelegt (§ 9.3 Nr. 1) | offen |
| Derselbe Schlüsselwechsel trifft seit dem Bestellablauf ein Betroffenenrecht, und das wiegt schwerer. Der Suchwert über die E-Mail-Adresse des Beschenkten hängt am selben Schlüssel. Wird er gewechselt, ohne die Suchwerte neu zu berechnen, findet eine Löschung nach Art. 17 die Zeilen der beschenkten Person nicht mehr — und meldet trotzdem Vollzug, weil „keine Zeile getroffen" von „keine Zeile vorhanden" nicht zu unterscheiden ist. Dasselbe gilt für den Suchwert des Gutscheincodes: Der Riegel gegen eine doppelte Codevergabe wäre nach einem Wechsel wirkungslos. Der Quelltext benennt den Neuberechnungslauf als Pflichtschritt einer Rotation; gebaut ist er nicht. Solange nur ein Schlüssel im Einsatz ist, tritt der Fall nicht ein | offen, vor dem ersten Schlüsselwechsel zu schließen |
| Verwaiste unabgeschlossene Webhook-Ansprüche werden nie entfernt. Kein Personenbezug, sie belegen nur Platz (§ 9.3 Nr. 3) | bewusst offen |
| Aufnahmedaten (EXIF) hochgeladener Bilder werden nicht entfernt. Trägt ein Foto aus einem Mobiltelefon einen Standort, bleibt er im gespeicherten Bild und reist in das erzeugte PDF mit. Der Grund ist benannt und nicht behoben: Ein Entfernen hieße, das Bild neu zu kodieren — bei JPEG mit sichtbarem Qualitätsverlust bei jedem Upload, und der Inhalt entspräche danach nicht mehr der Prüfsumme, unter der er abgelegt ist. Solange die Bilder vom Händler stammen (sein Logo, sein Produktfoto), ist das vertretbar. Sobald ein Kunde oder ein Beschenkter ein Bild hochladen kann, ist es das nicht mehr — dann ist ein Schritt zum Verwerfen der Metadaten Voraussetzung, und über das Neukodieren ist neu zu entscheiden (§ 2.1, § 2.2, Anlage 2 Abschnitt 2.6) | offen, mit benannter Bedingung |
| Verwaiste Objekte werden nicht aufgeräumt, und ein Händler kann kein einzelnes Bild löschen. Ein hochgeladenes und nie oder nicht mehr benutztes Motiv bleibt liegen, solange der Shop besteht. Es gibt keinen Suchlauf dafür und keine Löschfunktion in der App; die Löschung auf Verlangen erfolgt von Hand (§ 7.3, § 9.3 Nr. 6 b) | bewusst offen |
| Keine Sicherung der Bildmotive. Die tägliche Sicherung erfasst die Datenbank, nicht den Objektspeicher. Geht der Eimer verloren, sind die Motive weg (Anlage 2 Abschnitt 3) | offen |
| Keine Frist für die Gutscheindaten nach Zweckfortfall. Ein eingelöster, abgelaufener oder stornierter Gutschein wird von keinem Lauf entfernt; die Zeilen liegen, bis der Shop verschwindet. Die Frist ist eine Entscheidung und keine Programmierfrage (§ 9.3 Nr. 7 a) | offen, mit Klärungsmarkierung |
Kein Auslöser für die Löschung einer beschenkten Person. Sie hat keine Kundennummer und erscheint in Shopifys customers/redact nur zufällig. Der Suchweg über den Suchwert ihrer Adresse ist gebaut, ein Weg für den Händler, ihn auszulösen, nicht. Bis dahin führt KYTH die Löschung auf Weisung von Hand aus (§ 7.2, § 9.3 Nr. 7 c) |
offen |
| Keine Möglichkeit, die Angaben einer bestellten Karte zu berichtigen. Empfängername, Adresse, Absendername und Grußtext stammen aus einem Kundenformular und können unrichtig sein; eine Oberfläche zum Ändern gibt es nicht — auch nicht für den Händler. Eine Berichtigung erfolgt von Hand (§ 7.3) | offen |
| Keine Oberfläche für den Stand einer Gutscheinbestellung. Fehlgeschlagene Gutscheine tragen ihren Grund an der Zeile und sind für den Händler heute trotzdem nicht sichtbar — es gibt keinen Statusbildschirm. Ein Fehlschlag fällt damit nur im Anwendungsprotokoll auf | offen |
| Eine Geschenkkarte kann verwaisen. Lehnt Shopify einen bereits gespeicherten Gutscheincode als vergeben ab, existiert die Karte, ihre Kennung ist aber unbekannt und sie lässt sich bei einem Storno nicht deaktivieren. Der Gutschein endet dafür in einem sichtbaren Fehlzustand statt in einer stillen zweiten Karte (2.7) | bewusst offen |
| Das Deaktivieren einer Geschenkkarte beim Storno ist nicht gebaut, obwohl der Berechtigungsumfang es deckt und der Zustand „storniert" im Datenmodell vorgesehen ist (Anlage 1 C) | offen |
Zur Verschlüsselung der Sicherungen: Gegenüber Händlern und gegenüber Shopify darf nicht behauptet werden, es gebe durchgängig verschlüsselte Sicherungen. Zugesagt ist die Feldverschlüsselung der schutzbedürftigen Werte innerhalb des Abzugs und die verschlüsselte Übertragung — nicht mehr. Diese Zeile ist vor jeder Verwendung dieses Vertrages zu prüfen.
Hinweis zur rechtlichen Prüfung
Dieser Vertrag ist ein Entwurf und wurde nicht anwaltlich geprüft.
Er wurde auf Grundlage einer Erhebung am Quelltext vom 27.07.2026 erstellt und gibt den technischen Sachverhalt nach bestem Wissen wieder. Er ersetzt keine Rechtsberatung. Vor der Verwendung gegenüber Händlern — insbesondere vor der Einbindung in den Installationsablauf der App — ist er durch eine Rechtsanwältin oder einen Rechtsanwalt mit Schwerpunkt Datenschutzrecht zu prüfen.
Sämtliche mit einer KLÄREN-Marke versehenen Stellen sind offene Punkte. Sie müssen geklärt und im Text ersetzt werden, bevor der Vertrag eingesetzt wird. Es sind acht; die Tabelle führt sie in sieben Zeilen, weil § 3.4 und die Markierung in Anlage 1 an derselben Beschaffung hängen und nur gemeinsam zu schließen sind:
Stelle Wer Was § 0.4 technische Leitung, gemeinsam mit den übrigen Zuständigen die offenen Stellen schließen; erst dann liefert die App die beiden Rechtstexte auch in der Produktivumgebung aus § 3.4 und Anlage 1 (Art. 30 Abs. 2 lit. c) Stefan Grasse Shopify-DPA beschaffen: Fassung, Datum, Standardvertragsklauseln Modul 3, Data Privacy Framework § 4 Geschäftsführung feststellen, ob über die Geschäftsführung hinaus Personen Zugriff haben, und die Vertraulichkeitsverpflichtungen ablegen § 6.3 (Verträge) Stefan Grasse Verträge nach Art. 28 Abs. 4 DSGVO mit IONOS und Shopify mit Fassung und Datum benennen § 6.3 (Anschriften) Stefan Grasse ladungsfähige Anschriften für Shopify und die Vertragsgesellschaft des Objektspeichers nachtragen § 9.3 Nr. 7 Geschäftsführung, gemeinsam mit dem Händler als Verantwortlichem Aufbewahrungsfrist der Gutscheindaten nach Zweckfortfall festlegen und den Aufräumlauf dafür bauen. Neu mit dem Bestellablauf — die größte gespeicherte Datenkategorie hat heute keine eigene Frist Zwei davon erfordern zuerst eine technische Umsetzung und nicht nur eine redaktionelle Entscheidung: der fehlende Auslöser der Aufräumläufe (§ 9.3 Nr. 1 und Nr. 3) und der Aufräumlauf für die Gutscheindaten (§ 9.3 Nr. 7). Beide betreffen Zusagen, die dieser Vertrag bereits ausspricht oder ausdrücklich verweigert.
Was seit dem vorherigen Entwurf erledigt ist: Zustimmungserfassung und Vertragsschluss (§ 0), Kontaktadresse des Händlers (§ 2a Nr. 4), Aufbewahrungsfristen (§ 9.3), Rolle von Cloudflare (§ 6.4) und die Auslagerung der Sicherungen (§ 6.3, § 9.3 Nr. 2). Frühere Fassungen dieses Vertrages sagten dazu teilweise das Gegenteil.
Was Fassung 1.1 gegenüber 1.0 nachträgt — sämtlich Änderungen an der Software vom selben Tag: den Client für die Admin API und den daraus gelesenen Abonnementstand (§ 2.3, Anlage 1 A), den Webhook
app_subscriptions/update(Anlage 1 C), den PDF-Erzeuger mit seiner Vorlagenauswahl (§ 1.1, § 1.3, Anlage 1 B), die Auslieferung dieser beiden Texte unter/rechtliches/(§ 0.4) und — als zweiter Nachtrag innerhalb derselben Fassung — die Ablage hochgeladener Bildmotive: die neue Datenkategorie (§ 2.1, § 2.2, Anlage 1 A), den Objektspeicher als produktive Ablage neben der Sicherungsablage (§ 3.4, § 6.3, § 6.5), die Löschung über den Namensraum samt ihren zwei Grenzen (§ 9.1, § 9.3 Nr. 6), das Herausgabeverlangen (§ 7.3, § 9.2), die Prüfung beim Hochladen (Anlage 2 Abschnitt 2.6) und die vier daraus folgenden Einträge in Anlage 2 Abschnitt 7.2, darunter die nicht entfernten Aufnahmedaten.Dritter Nachtrag innerhalb derselben Fassung — der Bestellablauf. Er ist der weitreichendste, weil er nicht eine Kategorie ergänzt, sondern die tragende Aussage dieses Vertrages umgekehrt hat: „Eine Verarbeitung von Bestell- und Kundendaten findet nicht statt." Nachgeführt sind - die neuen Datenkategorien und ihre Speicherform (§ 2.2, Anlage 1 A), - die drei betroffenen Personen, darunter die beschenkte Person in ihren zwei Rollen (§ 2.1), - die tatsächliche Ausübung aller fünf Berechtigungen samt der bis dahin gar nicht genannten Umfänge
write_gift_cardsundwrite_products(§ 2.3), - die Zwecke der Produkteinrichtung und der Bestellabwicklung (§ 1.1, § 1.3), - die sechs Aufrufe an die Admin-API und was sie tragen (§ 3.4, § 6.3), - Auskunft und Anonymisierung, die nicht mehr ins Leere laufen (§ 7.2), die fehlende Berichtigungsmöglichkeit (§ 7.3) und die Herausgabe (§ 9.2), - die Löschung mit dem Shop und die fehlende Frist nach Zweckfortfall samt Klärungsmarkierung (§ 9.1, § 9.3 Nr. 7), - die Maßnahmen des Bestellablaufs — Idempotenzschlüssel, verschlüsselte Codes und Empfängerangaben, Zustandslauf (Anlage 2 Abschnitte 1.1, 1.3, 1.4, 1.5, 2.7), - und sieben daraus folgende Einträge in Anlage 2 Abschnitt 7.2.Was dabei nicht nachzuführen war, weil es sich damals nicht geändert hatte: Es gab zu jenem Zeitpunkt keinen Mailversand, kein gespeichertes PDF, keinen Abruf über den erzeugten Link und keine Abfrage von Bestellungen über die Admin-API. Der erste dieser vier Punkte gilt nicht mehr — die Zustellung ist gebaut, und die Fassung vom 01.08.2026 führt sie nach.
Warum die Fassungskennung dabei nicht gestiegen ist. Fassung 1.1 ist nie ausgeliefert worden: Die Produktions-App ist nicht ausgerollt, und die Route für die Rechtstexte verweigert dort den Dienst, solange KLÄREN-Marken im Text stehen. Es hat ihr also niemand zugestimmt, und es gibt keine Zeile in der Datenbank, die auf sie verweist. Eine Erhöhung auf 1.2 wäre eine Fassungshistorie ohne Leser — und sie würde die Regel entwerten, dass eine steigende Kennung jeden Händler erneut fragt.
KYTH. Systems UG (haftungsbeschränkt) · Prof.-Mederer-Straße 4 · 92348 Berg · datenschutz@kyth.systems