Kapitoly manuálu

Kochy / Portály KAMSY#

Úplný uživatelský, produktový, bezpečnostní a provozní manuál#

Verze dokumentu: 1.0
Stav popisované aplikace: implementováno v repozitáři, produkční přepnutí tří nových domén čeká na dokončení DNS a provozních klíčů
Aktuální k: 3. srpna 2026
Určeno pro: vlastníka KAMSY, administrátory, techniky, obchodní zástupce, zákazníky a správce serveru

Kochy je interní jedno-firemní systém KAMSY s.r.o. Není to veřejná SaaS služba ani produkt ProtokolOnline. Portály sdílejí jednu aplikaci a databázi, ale každý typ uživatele má vlastní doménu, vlastní povolené stránky a vlastní omezené API.

Obsah#

  1. Jak tento manuál používat
  2. Co systém řeší
  3. Tři portály a jejich hranice
  4. Role, oprávnění a odpovědnosti
  5. Přihlášení, aktivace a relace
  6. Zaměstnanecký portál
  7. Zákaznická karta
  8. Generátor revizí a údržby
  9. Archiv protokolů a regenerace
  10. Generátor smluv a GDPR dokumentace
  11. Servisní zásahy
  12. Přílohy a jejich zveřejnění
  13. Poznámky a paměť vybavení
  14. Docházka, cesty, výdaje a dovolená
  15. Administrace obchodních tipů a provizí
  16. Partnerský portál obchodního zástupce
  17. Zákaznický portál
  18. Hlavní uživatelské scénáře
  19. Dokumentové a publikační mechanismy
  20. Fakturoid a další integrace
  21. Architektura aplikace
  22. Datový model a ukládání
  23. Bezpečnostní model
  24. Audit, retence a automatické úlohy
  25. Nasazení a provoz
  26. Zálohování, obnova a návrat verze
  27. Rozhodnutí, hranice a vědomé kompromisy
  28. Řešení problémů
  29. Kontrolní seznamy
  30. Slovník a referenční přílohy

1. Jak tento manuál používat#

Manuál má dvě úrovně. Kapitoly 1 až 20 vysvětlují produkt a běžnou práci uživatelů. Kapitoly 21 až 30 popisují technické mechanismy, bezpečnost a provoz.

Po přečtení příslušné části má čtenář umět:

  • vlastník nebo administrátor: spravovat uživatele, zákazníky, publikaci dokumentů, obchodní tipy a provize;
  • technik: vyhledat zákazníka, vygenerovat protokol, zapsat servisní zásah, nahrát přílohu a vyplnit docházku;
  • obchodní zástupce: poslat nový tip a porozumět stavu zakázky i provize;
  • zákazník: bezpečně najít dokumenty, které mu KAMSY zveřejnilo;
  • správce serveru: aplikaci sestavit, nasadit, sledovat, zálohovat a obnovit;
  • budoucí vývojář: rozumět hranicím rolí, datovým tokům a rozhodnutím, která se nesmějí obejít „zjednodušením“.

1.1 Co znamenají stavové značky#

Značka Význam
Implementováno Funkce je v aktuálním kódu a má testy.
Provozní krok Nejde o programování; musí ho provést vlastník nebo správce serveru.
Odloženo Záměrně není součástí současné verze.
Citlivé Obsah se nesmí posílat nechráněným kanálem ani kopírovat mimo řízené úložiště.

1.2 Důležitá hranice stavu#

K 30. červenci 2026 jsou zaměstnanecký, zákaznický i partnerský portál implementované. Veřejné produkční přepnutí nových domén však stále vyžaduje dokončit DNS záznamy, doplnit reálné klíče Turnstile, nasadit aktuální release a provést produkční smoke test. „Implementováno“ proto neznamená automaticky „už je veřejně dostupné na všech třech doménách“.


2. Co systém řeší#

Kochy spojuje činnosti, které dříve žily v samostatných souborech, složkách, tabulkách nebo jednoduché PHP stránce:

  • evidence zákazníků a jejich objektů;
  • generování revizních a údržbových protokolů;
  • neměnný archiv původních protokolů a jejich pozdějších revizí;
  • generování servisních smluv, smluv o dílo a GDPR dokumentace;
  • historie servisních zásahů a měněných komponent;
  • přílohy rozdělené podle druhu, data a viditelnosti;
  • šifrované interní poznámky a paměť instalovaného vybavení;
  • docházka techniků, více míst za den, kilometry, parkování, nákupy a dovolená;
  • doporučení zákazníků obchodními zástupci;
  • jednorázové i každoroční servisní provize;
  • bezpečné zpřístupnění vybraných dokumentů zákazníkům;
  • uživatelé, audit, údržba, zálohy a obnovovací postupy.

Systém je kalibrovaný pro jednu firmu, přibližně pět interních uživatelů a dva až tři ověřené obchodní zástupce. Návrh proto upřednostňuje čitelnost, bezpečnost a malý počet provozních částí před univerzální SaaS architekturou.


3. Tři portály a jejich hranice#

Doména Pro koho Co obsahuje Co záměrně neobsahuje
portal.kamsy.cz zaměstnanci KAMSY zákazníci, revize, smlouvy, servis, přílohy, docházka, správa partnerský nebo zákaznický samoobslužný pohled
zakaznik.kamsy.cz pozvaní zákazníci jen výslovně zveřejněné protokoly, schválené smlouvy a zákaznické přílohy interní poznámky, zálohy databází, servisní historie, provize
partner.kamsy.cz pozvaní obchodní zástupci vlastní tipy, stav zakázky a vlastní provizní kniha interní zákaznické karty, kontakty po odeslání tipu, data jiných zástupců
revize.kamsy.cz staré záložky trvalé přesměrování na zaměstnanecký portál žádná samostatná aplikace

Oddělení je vícevrstvé:

  1. Caddy na externích doménách servíruje pouze výslovně povolené stránky.
  2. Role jsou na serveru vyhodnocovány pro každou chráněnou akci.
  3. Partnerské a zákaznické služby mají datové dotazy, které umějí vrátit pouze řádky přihlášeného uživatele.
  4. Zákaznický obsah je ve výchozím stavu neveřejný.
  5. Citlivé čtení i změny se zapisují do auditu.

Přehled architektury a hranic portálů


4. Role, oprávnění a odpovědnosti#

4.1 Přehled rolí#

Oblast Administrátor Technik Obchodní zástupce Zákaznický účet
Přihlášení a vlastní relace ano ano ano ano
Zákazníci a vyhledávání ano ano ne jen přidělené objekty
Vytvoření protokolu ano ano ne ne
Archiv protokolů ano ano ne jen zveřejněné
Interní poznámky ano ano ne ne
Přílohy ano ano ne jen s viditelností „zákazník“
Zveřejnění přílohy ano ano ne ne
Smlouvy a GDPR generátor ano ne ne jen schválené a zveřejněné
Schválení a publikace smlouvy ano ne ne ne
Servisní zásahy ano ano ne ne
Vlastní docházka ano ano ne ne
Docházka všech pracovníků a opravy uzavřených dní ano ne ne ne
Šablony protokolů – použití ano ano ne ne
Šablony protokolů – správa ano ne ne ne
Zákaznické účty a publikace protokolů ano ne ne ne
Provize a obchodní tipy – správa ano ne vlastní data ne
Uživatelé a audit ano ne ne ne

4.2 Administrátor#

Administrátor je provozní vlastník aplikace. Může spravovat interní účty, pozvánky zákazníků a obchodních zástupců, schvalovat a publikovat dokumenty, opravovat uzavřenou docházku, řídit obchodní stavy a vyplácení provizí a číst auditní log.

Administrátor by měl používat práva pouze k činnosti, kterou právě provádí. Audit uchovává, kdo konkrétní citlivou akci provedl; sdílený administrátorský účet by tento účel zničil.

4.3 Technik#

Technik je důvěryhodný interní pracovník. Může pracovat se zákaznickými kartami, protokoly, poznámkami, vybavením, servisními zásahy a přílohami. Může také změnit viditelnost přílohy na „Vidí zákazník“; tato změna je samostatně auditovaná. Nemůže spravovat smluvní/GDPR generátor, zákaznické účty, protokolovou publikaci, uživatele, audit ani provize.

Technik vidí a upravuje vlastní docházku. Záznam jiného technika ani uzavřený starší den bez administrátora změnit nemůže.

4.4 Obchodní zástupce#

Obchodní zástupce je externí role s výchozím zákazem. Smí pouze:

  • zobrazit vlastní profil a relaci;
  • poslat nový obchodní tip;
  • zobrazit své tipy;
  • zobrazit své provizní nároky a stavy výplaty.

Nemá obecný přístup k zákazníkům. Partnerská služba neobsahuje funkci, která by uměla vrátit data jiného zástupce. To je silnější ochrana než pouhé spoléhání na správně napsanou podmínku v každém dotazu.

4.5 Zákaznický účet#

Zákaznický účet je externí role s výchozím zákazem. Je svázán s jedním nebo více konkrétními zákaznickými objekty. Vidí pouze dokumenty, které:

  1. patří do některého z jeho členství;
  2. byly výslovně zveřejněné;
  3. u smluv navíc prošly administrátorským schválením.

