Listopad 2024. UODO publikuje Plan Sektorowych Kontroli na rok 2025 — corocznie aktualizowany dokument wyznaczający priorytety inspekcji. W obszarze szczególnego nadzoru — e-commerce, programy lojalnościowe, profilowanie marketingowe oraz przetwarzanie danych w celu kierowania komunikacji handlowej. Plan na 2026 kontynuuje większość tych obszarów, dokładając kontrole post-PKE compliance.
Marta — właścicielka 8-osobowego DTC z marżą 12% — czyta ten plan w niedzielę wieczór. Kary RODO sięgają do 4% globalnego obrotu rocznego lub 20 milionów EUR. Dla sklepu robiącego 3 miliony PLN obrotu rocznie teoretyczna kara to 120 000 PLN — równowartość sześciu miesięcy operacyjnego runwayu, znikających w jednym piśmie z UODO.
Marta otwiera swój stack. Yotpo — domyślny consent log loguje user_id i email z timestampem, ale nie wersjonuje treści klauzuli, którą użytkownik widział. Klaviyo — hosting w Wirginii, audit trail trzy miesiące. ReferralCandy — data flow opisany w DPA niejasno. Wszystkie obiecują "GDPR-ready" na landing page'u. W drobnym druku — minimum, które może nie wytrzymać kontroli UODO.
Większość zachodnich SaaSów loguje consent w sposób minimalny — wystarczająco, żeby nie naruszyć GDPR formalnie, ale niewystarczająco, żeby przetrwać kontrolę UODO bez paniki.
Czym jest consent log w RODO art. 7 ust. 1
RODO art. 7 ust. 1 (warunki wyrażenia zgody) brzmi — "Jeżeli przetwarzanie odbywa się na podstawie zgody, administrator musi być w stanie wykazać, że osoba, której dane dotyczą, wyraziła zgodę."
Słowo klucz — wykazać. Nie zebrać. Nie udokumentować ogólnie. Wykazać — to znaczy przedstawić dowód, który wytrzyma weryfikację UODO podczas kontroli. Sam checkbox z timestampem to zebranie. Pełen audit trail z wersją klauzuli, kontekstem zbierania i mechanizmem wycofania to wykazanie.
Recital 32 precyzuje — zgoda musi być dobrowolna, świadoma, konkretna, jednoznaczna. Każdy wymóg ma konsekwencje dla tego, co loguj:
- Dobrowolna — loguj kontekst zbierania (czy nie była wymuszona np. wymogiem zaakceptowania przed checkout)
- Świadoma — loguj wersję klauzuli (co dokładnie użytkownik widział)
- Konkretna — loguj scope (jakie konkretne cele przetwarzania zostały wskazane)
- Jednoznaczna — loguj mechanizm (active opt-in, nie pre-checked checkbox)
Recital 42 dokłada wymóg wycofywalności — "wycofanie zgody musi być tak proste jak jej wyrażenie". To znaczy że w consent log musisz logować nie tylko moment zgody, ale i moment wycofania.
7 rzeczy, które MUSI mieć consent log
Te siedem pól to minimalny zestaw, który pozwoli przetrwać kontrolę UODO bez paniki. Nie idealny. Nie premium. Minimalny, który jest wystarczający w oparciu o praktykę 2025-2026.
2.1 User identifier (pseudonimizowany)
Co loguj: unikalny identyfikator osoby. Nie raw email, nie raw IP, nie imię i nazwisko. UUID lub pseudonimowany hash.
Dlaczego: Trybunał Sprawiedliwości UE w sprawie C-582/14 Breyer potwierdził, że dynamiczny adres IP jest danymi osobowymi. Logging surowego IP w consent log = przetwarzanie danych osobowych bez jednoznacznej, oddzielnej podstawy.
Standard polskiej praktyki: SHA-256 hash IP plus daily salt. Hash jest deterministyczny w obrębie dnia, ale nie da się go odwrócić po 24 godzinach.
texthashed_ip = SHA256(raw_ip + daily_salt)2.2 Timestamp (ISO 8601, z retention policy)
Format ISO 8601 UTC z dokładnością do sekundy. Przykład — 2026-04-14T16:23:47Z. UODO oczekuje udokumentowania kiedy zgoda została wyrażona w sposób, który pozwala odtworzyć kontekst.
Retention policy:
- Aktywni użytkownicy — okres aktywnego przetwarzania plus okres przedawnienia roszczeń, który ustalasz ze swoim prawnikiem (dla roszczeń związanych z działalnością gospodarczą to zwykle 3 lata, art. 118 KC)
- Po wycofaniu zgody — dowód zgody trzymasz tak długo, jak długo możesz musieć wykazać jej udzielenie
- Po deletion request (RODO art. 17) — zachowujemy fakt usunięcia z metadanymi, ale nie samą treść danych
2.3 Consent type (granularnie, jako JSON)
Dokładny zakres zgody jako strukturalny JSON, nie jeden bool flag:
json{ "marketing_email": true, "marketing_sms": false, "profiling_behavioral": true, "profiling_predictive": false, "referral_program_participation": true, "third_party_sharing": false}RODO art. 7 ust. 2 wymaga, żeby zgoda była konkretna. Jeden checkbox "zgadzam się na marketing" nie spełnia wymogu — to "zgoda zbiorcza" odrzucona w wielu interpretacjach UODO.
2.4 Consent text version (history versioning)
Wersja konkretnej treści klauzuli, którą użytkownik widział. Nie reference do "regulaminu" jako abstrakcyjnego dokumentu — referencyjne ID konkretnej wersji.
json{ "consent_version": "consent_v3_2026_01_15", "consent_url_at_time_of_acceptance": "https://example.pl/regulamin?v=3"}Po roku użytkownik może wycofać zgodę i zażądać udokumentowania, na co dokładnie się zgodził w styczniu. Jeśli logujesz tylko consent: true, a regulamin zmieniłeś trzy razy — nie masz dowodu, której wersji dotyczyła ta zgoda.
2.5 Source / UI context
json{ "collection_source": "checkout_step_2", "collection_url": "https://example.pl/checkout?step=consent", "ui_component": "checkout_consent_modal_v2", "referrer": "https://example.pl/cart"}UODO sprawdza czy zgoda była dobrowolna. Zgoda zebrana na checkout (gdzie użytkownik musi zaznaczyć żeby kupić) jest mniej dobrowolna niż w niezależnym pop-upie. Logging source pozwala udokumentować kontekst.
2.6 Withdrawal mechanism (logowane przy wycofaniu)
Recital 42 — wycofanie musi być tak łatwe jak wyrażenie. W praktyce:
- Jeśli zgoda została wyrażona przez kliknięcie checkboxa w 30 sekund, wycofanie nie może wymagać emaila do supportu
- Wycofanie powinno być dostępne w panelu użytkownika, jednym klikiem
- Po wycofaniu natychmiast zatrzymujemy przetwarzanie objęte tą zgodą
json{ "event_type": "consent_withdrawn", "user_id": "uuid_xxx", "withdrawn_at": "2026-04-14T16:23:47Z", "consent_type_withdrawn": "marketing_email", "withdrawal_method": "user_panel_self_service", "withdrawal_url": "https://example.pl/panel/preferences", "previous_consent_id": "uuid_yyy"}2.7 Audit trail (append-only, immutable)
Każda operacja na consent — append-only. Nigdy nie nadpisuj istniejącego entry. Tabela z UPDATE/DELETE permission to nie audit trail — to log z możliwością manipulacji.
- INSERT only permission dla aplikacji
- Hard delete tylko jako reakcja na żądanie usunięcia (RODO art. 17), z osobnym entry dokumentującym operację
- created_at immutable timestamp od strony bazy (PostgreSQL DEFAULT NOW())
- Idealnie — cryptographic hash chain (każdy wpis zawiera hash poprzedniego)
Konkretny przykład consent log — SQL schema
sqlCREATE TABLE consent_log ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), hashed_ip TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), consent_scope JSONB NOT NULL, consent_version_id UUID NOT NULL REFERENCES consent_versions(id), collection_source TEXT NOT NULL, collection_url TEXT NOT NULL, ui_component TEXT, referrer TEXT, event_type TEXT NOT NULL DEFAULT 'consent_granted', withdrawal_method TEXT, previous_consent_id UUID REFERENCES consent_log(id));-- Audit trail append-only — brak UPDATE/DELETE policyREVOKE UPDATE, DELETE ON consent_log FROM authenticated;Co UODO sprawdza w kontroli sektorowej 2026
Pięć konkretnych obszarów w trakcie inspekcji:
- 01Rejestr czynności RODO art. 30 — dokumentacja przetwarzania
- 02Przykładowy consent log entry — czy zawiera 7 wymaganych pól
- 03Klauzula z dnia X — czy potrafisz pokazać dokładnie tę wersję klauzuli, którą widział konkretny użytkownik miesiące temu
- 04Procedura withdrawal — self-service vs email do supportu
- 05DPA z sub-processorami (Stripe, mailer, hosting) — gdzie dane fizycznie trafiają
Jak sprawdzić to u swojego dostawcy
Zamiast rankingu, który i tak zestarzeje się przy najbliższym release dowolnego narzędzia: weź listę siedmiu pól z tego tekstu i poproś swojego dostawcę o eksport jednego rekordu zgody. To zajmuje jeden mail, a odpowiedź mówi więcej niż każda tabela porównawcza — łącznie z naszą.
U nas rejestr zgód ma te pola od początku: zakres zgody osobno dla każdej kategorii, wersjonowanie treści zgody, zapis wyłącznie przez dopisanie (bez edycji historii), IP jako hash SHA-256 z solą dobową. Dane trzymamy w Unii, w regionie AWS eu-west-1 (Irlandia) — lokalizacja i lista podprocesorów są w umowie powierzenia.
Compliance checklist na koniec
- 01Pseudonimowany user_id (UUID, nie raw email)
- 02SHA-256 hash IP plus daily salt
- 03ISO 8601 UTC timestamp z retention 5+ lat
- 04Granular consent scope jako JSONB
- 05consent_version_id z linkiem do tabeli consent_versions
- 06Source, URL, UI component, referrer
- 07Withdrawal event log z previous_consent_id
- 08INSERT-only permission na tabeli
- 09DPA z każdym sub-processorem
- 10Hosting w UE — sprawdź w umowie powierzenia, w którym regionie faktycznie leżą dane
Źródła
- UODO Plan Sektorowych Kontroli 2025
- Interaktywny tekst RODO art. 7
- Lex Digital — komentarz art. 7 RODO
- ETS C-582/14 Breyer — IP jako dane osobowe