# Zpracování osobních údajů – technický popis prototypu Tento dokument popisuje, **co systém dělá** s osobními údaji a jaká opatření jsou skutečně implementována. Není to právní posudek ani certifikace souladu s GDPR; organizační a právní předpoklady (viz poslední sekce) musí zajistit provozovatel. ## 1. Účel a rozsah zpracování | Položka | Popis | |---|---| | Účel | Prototyp diplomové práce: automatická extrakce entit, tématu a sentimentu z textových zpráv zákaznické podpory a jejich strukturované uložení. | | Vstup | Text zpráv (a volitelně `conversation_id`, `speaker`, `timestamp`) nahraný přes `/analyze` nebo `/ingest`. | | Kategorie údajů ve vstupu | Cokoli, co uživatelé do zpráv napíší: jména, e-maily, telefony, adresy, čísla objednávek apod. | | Testovací data | Veřejný dataset *Customer Support on Twitter* (uživatelská jména v něm jsou již nahrazena identifikátory). Pro demonstrace a testy se mají používat smyšlené údaje. | ## 2. Tok dat ``` vstup → NER + datumy/časy → téma → sentiment → maskování (Presidio) → uložení ↘ (volitelně) maskovaný text → LLM API ``` * Lokální větev (výchozí): žádná data neopouštějí aplikaci. * LLM větev: poskytovateli (Anthropic / Google / OpenAI) se posílá **pouze maskovaný text** (režim `pre_pseudonymized`). Režim `raw` posílá text bez maskování; je vypnutý a zapíná se výhradně `LLM_ALLOW_RAW=true`. * Selže-li maskování, text se do LLM neodešle a nic se neuloží (viz 4.). * Odpověď `/analyze` a stav ingest úlohy (`/ingest/status/{id}`) obsahují původní text a entity – vrací se jen tomu, kdo text poslal, a úloha žije pouze v paměti procesu. ## 3. Co se ukládá | Sloupec | Obsah | Poznámka | |---|---|---| | `original_hash` | SHA-256 původního textu | slouží k deduplikaci; krátké/předvídatelné texty lze hashem ověřit, proto jde stále o pseudonymizaci | | `anonymized_text` | text po maskování (`[NAME]`, `[EMAIL]`, …) | maskování je statistické – může nechat drobnost nezakrytou | | `entities` | typ, skóre, `[TYP]` místo textu; u `DATE`/`TIME` i normalizovaná hodnota | původní text entit se **neukládá** (`STORE_RAW_ENTITIES=false`) | | `conversation_id`, `speaker`, `input_timestamp`, `input_id` | metadata vstupu | `conversation_id` může být identifikátor převzatý ze vstupního souboru – posuzuje provozovatel | | `topic`, `sentiment` (+ skóre), `engine`, `provider`, `model`, `latency_ms`, `cost_usd` | výsledek a provozní údaje | | Datum/čas: v `anonymized_text` je maskováno (`[DATE]`), ale jako strukturovaný výstup extrakce se jeho normalizovaná hodnota ukládá (je to požadovaný výstup práce). Datum sám o sobě zpravidla neidentifikuje osobu, v kombinaci s jinými údaji ale může – při vyšším riziku vypněte extrakci v `processors/temporal.py`. ## 4. Chybové stavy a maskování * Nelze-li zaručit plné maskování (Presidio nedostupné / selhalo), používá se slabší regex maskování **jen** při `ANONYMIZER_ALLOW_FALLBACK=true`. Regex nemaskuje osobní jména. Výchozí chování: text se odmítne (`/analyze` → 503). * Neúspěšná analýza se ukládá jako nic – v databázi není žádný „prázdný“ nebo „neutrální“ záznam vzniklý z chyby. ## 5. Uchovávání, výmaz, zálohy | Téma | Stav | |---|---| | Doba uchování | `RETENTION_DAYS=N` maže při startu záznamy starší než N dní. Není-li nastaveno, data se uchovávají neomezeně. | | Výmaz na žádost | `db.purge_older_than(0)` smaže vše; cílený výmaz jednoho subjektu není implementován (uložený text je maskovaný, subjekt se v něm nedá spolehlivě dohledat). | | Zpětné čištění | `db.scrub_stored_entities()` nevratně přepíše entity ve starších záznamech. | | Zálohy | Zajišťuje poskytovatel databáze (např. Neon); prototyp je neřeší ani nemaže. Zálohy pořízené před čištěním mohou obsahovat původní entity. | | Přístup | API nemá autentizaci. Historie a exporty obsahují jen maskovaná data; omezení přístupu musí zajistit infrastruktura (reverzní proxy, síťová pravidla). | ## 6. Externí poskytovatelé Do poskytovatele LLM odchází maskovaný text a technické údaje (model, identifikátor požadavku). Provozovatel musí mít s poskytovatelem uzavřené podmínky odpovídající jeho roli (zpracovatel / samostatný správce) a ověřit umístění zpracování. Maskování před odesláním snižuje riziko, ale samo o sobě nenahrazuje smluvní ošetření ani nezaručuje anonymitu. ## 7. Co prototyp nezajišťuje * právní základ zpracování, informování subjektů údajů, záznamy o zpracování, posouzení vlivu na ochranu údajů, * autentizaci a autorizaci uživatelů API, * šifrování uložených dat nad rámec toho, co nabízí použitá databáze, * spolehlivost detekce osobních údajů: na 600 anotovaných zprávách zamaskoval samotný Presidio 68,1 % jmen osob (119 osob, 38 zůstalo viditelných, převážně podpisy agentů a oslovení). Doplňující pravidla (`mask_name_patterns`) zvýšila podíl na 93,3 % na vzorku, ze kterého vznikla, což je optimistický odhad. Míra odhalení adres, čísel objednávek a míst změřena nebyla.