5. Přihlášení, aktivace a relace#

5.1 Pozvánka a první heslo#

Účty se nezakládají veřejnou registrací. Administrátor vytvoří pozvánku a aplikace zobrazí jednorázový aktivační odkaz. Odkaz:

  • platí 24 hodin;
  • je použitelný jen jednou;
  • není posílán e-mailem přímo aplikací;
  • má být předán bezpečným kanálem;
  • vyžaduje nové heslo o délce nejméně 12 znaků.

Pozvánka interního uživatele se vytváří ve správě uživatelů. Pozvánka zákazníka se vytváří v jeho zákaznické kartě a současně vytvoří členství k danému objektu. Pozvánka obchodního zástupce vzniká v administraci provizí a zároveň založí jeho výchozí provizní sazbu.

5.2 Přihlášení krok za krokem#

  1. Uživatel otevře přihlašovací stránku své domény.
  2. Vyplní e-mail a heslo.
  3. Projde kontrolou Cloudflare Turnstile.
  4. Server normalizuje e-mail, ověří heslo a stav účtu.
  5. Technik pokračuje přímo do aplikace.
  6. Administrátor, obchodní zástupce a zákaznický účet pokračují druhým faktorem.
  7. Po úspěchu server vytvoří relaci a CSRF token.
  8. Uživatel je přesměrován na správný portál podle role.

5.3 Dvoufázové ověření#

Druhý faktor je TOTP kód z aplikace typu Bitwarden, 1Password, Google Authenticator nebo Microsoft Authenticator. Při prvním přihlášení chráněné role systém:

  1. zobrazí QR kód a ruční klíč;
  2. vytvoří deset obnovovacích kódů;
  3. požádá o potvrzení aktuálním šestimístným kódem;
  4. uloží TOTP tajemství šifrovaně;
  5. uloží pouze hashe obnovovacích kódů;
  6. po potvrzení vyžádá nové přihlášení.

Obnovovací kód nahrazuje TOTP jen jednou. Použití se auditované. Obnovovací kódy je nutné uložit mimo běžný počítač nebo telefon.

5.4 Hesla, limity a uzamčení#

  • Hesla se ukládají jako scrypt hash, nikoli jako čitelný text.
  • Výpočet scryptu je omezen na dvě souběžné operace kvůli 4GB serveru.
  • Přihlašovací endpoint přijme nejvýše 20 pokusů z jedné IP za minutu.
  • Druhý faktor přijme nejvýše 30 požadavků z jedné IP za minutu.
  • Jedna 2FA výzva končí po pěti chybných pokusech.
  • Jeden účet může mít nejvýše deset TOTP pokusů za hodinu.
  • Patnáct neúspěšných hesel v patnáctiminutovém okně uzamkne účet na 15 minut.

5.5 Relace a odhlášení#

Relace má osmihodinovou posuvnou platnost. Při aktivitě se nejvýše jednou za pět minut posune platnost databázové relace i obou cookies. Cookies jsou Secure; session cookie je HttpOnly; politika SameSite=Lax umožní otevřít odkaz z e-mailu nebo chatu bez zbytečného odhlášení a současně blokuje běžné cross-site formuláře.

Změnové požadavky navíc vyžadují CSRF token z druhé cookie. Odhlášení relaci smaže a obě cookies zneplatní. Deaktivace uživatele smaže jeho aktivní relace i rozpracované ověřovací výzvy.

5.6 Reset hesla a TOTP#

Samoobslužný reset e-mailem není implementován. Správce spustí obslužný příkaz, který vytvoří jednorázový odkaz, a bezpečně ho předá uživateli. Reset TOTP odstraní staré tajemství a obnovovací kódy; při dalším přihlášení proběhne nové spárování.


6. Zaměstnanecký portál#

6.1 Hlavní navigace#

Zaměstnanecký portál obsahuje:

  • Přehled – rychlé metriky, poslední protokoly, poslední zákazníci a koncepty;
  • Zákazníci – vyhledávání a zákaznické pracovní prostory;
  • Docházka – denní práce, cesty, výdaje a dovolená;
  • Archiv – všechny protokoly s filtry;
  • Šablony – správa přednastavení protokolů, pouze admin;
  • Provize – obchodní zástupci, tipy, smlouvy a kniha, pouze admin;
  • Uživatelé – pozvánky, role a deaktivace, pouze admin;
  • Audit – bezpečnostní a provozní historie, pouze admin.

Na mobilu se postranní panel mění na vysouvací menu. Funkce a oprávnění zůstávají stejné jako na desktopu.

6.2 Přehled#

Přehled načítá poslední záznamy ze stejných API jako jednotlivé moduly. Slouží k orientaci, ne jako samostatná databáze. Zobrazuje:

  • počet a poslední protokoly;
  • nedávné zákazníky;
  • vlastní rozpracované koncepty;
  • rychlé odkazy na nový protokol a archiv.

6.3 Zákazníci a vyhledávání#

Vyhledávání pracuje nad IČO, názvem/jménem a adresou:

  1. nejprve vrátí odpovídající lokální zákazníky z PostgreSQL;
  2. poté doplní výsledky z Fakturoidu;
  3. shodné záznamy sloučí;
  4. výsledek z Fakturoidu lze „materializovat“ do lokální zákaznické karty.

Zákazník může být právnická osoba s IČO i soukromá osoba bez IČO. Interní identita zákazníka je proto samostatné číselné ID, ne IČO.

Pokud Fakturoid neodpovídá, lokální zákazníci zůstávají použitelní. Na stránce Zákazníci je tlačítko Přidat zákazníka ručně. Povinný je jen název nebo jméno; IČO, adresa a e-mail jsou nepovinné. Záznam se uloží přímo do PostgreSQL, zobrazí se i bez protokolu a jeho vznik se zapíše do auditu. Formulář protokolu navíc dovoluje ruční doplnění údajů bez založení samostatné karty.


7. Zákaznická karta#

Zákaznická karta je centrální pracovní prostor pro konkrétní objekt. Horní část obsahuje název, adresu, IČO, e-mail, datum posledního protokolu a počet protokolů. Karta má následující záložky.

7.1 Přehled#

Souhrn základních údajů a správa zákaznických účtů. Administrátor zde:

  • zadá jméno a e-mail zákaznického uživatele;
  • vytvoří jednorázovou pozvánku;
  • zkopíruje aktivační odkaz;
  • vidí účty již přiřazené k objektu.

Jeden zákaznický účet může mít více členství, například správce více domů.

7.2 Revize#

Obsahuje historii protokolů zákazníka. Administrátor může každý protokol samostatně publikovat nebo stáhnout zpět. Publikace nemění původní PDF; mění jen viditelnost v zákaznickém portálu a zapisuje auditní událost.

7.3 Smlouvy#

Administrátorská záložka s osmi generátory, neměnným archivem dokumentů, schválením a samostatnou publikací. Technik tuto záložku ani příslušné API nemá povolené.

7.4 Servisní zásahy#

Chronologická interní historie oprav a komponent. Je určena zaměstnancům, nikoli zákaznickému portálu.

7.5 Přílohy#

Soubory jsou seskupené podle roku a druhu. Každý má vlastní viditelnost „Jen interní“ nebo „Vidí zákazník“.

7.6 Poznámka#

Jedna aktuální šifrovaná Markdown poznámka a její historie. Je určena například pro technické údaje a přístupové informace.

7.7 Vybavení#

Aktuální paměť zařízení po modulech CCTV, EKV, DT a dveře. Používá se k předvyplnění dalšího protokolu.

7.8 Historie vybavení#

Administrátor vidí starší stavy a může jeden z nich obnovit jako aktuální. Obnovení je auditované.


8. Generátor revizí a údržby#

8.1 Podporované dokumenty#

Generátor pracuje se dvěma druhy protokolu:

  • Revize
  • Údržba

K jednomu dokumentu lze přidat libovolnou neprázdnou kombinaci čtyř modulů:

Modul Obsah
CCTV záznamové zařízení, kamery, napájení, síť, firmware, testy a volitelný HDD SMART
EKV přístupový systém, řídicí jednotky, čtečky, zámky, zálohy a databáze
DT domovní telefony, tabla, hlasová jednotka, komunikace a kabeláž
Dveře elektrické otvírače, samozavírače, snímače polohy, mechanika a vazby na EKV/DT

Výsledný název a struktura PDF se odvozují z druhu a vybraných modulů.

8.2 Práce s formulářem#

  1. Vyberte Revizi nebo Údržbu.
  2. Zaškrtněte nejméně jeden modul.
  3. Volitelně načtěte administrátorskou šablonu.
  4. Vyhledejte zákazníka nebo vyplňte údaje ručně.
  5. Pokud existuje paměť vybavení, zvolte „Načíst vybavení“ nebo „Začít znovu“.
  6. Vyplňte zařízení a testy jednotlivých modulů.
  7. Doplňte společný posudek, opravy, přístroje a termíny.
  8. Uložte koncept, nebo rovnou vygenerujte PDF.

Jméno technika se přebírá z přihlášeného účtu. Evidenční číslo nelze ručně vnutit; přiděluje ho server až při generování.

