# 99 - Zaznam zmen Nejnovejsi nahore. ## 2026-08-03 Tickety predelane na plnohodnotny konektor. Prestavaji byt polozkou v seznamu a stavaji se prichozim pozadavkem, ktery ma sveho cloveka a dohledatelny prubeh. Popis modelu je v [06-tickety.md](06-tickety.md). ### Pridano - Kanaly do ticketu: WhatsApp jako novy konektor, e-mail a hlasova linka jako plnohodnotne spoustece. - Konektor Tickety presunut do nove kategorie `servicedesk`, rozsiren o spoustece `created`, `unknown-customer`, `assigned`, `status-changed` a akce `assign`, `set-status`, `link-customer`. - Resitele (`src/data/people.ts`) oddelene od uzivatelu portalu, spojka e-mailem. - Log ticketu ve strome vcetne toho, co ktera volana sluzba vratila. - Prehled vytizeni tymu, kdo co ma u sebe, zaroven jako filtr seznamu. - Detail ticketu `/dashboard/tickety/:id`: prubeh a log, prirazeni, stav, zakaznik, komentare. - Filtry seznamu ticketu na serveru: resitel (vcetne `me` a `unassigned`), stav, kanal. - `providedFields` v katalogu konektoru: parametry, ktere spoustec predava sam. - Udalost `ticket.assigned` na sbernici i v portalu. - Endpointy `/api/dashboard/people`, `/tickets/workload`, `/tickets/:id` a POST varianty pro assign, status a comment. Vse ve Swaggeru. ### Zmeneno - `Ticket` ma misto volneho `requester` strukturovaneho `customer` s nullable `id` firmy v CRM, k tomu `channel`, `assignee` jako odkaz na cloveka a `automationId`. - `customer.id === null` je nosna informace, ne chybejici udaj. Prave na ni se pta podminka "mame zakaznika?" ve strome automatizace. - Simulace ticketu bere kanal a prepinac, jestli se zakaznik dohleda. Zakladany ticket dostane cely realisticky log. - Builder ukazuje parametry od sluzby jen ke cteni. Server je pri ulozeni vzdy dosadi z katalogu, a to jeste pred validaci stromu. ### Vedome neudelano Bugs a wishes zustavaji mimo. Vyvojarska agenda ma jiny zivotni cyklus a slucovat ji s tickety by znamenalo, ze ani jedna evidence nefunguje poradne. ### Doplneno pote Puvodni verze mela diru: ticket nemel zadny obsah a krok "Zalozit ticket" nesel nastavit. Slo tedy rict "z WhatsApp udelej ticket", ale ne uz co se ma kam ulozit. - `Ticket.body` a `Ticket.sourceRef`. Predmet je shrnuti, telo je cely text pozadavku. `body` vystaveno i ve spoustecich `created` a `unknown-customer`, takze na obsah ticketu jde udelat podminka v navazne automatizaci. - Nastavitelna pole akci (`OperationField` a `FlowStep.inputs`). Ticket, e-mail a WhatsApp maji skutecna pole misto pouhe napovedy. - Sablony `{{parametr}}` v hodnotach poli (`src/data/templates.ts`) vcetne nabidky parametru, ktera je vklada na pozici kurzoru. - Vyber resitele u akci se plni ze seznamu lidi, ne z rucne psaneho ID. - Nevyplnene povinne pole a odkaz na neexistujici parametr se hlasi jako nedodelek. Nastaveni pole, ktere akce nema, je chyba 400. - Akce bez `inputs` to v builderu napisou primo na karte kroku. ### Vystupy kroku a predvalidace Druha dira: kroky slo vkladat kamkoliv, ale podminka videla jen parametry spoustece. Slo tedy pridat krok "zeptej se CRM", ale ne se vetvit podle toho, co vratil. Bez toho byla predvalidace k nicemu. - `outputFields` v katalogu: co akce vrati dalsim krokum. Ma je "Dohledat firmu" (`customerKnown`, `companyId`, `companyName`), "Zaradit do kategorie", "Zalozit obchodni pripad" i "Zalozit ticket". - Nova akce RAYNET "Dohledat firmu". Nic nezaklada, jen odpovi, jestli odesilatele zname. Presne pro predvalidaci. - `src/data/flowScope.ts` pocita, co je videt v kterem miste stromu. Krok vidi spoustec plus vystupy kroku pred nim. Vetev nepridava nic do sekvence za podminkou, protoze nemusela probehnout. - Builder nabizi v podmince i v polich akce presne ty parametry, ktere v danem miste doopravdy jsou. - Odkaz na parametr, ktery ve strome neni, je chyba 400. Odkaz na parametr, ktery vznika az pozdeji, je nedodelek s radou posunout podminku niz. - Duplicitni jmeno parametru ve scope je nedodelek. V sablone by nesl poznat, ktery se dosadi. ### Kanaly a vzorove automatizace - Konektory Facebook Messenger a Instagram, kanaly `facebook` a `instagram` u ticketu. - Ctyri nove vzorove automatizace v rozdeleni, ktere odpovida zameru: jedna na kanal pro prijem, jedna spolecna pro smerovani na resitele. Prijmove zamerne neprirazuji, smerovani si ticket prevezme a podminkou `assigned neni splneno` neprepise rucni rozhodnuti. ### Firmy a prava Treti a nejvazneji dira: portal nemel zadnou tenanci. Kterykoliv prihlaseny uzivatel videl vsechny tickety vsech firem a cely seznam resitelu, `requireRole` se nikde nevolal. Popis v [07-firmy-a-prava.md](07-firmy-a-prava.md). - Tenant jako hranice viditelnosti. `tenantId` na ticketu, resiteli i automatizaci. - Uzivatel muze patrit do **vic firem**, v kazde s jinou roli (`memberships`). Pristup napric firmami je zvlast jako `platformAdmin`. - Tri pohledy na tickety: `all`, `tenant`, `mine`. Admin mezi nimi prepina, vcetne vyberu firmy. - `src/data/access.ts` jako jedine misto, kde se rozhoduje o pravech. `GET /api/dashboard/access` rekne klientovi, co smi kreslit. - Filtr na firmu je v ulozistich **povinny argument**. Zapomenuty filtr neznamena "vse", ale nezkompiluje se. - Nikdy tise nezuzujeme. Cizi firma vraci 403 nebo 404. - Prirazeni jen v ramci firmy. Prehazovat praci mezi lidmi smi jen admin, agent si smi vzit ticket na sebe. - `requireRole` nahrazen `requirePlatformAdmin`. Prava uvnitr firmy resi `access.ts`, protoze zavisi na tom, ktera firma pozadavek zajima. - Demo ucty pokryvaji vsechny tri situace vcetne cloveka ve dvou firmach. ### Zapsano jako otevrene rozhodnuti Vsechny automatizace se stejnym spoustecem se spusti. Doporucene rozdeleni na to nenarazi, ale az se bude psat runtime, musi se to rozhodnout vedome. Varianty a doporuceni v [06-tickety.md](06-tickety.md). ## 2026-07-31 Prvni nasazeni aplikace do repozitare csbot-prototype. Puvodni sablona byla holy Express s endpointy `/` a `/health`. Nahradil ji kompletni web a klientsky portal. ### Pridano - Verejny web: homepage se sekcemi, sluzby, o nas, kontakt s formularem, 404. - Prihlaseni pres JWT s demo ucty. - Klientsky portal: prehled s grafem, tickety, incidenty, automatizace, konektory, nastaveni. - Builder automatizaci: strom akci, spoustec, vetveni podminkou. - Katalog 25 konektoru v 8 kategoriich. - Webhook s registrovanou adresou, token generuje server. - Zivy dashboard pres SSE, vcetne indikatoru spojeni a bublin s udalostmi. - Simulace provozu pod tlacitkem v postrannim menu portalu. - Swagger UI na `/docs` a OpenAPI definice na `/openapi.json`. - Dokumentace ve slozce `documentation/`. - `.gitignore`, ktery drzi `node_modules` a `dist` mimo repozitar. ### Zmeneno oproti sablone - Aplikace prepnuta na ESM (`"type": "module"`) a `module: NodeNext`. - Jeden container obsluhuje API i zbuildovanou React aplikaci z `dist/public`. - Dockerfile buildu je server i web, vysledny image dostava jen `dist`. - Port zustava 3000, naslouchani na `0.0.0.0` beze zmeny. ### Reseni reverse proxy - `ROOT_PATH` se cte z prostredi, nikde neni hardcoded. - Aplikace se mountuje na koren i na prefix, funguje tedy at Caddy prefix odstrani nebo ne. - Server vklada do `index.html` znacku `` a `window.__BASE_PATH__`, aby SPA nasla soubory i na vnorenych cestach. - OpenAPI `servers` obsahuje prefix, takze Swagger Try it out vola spravnou adresu. - Router ma `strict: true`, jinak by se presmerovani `/docs` na `/docs/` zacyklilo. ### Overeno lokalne S `ROOT_PATH=/apps/csbot-prototype`: - `/apps/csbot-prototype/health` i `/health` vraci 200, - `/apps/csbot-prototype/docs` presmeruje na `/docs/`, ta vraci Swagger UI, - `swagger-ui.css` se nacte pres prefix, - OpenAPI `servers` obsahuje `/apps/csbot-prototype`, - `index.html` na vnorene ceste obsahuje spravny ``, - prihlaseni pres prefix vraci token, - neexistujici cesta pod `/api` vraci JSON, ne HTML aplikace. ### Znama omezeni Data jsou v pameti, restart je vrati do vychoziho stavu. Obsah webu je ukazkovy. Ulozeny strom automatizace se nevykonava.