Files
csbot-prototype/documentation/99-zmeny.md
T
JiriUhlirandClaude Opus 5 5d186dcd2e Runtime vykonava strom, prokliky z widgetu, oprava ukladani rozlozeni
Runtime: `src/runtime/executor.ts` jde krok po kroku, u podminky se vetvi,
do poli dosadi parametry, akci pusti pres runScript a vystupy pripise do
kontextu pro dalsi krok. Cely prubeh jde do logu ticketu vcetne toho, co
sluzba vratila. Pouzivaji ho obe cesty: akce na ticketu i webhook.

Opraveno: rozlozeni dashboardu s vlastnim widgetem se NEDALO ULOZIT.
`validateLayout` znala jen vestaveny katalog, takze kazdy pokus skoncil
hlaskou "widget v katalogu neexistuje" - presne to, co hlasil uzivatel.
Katalog je ted jedna funkce a pouziva ji nabidka i kontrola. Zaroven je
za konkretni firmu, driv slo polozit dlazdici jedne firmy na dashboard druhe.

Prokliky: z widgetu lidi na cloveka, ze seskupeni na vyfiltrovany seznam
ticketu. Odkazy sklada server, protoze on jediny zna filtr widgetu. Seznam
ticketu cte filtr z adresy a umi filtrovat na typ, tag a skupinu.

Tabulky: spolecna `TicketTable` pro seznam i detail osoby. Na mobilu se
neposouva do strany, uzka obrazovka dostane karty. Detail osoby ma velkou
tabulku se zalozkami "ma u sebe" a "vyresil" a prepinacem pohledu.

Odebrano: simulace vcetne tlacitka, dialogu i endpointu. Trojice pohledu
nad tickety - vyber firmy je select, "moje" je prepinac, driv to delalo
totez dvakrat.

Pridan zmereny rozbor kapacity pro 200 firem (19-kapacita-200-firem.md):
soucasny stav to nezvladne, protoze data jsou v pameti a vypis je linearni.
Zmereno na 5 000 ticketech, vcetne toho, co s tim a kolik serveru to chce.

Overeno 7 kontrolami proti bezicimu serveru.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 15:54:17 +02:00

26 KiB

99 - Zaznam zmen

Nejnovejsi nahore.

2026-08-13 - runtime, prokliky z widgetu a kapacitni rozbor

Pridano

  • src/runtime/executor.ts: strom se konecne vykonava. Jde krok po kroku, u podminky se vetvi, do poli dosadi {{parametry}}, akci pusti pres runScript a vystupy pripise do kontextu, aby na ne mohl dalsi krok odkazat. Cely prubeh jde do logu ticketu vcetne toho, co sluzba vratila. Pouzivaji ho obe cesty: akce na ticketu i webhook automatizace.
  • Z widgetu se da prokliknout na to, co je za cislem: z lidi na cloveka, ze seskupeni na uz vyfiltrovany seznam ticketu. Odkazy sklada server, protoze on jediny zna filtr widgetu.
  • Seznam ticketu cte filtr z adresy (?typeId=, ?tag=, ?assignee=, ...), takze proklik vede na spravny vyber a odkaz jde poslat kolegovi.
  • Seznam ticketu umi filtrovat na typ, tag a skupinu.
  • Spolecna TicketTable: jedna tabulka pro seznam i pro detail osoby. Na mobilu se neposouva do strany, uzka obrazovka dostane karty.
  • 19-kapacita-200-firem.md: zmereny rozbor toho, co se stane pri 200 firmach, a co to bude chtit za server.

Opraveno

  • Rozlozeni dashboardu s vlastnim widgetem se nedalo ulozit. validateLayout znala jen vestaveny katalog, takze kazdy pokus skoncil hlaskou, ze widget v katalogu neexistuje. Katalog je ted jedna funkce (widgetCatalog) a pouziva ji nabidka i kontrola.
  • Katalog widgetu je za konkretni firmu, ne za vsechny firmy uzivatele. Driv slo polozit dlazdici jedne firmy na dashboard druhe, kde k ni data nikdy neprisla.