8.3 Evidenční číslo#

Formát je RRRRMMDD-NNN, například 20260730-001. Čítač je přidělovaný atomicky v databázi. Dva souběžné požadavky proto nedostanou stejné číslo. Přepsání již existujícího protokolu není povolené.

8.4 Koncepty#

Koncept:

  • patří pouze uživateli, který ho vytvořil;
  • je uložený na serveru, ne v localStorage prohlížeče;
  • je šifrovaný klíčem pro poznámky;
  • má platnost 24 hodin;
  • automatická údržba ho po expiraci smaže.

Koncept není právní ani archivní dokument. Teprve úspěšné generování vytvoří evidenční číslo, PDF, JSON a archivní metadata.

8.5 Šablony#

Šablona je pojmenované přednastavení druhu, modulů a formulářových hodnot. Technik ji může použít. Administrátor může novou šablonu uložit, přejmenovat nebo odstranit.

Šablona není kopie zákazníka ani archivu. Je to znovupoužitelné výchozí nastavení pro budoucí protokoly.

8.6 Výstup PDF#

Aktuální renderer protokolů používá verzi v2. Obsahuje:

  • KAMSY identitu a evidenční číslo;
  • oddělený blok dodavatele a zákazníka;
  • modulové sekce a tabulky testů;
  • českou diakritiku z vložených DejaVu Sans fontů;
  • datum, technika, posudek a podpisový prostor;
  • čísla stran a technická metadata dokumentu.

Původní renderer v1 zůstává v registru pro historickou čitelnost. Nové generování používá aktuální v2.


9. Archiv protokolů a regenerace#

9.1 Co se při generování ukládá#

Každý nový protokol vytvoří:

  1. původní PDF;
  2. JSON s přesným vstupem a technickými metadaty;
  3. databázový řádek pro vyhledávání;
  4. auditní událost;
  5. aktualizaci paměti vybavení použitých modulů.

Původní PDF i JSON jsou neměnné a uchovávají se bez automatické expirace.

9.2 Filtrování archivu#

Archiv lze filtrovat podle:

  • roku;
  • IČO nebo zákazníka;
  • technika;
  • modulu;
  • stránky a počtu výsledků.

Citlivý seznam i stažení se auditují.

9.3 Regenerace#

Regenerace slouží k vytvoření nové čitelné kopie ze starého vstupu:

  1. server načte archivní JSON;
  2. znovu ho validuje aktuálním schématem;
  3. vygeneruje PDF aktuální šablonou;
  4. přidá vodoznak Regenerated YYYY-MM-DD;
  5. uloží ho jako další číslovanou revizi.

Původní PDF se nikdy nepřepisuje. Regenerovaná kopie není náhradou původního archivního záznamu.

9.4 Publikace zákazníkovi#

Administrátor zveřejňuje každý původní protokol samostatně. Zákaznický portál čte pouze řádky s aktivní publikací a současně ověřuje členství přihlášeného zákazníka k objektu.


10. Generátor smluv a GDPR dokumentace#

10.1 Původ a účel#

Generátor vznikl podle osmi vzorových PDF poskytnutých KAMSY:

Druh v aplikaci Vzorový účel
Smlouva o servisní činnosti pravidelný servis kamer, zvonků a čteček
Smlouva o dílo montáž nebo dodávka díla
Zpracovatelská smlouva (GDPR) ujednání podle článku 28 GDPR
Balanční test posouzení oprávněného zájmu kamerového systému
Informace o zpracování osobních údajů informační povinnost správce
Záznam o činnostech zpracování evidence činností správce
Formuláře pro subjekty údajů žádosti a vyřízení práv subjektu údajů
Provozní deník přístupů tabulkový záznam přístupů ke kamerovým záznamům

Vzorová PDF obsahovala reálné osobní a zákaznické údaje, proto nejsou součástí repozitáře ani tohoto manuálu. Generátor je nepoužívá jako vyplňovací formuláře. Místo toho vytváří nové PDF z verzovaných strukturovaných šablon.

10.2 Vstupní údaje#

Společný formulář obsahuje zejména:

  • druh dokumentu a jeho číslo;
  • objekt nebo projekt;
  • datum účinnosti;
  • zástupce zákazníka;
  • kontaktní e-mail;
  • předmět a rozsah systému;
  • počet kamer a dobu uchování záznamu;
  • cenu bez DPH;
  • platební podmínky;
  • doplňující ujednání.

Zákaznické jméno, adresa, IČO a e-mail se snímají z aktuální zákaznické karty. Do archivního vstupu se uloží jejich snapshot, aby bylo později zřejmé, z jakých údajů dokument vznikl.

10.3 Řízený životní cyklus#

Životní cyklus smlouvy a GDPR dokumentu

  1. Administrátor vyplní formulář a zvolí „Vygenerovat návrh“.
  2. Vznikne neměnný PDF návrh označený NÁVRH K REVIZI.
  3. Vstup i výsledné PDF se uloží šifrovaně.
  4. Administrátor otevře a zkontroluje celý dokument.
  5. Právní nebo vlastnická kontrola se zaznamená tlačítkem schválení.
  6. Teprve schválený dokument lze samostatně zveřejnit zákazníkovi.
  7. Podepsaný scan se po podpisu vrací jako příloha typu „Smlouva“.

Databázové omezení nedovolí zveřejnit neschválený dokument ani při chybě uživatelského rozhraní.

10.4 Verze a vizuální podoba#

Aktuální verze právní šablony je legal-v2-review. Dokumenty používají:

  • jednotnou typografii KAMSY;
  • výrazné označení návrhu a právní revize;
  • záhlaví, patičky a čísla stran;
  • čitelné podpisové bloky;
  • tabulkový layout provozního deníku;
  • plnou českou diakritiku;
  • technická metadata s ID dokumentu a verzí šablony.

Schválení neznamená elektronický podpis. PDF generované aplikací je návrh nebo řízený dokument; právní účinek podepsané smlouvy vzniká podle skutečného podpisového procesu KAMSY.


11. Servisní zásahy#

Servisní zásah je interní, přidávací záznam. Obsahuje:

  • datum zásahu;
  • co bylo provedeno;
  • seznam instalovaných, vyměněných nebo odebraných komponent;
  • autora z přihlášeného účtu;
  • čas vytvoření.

Popis a komponenty jsou šifrované. Datum, zákazník a autor zůstávají dotazovatelné kvůli řazení a auditu.

11.1 Doporučený zápis#

Dobře napsaný zásah odpovídá na tři otázky:

  1. Jaký byl projev nebo požadavek?
  2. Co technik skutečně provedl?
  3. Jaké komponenty vložil, vyměnil nebo odebral?

Příklad:

Ověřena ztráta obrazu kamery u vstupu. Vyměněn PoE injektor, znovu zakončen konektor, provedena kontrola záznamu a času. Komponenty: PoE injektor 48 V, konektor RJ45.

Záznamy jsou řazené od nejnovějších a lze je filtrovat podle kalendářního roku. Aktuální verze neobsahuje skladové hospodářství ani editaci starého zásahu.


12. Přílohy a jejich zveřejnění#

12.1 Druhy příloh#

Druh Typický obsah
Záloha export databáze nebo konfigurace zákaznického systému
Smlouva podepsaná smlouva nebo dodatek
Schéma technické schéma, situační plán
Fotografie dokumentační snímek
Protokol externí protokol nebo související zpráva
Ostatní jiný podporovaný soubor

Druh slouží pouze k řazení a orientaci. O přístupu rozhoduje výhradně Viditelnost.

12.2 Viditelnost#

  • Jen interní – soubor vidí zaměstnanci s právem na přílohy.
  • Vidí zákazník – soubor navíc uvidí zákaznický účet s členstvím k objektu.

Nový upload vždy začíná jako interní. Zveřejnění je druhý vědomý krok a zapíše auditní událost s původní a novou hodnotou.

Technik i administrátor mají v současné roli právo viditelnost přílohy změnit. Publikaci protokolu, smlouvy nebo zákaznického účtu však provádí pouze administrátor.

12.3 Povolené formáty a limity#

Povoleny jsou:

  • PDF;
  • PNG, JPEG, WebP a GIF;
  • prostý text;
  • Markdown.

Nepovoleny jsou ZIP archivy, kancelářské dokumenty a spustitelné soubory. Server nekontroluje jen příponu; ověřuje skutečnou signaturu nebo povolený textový obsah.

Limity:

  • 30 MB na jeden soubor;
  • 1 GB souborů na jednoho zákazníka;
  • maximálně 2 000 znaků popisu.

12.4 Uložení a mazání#

Obsah souboru je před uložením zašifrován AES-256-GCM klíčem pro přílohy. Volitelný popis je šifrován klíčem pro poznámky. Úložiště nemá veřejné URL; stažení vždy prochází serverem, který ověří roli, zákazníka, viditelnost a záznam v databázi.

Odstranění je nejprve měkké. Po 30 dnech automatická údržba smaže metadata i šifrovaná data ze souborového úložiště.


13. Poznámky a paměť vybavení#

13.1 Interní poznámka#

