Preskočiť na obsah

GDPR a ochrana osobných údajov

Ochrana osobných údajov od návrhu

qr3.app je od základu navrhnutý v súlade s GDPR:

  • Pseudonymizácia IP adries — IP adresy sa v Edge Workeri okamžite konvertujú na denné pseudonymy HMAC-SHA-256 UTC. Pôvodná IP adresa sa nikdy neukladá; pseudonym zostáva osobným údajom.
  • Minimalizácia údajov — Zaznamenávajú sa iba údaje nevyhnutné na prevádzku.

Privacy API

Súhrn údajov (čl. 15 GDPR)

GET /v1/account/privacy — Vracia prehľad všetkých uložených údajov.

Terminal window
curl https://qr3.app/v1/account/privacy \
-H "Authorization: Bearer qr3_sk_..."

Response:

{
"data": {
"workspace_id": "ws_xxx",
"organization_id": "org_xxx",
"account": {
"email": "[email protected]",
"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číta uložené záznamy. scan_records sú skeny QR kódov, dpp_scan_records požiadavky na produktové pasy cez verejný DPP resolver. Oba obsahujú IP pseudonym.

dashboard_activity_records a dashboard_document_activity_records počítajú dni, keď člen otvoril dashboard (dve tabuľky), api_operation_records denné počítadlá požiadaviek podľa API kľúča, operácie a výsledku a webhook_delivery_records pokusy o doručenie webhookov vrátane pokusov vymazaných webhookov. Žiadna z nich neukladá IP adresu ani User-Agent; log doručenia však ukladá payload udalosti a prvý kilobajt (1 KB) odpovede príjemcu. Všetky štyri sa mažú po 90 dňoch UTC (usage_retention, webhook_delivery_retention).

account uvádza osobu, ktorá stojí za požiadavkou — v dashboarde prihlásenú osobu, inak osobu, ktorá vytvorila kľúč — s e-mailom, menom, jazykom a dátumom vytvorenia; pri Publishable Key je hodnota null. Ostatné počítadlá pokrývajú každú ďalšiu tabuľku s údajmi účtu: produktové pasy, dokumenty DPP, súbory, identifikátory GS1, komentáre, záznamy auditu, behy importu, členov workspace a upozornenia na kvótu organizácie (scan_quota_alerts). Mäkko vymazané riadky sa započítavajú, pretože sú stále uložené. erasure, backup_retention a billing_records opisujú, čo DELETE /v1/account vymaže a čo ešte nejaký čas zostáva; pii_in_export je true, pretože export uvádza osobu (e-mail, meno) — IP pseudonymy nikdy neopúšťajú databázu.


Export údajov (čl. 20 GDPR — prenosnosť údajov)

GET /v1/account/export — Stiahne všetky údaje ako JSON súbor.

Terminal window
curl https://qr3.app/v1/account/export \
-H "Authorization: Bearer qr3_sk_..." \
-o my-data.json

Export obsahuje:

  • Všetky QR kódy (vrátane vymazaných)
  • Agregované štatistiky skenovania (žiadne surové IP hashe)
  • Agregované požiadavky na DPP pre každý produktový pas (dpp_scan_aggregates, takisto bez IP hashov)
  • Agregované štatistiky používania (dashboard_activity_aggregates, api_operation_aggregates): aktívne dni a počet aktívnych používateľov podľa kanála dashboardu, počítadlá požiadaviek podľa operácie a výsledku — bez ID používateľov a kľúčov
  • Agregované pokusy o doručenie webhookov podľa webhooku a typu udalosti (webhook_delivery_aggregates), bez payloadu a odpovede
  • Osobu, ktorá stojí za požiadavkou (account), organizáciu (organization; fakturačnú a notifikačnú adresu len pre správcov organizácie) a workspace (workspace)
  • Produktové pasy, metadáta dokumentov DPP a súborov (nie samotné súbory), identifikátory GS1, žiadosti o ich overenie a behy importu (dpp_passports, dpp_documents, files, gs1_identifiers, gs1_verification_requests, dpp_import_jobs)
  • Komentáre bez polí autora (code_comments), záznamy auditu ako agregáty (audit_log_aggregates) a členov podľa roly (member_aggregates)
  • API kľúče bez ID a hashu (api_keys), webhooky bez URL a tajomstva (webhooks) a upozornenia na kvótu organizácie (scan_quota_alerts)
  • Časové pečiatky vytvorenia a zmeny

Publishable Keys (qr3_pk_) dostanú 403: súbor obsahuje cieľové adresy a poznámky všetkých kódov.


Vymazanie účtu (čl. 17 GDPR — právo na zabudnutie)

DELETE /v1/account — Okamžite a nevratne vymaže účet osoby, ktorá stojí za požiadavkou: v dashboarde prihlásenú osobu, inak osobu, ktorá vytvorila kľúč. Žiadosť o vymazanie e-mailom vedie k rovnakému vymazaniu: prevádzkovateľ vymaže prihlásenie v Clerk a qr3 potom vymaže účet.

Terminal window
curl -X DELETE https://qr3.app/v1/account \
-H "Authorization: Bearer qr3_sk_..."

Čo sa stane:

  1. Organizácie, ktoré patria osobe, sa vymažú so všetkými workspace, kódmi, produktovými pasmi, súbormi, štatistikami a logmi vrátane ich súborov v úložisku. Ak má takáto organizácia ďalšieho aktívneho správcu organizácie, namiesto toho ju prevezme ten s najdlhším pôsobením — aj s údajmi a predplatným.
  2. Predplatné: prebiehajúce predplatné sa končí okamžite, bez pomerného vrátenia peňazí a bez záverečnej faktúry; potom sa vymaže zákazník v Stripe. Faktúry zostávajú v Stripe počas zákonnej lehoty uchovávania (7 rokov, § 132 BAO).
  3. Tímy: členstvá osoby v iných organizáciách sa končia; tieto tímy si ponechávajú svoje údaje. Komentáre osoby už neuvádzajú autora, jej záznamy auditu strácajú IP pseudonym a user agent a API kľúče, ktoré tam vytvorila, sa zrušia.
  4. Osoba: prihlásenie (Clerk) a používateľský záznam sa vymažú.

Odpoveď je 200 so status: "completed" a počítadlami organizations_deleted, organizations_transferred, memberships_removed a login_deleted. Pri veľmi veľkých organizáciách jedna požiadavka nestačí: odpoveď je potom 202 so status: "in_progress" a vymazanie sa v priebehu niekoľkých hodín dokončí samo.

Vyžaduje Secret alebo Test Key s právom zápisu alebo reláciu v dashboarde (akákoľvek rola, pretože ide o vlastný účet). Publishable Keys a kľúče len na čítanie dostanú 403, kľúč bez osoby za ním (created_by = 'system') dostane 409. 503 znamená, že nasadeniu chýba tajomstvo, ktoré vymazanie potrebuje; nič sa nevymazalo.


Správa súhlasov

GET /v1/account/privacy/consents — Získanie aktuálnych súhlasov.

POST /v1/account/privacy/consents — Aktualizácia súhlasov.

Terminal window
# Načítanie aktuálnych súhlasov
curl https://qr3.app/v1/account/privacy/consents \
-H "Authorization: Bearer qr3_sk_..."
# Vypnutie marketingových e-mailov
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 }'

Polia súhlasu:

PolePredvolenéPopis
marketing_emailsfalseNewsletter a reklamné e-maily
analyticstrueAgregované štatistiky používania
product_updatestrueNovinky o produktoch a changelogy

Zmena súhlasov vyžaduje oprávnenie na zápis: rola viewer a Publishable Keys dostanú 403.


Technická implementácia GDPR

Pseudonymizácia IP adries (čl. 25 GDPR)

HTTP požiadavka → Cloudflare Edge Worker
↓
Hlavička CF-Connecting-IP → HMAC-SHA-256(IP_HASH_SALT, účel, deň UTC, IP)
↓
ip_hash (denný pseudonym) → databáza D1
↓
Pôvodná IP adresa sa nikdy neukladá

IP_HASH_SALT je dlhodobé hlavné tajomstvo; účel a deň UTC automaticky odvodzujú oddelené denné pseudonymy. Pseudonymy z rôznych dní UTC nie sú priamo rovnaké, držiteľ tajomstva však môže pre konkrétny deň znovu vypočítať známeho kandidáta IP adresy. Nepoužíva sa denná soľ v KV ani ručná denná rotácia.

Uchovávanie údajov (automatizované)

PredplatnéUchovávanie
Všetky programy90 dní

Štatistiky používania (aktivita v dashboarde, počítadlá používania API) a logy doručenia webhookov sa tiež uchovávajú 90 dní UTC: aktuálny deň UTC a 89 predchádzajúcich dní. Tá istá denná úloha cron maže staršie riadky (purgeOldDashboardActivity, purgeOldApiOperationUsage, purgeOldWebhookDeliveries).

DPA so subdodávateľmi

Spoločnosť Cloudflare, Inc. spracúva údaje ako sprostredkovateľ. Zmluva DPA je dostupná na adrese cloudflare.com/cloudflare-customer-dpa.

Cloudflare spracúva údaje s lokalizačným tipom (location hint) pre región EÚ (okrem iného Frankfurt); zmluvne garantovaná jurisdikcia EÚ nie je v súčasnosti predplatená. Keďže spoločnosť Cloudflare, Inc. sídli v USA, ako základ pre prenos platia štandardné zmluvné doložky (SCC) podľa čl. 46 GDPR.


Kontakt