Odebrano

  • Simulace vcetne tlacitka, dialogu i endpointu /api/simulate. Provoz se ted dela prijmem udalosti, ktery je skutecny.
  • Trojice pohledu nad tickety. Vyber firmy je select, "moje" je prepinac - driv to delalo totez dvakrat.

Overeno

7 kontrol proti bezicimu serveru: ulozeni rozlozeni s vlastnim widgetem, oddeleni katalogu po firmach, vykonani stromu akce i webhooku, zapis behu do logu, odkazy z widgetu a filtrovani podle nich. K tomu mereni na 5 000 ticketech, ze ktereho vychazi rozbor kapacity.

2026-08-13 - ticketovaci system: udalosti, externi ID, statistiky, widgety

Popis v 18-ticketovaci-system.md.

Pridano - prijem udalosti

  • POST /webhook/ticket/:token: jakakoliv udalost se muze stat ticketem. Token patri firme, ne automatizaci, takze zalozit ticket jde i bez stromu.
  • externalId na ticketu, unikatni v ramci firmy. Dalsi udalost se stejnym ID se navesi na existujici ticket misto zalozeni druheho. Cislo a retezec jsou tentyz klic, jinak by 3 a "3" byly dva tickety.
  • Udalosti se u ticketu drzi cele vcetne prijatych dat a jdou rozbalit v detailu. Je to neco jineho nez log: log je nase stopa, udalost fakt zvenku.

Pridano - co se meri

  • firstResponseAt, resolvedAt, resolvedById a reopenCount na ticketu. Bez nich neslo rict, kdo kolik odbavil ani jak dlouho zakaznik cekal.
  • getAgentStats: odbavene za obdobi, fronta, medianove casy do vyreseni a do prvni reakce, vracene tickety. Median zamerne, ne prumer.
  • Widget Vykon resitelu a detail osoby pouzivaji tutéž funkci, takze cisla sedi na obou mistech.

Pridano - widgety

  • Klient konecne vola /api/dashboard/widget-data. Predtim endpoint existoval, ale nikdo ho nepouzival, takze vlastni widget hlasil "nepodarilo se zobrazit".
  • Novy zdroj connector: co umi zjistit napojena sluzba, jde vytahnout do dlazdice. Vola se tentyz skript jako v kroku automatizace, vysledek se cachuje (ttlSec, nejmene 30 s).
  • Mrtvy odkaz v rozlozeni jde v rezimu uprav odstranit, ne jen precist.

Zmeneno

  • Akce a widgety maji vlastni zalozku, uz nejsou v nastaveni. Je to definice toho, co aplikace umi, stejna uroven jako automatizace.
  • Telo akce se sklada stromem, ne JSONem v textarei. Je to tentyz editor jako u automatizaci, jen misto karty spoustece je "spousti clovek".
  • Nova zalozka Lide se seznamem resitelu a detailem osoby.
  • Seznam ticketu i lidi ma dva pohledy, tabulku a dlazdice.
  • Dlouhe pomlcky pryc z celeho projektu (48 znaku ve 23 souborech).

Opraveno

  • createTicket bral typeId, fields, tags i assigneeGroupId, ale nikdy je neukladal. Ticket zalozeny s typem tak zustaval bez typu a bez vlastnich poli.

Overeno

21 kontrol proti bezicimu serveru v rezimu souboru: navazani druhe udalosti na tentyz ticket, oddeleni firem pri stejnem externim ID, ulozeni typu a poli z prijmu, vyreseni s casem i clovekem, zapocteni navratu z vyreseno, cisla ve widgetu vykonu, cele chybove hlaseni u widgetu nad nenapojenym konektorem, detail osoby, rozsah parametru akce, ulozeni stromu akce a navigace.

2026-08-13 - firmy, prava, typy ticketu, akce, widgety a uloziste pro vsechno

Dodelany cely navrh rozsireni a vsechna data se ukladaji. Rejstrik novych funkci a komponent je v 15-rejstrik-funkci.md.