Každý zákazník má jednu aktuální poznámku. Text podporuje omezený Markdown. HTML se sanitizuje; skripty, událostní atributy, nebezpečné odkazy a styly se nepovolují.

Každé otevření poznámky je auditované. Uložení vytvoří historii staré verze. Administrátor může starší verzi obnovit; technik může historii číst, ale ne obnovovat.

Poznámka není vyhledávatelná. Je to vědomý důsledek šifrování: server by jinak musel udržovat plaintextový index.

13.2 Poznámka z Fakturoidu#

Pokud Fakturoid vrátí soukromou poznámku zákazníka, aplikace ji zobrazí jen pro čtení vedle interní šifrované poznámky. Kochy ji nikdy nezapisuje zpět.

13.3 Paměť vybavení#

Po úspěšném protokolu se zařízení použitých modulů uloží jako aktuální stav zákazníka. Před nahrazením se starý stav zapíše do historie.

Při příštím protokolu uživatel výslovně volí:

  • Načíst vybavení – předvyplní formulář;
  • Začít znovu – použije prázdné hodnoty.

Historie vybavení je administrátorská, protože obnovení mění výchozí data pro další práci.


14. Docházka, cesty, výdaje a dovolená#

14.1 Denní záznam#

Jeden pracovní den může obsahovat více řádků. Každý řádek má:

  • místo nebo objekt;
  • počet minut;
  • volitelnou vazbu na zákazníka;
  • volitelnou poznámku.

Na úrovni dne se dále zadává:

  • celkový počet kilometrů;
  • parkování v Kč;
  • nákupy v Kč;
  • vysvětlení výdajů.

Alternativou k pracovnímu dni je záznam typu Dovolená.

14.2 Filtrování a součty#

Přehled lze filtrovat:

  • od–do;
  • podle technika, pokud je přihlášen administrátor;
  • podle textu místa.

Aplikace sčítá:

  • hodiny a minuty;
  • kilometry;
  • parkování;
  • nákupy;
  • počet dnů dovolené.

Tím lze získat denní, týdenní, měsíční i libovolný vlastní interval bez samostatných tabulek.

14.3 Oprávnění a uzavření#

Technik může číst a měnit pouze vlastní docházku. Administrátor může filtrovat a opravovat všechny pracovníky.

Den se automaticky považuje za uzavřený, pokud je starší než 14 kalendářních dnů podle časové zóny Europe/Prague. Technik ho již neupraví. Administrátor může provést opožděné založení nebo opravu, ale musí zadat důvod.

Předchozí stav i důvod opravy se ukládají šifrovaně do revizní historie. Není tedy možné starou docházku tiše přepsat bez stopy.


15. Administrace obchodních tipů a provizí#

15.1 Model obchodního případu#

Obchodní tip a výplata jsou dvě nezávislé osy.

Stav tipu:

Odesláno → V realizaci → Vyhráno

nebo:

Odesláno / V realizaci → Prohráno

Stav provize:

Vzniklý nárok → K fakturaci → Vyplaceno

Oddělení je důležité. Zakázka může být hotová, ale provize ještě nemusí být vyfakturovaná nebo vyplacená.

15.2 Obchodní zástupci#

Administrátor může:

  • pozvat zástupce;
  • nastavit jeho výchozí roční sazbu v bazických bodech;
  • aktivovat nebo deaktivovat účet;
  • upravit budoucí výchozí sazbu.

Deaktivace současně zneplatní relace a ověřovací výzvy. Historické tipy a provize zůstávají zachované.

15.3 Tipy#

Tip může vzniknout:

  • odesláním z partnerského portálu;
  • ručním importem historického vztahu.

Citlivý vstup obsahuje adresu, kontakt a poznámku. Je šifrovaný. Administrátor může tip propojit s lokálním zákazníkem a posouvat stav. Prohraný tip vyžaduje důvod. Návrat proti běžnému směru stavů je oprava a také vyžaduje důvod.

15.4 Jednorázová provize#

Jednorázový bonus:

  • lze vytvořit jen pro vyhraný tip;
  • částku zadává vlastník ručně;
  • vyžaduje slovní odůvodnění;
  • pro jeden tip vznikne nejvýše jednou;
  • uloží se jako neměnný historický snapshot.

Není zde automatický procentní vzorec ani strop, protože současné obchodní pravidlo je individuální rozhodnutí vlastníka.

15.5 Servisní smlouva a roční provize#

Vyhraný tip lze spojit s pravidelným fakturačním generátorem z Fakturoidu. U vazby se ukládá:

  • ID generátoru;
  • volitelná sazba odlišná od výchozí sazby zástupce;
  • odečitatelná částka;
  • povinný důvod, pokud je odečet nenulový;
  • poslední ručně porovnaný roční zdroj.

Odečet řeší například internet nebo jiný průtokový náklad, ze kterého obchodník nemá dostávat provizi. Neukládá se ručně přepsaný základ jako jediná pravda; uchovává se zdroj z Fakturoidu a transparentní odečet.

15.6 Výpočet#

Výpočet pracuje v haléřích a používá zaokrouhlení half-up:

roční zdroj = subtotal bez DPH × 12 / months_period
provizní základ = roční zdroj − odečet
provize = provizní základ × sazba / 10 000

Příklad:

měsíční subtotal:     2 000 Kč
roční zdroj:         24 000 Kč
odečet za internet:   4 800 Kč
provizní základ:     19 200 Kč
sazba:               15 % = 1 500 bps
roční provize:        2 880 Kč

Záporný základ je chyba a generování se zastaví.

15.7 Náhled a roční uzávěrka#

Před vygenerováním administrátor zvolí rok a zobrazí náhled:

  • jen vyhrané tipy;
  • jen aktivní generátory v CZK;
  • jen smlouvy účinné v daném roce;
  • bez smluv, které už pro daný rok mají záznam;
  • včetně seznamu přeskočených smluv a důvodu.

Konečné vygenerování vyžaduje čerstvý Fakturoid snapshot. Databázová unikátní podmínka zaručuje, že opakované spuštění nevytvoří druhý nárok za stejnou smlouvu a rok.

15.8 Neměnná provizní kniha#

Každý nárok ukládá celý výpočet, sazbu, základ, odečet, zdroj, období a verzi zaokrouhlení. Pozdější změna ceny ve Fakturoidu proto nepřepisuje minulou provizi.

Při změně stavu výplaty vzniká samostatná událost. Běžný postup je dopředný. Neobvyklý návrat vyžaduje důvod.


16. Partnerský portál obchodního zástupce#

16.1 Přehled#

Partner vidí tři částky:

  • Vzniklý nárok
  • K fakturaci
  • Vyplaceno

Pod nimi je seznam vlastních tipů a provizní kniha. Částky v knize jsou historické a nemění se po pozdější změně ceny servisní smlouvy.

16.2 Odeslání tipu#

Formulář vyžaduje:

  • budovu nebo adresu;
  • kontakt na zájemce;
  • volitelnou poznámku do 2 000 znaků.

Jeden účet může odeslat nejvýše deset tipů za hodinu. Po odeslání:

  1. KAMSY obdrží nový interní záznam;
  2. volitelně odejde Telegram upozornění;
  3. partner v přehledu dále vidí jen adresní štítek a stav;
  4. citlivý kontakt se mu znovu nevrací.

Tím se snižuje množství osobních údajů dostupných přes externí portál.

16.3 Izolace#

Každý partnerský dotaz začíná ID přihlášeného uživatele, přes aktivního zástupce se váže na jeho tipy a teprve poté na provize. Neexistuje obecné partnerské „list all“. Cizí ID vrátí 404, nikoli záznam jiného zástupce.

Veřejná affiliate registrace není součástí této verze. Brání jí nevyřešené daňové, GDPR, souhlasové, anti-abuse a duplicitní-referral otázky.


17. Zákaznický portál#

17.1 Co zákazník vidí#

Po přihlášení se zobrazí:

  • přidělené objekty;
  • počet revizních protokolů;
  • počet smluv a příloh;
  • datum posledního dostupného dokumentu;
  • knihovna s filtry Vše, Revize a Smlouvy a přílohy.

Dokument lze otevřít nebo stáhnout pouze přes zákaznické API. API znovu ověří členství a publikaci i v případě, že uživatel ručně upraví URL.

17.2 Co zákazník nikdy neuvidí#

  • interní poznámky a jejich historii;
  • paměť vybavení;
  • servisní zásahy;
  • přílohy s interní viditelností;
  • databázové zálohy;
  • neschválené nebo nepublikované smlouvy;
  • nepublikované protokoly;
  • jiné zákazníky;
  • interní uživatelské, auditní nebo provizní stránky.

17.3 Publikační pravidlo#

Zákaznický portál nic „nezdědí“ automaticky. Nový protokol, smlouva i příloha začínají skryté. Zaměstnanec musí provést explicitní publikační akci pro každý soubor. Odebrání publikace dokument opět skryje, ale nesmaže archiv.


18. Hlavní uživatelské scénáře#

