Files
csbot-prototype/documentation/99-zmeny.md
T
JiriUhlirandClaude Opus 5 ad56c7f513 Transformace dat, oprava ukladani udaju konektoru
Transformace dat ve dvou rezimech plus oprava chyby, kvuli ktere se neukladaly
pristupove udaje konektoru. Popis v documentation/13-transformace-dat.md.

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

Dva rezimy transformace, oba nad enginem v src/scripts/mapping.ts:
- transform.map-fields: pole na pole s prevody, klikatelne
- transform.to-json: sablona cileveho objektu s ${cesta}

Marker ${...} je zamerne jiny nez {{...}}. Sablony kroku se dosazuji driv, nez
krok bezi, takze {{total}} by strom stihl vyhodnotit, nenasel by parametr toho
jmena a dosadil by prazdno. Cely retezec navic zachova typ, takze
"unitPrice": "${total}" vyrobi cislo - jinak by cizi sluzba dostala castku jako
text a odmitla ji.

Prevod map pro seznamy je to, bez ceho by priklad nesel dokoncit. Bez nej jde
prevest hlavicku dokladu, ale ne polozky objednavky, a doklad by byl na nulu.

Dal pridano:
- idoklad.create-invoice-from-object: druha polovina prikladu, bere hotove telo
  dokladu z transformace a doplni povinna pole ze vzoru iDokladu
- spoustec e-shopu predava celou objednavku jako objekt a polozky jako seznam
- klikaci editor pravidel vcetne rezimu JSON pro vnorena pravidla u map
- 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, overeno
volanim POST i PATCH. 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.

Overeno: npm run typecheck prochazi na serveru i webu, node --check na skriptech.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:32:39 +02:00

16 KiB

99 - Zaznam zmen

Nejnovejsi nahore.

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.