Pridano - obecne vrstvy

  • src/data/store/: jedno rozhrani EntityStore<T> a dve implementace, soubor nebo pamet (local.ts) a Postgres nad tabulkou records (postgres.ts). Volajici nepozna, ktera bezi. Nova entita znamena jeden defineStore a jeden radek v bootstrap.ts.
  • store/cached.ts (withCache) pro konfiguracni entity ctene pri kazdem requestu a store/mirror.ts (withMirror) pro provozni data, ktera se meni v pameti a po zmene se cela zapisuji. Dva pomocniky, ne osm skoro stejnych souboru.
  • put v rozhrani uloziste: zapis celeho zaznamu bez skladani patche.
  • src/routes/crud.ts: fabrika CRUD rout. Seznam, detail, zapis, mazani, pravo a audit na jednom miste.
  • components/dashboard/EntityAdmin.tsx: obecna sprava zaznamu na klientovi. Nova zalozka nastaveni je popis sloupcu a poli, ne nova stranka.

Pridano - funkce

  • Firmy, uzivatele, clenstvi, osoby a skupiny resitelu se spravuji z portalu.
  • Role a prava jsou data, ne pevny seznam v kodu: katalog 26 prav, vlastni role za firmu, systemove role nejde menit. Navigace chodi ze serveru jako prunik toho, co firma ma, a toho, na co ma clovek pravo.
  • Typy ticketu s vlastnimi poli, tagy a vlastni workflow stavu.
  • Vydefinovane akce na ticketu: vazba na typ nebo tag, telo je jedna operace, vlastni strom, nebo skript. Server posila jen akce, ktere v dane situaci projdou podminkami a pravy - klient si nepocita, co ukazat.
  • Vlastni widgety dashboardu vcetne dat na jeden request a seskupeni.
  • Audit a prepnuti spravce na jiny ucet. Prepnuti je vychozi jen pro cteni, zapis se musi zapnout vedome a je videt v auditu.
  • Detail ticketu: CTA akci, typ, tagy, vlastni pole a prehozeni na skupinu.

Pridano - uloziste pro provozni data

Tickety vcetne logu, automatizace, incidenty a rozlozeni dashboardu se po kazde zmene zapisuji. Citace ID se pri startu dopocitaji z ulozenych zaznamu, takze novy ticket nikdy neprepise stary.

Overeno

V rezimu file: zmena typu, tagu, vlastnich poli, stavu, komentare, nova automatizace, novy incident a upravene rozlozeni dashboardu prezily tvrde ukonceni procesu a po restartu byly zpatky vcetne logu ticketu. Novy ticket dostal dalsi cislo, ne cislo existujiciho. Agent bez prav dostane 403 na spravu roli a uzsi navigaci. passwordHash se nikdy nevraci.

Databaze se v tomhle kole neoverovala, nebylo na cem - kod pro ni je stejny a psany soucasne, ale nebezel.

2026-08-12 - soubor jako uloziste bez databaze

Mockup se k databazi nedostane, takze pribyl treti rezim: JSON soubor. Prezije restart procesu i containeru, ale ne redeploy.

Pridano

  • src/data/snapshot.ts: atomicky zapis (.tmp a prejmenovani), slucovani zapisu a dokonceni rozepsaneho zapisu pri SIGTERM. Rozbity soubor se prejmenuje na .broken, zaloguje a jede se s prazdnymi daty - aplikace, ktera nenastartuje, je pro AppFactory nefunkcni sluzba.
  • src/data/connectors/local.ts: jeden kod pro pamet i soubor, lisi se jen tim, kam se zapisuje. Nahrazuje memory.ts - dve implementace by se casem rozesly.
  • Klic k sifrovani se mimo databazi vygeneruje do DATA_DIR/secrets.key, takze sifrovani funguje bez nastaveni. U databaze se negeneruje: kdo ma zalohu tabulky, ma i klic ze stejneho stroje.
  • DATA_DIR v konfiguraci, data/ v .gitignore a .dockerignore.
  • Hlaska v portalu rozlisuje tri nasledky: pamet (ztrata pri restartu), soubor (ztrata pri redeployi) a databaze (bez ztraty, hlaska se nezobrazuje).

