Skip to content

GDPR in varstvo podatkov

Vgrajeno varstvo podatkov (Privacy by Design)

qr3.app je od samega začetka zasnovan v skladu z GDPR:

  • Psevdonimizacija IP-naslovov — IP-naslovi se v Edge Workerju takoj pretvorijo v dnevne psevdonime HMAC-SHA-256 UTC. Izvirni IP-naslov se nikoli ne shrani; psevdonim ostaja osebni podatek.
  • Minimizacija podatkov — Zbirajo se le podatki, ki so nujno potrebni za delovanje.

Privacy-API

Povzetek podatkov (čl. 15 GDPR)

GET /v1/account/privacy — Vrne pregled vseh shranjenih podatkov.

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 šteje shranjene vnose. scan_records so skeniranja kod QR, dpp_scan_records pa zahteve za potne liste izdelkov prek javnega DPP resolverja. Oba vsebujeta psevdonim IP.

dashboard_activity_records in dashboard_document_activity_records štejeta dneve, ko je član odprl nadzorno ploščo (dve tabeli), api_operation_records dnevne števce zahtev po ključu API, operaciji in izidu, webhook_delivery_records pa poskuse dostave webhookov, vključno s poskusi izbrisanih webhookov. Nobena od njih ne shranjuje naslova IP ali uporabniškega agenta (User-Agent); dnevnik dostave pa shranjuje payload dogodka in prvi kilobajt (1 KB) odgovora prejemnika. Vse štiri se izbrišejo po 90 dneh UTC (usage_retention, webhook_delivery_retention).

account navaja osebo, ki stoji za zahtevo — na nadzorni plošči prijavljeno osebo, sicer osebo, ki je ustvarila ključ — z e-poštnim naslovom, imenom, jezikom in datumom ustvarjanja; pri Publishable Key je vrednost null. Preostali števci zajemajo vsako nadaljnjo tabelo s podatki uporabniškega računa: potne liste izdelkov, dokumente DPP, datoteke, identifikatorje GS1, komentarje, revizijske vnose, zagone uvoza, člane delovnega prostora in obvestila o kvoti organizacije (scan_quota_alerts). Mehko izbrisane vrstice se štejejo, ker so še shranjene. erasure, backup_retention in billing_records opisujejo, kaj izbriše DELETE /v1/account in kaj še nekaj časa ostane; pii_in_export je true, ker izvoz navaja osebo (e-pošta, ime) — psevdonimi IP nikoli ne zapustijo baze podatkov.


Izvoz podatkov (čl. 20 GDPR — prenosljivost podatkov)

GET /v1/account/export — Prenese vse podatke kot datoteko JSON.

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

Izvoz vsebuje:

  • Vse kode QR (vključno z izbrisanimi)
  • Agregirano statistiko skeniranj (brez surovih zgoščenih vrednosti IP)
  • Agregirane zahteve DPP za posamezen potni list izdelka (dpp_scan_aggregates, prav tako brez zgoščenih vrednosti IP)
  • Statistika uporabe kot agregati (dashboard_activity_aggregates, api_operation_aggregates): aktivni dnevi in število aktivnih uporabnikov po kanalu nadzorne plošče, števci zahtev po operaciji in izidu — brez ID-jev uporabnikov in ključev
  • Poskusi dostave webhookov po webhooku in vrsti dogodka (webhook_delivery_aggregates), brez payloada in odgovora
  • Osebo, ki stoji za zahtevo (account), organizacijo (organization; naslov za obračun in obvestila samo za skrbnike organizacije) in delovni prostor (workspace)
  • Potne liste izdelkov, metapodatke dokumentov DPP in datotek (ne samih datotek), identifikatorje GS1, zahteve za njihovo potrditev in zagone uvoza (dpp_passports, dpp_documents, files, gs1_identifiers, gs1_verification_requests, dpp_import_jobs)
  • Komentarje brez polj avtorja (code_comments), revizijske vnose kot agregate (audit_log_aggregates) in člane po vlogi (member_aggregates)
  • Ključe API brez ID-ja in zgoščene vrednosti (api_keys), webhooke brez URL-ja in skrivnosti (webhooks) ter obvestila o kvoti organizacije (scan_quota_alerts)
  • Časovne žige ustvarjanja in sprememb

Publishable Keys (qr3_pk_) prejmejo 403: datoteka vsebuje ciljne naslove in opombe vseh kod.


Izbris računa (čl. 17 GDPR — pravica do pozabe)

DELETE /v1/account — Takoj in nepreklicno izbriše uporabniški račun osebe, ki stoji za zahtevo: na nadzorni plošči prijavljene osebe, sicer osebe, ki je ustvarila ključ. Zahteva za izbris po e-pošti vodi do istega izbrisa: upravljavec izbriše prijavo pri Clerk, nato pa qr3 izbriše uporabniški račun.

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

