GDPR & ochrana osobních údajů
Ochrana soukromí od návrhu (Privacy by Design)
qr3.app je od základu navržen v souladu s GDPR:
- Pseudonymizace IP adres — IP adresy jsou v Edge Workeru okamžitě převedeny na denní pseudonymy HMAC-SHA-256 UTC. Původní IP adresa se nikdy neukládá; pseudonym zůstává osobním údajem.
- Minimalizace dat — Shromažďují se pouze data nezbytná pro provoz.
Privacy API
Přehled údajů (čl. 15 GDPR)
GET /v1/account/privacy — Vrací přehled všech uložených dat.
curl https://qr3.app/v1/account/privacy \ -H "Authorization: Bearer qr3_sk_..."Response:
{ "data": { "workspace_id": "ws_xxx", "organization_id": "org_xxx", "account": { "name": "Alex Example", "locale": "en", "created_at": "2026-01-15T09:00:00.000Z" }, "stored_data": { "qr_codes": 42, "scan_records": 15000, "dpp_scan_records": 3200, "dashboard_activity_records": 0, "dashboard_document_activity_records": 36, "api_operation_records": 180, "webhook_delivery_records": 640, "api_keys": 2, "webhooks": 1, "dpp_passports": 12, "dpp_documents": 30, "files": 4, "gs1_identifiers": 2, "gs1_verification_requests": 1, "code_comments": 5, "audit_log_entries": 0, "dpp_import_jobs": 1, "workspace_members": 3, "scan_quota_alerts": 1 }, "gdpr_rights": { "access": "GET /v1/account/privacy", "export": "GET /v1/account/export", "erasure": "DELETE /v1/account", "consents": "GET /v1/account/privacy/consents" }, "data_processing": { "ip_storage": "Purpose-separated HMAC-SHA-256 UTC-day IP pseudonym — pseudonymous personal data", "scan_retention": "90 days by default", "usage_retention": "90 UTC days", "webhook_delivery_retention": "90 UTC days", "pii_in_export": true, "erasure": "DELETE /v1/account erases the person's account: organizations they own with all workspaces and data (unless another org admin takes them over), their memberships in other organizations, their login and their Stripe customer. A running subscription ends immediately, without refund.", "backup_retention": "Erased rows stay restorable from the database backups (Cloudflare D1 Time Travel) for up to 30 days, then they are gone.", "billing_records": "Invoices stay with Stripe for the statutory retention period (7 years, § 132 BAO)." } }, "meta": { "request_id": "req_xxx" }}stored_data počítá uložené záznamy. scan_records jsou skeny QR kódů, dpp_scan_records dotazy na produktové pasy přes veřejný DPP resolver. Oba obsahují IP pseudonym.
dashboard_activity_records a dashboard_document_activity_records počítají dny, kdy člen otevřel dashboard (dvě tabulky), api_operation_records denní čítače požadavků podle API klíče, operace a výsledku a webhook_delivery_records pokusy o doručení webhooků, včetně pokusů smazaných webhooků. Žádná z nich neukládá IP adresu ani User-Agent; log doručení však ukládá payload události a první kilobajt (1 KB) odpovědi příjemce. Všechny čtyři se mažou po 90 dnech UTC (usage_retention, webhook_delivery_retention).
account uvádí osobu, která stojí za požadavkem — v dashboardu přihlášenou osobu, jinak osobu, která klíč vytvořila — s e-mailem, jménem, jazykem a datem vytvoření; u Publishable Key je hodnota null. Ostatní čítače pokrývají každou další tabulku s daty účtu: produktové pasy, dokumenty DPP, soubory, identifikátory GS1, komentáře, záznamy auditu, běhy importu, členy workspace a upozornění na kvótu organizace (scan_quota_alerts). Měkce smazané řádky se počítají, protože jsou stále uložené. erasure, backup_retention a billing_records popisují, co DELETE /v1/account smaže a co ještě nějakou dobu zůstává; pii_in_export je true, protože export uvádí osobu (e-mail, jméno) — pseudonymy IP adres databázi nikdy neopouštějí.
Export dat (čl. 20 GDPR — přenositelnost údajů)
GET /v1/account/export — Stáhne všechna data jako soubor JSON.
curl https://qr3.app/v1/account/export \ -H "Authorization: Bearer qr3_sk_..." \ -o my-data.jsonExport obsahuje:
- Všechny QR kódy (včetně smazaných)
- Agregované statistiky skenování (žádné surové hashe IP adres)
- Agregované dotazy na DPP pro každý produktový pas (
dpp_scan_aggregates, rovněž bez hashů IP adres) - Statistiky využití jako agregáty (
dashboard_activity_aggregates,api_operation_aggregates): aktivní dny a počet aktivních uživatelů podle kanálu dashboardu, čítače požadavků podle operace a výsledku — bez ID uživatelů a klíčů - Pokusy o doručení webhooků podle webhooku a typu události (
webhook_delivery_aggregates), bez payloadu a odpovědi - Osobu, která stojí za požadavkem (
account), organizaci (organization; fakturační a notifikační adresu jen pro správce organizace) a workspace (workspace) - Produktové pasy, metadata dokumentů DPP a souborů (ne soubory samotné), identifikátory GS1, žádosti o jejich ověření a běhy importu (
dpp_passports,dpp_documents,files,gs1_identifiers,gs1_verification_requests,dpp_import_jobs) - Komentáře bez polí autora (
code_comments), záznamy auditu jako agregáty (audit_log_aggregates) a členy podle role (member_aggregates) - API klíče bez ID a hashe (
api_keys), webhooky bez URL a tajného klíče (webhooks) a upozornění na kvótu organizace (scan_quota_alerts) - Časová razítka vytvoření a změny
Publishable Keys (qr3_pk_) dostanou 403: soubor obsahuje cílové adresy a poznámky všech kódů.
Smazání účtu (čl. 17 GDPR — právo být zapomenut)
DELETE /v1/account — Okamžitě a nevratně smaže účet osoby, která stojí za požadavkem: v dashboardu přihlášenou osobu, jinak osobu, která klíč vytvořila. Žádost o smazání e-mailem vede ke stejnému smazání: provozovatel smaže přihlášení u Clerk a qr3 poté smaže účet.
curl -X DELETE https://qr3.app/v1/account \ -H "Authorization: Bearer qr3_sk_..."Co se stane:
- Organizace, které osobě patří, se smažou se všemi workspace, kódy, produktovými pasy, soubory, statistikami a protokoly, včetně jejich souborů v úložišti. Má-li taková organizace dalšího aktivního správce organizace, převezme ji místo toho ten nejdéle působící — i s daty a předplatným.
- Předplatné: běžící předplatné končí okamžitě, bez poměrného vrácení peněz a bez závěrečné faktury; poté se smaže zákazník ve Stripe. Faktury zůstávají ve Stripe po zákonnou dobu uchování (7 let, § 132 BAO).
- Týmy: členství osoby v cizích organizacích končí; tyto týmy si svá data ponechají. Komentáře osoby už neuvádějí autora, její záznamy auditu ztratí pseudonym IP adresy a user agent a API klíče, které tam vytvořila, se zneplatní.
- Osoba: přihlášení (Clerk) a uživatelský záznam se smažou.
Odpověď je 200 se status: "completed" a čítači organizations_deleted, organizations_transferred, memberships_removed a login_deleted. U velmi velkých organizací jeden požadavek nestačí: odpověď je pak 202 se status: "in_progress" a smazání se během několika hodin dokončí samo.
Vyžaduje Secret nebo Test Key s právem zápisu, nebo relaci v dashboardu (jakákoli role, protože jde o vlastní účet). Publishable Keys a klíče jen pro čtení dostanou 403, klíč bez osoby za ním (created_by = 'system') dostane 409. 503 znamená, že nasazení chybí tajný klíč, který smazání potřebuje; nic nebylo smazáno.
Správa souhlasů
GET /v1/account/privacy/consents — Získat aktuální souhlasy.
POST /v1/account/privacy/consents — Aktualizovat souhlasy.
# Načtení aktuálních souhlasůcurl https://qr3.app/v1/account/privacy/consents \ -H "Authorization: Bearer qr3_sk_..."
# Vypnutí marketingových e-mailůcurl -X POST https://qr3.app/v1/account/privacy/consents \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "marketing_emails": false, "analytics": true, "product_updates": true }'Pole souhlasu:
| Pole | Výchozí | Popis |
|---|---|---|
marketing_emails | false | Newslettery a reklamní e-maily |
analytics | true | Agregované statistiky používání |
product_updates | true | Novinky o produktech a changelogy |
Změna souhlasů vyžaduje oprávnění k zápisu: role viewer a Publishable Keys dostanou 403.
Technická implementace GDPR
Pseudonymizace IP adres (čl. 25 GDPR)
HTTP požadavek → Cloudflare Edge Worker ↓Hlavička CF-Connecting-IP → HMAC-SHA-256(IP_HASH_SALT, účel, den UTC, IP) ↓ip_hash (denní pseudonym) → databáze D1 ↓Původní IP adresa se nikdy neukládáIP_HASH_SALT je dlouhodobé hlavní tajemství; účel a den UTC automaticky odvozují oddělené denní pseudonymy. Pseudonymy z různých dnů UTC nejsou přímo stejné, držitel tajemství však může pro konkrétní den znovu spočítat známého kandidáta IP adresy. Nepoužívá se denní sůl v KV ani ruční denní rotace.
Uchovávání dat (automatizované)
| Tarif | Uchovávání (Retention) |
|---|---|
| Všechny tarify | 90 dní |
Statistiky využití (aktivita v dashboardu, čítače využití API) a logy doručení webhooků se rovněž uchovávají 90 dnů UTC: aktuální den UTC a 89 předchozích dnů. Tatáž denní úloha cron maže starší řádky (purgeOldDashboardActivity, purgeOldApiOperationUsage, purgeOldWebhookDeliveries).
Zpracovatelská smlouva (DPA) subdodavatelů
Společnost Cloudflare, Inc. zpracovává data jako zpracovatel. Smlouva DPA je k dispozici na adrese cloudflare.com/cloudflare-customer-dpa.
Cloudflare zpracovává data s lokalizačním tipem (location hint) pro region EU (mj. Frankfurt); smluvně garantovaná jurisdikce v EU není v současné době předplacena. Vzhledem k tomu, že společnost Cloudflare, Inc. sídlí v USA, platí jako základ pro předávání standardní smluvní doložky (SCC) podle čl. 46 GDPR.
Kontakt
- Pověřenec pro ochranu osobních údajů: [email protected]
- Smlouva o zpracování osobních údajů (DPA): [email protected] (na vyžádání)
- Zásady ochrany osobních údajů: qr3.app/de/legal/datenschutz