Overeno

Bez databaze: konektor s vyplnenymi udaji prezil restart, v JSONu jsou hodnoty sifrovane a plaintext v nem neni. S databazi: rezim postgres funguje dal a klic vedle dat se nevygeneroval.

2026-08-12 - databaze pro konektory

Konektory se ukladaji do Postgresu, pristupove udaje sifrovane. Popis v 14-databaze.md.

Pridano

  • pg jako zavislost, pool v src/db/pool.ts vcetne transakci a dbFor(tenantId) jako sev pro budouci oddelenou databazi jednoho klienta.
  • Migrace ze souboru src/db/migrations/*.sql, pousti se pri startu pod pg_advisory_lock - pri rolling deployi je jinak pusti vsechny instance naraz. Jeden soubor je jedna transakce, takze pri chybe nevznikne rozdelane schema.
  • Sifrovani pristupovych udaju (src/db/secretBox.ts), AES-256-GCM s nahodnym IV a verzi klice. Nerozsifrovatelna hodnota nepada, chova se jako nevyplnena a zaloguje se - jeden rozbity konektor nesmi shodit seznam ostatnich.
  • Dve implementace uloziste konektoru za jednim rozhranim (memory, postgres). Rozhodnuti je jen na jednom miste, v src/data/connectorStore.ts.
  • /health/ready s pingem do databaze. /health na databazi zamerne nezavisi: kratky vypadek DB by jinak vedl k restartovani containeru.
  • GET /api/dashboard/storage a hlaska na strance Konektory o tom, ze data jsou jen v pameti. Bez toho se clovek divi, kam se podely jeho konektory.
  • Jediny vychozi konektor na firmu a sluzbu hlida castecny unikatni index, ne jen kod. Dva soubezne zapisy by jinak udelaly dva vychozi.

Zmeneno

  • Cteni i zapis konektoru je asynchronni, vcetne validace stromu.
  • Databaze je volitelna. Bez DATABASE_URL nebo SECRETS_KEY se jede v pameti a rekne se to v logu i v portalu. Container, ktery nenastartuje, je pro AppFactory nefunkcni sluzba.
  • Kdyz jsou migrace nastavene a selzou, jede se dal v pameti. Psat do rozbiteho schematu je horsi nez neukladat.

Overeno

Proti Postgresu 16 v kontejneru: migrace, sifrovani v tabulce, preziti restartu, rozsifrovani spravnym klicem, degradace pri spatnem klici, PATCH bez tajneho pole, prepnuti a smazani vychoziho konektoru, a pametovy rezim bez DATABASE_URL.

2026-08-12 - transformace dat a oprava konektoru

Transformace dat popsana v 13-transformace-dat.md.

Pridano

  • Kroky si predavaji i cele struktury. FieldType ma object a list. Do sablony se nedosazuji, predavaji se jako celek dalsimu kroku - proto je u nich v builderu vyber a ne textove pole. Z podminek nad nimi ma smysl jen "prisla / neprisla".
  • Strop na velikost struktury (SCRIPT_MAX_VALUE_BYTES, vychozi 256 kB). Radek s vystupem kroku je nejrychleji rostouci tabulka v systemu.
  • src/scripts/mapping.ts: cesty, prevody, pravidla a sablona JSON. Skripty ho dostanou na ctx.util jako get, applyRules a fillJson.
  • Dva rezimy transformace: transform.map-fields (pole na pole s prevody) a transform.to-json (sablona cileveho objektu s ${cesta}). V sablone je marker ${...} zamerne jiny nez {{...}}: sablony kroku se dosazuji driv, nez krok bezi, a stihly by ji prepsat.
  • Prevod map pro seznamy. Bez nej by slo prevest hlavicku dokladu, ale ne polozky objednavky, a doklad by byl na nulu.
  • idoklad.create-invoice-from-object: druha polovina prikladu, bere hotove telo dokladu z transformace.
  • Spoustec e-shopu predava celou objednavku jako objekt a polozky jako seznam.
  • Klikaci editor pravidel v builderu vcetne rezimu JSON pro vnorena pravidla.
  • Kontrola JSONu a tvaru pravidel uz pri ulozeni stromu. Preklep je nedodelek, ne chyba ukladani - rozdelana prace se nezahazuje.

Opraveno

  • Konektor neukladal pristupove udaje. Server byl v poradku, chyba byla v prohlizeci: u pole type="password" prohlizec ignoruje autocomplete="off" a dosazuje ulozene prihlaseni. Uzivatel pak videl jednu hodnotu, React drzel jinou, a ulozilo se to, co drzel React, tedy nic. Resi to autocomplete new-password, jmena poli, ktera nepripominaji heslo, a prepinac zobrazeni, aby slo overit, co je opravdu zapsane.
  • Zakladani a uprava konektoru se presunuly do dialogu. Na strance jsou jen male karty - formulare rozlozene po strance byly u vic konektoru neprehledne.

2026-08-12 - sluzby a konektory

Rozdeleni na sluzbu a konektor. Popis v 12-sluzby-a-konektory.md.

Slovo "konektor" driv v kodu znamenalo katalog toho, co umime. Ted znamena napojeni jedne firmy, tedy to, co tim mysli i uzivatel.

Pridano

  • src/data/services.ts: sluzba nese general, appId, visibility, credentials a verifyPath. Kategorie obecne sdruzuje veci, ktere ma kazdy a nepotrebuji konektor: webhook, planovac, tickety, transformace dat, HTTP pozadavek, pauza, log.
  • Viditelnost sluzby: vsichni, jen uvedene firmy a lide, nebo jen spravce platformy. Neviditelna sluzba se z API nevraci vubec.
  • src/data/connectorStore.ts: konektory za firmu vcetne hodnot pristupovych udaju. Hodnoty se z API nikdy nevraci, jen filled a missing.
  • FlowStep.connectorId: krok rika, pod kterym napojenim se ma volat. null = vychozi konektor firmy, takze vzorovy strom je prenositelny.
  • Overeni konektoru pres verifyPath, tedy cteci volani vyzadujici autorizaci. U sluzby bez nej se overi jen dostupnost a odpoved to rekne nahlas.
  • Stranky /dashboard/sluzby a /dashboard/konektory vcetne formularu udaju.
  • Endpointy /api/dashboard/services a CRUD /api/dashboard/connectors vcetne Swaggeru.
  • Predvyplnene prihlaseni spravcem platformy a prepinac demo uctu na login strance. Kvuli testovani prototypu, pred ostrym pouzitim odebrat.

Zmeneno

  • Pristupove udaje se prestaly cist z environment variables. Cela instance by mela jedny udaje spolecne a dve firmy by fakturovaly z jednoho uctu. Z prostredi zustava jen SERVICES_BASE_URL.
  • Stav "napojeno" se prestal cist z katalogu a zacal pocitat z konektoru firmy. Sluzba ma jen available nebo planned.
  • Prejmenovani napric kodem: Connector na Service, FlowStep.connectorId na serviceId, GET /connectors na GET /services, connectorIcons na serviceIcons, stranka Konektory (katalog) na Sluzby. Prevodni tabulka je v dokumentu 12.
  • Validace stromu overuje i konektor. Cizi konektor je chyba, chybejici napojeni nedodelek.

2026-08-12 - skripty konektoru

Naprogramovana vykonna cast konektoru. Popis je v 11-skripty-konektoru.md.

Pridano

  • scripts/ se skripty konektoru. Jeden soubor nese manifest (vstupni a vystupni parametry) i kod. Obycejny JavaScript, aby se nemusel prekladat.
  • Hot reload podle casu zmeny souboru. Uprava v portalu i rucni uprava souboru se projevi bez restartu.
  • Kontrola vstupu i vystupu proti manifestu, jedna funkce pro obe strany. Chybejici povinny vystup je chyba skriptu, ne uzivatele.
  • ctx predavany skriptu: http nad adresou napojeni, util, log, config, idempotencyKey, fail a retry. Skript nedostane pristupove udaje.
  • Rozliseni opakovatelne a koncove chyby. Runner nikdy nevyhodi vyjimku, vzdy vraci vysledek vcetne retryable.
  • Redakce tajnych hodnot pred zapisem do logu.
  • Napojeni z environment variables (src/scripts/connections.ts) vcetne iDokladu.
  • Sest ukazkovych skriptu pro iDoklad proti skutecnemu API sluzby services.csbot.cz/apps/idoklad, kazdy na jiny vzor.
  • Stranka /dashboard/skripty: seznam, manifest, editor, zkusebni spusteni. Formular testu se sklada z manifestu, nepise se pro kazdy skript.
  • Endpointy /api/dashboard/scripts, /:id, PUT /:id, /:id/test a /reload. Vse ve Swaggeru.

Zmeneno

  • Katalog konektoru uz neni jen staticky seznam. Akce ze skriptu se domeruji prekryvem v src/data/connectors.ts, takze se naraz objevi ve validaci stromu, ve vypoctu scope i v sablonach. Pri stejnem ID operace vyhrava skript.
  • ConnectorOperation ma implementation a scriptId. Katalog v portalu operace se skriptem oznacuje ikonou.
  • ApiError na klientovi nese cele telo odpovedi a umi z nej vytahnout issues.
  • Dockerfile kopiruje scripts/ do vysledneho image.

Vedome neudelano

Skripty bezi v procesu serveru, ne v sandboxu. Jsou nase a prosly gitem. Zakaznicke skripty budou potrebovat izolovany engine ve vlastnim vlakne, duvod je v 10-runtime-a-kapacita.md.

Ulozeni z portalu zapisuje do souboru v containeru. Bez trvaleho svazku ho redeploy vrati na verzi z gitu.

2026-08-12 - navrhy

Pridany 09-navrh-rozsireni.md a 10-runtime-a-kapacita.md.

09 popisuje datove modely: akce navazane na typ nebo tag ticketu s telem jako operaci, vlastnim stromem nebo skriptem, typy a tagy ticketu, role a prava jako data misto unionu, zalozky a zpristupneni konektoru za firmu, konektory rozdelene na definici, zpristupneni a napojeni, cekaci krok, sablony zprav, vlastni widgety se seskupovanim a prevod na Postgres. Soucasti je kontrola navrhu proti celemu prikladu se dvema firmami jednoho cloveka.

10 popisuje vykonnou cast: cestu udalosti od webhooku pres inbox a dispatcher k workeru, frontu v Postgresu se SKIP LOCKED, davkovy odber, spravedlnost mezi klienty, idempotenci, retence a rozpocet na 150 klientu ve dvou scenarich objemu.

Nic z toho neni naprogramovane, oba dokumenty jsou navrh k rozhodnuti. Kod se nemenil.

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.

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.

  • 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.

Nastavitelny dashboard

Prehled byl pevne dany. Ted si ho kazdy sklada sam, popis v 08-dashboard-widgety.md.

  • Katalog widgetu na serveru vcetne toho, ktere sirky ktery widget unese. Graf v tretine sloupce se necte, proto se tam ani nenabizi.
  • Rezim uprav na /dashboard: pridani z nabidky, vyber sirky, poradi sipkami, odebrani. Ulozi se az tlacitkem, Zrusit vrati puvodni stav.
  • Rozlozeni se uklada za dvojici uzivatel a firma, ne jen za uzivatele.
  • Data nacita prehled a rozdava je widgetum. Deset dlazdic tak neznamena deset stejnych dotazu.
  • Server rozlozeni overuje proti katalogu. Neznamy widget nebo nepodporovana sirka se neulozi, widget zmizely z katalogu se v prehledu ukaze jako chyba, ne ze tise zmizi.

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.

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 <base> 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 <base>,
  • 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.