18.1 Technik vytvoří revizi#

  1. Přihlásí se na zaměstnaneckém portálu.
  2. Otevře Nový protokol.
  3. Vybere druh a moduly.
  4. Najde zákazníka a případně načte předchozí vybavení.
  5. Vyplní výsledky měření a posudek.
  6. Uloží koncept, pokud práci přerušuje.
  7. Vygeneruje PDF.
  8. Stáhne výsledek a zkontroluje evidenční číslo.
  9. V zákaznické kartě ověří archiv a aktualizovanou paměť vybavení.

18.2 Technik zapíše servis#

  1. Otevře Zákazníci a konkrétní objekt.
  2. Přepne na Servisní zásahy.
  3. Zadá datum, práci a komponenty.
  4. Uloží záznam.
  5. Ověří, že se zobrazil v nejnovějším roce a se správným autorem.

18.3 Technik nahraje zákaznický soubor#

  1. V zákaznické kartě otevře Přílohy.
  2. Nahraje podporovaný soubor; nový soubor zůstane interní.
  3. Vybere správný druh a doplní popis.
  4. Po kontrole změní viditelnost na „Vidí zákazník“.
  5. Změnu ověří v seznamu a případně ji zase stáhne.

18.4 Administrátor vytvoří a publikuje smlouvu#

  1. Otevře zákazníka a záložku Smlouvy.
  2. Vybere druh dokumentu.
  3. Zkontroluje zákaznická data a vyplní společná pole.
  4. Vygeneruje návrh.
  5. Otevře kompletní PDF a provede právní/vlastnickou kontrolu.
  6. Zaznamená schválení.
  7. Samostatně dokument publikuje zákazníkovi.
  8. Po podpisu nahraje podepsaný scan jako přílohu typu Smlouva.

18.5 Administrátor zpřístupní zákazníka#

  1. V kartě zákazníka vytvoří pozvánku.
  2. Zkopíruje jednorázový aktivační odkaz.
  3. Předá ho zákazníkovi bezpečným kanálem.
  4. Zveřejní vybrané protokoly, schválené smlouvy a přílohy.
  5. Přihlásí se testovacím zákaznickým účtem nebo provede kontrolní smoke test.

18.6 Obchodník odešle tip#

  1. Přihlásí se na partnerském portálu.
  2. Otevře formulář Nový obchodní tip.
  3. Vyplní adresu, kontakt a poznámku.
  4. Tip odešle.
  5. Sleduje adresní štítek a stav; kontakt se mu znovu nezobrazuje.

18.7 Administrátor uzavře roční provize#

  1. Zkontroluje nové tipy a propojí vyhrané případy se zákazníky.
  2. Připojí příslušné pravidelné generátory z Fakturoidu.
  3. Zkontroluje sazby a zdůvodněné odečty.
  4. Obnoví čerstvý Fakturoid snapshot.
  5. Zobrazí náhled pro rok a vyřeší přeskočené smlouvy.
  6. Vygeneruje roční nároky.
  7. Posouvá je přes K fakturaci do Vyplaceno.

18.8 Technik vyplní docházku#

  1. Otevře Docházku a zvolí datum.
  2. Přidá jeden nebo více řádků míst a času.
  3. Doplní kilometry a případné výdaje.
  4. Uloží den.
  5. Na konci období zkontroluje filtr a součty.

19. Dokumentové a publikační mechanismy#

19.1 Tři odlišné typy dokumentu#

Typ Archivní pravidlo Zveřejnění
Protokol revize/údržby původní PDF + JSON neměnné; regenerace je nová revize s vodoznakem admin samostatně
Smlouva/GDPR PDF vstup i PDF šifrované a neměnné; povinná kontrola až po schválení, admin
Běžná příloha tělo šifrované; měkké smazání a 30denní GC admin nebo technik změnou viditelnosti

Tyto mechanismy se nesmějí sloučit do jednoho „veřejný soubor ano/ne“ bez zachování jejich rozdílných pravidel.

19.2 Proč jsou šablony verzované#

PDF je bodový záznam toho, co bylo vygenerováno určitou verzí. Verze šablony:

  • dovolí zpětně vysvětlit vzhled a text;
  • chrání před tichým přepsáním starého dokumentu;
  • umožní zavést novou podobu bez změny archivu;
  • je součástí PDF metadat a databázového řádku.

19.3 Proč se podepsané dokumenty vracejí jako přílohy#

Generátor vytváří návrh z dat aplikace. Podpis může proběhnout na papíře nebo mimo systém. Podepsaný scan je jiný artefakt než vygenerovaný návrh, proto se ukládá jako samostatná příloha. Tím zůstane zachovaná historie návrhu, schválení i skutečně podepsané verze.


20. Fakturoid a další integrace#

20.1 Fakturoid – pouze čtení#

Kochy používá Fakturoid pro:

  • hledání subjektů;
  • přesné načtení zákazníka;
  • čtení pravidelných fakturačních generátorů;
  • výpočet ročního zdroje servisní provize;
  • denní kontrolu očekávaného tvaru API odpovědi.

Klient přijímá pouze metodu GET a před síťovým voláním kontroluje cestu proti úzkému allowlistu. Pokus o zápis selže ještě před odesláním požadavku.

Použitý Fakturoid aplikační účet může mít z historických důvodů zápisová práva, proto je runtime allowlist hlavní bezpečnostní hranicí Kochy. Každé volání se auditované.

20.2 Cache a výpadek#

Data Běžná platnost cache Chování při výpadku
Přesný subjekt 5 minut lokální zákazník nebo ruční údaje
Vyhledávání 60 sekund lokální výsledky
Pravidelné generátory 24 hodin nejvýše 90 dní starý snapshot pro zobrazení

Starý snapshot lze použít pro orientaci a historii, ale konečné roční vygenerování provizí vyžaduje čerstvý snapshot.

Před použitím klient ověří, že přihlášený Fakturoid účet odpovídá konfigurované KAMSY firmě a IČO.

20.3 Cloudflare Turnstile#

Cloudflare v tomto řešení neprovozuje DNS ani proxy. Používá se pouze jeho Turnstile widget na přihlášení. Site key je veřejný, secret key zůstává na serveru.

20.4 Telegram#

Telegram je volitelný:

  • může upozornit na nový obchodní tip;
  • může upozornit na druhé po sobě jdoucí selhání stejného typu zálohy.

Pokud nejsou oba Telegram klíče nastavené, funkce se bezpečně přeskočí a zbytek aplikace funguje.

20.5 E-mail#

Aplikace neposílá e-maily a neprovozuje SMTP. Aktivační a obnovovací odkazy se předávají ručně. Kontaktní e-mail v zákaznickém portálu je obyčejný odkaz pro uživatelův poštovní program.


21. Architektura aplikace#

21.1 Produkční topologie#

Prohlížeč
   │ HTTPS
   ▼
