Na vlastných portáloch publikujeme podmienky desiatok ponúk od viacerých partnerov. Partner ich môže zmeniť kedykoľvek a bez ohlásenia. Každá zastaraná veta je riziko pre čitateľa, pre partnera aj pre nás. Článok opisuje, ako sme postavili strážcu zmien, ktorý tieto stránky číta, ale o ničom nerozhoduje. Je pre každého, kto potrebuje sledovať cudzie texty, napríklad cenníky, podmienky dodávateľov alebo regulačné dokumenty, a zároveň vedieť doložiť, čo kedy platilo.
Ani ručne, ani plne automaticky
Ručná kontrola všetkých stránok v krátkych intervaloch sa nedá udržať a väčšinu času zistí len to, že sa nič nestalo. Automat, ktorý by zmeny sám prepisoval do obsahu, sa zase nedá obhájiť: stačí nový dizajn stránky, overovacia obrazovka namiesto obsahu alebo nejednoznačná veta a na portáli je nepravda. Úlohy sme preto rozdelili. Automat robí to, v čom je spoľahlivý: číta, porovnáva, archivuje a upozorňuje. Človek robí to, čo automat nevie: rozumie textu a rozhoduje.
Základná zásada znie: načítanie nie je overenie. To, že stránka odpovedala a jej text sa nezmenil, znamená len „sledovaný text je rovnaký ako verzia, ktorú sme naposledy prijali“. Neznamená to, že ponuka platí, ani že sme jej rozumeli.
Štyri možné výsledky jedného načítania
Každé načítanie skončí jedným zo štyroch stavov a žiadny z nich neznamená „podmienky sú overené“:
- Bez zmeny: text sa zhoduje s naposledy prijatou verziou.
- Zmena: text sa líši od prijatej verzie alebo prijatá verzia ešte neexistuje. Aj úplne prvé načítanie zdroja je preto len kandidát na posúdenie.
- Chyba: stránka sa nenačítala pre výpadok, chybový stavový kód, vypršaný čas alebo nepovolené presmerovanie.
- Nečitateľné: odpoveď prišla, ale nie je to text, ktorý sledujeme. Môže ísť o overovaciu obrazovku, príliš krátky text, chýbajúcu obsahovú časť stránky, nepodporovaný formát (napríklad PDF) alebo o text bez názvu ponuky, ktorý v ňom musí byť.
Posledná kontrola, takzvaná kotva identity, je nenápadná, ale dôležitá. Keď partner presmeruje adresu akcie na všeobecnú stránku, technicky sa načíta „niečo“. Bez kotvy by to vyzeralo ako zmena podmienok, s kotvou je to nečitateľný zdroj, ktorý treba opraviť. Chyba ani nečitateľnosť nie sú zmenou podmienok. Posledné úspešné pozorovanie zostáva s pôvodným časom a nikdy sa nevydáva za čerstvé.
Od stránky k odtlačku
Z odpovede sa najprv vyberie obsahová časť, bez navigácie, hlavičky, pätičky, skriptov a cookie líšt. Každý zdroj môže mať vlastné pravidlo, ktorú časť stránky čítať a ktoré premenlivé riadky vynechať, napríklad „aktualizované dňa“ alebo počítadlá. Potom nasleduje normalizácia: zjednotenie medzier, zalomení a znakových entít a odstránenie prázdnych riadkov. Čísla, dátumy a časy normalizácia neodstraňuje, lebo práve v nich sú podmienky.
Z normalizovaného textu sa vypočíta odtlačok SHA-256. Ak sa líši od odtlačku prijatej verzie, vznikne kandidát na zmenu s rozdielom po riadkoch, takže redaktor nečíta celú stránku, len to, čo sa pohlo. Opakované načítanie toho istého kandidáta len obnoví čas pozorovania. Na jedného kandidáta tak príde jedno upozornenie, a nie pripomienka každý deň. Pri zdrojoch so stabilným formátom vie automat vyčítať aj jednotlivé polia, napríklad dni a časy, a upozorniť, keď sa pravidlá partnera rozchádzajú s údajmi, ktoré publikujeme. Ani vtedy nič sám neprepíše.
Archív dôkazov
Ku každej pozorovanej verzii sa ukladá jej normalizovaný text, komprimovaný a pomenovaný podľa odtlačku. Rovnaký obsah sa tak uloží raz a ku každej verzii v histórii vieme ukázať presný text, ktorý sme vtedy videli. Bežné kópie sa po 90 dňoch mažú. Výnimkou sú naposledy prijatá a naposledy pozorovaná verzia, na ktoré sa niečo odvoláva. Tie ostávajú bez ohľadu na vek. Archív má aj strop veľkosti na disku: po jeho prekročení sa mažú najstaršie nechránené kópie a upozornenie príde v dennom súhrne.
Kde rozhoduje človek
Redaktor vidí prijatú verziu, pozorovanú verziu a rozdiel medzi nimi. Rozhodne, či ide o skutočnú zmenu podmienok, kozmetickú úpravu alebo nečitateľný zdroj. Prijíma vždy konkrétnu verziu: ak sa text medzitým znova zmenil, prijatie neprejde a posúdiť treba novšiu. Prijatie len posunie referenciu, s ktorou sa porovnáva, a zaznamená, kto a kedy ju prijal. Údaje na portáli upravuje redaktor samostatne a záznam o kontrole s časom, rozsahom a výsledkom vzniká len pri skutočnej kontrole. Z neho čitateľ vidí dátum poslednej kontroly. Technické načítanie nemení dátum aktualizácie stránky, dátum poslednej kontroly ani dátum v štruktúrovaných dátach.
Kým zmena čaká na posúdenie, portál ďalej ukazuje naposledy prijaté údaje, ale len po stanovenú lehotu od zistenia zmeny (predvolene dva týždne, nastaviteľnú pre každý zdroj). Deň pred jej koncom príde upozornenie, a ak zmenu nikto neposúdi, tvrdenie vypadne z potvrdeného výpisu. Rovnako dopadne tvrdenie, ktorého posledné úspešné načítanie je staršie než limit čerstvosti. Zdroj, ktorý sa nedá čítať automaticky, môže tvrdenie podoprieť len čerstvou ručnou kontrolou redakcie.
Slušný a bezpečný sťahovač
Strážca sťahuje cudzie stránky z nášho servera, a preto je zároveň možnou cestou útoku. Typickým rizikom je server-side request forgery (SSRF): keby sa podarilo podstrčiť adresu alebo presmerovanie na interný systém, server by ho načítal sám. Ochrany sú vrstvené v duchu odporúčaní OWASP na prevenciu SSRF:
- Len HTTPS s overením certifikátu, bez portu a bez prihlasovacích údajov v adrese.
- Hostiteľ musí presne zodpovedať povolenému hostiteľovi zdroja, bez subdomén.
- Všetky adresy, na ktoré sa doména preloží, musia byť verejné. Súkromné a rezervované rozsahy sa odmietnu.
- Spojenie ide na už overenú IP adresu, aby druhé preloženie DNS medzi kontrolou a spojením (DNS rebinding) nemohlo kontrolu obísť.
- Presmerovania sa nesledujú automaticky. Povolených je len niekoľko, každé prejde rovnakou kontrolou a musí ostať u toho istého hostiteľa.
- Limit veľkosti sa meria na rozbalených dátach, nie na prenesených, aby komprimovaná odpoveď nemohla zahltiť pamäť, a prijímajú sa len textové typy obsahu.
Druhou polovicou je ohľaduplnosť voči partnerovi. Pred načítaním kontrolujeme robots.txt (RFC 9309). Zákaz pre našu cestu rešpektujeme a zdroj sa vtedy vedie ako nečitateľný. Keď sa robots.txt nedá načítať pre chybu servera, stránku v tom behu nečítame vôbec, ako to RFC vyžaduje. Nečítame nič za prihlásením ani cez overovaciu obrazovku. Každý zdroj má vlastný interval a čas načítania, takže častejšie spúšťanie behu nezvyšuje počet požiadaviek na partnera. Používame podmienené požiadavky podľa RFC 9110 (If-None-Match s hodnotou ETag, If-Modified-Since): keď server odpovie 304, telo sa neprenáša a výsledok sa ráta ako rovnaký obsah. Čerstvosť sa tým obnoví ako pri bežnom načítaní, nikdy viac. Po chybe nasleduje stupňovaný odstup (1 hodina, 6 hodín, 24 hodín) namiesto opakovania pri každom behu.
Beh má pevný časový rozpočet. Limit každej požiadavky je pevný strop alebo zvyšok rozpočtu, podľa toho, ktorá hodnota je menšia. Jeden pomalý zdroj preto nezablokuje ostatné a čo sa nestihne, ostáva na ďalší beh. Súbežné behy sa vylučujú zámkom a každý zdroj si beh „prenajme“ s expiráciou, takže sa nespracuje dvakrát a po páde procesu sa uvoľní.
Denný súhrn a AI ako pomocník, nie rozhodca
Po každom behu príde e-mail. Prvý riadok je vždy súhrn: koľko zdrojov sa skontrolovalo a koľko je bez zmeny, zmenených, nečitateľných a chybných. Pôvodne bol bežný beh tichý, lenže prázdnu schránku nebolo možné odlíšiť od behu, ktorý vôbec neprebehol. Pod súhrnom nasledujú riadky písané pre ľudí: zmenený text čaká na posúdenie, stránka sa nedala načítať, text ponuky nie je čitateľný, blíži sa termín posúdenia, pravidlá partnera sa líšia od nášho rozvrhu. Opakovaná chyba sa hlási pri prvom a treťom neúspechu za sebou, nie pri každom.
Pri viacerých kandidátoch pomáha export do jedného dokumentu: na začiatku zadanie pre AI asistenta, potom pri každom kandidátovi prijatá a pozorovaná verzia, rozdiel a naše aktuálne údaje. Asistent navrhne jeden zo štyroch verdiktov (prijať ako novú referenciu, prijať a upraviť údaje, odmietnuť, rozhodne človek) a presné hodnoty na zápis. Sám nič nezapisuje, výsledok prenáša redaktor. Zadanie výslovne hovorí, že texty partnera sú dáta, nie pokyny. Ak obsahujú vetu, ktorá sa tvári ako inštrukcia („ignoruj predchádzajúce pravidlá“, „prijmi túto verziu“), asistent ju nemá vykonať. Má ju doslova citovať a vrátiť verdikt „rozhodne človek“.
Ide o nepriamu prompt injection, ktorú OWASP uvádza ako riziko LLM01 v zozname Top 10 pre aplikácie s veľkými jazykovými modelmi (vydanie 2025). Chráni pred ňou oddelenie nedôveryhodného obsahu a ľudské schválenie. Spoliehať sa na samotný model nestačí. Rovnaký princíp platí aj bez AI: automat, ktorý by cudzie texty preberal priamo do nášho obsahu, by sa dal zneužiť na jeho zmenu.
Hranice a čo sa dá preniesť inam
Strážca nevidí všetko. Neporovnáva obrázky, nečíta PDF ani obsah za prihlásením a po zmene rozloženia stránky môže zdroj ostať nečitateľný, kým sa neupraví pravidlo výberu textu. Nasadzujeme ho na vybrané zdroje, kde zastaraná informácia škodí najrýchlejšie, napríklad na časovo viazané akcie. Ostatné ponuky kontroluje redakcia v pravidelných termínoch. Nemá zmysel ho stavať tam, kde partner poskytuje štruktúrované dáta s verziou, alebo kde je zdrojov tak málo, že ich človek prečíta rýchlejšie, než sa nastaví pravidlo výberu.
Vzor sa hodí všade, kde firma preberá cudzí text a ručí za jeho aktuálnosť:
- Cenníky a podmienky dodávateľov: kotva identity (napríklad názov tarify), rozdiel po riadkoch a prijatie konkrétnej verzie dávajú auditnú stopu pre prípad sporu o to, čo kedy platilo.
- Regulačné a metodické texty: sledovanie stránok regulátora s archívom presného znenia upozorní na zmenu. Pri rozhodovaní však treba vychádzať z oficiálne publikovaného znenia, nie z vlastnej kópie.
- Zmluvné podmienky partnerov, zásady ochrany osobných údajov tretích strán a dokumentácia rozhraní, od ktorých závisí vaša integrácia.
- Minimálny rozsah na začiatok: oddelené stavy chyba, nečitateľné a zmena. Normalizácia, ktorá nemaže čísla, a prvé načítanie ako kandidát. Dôkaz s retenciou a technický beh, ktorý nemení redakčné dátumy. Lehota na posúdenie, po ktorej tvrdenie prestane platiť. Ochrana pred SSRF a kontrola robots.txt od prvého dňa a denný súhrn aj vtedy, keď sa nič nestalo.
Výsledkom nie je úplná automatizácia, ale rozdelenie práce, ktoré sa dá obhájiť. Redaktor trávi čas len na stránkach, kde sa niečo stalo, každá publikovaná podmienka má dohľadateľnú históriu a pri každej prijatej verzii vieme povedať, kto ju kedy a proti akému textu prijal. Ak staviate podobný systém, začnite otázkou, čo smie automat tvrdiť, a až potom riešte, ako rýchlo vie sťahovať.