Kaj se zgodi:

  1. Organizacije, ki pripadajo osebi, se izbrišejo z vsemi delovnimi prostori, kodami, potnimi listi izdelkov, datotekami, statistiko in dnevniki, vključno z njihovimi datotekami v shrambi. Če ima takšna organizacija drugega aktivnega skrbnika organizacije, jo namesto tega prevzame tisti z najdaljšim stažem — skupaj s podatki in naročnino.
  2. Naročnina: tekoča naročnina se konča takoj, brez sorazmernega vračila denarja in brez končne fakture; nato se izbriše stranka pri Stripe. Fakture ostanejo pri Stripe v zakonsko predpisanem roku hrambe (7 let, § 132 BAO).
  3. Ekipe: članstva osebe v drugih organizacijah se končajo; te ekipe obdržijo svoje podatke. Komentarji osebe ne navajajo več avtorja, njeni revizijski vnosi izgubijo psevdonim IP in user agent, ključi API, ki jih je tam ustvarila, pa se prekličejo.
  4. Oseba: prijava (Clerk) in uporabniški zapis se izbrišeta.

Odgovor je 200 s status: "completed" in števci organizations_deleted, organizations_transferred, memberships_removed in login_deleted. Pri zelo velikih organizacijah ena zahteva ne zadošča: odgovor je tedaj 202 s status: "in_progress", izbris pa se v nekaj urah zaključi sam.

Zahteva Secret ali Test Key s pravico pisanja ali sejo na nadzorni plošči (katera koli vloga, ker gre za lasten uporabniški račun). Publishable Keys in ključi samo za branje prejmejo 403, ključ brez osebe za njim (created_by = 'system') prejme 409. 503 pomeni, da namestitvi manjka skrivnost, ki jo izbris potrebuje; nič ni bilo izbrisano.


Upravljanje privolitev

GET /v1/account/privacy/consents — Pridobitev trenutnih privolitev.

POST /v1/account/privacy/consents — Posodobitev privolitev.

Terminal window
# Pridobivanje trenutnih privolitev
curl https://qr3.app/v1/account/privacy/consents \
-H "Authorization: Bearer qr3_sk_..."
# Izklop trženjskih e-poštnih sporočil
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 }'

Polja privolitve:

PoljePrivzetoOpis
marketing_emailsfalseE-novice in oglaševalska e-poštna sporočila
analyticstrueAgregirana statistika uporabe
product_updatestrueNovosti o izdelkih in dnevniki sprememb (changelogs)

Za spreminjanje privolitev so potrebne pravice za pisanje: vloga viewer in Publishable Keys prejmejo 403.


Tehnična implementacija GDPR

Psevdonimizacija IP-naslovov (čl. 25 GDPR)

Zahteva HTTP → Cloudflare Edge Worker
↓
Glava CF-Connecting-IP → HMAC-SHA-256(IP_HASH_SALT, namen, dan UTC, IP)
↓
ip_hash (dnevni psevdonim) → podatkovna baza D1
↓
Izvirni IP-naslov se nikoli ne shrani

IP_HASH_SALT je dolgoživeča glavna skrivnost; namen in dan UTC samodejno izpeljeta ločene dnevne psevdonime. Psevdonimi različnih dni UTC niso neposredno enaki, vendar lahko imetnik skrivnosti za določen dan znova izračuna znanega kandidata IP. Ne uporablja se dnevna sol v KV niti ročna dnevna rotacija.

Hramba podatkov (avtomatizirana)

PaketHramba
Vsi paketi90 dni

Statistika uporabe (dejavnost v nadzorni plošči, števci uporabe API-ja) in dnevniki dostave webhookov se prav tako hranijo 90 dni UTC: tekoči dan UTC in 89 prejšnjih dni. Isto dnevno opravilo cron izbriše starejše vrstice (purgeOldDashboardActivity, purgeOldApiOperationUsage, purgeOldWebhookDeliveries).

DPA s podobdelovalci

Cloudflare, Inc. obdeluje podatke kot pogodbeni obdelovalec. Pogodba o obdelavi podatkov (DPA) je na voljo na naslovu cloudflare.com/cloudflare-customer-dpa.

Cloudflare obdeluje podatke z usmeritvijo lokacije na regijo EU (med drugim Frankfurt); pogodbeno zagotovljena jurisdikcija EU trenutno ni zakupnjena. Ker ima družba Cloudflare, Inc. sedež v ZDA, veljajo kot podlaga za prenos standardne pogodbene klavzule (SCC) v skladu s čl. 46 GDPR.


Kontakt