Caddy na Hetzner serveru
   ├─ statické HTML/CSS/JS z povoleného seznamu dané domény
   └─ /api/* a /healthz → 127.0.0.1:8080
                          │
                          ▼
                     Node.js 22 + Hono
                          ├─ PostgreSQL 16
                          ├─ lokální archiv a přílohy
                          ├─ Fakturoid API (GET)
                          ├─ Turnstile verify
                          └─ volitelný Telegram

21.2 Jedna aplikace, tři povrchy#

Všechny portály sdílejí:

  • jeden Node proces;
  • jednu PostgreSQL databázi;
  • stejné přihlášení, šifrování a audit;
  • jeden release na serveru.

Nesdílejí však neomezenou statickou plochu. Caddy na zákaznické a partnerské doméně odmítne interní stránky 404 ještě před aplikací. API oprávnění je stále hlavní hranicí; statický allowlist je druhá obranná vrstva.

21.3 Serverová vrstva#

Hono zajišťuje směrování a middleware. Každý modul má:

  • route vrstvu pro validaci HTTP vstupu;
  • service vrstvu pro business pravidla a databázi;
  • auditní zápisy na citlivých operacích.

Databázové služby používají D1-kompatibilní rozhraní nad PostgreSQL. To je historický adaptační tvar, nikoli důkaz, že produkce běží na Cloudflare Workers.

21.4 Frontend#

Frontend je čisté HTML, CSS a JavaScript bez bundleru a frameworku. Jedna stránka odpovídá jednomu HTML souboru a jeho JS modulu. Výhody:

  • žádný frontendový build krok;
  • malý počet závislostí;
  • rychlé načtení;
  • snadná obsluha na desktopu i mobilu;
  • menší aktualizační a supply-chain plocha.

Sdílená helper vrstva řeší tvorbu DOM, API požadavky, CSRF, formátování a odhlášení. Uživatelské texty jsou česky.

21.5 Databáze#

Produkce používá PostgreSQL 16. Připojovací pool je na 4GB serveru omezený na čtyři spojení. Dotazy mají časový limit a čekání na spojení selže rychle, aby jedna závada nezablokovala proces neomezeně.

Živé migrace jsou PostgreSQL migrace 0001 až 0018. Staré D1 migrace jsou zmrazená historie a nesmějí se používat pro produkční nasazení.

21.6 Souborové úložiště#

Archiv a přílohy jsou lokální adresáře pod /opt/kochy/storage. Aplikace nad nimi používá R2-tvarovaný adaptér, ale žádný objektový cloud pro běžný provoz.

Adaptér:

  • převádí objektový klíč na bezpečnou cestu pod daným kořenem;
  • odmítá path traversal;
  • vytváří podadresáře;
  • podporuje put, get, head, list a delete;
  • nepublikuje soubor přímo přes webový server.

S3 konfigurační proměnné se stále parsují kvůli kompatibilitě staré konfigurace, ale aktuální ukládání je nepoužívá.


22. Datový model a ukládání#

22.1 Hlavní datové skupiny#

Skupina Hlavní entity Charakter
Zákazníci zákazník, vybavení, historie vybavení dlouhodobá pracovní paměť
Protokoly protokol, revize, čítač, koncept, šablona neměnný archiv + dočasné koncepty
Interní obsah poznámka, historie, příloha šifrovaný obsah
Servis zásah přidávací šifrovaná historie
Docházka den, revize dne šifrovaný denní payload a opravy
Smlouvy dokument, review, publikace šifrovaný neměnný archiv
Zákaznický portál členství, publikační příznaky strukturální izolace
Partner zástupce, tip, servisní vazba šifrovaná obchodní data
Provize nárok, změna výplaty neměnný finanční snapshot
Přístup uživatel, relace, 2FA výzva, recovery kód, token bezpečnostní stav
Provoz audit, rate limit, záloha, Fakturoid cache/token dohled a integrace

22.2 Co je šifrované#

Data Klíč
poznámky, jejich historie, koncepty NOTES_KEY
popisy příloh NOTES_KEY
servisní zásahy NOTES_KEY
docházka a její revize NOTES_KEY
vstupy smluv/GDPR NOTES_KEY
podmínky zástupců, tipy, důvody, výpočty provizí NOTES_KEY
těla příloh ATTACHMENTS_KEY
PDF smluv/GDPR ATTACHMENTS_KEY
TOTP tajemství a Fakturoid OAuth token AUTH_KEY

Každý šifrovaný záznam nese ciphertext, 12bajtový náhodný IV, autentizační tag a key_id. Díky tomu mohou po dobu rotace vedle sebe existovat záznamy více verzí klíče.

22.3 Co není aplikačně šifrované#

PostgreSQL obsahuje nezbytná dotazovatelná metadata, například datum, stav, uživatelské ID nebo evidenční číslo. Původní protokolová PDF a jejich JSON jsou v lokálním archivu čitelná pro proces a operační účet. Každá plná záloha, včetně těchto souborů, je proto před uložením šifrovaná nástrojem age.

22.4 Neměnnost a revize#

Neměnnost neznamená, že se data nikdy nemění. Znamená, že historický fakt se nepřepisuje:

  • regenerovaný protokol je nový revizní řádek;
  • servisní zásah je nový záznam;
  • změna výplaty je nová payout událost;
  • oprava docházky uloží předchozí snapshot;
  • změna poznámky uloží předchozí text;
  • nová verze smlouvy je nový dokument.

23. Bezpečnostní model#

23.1 Základní pravidla#

  1. Každá běžná API route vyžaduje přihlášenou relaci a konkrétní oprávnění.
  2. Externí role mají výchozí zákaz.
  3. Citlivá čtení se auditují stejně jako změny.
  4. Citlivý obsah je šifrovaný v klidu.
  5. Fakturoid je pouze pro čtení už konstrukcí klienta.
  6. Povinná tajemství chybí-li, aplikace odmítne zdravý start.
  7. Vstupy se validují před business logikou i před regenerací z archivu.
  8. Dokumenty začínají neveřejné.

Výjimkou bez běžné session je zálohovací notify endpoint. Ten používá vlastní silný workflow secret, porovnání v konstantním čase a idempotentní run ID.

23.2 HTTP ochrany#

Caddy i aplikace nastavují:

  • Content Security Policy bez unsafe-inline;
  • HSTS na jeden rok včetně subdomén a preload;
  • X-Content-Type-Options: nosniff;
  • Referrer-Policy: strict-origin-when-cross-origin;
  • zákaz geolokace, kamery a mikrofonu;
  • same-origin omezení rámců a zdrojů;
  • odstranění identifikační hlavičky Server.

Caddy před proxy odstraní příchozí X-Forwarded-For, X-Real-IP a CF-Connecting-IP a nastaví nový X-Real-IP ze skutečného TCP protějšku. Audit proto nepřebírá útočníkem podvrženou IP hlavičku.

23.3 CSRF#

Každá změnová metoda POST, PUT, PATCH nebo DELETE vyžaduje token shodný s tajemstvím relace. Frontend ho přidává automaticky. Chybný token vrátí 403 a zapíše csrf.rejected.

23.4 Ochrana proti zneužití#

  • globální limit těla běžného API je 512 KB;
  • upload má samostatný 31MB limit včetně multipart režie;
  • PDF generování má omezení souběhu;
  • scrypt má omezení souběhu;
  • přihlášení, 2FA, aktivace a odeslání tipu mají databázové rate limity;
  • MIME typ se určuje na serveru;
  • souborový adaptér odmítá únik z kořenového adresáře;
  • neznámá interní chyba vrací obecnou odpověď bez detailu.

23.5 Tři klíčové rodiny#

Oddělení NOTES, ATTACHMENTS a AUTH zmenšuje dopad jednoho uniklého klíče. Rotace probíhá přidáním nové verze, přepnutím aktivního zápisu, dávkovým přešifrováním, kontrolou a až poté odstraněním staré verze.

Bez zálohy klíčů nelze šifrovaná data obnovit. Aktivní i ještě používané staré klíče musí být v řízeném heslovém trezoru KAMSY.

23.6 Hranice, které nejsou bezpečnostní#

  • Kategorie přílohy není oprávnění.
  • Skrytí tlačítka v HTML není oprávnění.
  • Doména sama o sobě není oprávnění.
  • ID v URL není oprávnění.
  • Fakturoid OAuth scope není jediná ochrana proti zápisu.

Rozhodnutí vždy potvrzuje serverové oprávnění a datový dotaz.


24. Audit, retence a automatické úlohy#

24.1 Audit#

Audit zaznamenává zejména:

  • úspěšná a neúspěšná přihlášení;
  • lockout, reset hesla, TOTP a použití recovery kódu;
  • zobrazení zákazníka, poznámky, přílohy, zásahu, docházky a dokumentu;
  • vytvoření a regeneraci protokolu;
  • změnu viditelnosti protokolu, přílohy a smlouvy;
  • vytvoření a schválení smlouvy;
  • pozvánky, role, deaktivace a aktivace uživatele;
  • tipy, provize a jejich změny;
  • volání Fakturoidu a canary chyby;
  • zálohy, cron úlohy, CSRF a odmítnutá oprávnění.

Událost může nést uživatele, zákazníka, evidenční číslo, metodu, cestu, stav, bezpečně omezená metadata, IP a user-agent.

24.2 Retence#

  • Auditní události se mažou po 90 dnech.
  • Login pokusy se mažou po 30 dnech.
  • Expirující 2FA výzvy a relace se pravidelně odstraňují.
  • Smazané přílohy se fyzicky odstraní po 30 dnech.
  • Koncepty expirují po 24 hodinách.
  • Protokoly, jejich JSON a revize nemají automatickou expiraci.
  • Provizní kniha a její payout události jsou historické.

24.3 Denní úloha ve 04:00 UTC#

  • fyzické odstranění příloh po 30denní lhůtě;
  • odstranění expirovaných konceptů;
  • odstranění expirovaných relací;
  • jedno Fakturoid canary GET ověřující tvar API.

Chyba canary neblokuje údržbu; zapíše se samostatně.

24.4 Týdenní úloha v pondělí 02:00 UTC#

  • odstranění expirovaných ověřovacích výzev;
  • odstranění starých login pokusů;
  • export posledních sedmi dnů auditu do lokálního backup bucketu;
  • odstranění auditu staršího 90 dnů.

24.5 Záloha 1. a 15. den#

První a patnáctý den v měsíci ve 03:00 UTC se vytvoří plná age-šifrovaná záloha databáze a celého lokálního storage stromu. Podrobnosti jsou v kapitole 26.


25. Nasazení a provoz#

25.1 Produkční komponenty#

Komponenta Aktuální řešení
Server Hetzner, Ubuntu, 2 vCPU, 4 GB RAM, 75 GB disk
Aplikační runtime Node.js 22
Proces systemd kochy.service
Interní listen 127.0.0.1:8080
Databáze PostgreSQL 16 přes Unix socket
HTTPS a static Caddy
DNS Webglobe
Certifikát Let's Encrypt automaticky přes Caddy
Storage lokální disk
Firewall Hetzner Cloud Firewall + UFW

Cloudflare není před aplikací a neskrývá origin. Porty 80 a 443 jsou veřejné, SSH je omezený na schválené administrátorské IP adresy a klíče.

25.2 Lokální vývoj#

Předpoklady: Node 22, PostgreSQL 16 a vyplněný .env.dev.

npm ci
npm run db:migrate:pg
npm run seed-pg-fixtures
npm run dev:node

Pro produkční sestavení:

npm run typecheck
npm test
npm run build:node

Legacy příkazy založené na Wrangleru nejsou podporovaná vývojová ani produkční cesta.

25.3 Zdraví služby#

GET /healthz vrací pouze obecné:

{"ok":true}

Pokud chybí některé povinné tajemství, vrátí 503 a konkrétní seznam se objeví jen v serverovém journalu.

25.4 Povinná tajemství#

Při startu musí být nastaveno devět hodnot:

  1. NOTES_KEY_V1
  2. ATTACHMENTS_KEY_V1
  3. AUTH_KEY_V1
  4. FAKTUROID_CLIENT_ID
  5. FAKTUROID_CLIENT_SECRET
  6. FAKTUROID_ACCOUNT_SLUG
  7. TURNSTILE_SECRET_KEY
  8. TURNSTILE_SITE_KEY
  9. BACKUP_WORKFLOW_SECRET

Telegram je volitelný. Proměnné S3 jsou aktuálně vestigální kompatibilita konfigurace; storage používá STORAGE_DIR.

25.5 Release#

Produkční release je adresář podle Git SHA pod /opt/kochy/releases. Postup:

  1. lokálně ověřit typy, testy a build;
  2. vytvořit nový release adresář;
  3. přenést dist, public, živé migrace, ops a package lock;
  4. na serveru nainstalovat Linux produkční závislosti přes npm ci --omit=dev;
  5. před databázovou změnou vytvořit zálohu;
  6. spustit PostgreSQL migrace pod OS uživatelem kochy;
  7. atomicky přepnout symlink /opt/kochy/current;
  8. restartovat službu;
  9. provést smoke test všech domén a rolí.

Migrace jsou dopředné a aditivní. Starší release má tolerovat přidané tabulky a sloupce.

25.6 Produkční smoke test#

Minimálně ověřte:

  • všechny tři /healthz;
  • přesměrování staré domény;
  • admin login + 2FA;
  • technik login;
  • testovací protokol a archiv;
  • partner invite, onboarding, 2FA a vlastní přehled;
  • customer invite, onboarding, 2FA a zveřejněný testovací dokument;
  • 404 na interní stránce z obou externích domén;
  • nemožnost stáhnout dokument jiného zákazníka nebo zástupce;
  • auditní události všech provedených akcí.

26. Zálohování, obnova a návrat verze#

26.1 Současná zálohovací strategie#

Aktuální režim je full-local storage:

  • PostgreSQL i živé soubory jsou na jednom serverovém disku;
    1. a 15. den v měsíci vznikne plná záloha;
  • záloha obsahuje pg_dump i celý strom archivu a příloh;
  • výsledek je jeden soubor kochy-backup-YYYY-MM-DD.tar.age;
  • na serveru se drží posledních šest;
  • nejnovější soubor musí obsluha ručně stáhnout mimo server.

To je vědomý nákladový kompromis. Ztráta serverového disku před dalším off-box stažením může znamenat ztrátu všech změn od poslední off-box kopie.

26.2 Co záloha dělá#

  1. Vytvoří PostgreSQL custom-format dump.
  2. Ověří jeho seznam pomocí pg_restore --list.
  3. Dump zkomprimuje.
  4. Přidá celý /opt/kochy/storage.
  5. Streamuje tar přímo do age šifrování.
  6. Odstraní plaintext staging.
  7. Zachová posledních šest šifrovaných artefaktů.
  8. Zapíše stav přes interní notify endpoint.

Plaintextový tar se nikdy nevytváří. Záloha obsahuje PII, heslové hashe, obnovovací kódy a čitelná protokolová PDF, proto musí zůstat age-šifrovaná.

26.3 Povinnost off-box kopie#

Po každém běhu zálohy:

  1. zkontrolujte úspěšný stav služby;
  2. ověřte nenulovou velikost nového .tar.age;
  3. stáhněte ho na schválené šifrované externí úložiště;
  4. ověřte hash nebo velikost po přenosu;
  5. zapište předání do provozního logu.

Kopie na stejném Hetzner disku není disaster-recovery kopie.

Pro havarijní přístup přes pgAdmin používejte SSH tunel; port PostgreSQL se neotevírá veřejně. Databáze sama nestačí k úplné obnově, protože vlastní protokoly a přílohy jsou v /opt/kochy/storage. Podrobný postup je v docs/runbooks/emergency-data-access.md.

26.4 Restore drill#

Čtvrtletně a po každé migraci s převodem dat:

  1. určete očekávaný počet protokolů a poznámek;
  2. spusťte restore drill nad nejnovějším lokálním artefaktem;
  3. skript ho dešifruje a rozbalí;
  4. obnoví dump do dočasné databáze kochy_drill;
  5. porovná sentinel počty;
  6. ověří přítomnost storage stromu;
  7. zapíše výsledek do logu.

Drill nemaže ani neupravuje produkční databázi.

26.5 Skutečná obnova#

Při reálné havárii:

  1. zastavte zápisy;
  2. určete schválený bod obnovy a očekávanou ztrátu;
  3. připravte nový nebo vyčištěný server;
  4. bezpečně přeneste age identitu a zálohu;
  5. dešifrujte do omezeného staging adresáře;
  6. obnovte PostgreSQL;
  7. obnovte storage strom se správným vlastníkem a právy;
  8. použijte release kompatibilní se schématem;
  9. spusťte službu;
  10. proveďte smoke test a porovnání sentinelů;
  11. zaznamenejte incident a dobu obnovy;
  12. bezpečně odstraňte plaintext staging.

26.6 Rollback aplikace#

Pokud selže nový release, ale data jsou v pořádku:

  1. krátce zastavte zápisy a vytvořte nouzovou zálohu;
  2. zjistěte přesný předchozí release;
  3. přepněte /opt/kochy/current na něj;
  4. nevracejte automaticky aditivní databázovou migraci;
  5. restartujte kochy;
  6. reloadujte Caddy jen pokud se měnila jeho konfigurace;
  7. opakujte smoke test.

Cloudflare Workers není rollback cíl.


27. Rozhodnutí, hranice a vědomé kompromisy#

27.1 Zamčená rozhodnutí#

  • jedna firma, ne multi-tenant SaaS;
  • Node 22 + Hono + PostgreSQL 16;
  • Caddy a Let's Encrypt, DNS u Webglobe;
  • žádná Cloudflare proxy, pouze Turnstile;
  • lokální souborové úložiště;
  • čistý JavaScript bez frontend frameworku;
  • Fakturoid jen pro čtení;
  • čtyři role s výchozím zákazem externích rolí;
  • tři oddělené rodiny šifrovacích klíčů;
  • neměnný protokolový a provizní archiv;
  • řízené schválení smluv/GDPR;
  • žádný SMTP a žádné automatické zákaznické e-maily.

27.2 Proč jedna aplikace místo tří backendů#

Sdílení ověřené autentizace, šifrování, auditů a databázové vrstvy snižuje počet míst, kde může vzniknout rozdílná bezpečnostní chyba. Riziko širšího procesu se kompenzuje default-deny oprávněními, specializovanými službami, Caddy allowlisty a testy izolace.

27.3 Proč lokální disk#

Lokální disk snižuje měsíční náklady a počet služeb. Cenou je jediná živá kopie a off-box disciplína. Toto rozhodnutí je přijatelné jen tehdy, když se každý nový šifrovaný artefakt skutečně kopíruje mimo server.

27.4 Proč není veřejný affiliate#

Technická registrace účtu je snadná, ale neřeší:

  • právní titul pro předání kontaktu třetí osoby;
  • text souhlasu;
  • zdanění a fakturaci odměn;
  • duplicitní doporučení;
  • zneužití formuláře;
  • ověření identity a bankovního příjemce.

Veřejná registrace je proto odložená obchodní a právní fáze.

27.5 Co není v současné verzi#

  • mobilní PWA a offline koncepty;
  • samoobslužný reset hesla;
  • automatická tvorba faktur ve Fakturoidu;
  • fulltext v šifrovaných poznámkách;
  • ZIP a Office přílohy;
  • antivirus uploadů;
  • veřejné URL souborů;
  • stará šablona při regeneraci;
  • sklad komponent;
  • automatizované off-box zálohy;
  • multi-tenancy;
  • veřejný affiliate program.

Responsive mobilní viewport je implementovaný; „mobilní PWA“ v tomto seznamu znamená instalovatelnou offline aplikaci, nikoli běžné použití v mobilním prohlížeči.


28. Řešení problémů#

28.1 Přihlášení hlásí CAPTCHA#

  • Ověřte, že se widget načetl.
  • Zkontrolujte čas a síť prohlížeče.
  • Správce zkontroluje oba Turnstile klíče a journal aplikace.
  • Site key a secret musí patřit ke stejné konfiguraci domén.

28.2 Po zadání hesla se nezobrazí správný portál#

  • Zkontrolujte roli účtu.
  • Ověřte, že účet není deaktivovaný.
  • Zkuste se odhlásit a znovu přihlásit na správné doméně.
  • Externí role jsou po přihlášení směrovány na svůj portál.

28.3 Aktivace odkazu nefunguje#

Odkaz mohl vypršet, být použitý nebo poškozený kopírováním. Administrátor musí vytvořit nový. Starý odkaz se neobnovuje.

28.4 Nejde uložit změnu, ale čtení funguje#

Pravděpodobnou příčinou je expirovaná CSRF cookie nebo relace. Obnovte stránku. Pokud se problém opakuje, odhlaste se a přihlaste znovu. Správce zkontroluje csrf.rejected v auditu.

28.5 Zákazník nevidí dokument#

Zkontrolujte v tomto pořadí:

  1. má účet členství k objektu;
  2. je účet aktivní;
  3. je protokol nebo příloha skutečně publikovaná;
  4. je smlouva schválená;
  5. je schválená smlouva také samostatně publikovaná;
  6. je uživatel přihlášený na zákaznické doméně.

28.6 Smlouvu nelze publikovat#

Dokument ještě nemá zaznamenané schválení. Nejdříve otevřete celé PDF, proveďte kontrolu a potvrďte schválení. Teprve poté publikujte.

28.7 Příloha je odmítnutá#

  • překročila 30 MB;
  • zákazník překročil 1 GB;
  • formát není povolený;
  • skutečný obsah nesouhlasí s příponou;
  • upload přesáhl celkový request limit.

28.8 Fakturoid nevrací zákazníky#

  • lokální výsledky mohou stále fungovat;
  • zkontrolujte OAuth token a KAMSY account preflight;
  • ověřte kvótu;
  • prohlédněte audit fakturoid.call a případný fakturoid.canary_failed;
  • zákazníka lze pro protokol zadat ručně.

28.9 Roční provize nelze vygenerovat#

  • snapshot je starý;
  • tip není ve stavu Vyhráno;
  • generátor je neaktivní, mimo daný rok nebo není v CZK;
  • generátor ve snapshotu chybí;
  • odečet je vyšší než roční zdroj;
  • záznam pro tuto smlouvu a rok už existuje.

Nejdříve použijte Náhled a vyřešte přeskočené řádky.

28.10 Technik nemůže změnit docházku#

Den je starší než 14 dní nebo jde o cizího pracovníka. Opravu provede administrátor s povinným důvodem.

28.11 PDF má chybnou diakritiku nebo layout#

Jde o renderer nebo chybějící distribuované fonty, ne o nastavení prohlížeče. Ověřte, že release obsahuje vložené fonty a že vznikl aktuálním buildem. Chybný archivní originál nepřepisujte; opravu rendereru ověřte na novém testovacím dokumentu a pro starý vstup použijte vodotiskovou regeneraci.

28.12 Služba po deployi nenaběhne#

  1. systemctl status kochy --no-pager
  2. journalctl -u kochy -n 100 --no-pager
  3. kontrola devíti povinných tajemství;
  4. kontrola práv /opt/kochy/storage;
  5. kontrola PostgreSQL socketu a migrací;
  6. kontrola, že dist/server.js existuje;
  7. kontrola přesné instalace produkčních závislostí.

28.13 Caddy nevystaví certifikát#

  • všechny čtyři A záznamy musí mířit na správnou IP;
  • porty 80 a 443 musí být otevřené;
  • nesmí být aktivní stará Cloudflare-origin konfigurace;
  • zkontrolujte journalctl -u caddy.

28.14 Záloha selhala#

  • otevřete journalctl -u kochy-backup;
  • ověřte volné místo;
  • ověřte PostgreSQL peer autentizaci;
  • ověřte AGE_RECIPIENT;
  • ověřte zápis do /opt/kochy/backups;
  • po opravě spusťte zálohu znovu a proveďte restore drill.

29. Kontrolní seznamy#

29.1 Denní práce technika#

  • Přihlásit se vlastním účtem.
  • U zákazníka ověřit správný objekt a adresu.
  • Po zásahu zapsat práci a komponenty.
  • Přílohu správně označit druhem.
  • Před zveřejněním přílohu otevřít a zkontrolovat.
  • Vyplnit místa, čas, kilometry a výdaje v docházce.
  • Citlivé přístupy zapisovat do šifrované poznámky, ne do názvu souboru.

29.2 Publikace zákazníkovi#

  • Správné zákaznické členství.
  • Správný objekt.
  • Otevřený a zkontrolovaný dokument.
  • U smlouvy zaznamenané schválení.
  • Samostatně zapnutá publikace.
  • Žádné interní heslo, záloha nebo schéma omylem viditelné.
  • Auditní událost vznikla.
  • Kontrola pohledem zákaznického účtu.

29.3 Roční provize#

  • Aktivní obchodní zástupci a správné výchozí sazby.
  • Vyhrané tipy propojené se zákazníky.
  • Správná ID pravidelných generátorů.
  • Zdůvodněné odečty.
  • Čerstvý Fakturoid snapshot.
  • Náhled bez nevysvětlených přeskočení.
  • Správný rok.
  • Vygenerováno pouze jednou.
  • Výplaty posouvány přes K fakturaci.

29.4 Před deployem#

  • Čistý typecheck.
  • Všechny testy zelené.
  • Produkční build dokončený.
  • Změna migrace má shape test.
  • Před migrací existuje ověřená záloha.
  • Release používá správný commit.
  • Caddy a systemd jednotky jsou z aktuálního release.
  • Po přepnutí proběhne smoke test všech rolí.

29.5 Po každém běhu zálohy#

  • Timer proběhl úspěšně.
  • Nový .tar.age existuje a má očekávanou velikost.
  • Artefakt byl stažen mimo server.
  • Off-box kopie byla ověřena.
  • Událost byla zapsána do handover/provozního logu.
  • Disk je pod 80 %.

29.6 Čtvrtletně#

  • Restore drill.
  • Aktualizace OS a plánovaný reboot.
  • Kontrola SSH klíčů a firewallu.
  • Kontrola oprávnění Fakturoid aplikace.
  • Kontrola uživatelů a deaktivace nepotřebných účtů.
  • Kontrola klíčů, recovery materiálu a off-box záloh.

30. Slovník a referenční přílohy#

30.1 Slovník#

Pojem Význam
Objekt zákaznické místo nebo budova vedená v zákaznické kartě
Protokol PDF revize nebo údržby s evidenčním číslem
Revize protokolu vodotisková regenerace z původního vstupu
Šablona znovupoužitelné přednastavení formuláře protokolu
Koncept 24hodinový šifrovaný rozpracovaný protokol
Publikace explicitní zpřístupnění zákaznickému účtu
Review zaznamenaná právní nebo vlastnická kontrola dokumentu
Tip doporučení potenciálního zákazníka obchodním zástupcem
Servisní vazba propojení tipu s pravidelným Fakturoid generátorem
Snapshot neměnná kopie hodnot platných v okamžiku výpočtu nebo generování
Bazický bod (bps) setina procentního bodu; 1 500 bps = 15 %
CSRF ochrana proti podvrženému změnovému požadavku z cizí stránky
TOTP šestimístný časový kód druhého faktoru
AES-256-GCM autentizované symetrické šifrování citlivých dat
age nástroj pro šifrování úplných záložních artefaktů
GC pravidelný úklid expirovaných nebo měkce smazaných dat

30.2 Uživatelské stránky#

Povrch Stránka Účel
Zaměstnanci / přehled
Zaměstnanci /customers.html zákazníci
Zaměstnanci /customer.html?id=… zákaznická karta
Zaměstnanci /new.html nový protokol
Zaměstnanci /archive.html archiv
Zaměstnanci /archive-detail.html?ev=… detail protokolu
Zaměstnanci /attendance.html docházka
Admin /templates.html šablony
Admin /commissions.html obchod a provize
Admin /users.html uživatelé
Admin /audit.html audit
Partner / vlastní tipy a provize
Zákazník / vlastní dokumenty

30.3 API skupiny#

Prefix Odpovědnost
/api/auth login, 2FA, aktivace, session, logout
/api/customer vyhledávání a materializace zákazníka
/api/customers vybavení, poznámky, přílohy, servis a smlouvy
/api/protocols generování, archiv, stažení a revize
/api/drafts koncepty
/api/templates protokolové šablony
/api/attendance docházka
/api/customer-access pozvánky a publikace protokolů
/api/customer-portal strukturálně omezená zákaznická knihovna
/api/rep strukturálně omezené tipy a provize partnera
/api/commissions administrace obchodních případů a provizí
/api/users, /api/audit administrace a audit
/api/admin/backup stav a notifikace záloh

30.4 Technické příkazy#

Úkol Příkaz
Typecheck npm run typecheck
Testy npm test
Node build npm run build:node
Lokální Node vývoj npm run dev:node
PostgreSQL migrace lokálně npm run db:migrate:pg
Založení prvního admina npm run create-admin
Reset hesla npm run reset-password
Reset TOTP npm run reset-totp
Rotace NOTES npm run rotate-notes-key
Rotace ATTACHMENTS npm run rotate-attachments-key
Rotace AUTH npm run rotate-auth-key
GDPR odstranění zákaznického workspace npm run delete-customer-workspace

30.5 Související provozní dokumenty#


Závěrečné pravidlo#

Kochy chrání historii tím, že odděluje vytvoření, kontrolu, publikaci a výplatu do samostatných kroků. Když si nejste jistí, zda má uživatel něco vidět nebo zda se má starý záznam přepsat, správná výchozí odpověď je: nezveřejnit, nepřepisovat a použít auditovanou novou událost.