Files
csbot-prototype/documentation/03-architektura-a-mapa-kodu.md
T
JiriUhlirandClaude Fable 5.1 104ae36783 Revize projektu: prava, vykon, runtime, portal a ARES
Prava a bezpecnost: spravce firmy uz nemuze nastavit priznak spravce
platformy ani clenstvi v cizi firme; pozvanky, konektory a automatizace
kontroluji sve pravo; cizi firma v query je 404; zivy stream posila
udalosti jen firmam, kterych se tykaji; akce nad ticketem maji kontrolu
prava za firmu ticketu a strop viditelnosti; tokeny se nelogujou; limit
pokusu na prihlaseni, kontakt a pozvanky; bezpecnostni hlavicky;
zachyceni chyb v async handlerech; timing-safe porovnani tokenu.

Vykon: audit neskenuje celou kolekci pri kazdem zapisu a konecne maze
firemni zaznamy; ticket se uklada jednou misto trikrat; zapisy do
Postgresu jsou serializovane podle ID; prava se pocitaji jednou na
request; widgety nacitaji tickety jednou; strankovani seznamu; worker
je pool misto kol; na webu udalost ze streamu neodmontuje stranku,
dotazy maji spolecny debounce a cache, ciselniky drzi typovany sklad.

Runtime: opakuji se jen chyby oznacene retryable; smycka nenarazi na
strop 50 kroku (novy strop 1000 akci); podminka nad datem funguje;
vystup MCP nastroje neprepisuje spoustec; sandbox skriptu firmy nejde
opustit; MCP session id se drzi mezi volanimi; incident z kroku patri
firme; jedno rozhodnuti o rezimu uloziste; snapshot neprepise soubor
po chybe cteni.

Refaktory: sdilene typy API v src/shared (web nic nekopiruje, osm
rozjetych tvaru sjednoceno); spolecny modul net/guard pro volani ven;
formularova vrstva ui/form; rozdeleni Connectors a FlowCanvas; jeden
helper pro firmu z query, validaci a CRUD udalosti; pomucky ctx.util
pro skripty konektoru; i18n verejneho webu vcetne anglictiny.

Nova funkce: zalozeni firmy z registru ARES v Nastaveni (IC nebo nazev,
dotazeni IC, DIC, sidla a pravni formy, vyber soucasnych statutarnich
zastupcu a prokury, ucty spravce firmy s nahradnim e-mailem
IC-poradi@placeholder.cz).

Dokumentace: zaznam v 99-zmeny.md a aktualizace 15 dalsich dokumentu.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 10:26:07 +02:00

11 KiB

03 - Architektura a mapa kodu

Technologie

Vrstva Technologie
Server Node.js 20, Express 4, TypeScript, ESM
Web React 18, Vite 6, TypeScript, Tailwind 4, React Router 6
Auth JWT (jsonwebtoken), hesla bcrypt
Validace zod
Docs swagger-ui-express nad rucne psanou OpenAPI definici

Jeden package.json. Runtime zavislosti jsou v dependencies, nastroje pro build webu v devDependencies - runtime image je pak instaluje pres --omit=dev.

Build

tsc   src/**.ts   ->  dist/*.js
vite  web/        ->  dist/public/

Server obsluhuje dist/public jako statiku. Dockerfile kopiruje do vysledneho image jen dist, takze staci jedna slozka.

Mapa kodu - server

Cesta K cemu je
src/index.ts vstupni bod: middleware, mount routeru, statika, SPA, Swagger
src/config.ts cteni environment variables, normalizace ROOT_PATH
src/openapi.ts OpenAPI definice vcetne servers s prefixem proxy
src/types.ts typy uzivatele a JWT payloadu
src/shared/ ciste typove moduly API, jediny zdroj typu pro server i web
src/middleware/auth.ts requireAuth, requireRole, requirePlatformAdmin
src/middleware/asyncHandler.ts wrap, safeRouter: odchyceni odmitnute promise v handleru
src/middleware/tenant.ts attachAccess, tenantOrDeny, scopeOrDeny: firma requestu na jednom miste
src/middleware/rateLimit.ts limit requestu v pameti, 429 s Retry-After
src/middleware/validation.ts validationError, jeden tvar chyby validace
src/lib/secure.ts timingSafeEqualString pro tokeny v adrese
src/net/guard.ts kontrola adresy, cteni tela s limitem, popis chyby site - pro vsechno, co vola ven
src/events/bus.ts sbernice udalosti, ze ktere cerpa SSE stream, udalost nese firmu
src/routes/auth.ts prihlaseni, odhlaseni, kdo jsem
src/routes/dashboard.ts data portalu, tickety, behy, CRUD automatizaci
src/routes/ticketActions.ts akce nad ticketem vcetne vestavenych, pravo za firmu ticketu
src/routes/settings.ts CRUD entit pres crud.ts, uzivatele, ARES
src/routes/ares.ts firma z registru ARES, jen spravce platformy
src/routes/connectors.ts konektory firmy, overeni, nastroje MCP
src/routes/stream.ts SSE stream zmen, filtr podle firem uzivatele
src/routes/webhook.ts verejny prijem dat do automatizace
src/routes/contact.ts poptavkovy formular z webu
src/ares/client.ts klient verejneho API ARES
src/data/store/ tri rezimy uloziste, withCache, withMirror, initStores
src/data/snapshot.ts atomicky zapis JSONu pro rezim file
src/data/ticketStore.ts tickety, jejich resitele, log prubehu, prehled vytizeni
src/data/people.ts resitele ticketu - oddeleni od uzivatelu portalu
src/data/tenants.ts firmy, ktere portal pouzivaji, vcetne udaju z ARES
src/data/access.ts kdo co vidi - jedno misto pro cely portal
src/data/widgets.ts katalog widgetu prehledu
src/data/dashboardLayouts.ts rozlozeni dashboardu za dvojici uzivatel a firma
src/data/incidentStore.ts incidenty vcetne zmen a udalosti, filtr na firmu povinny
src/data/automationStore.ts automatizace, strom akci, tokeny webhooku
src/data/services.ts katalog sluzeb, jejich spousteču a akci
src/data/conditions.ts typy parametru a operatory podminek
src/data/templates.ts sablony {{parametr}} v nastaveni kroku
src/data/flowScope.ts co je videt v kterem miste stromu
src/data/users.ts uzivatele portalu, demo ucty
src/data/mock.ts souhrn pro prehled a casova rada grafu
src/runtime/ fronta, worker, executor stromu, vestavene kroky, sandbox skriptu firmy
src/scripts/ skripty konektoru: registr, runner, HTTP, pomocne funkce
src/mcp/ klient MCP, prihlaseni, dialekty, errors.ts se spolecnou chybou prihlaseni

Mapa kodu - web

Cesta K cemu je
web/src/main.tsx vstupni bod, basename routeru podle prefixu proxy
web/src/App.tsx routovani, portal se nacita lazy
web/src/index.css design tokeny a vlastni utility Tailwindu
web/src/config/brand.ts vsechny firemni udaje na jednom miste
web/src/lib/api.ts fetch wrapper, sprava tokenu, skladani adres, auth:expired na 401
web/src/lib/eventStream.ts cteni SSE streamu pres fetch
web/src/lib/useApiQuery.ts nacitani dat, cache, spolecny debounce, refreshing misto odmontovani
web/src/lib/collections.tsx klientsky sklad ciselniku za firmu, opravovany z udalosti
web/src/lib/ticketEvents.ts oprava seznamu ticketu z payload.ticket bez dotazu
web/src/lib/useSubmit.ts odeslani formulare: saving, chyba, reset na jednom miste
web/src/lib/options.ts pevne ciselniky (priority)
web/src/lib/useUnsavedChanges.ts varovani pri odchodu z rozepsaneho formulare
web/src/lib/flow.ts ciste funkce nad stromem automatizace
web/src/types/ fasada nad src/shared (alias @shared/*), zadne vlastni typy API
web/src/components/ui/ zakladni prvky, Chip
web/src/components/ui/form/ Field, Input, Select, Textarea, controlClass: jedna sada trid
web/src/components/dashboard/ shell portalu, dlazdice, graf, stream, TicketCard
web/src/components/dashboard/flow/ strom akci: FlowCanvas a karty ActionCard, ConditionCard, ForeachCard, StepControls
web/src/components/dashboard/TicketTrace.tsx log ticketu jako strom
web/src/components/dashboard/TicketWorkload.tsx prehled, kdo co ma u sebe
web/src/components/home/ sekce homepage
web/src/pages/ jedna stranka je jeden soubor
web/src/pages/dashboard/connectors/ casti stranky Konektory: karta, editor, log, nastroje

Klicova rozhodnuti

Jeden container misto dvou. AppFactory nasazuje jednu aplikaci, proto Express obsluhuje i statiku. Odpada CORS i druha deploy jednotka.

SSE misto WebSocketu. Tok dat je jednosmerny, server ke klientovi. Klient posila zmeny beznym REST volanim. SSE prochazi reverse proxy bez zvlastni konfigurace.

Stream pres fetch, ne pres EventSource. EventSource neumi poslat hlavicku Authorization a token by musel byt v adrese, odkud se dostane do access logu. Cenou je rucni parsovani a rucni znovupripojeni v web/src/lib/eventStream.ts.

Ceske cesty v URL. /sluzby, /o-nas, /prihlaseni, /dashboard/tickety. Kod zustava anglicky.

Uloziste je za rozhranim. Tri rezimy (Postgres, soubor, pamet), jedno rozhrani a jedno rozhodnuti v initStores. Routy nevedi, ktery rezim jede. Podrobnosti v 14-databaze.md.

Typy API jsou jednou. Ciste typove moduly v src/shared ctou server i web, web pres alias @shared/*. Kopie typu na klientovi se jednou rozejde se serverem a prekladac to nepozna. web/src/types/ je jen fasada, ktera je re-exportuje; ucet uzivatele bere i AuthContext ze @shared/users.

Kazdy async handler je odchyceny. Routy vznikaji pres safeRouter, odmitnuta promise skonci jako 500 s logem, ne padem procesu. Bez toho stacil jeden zapomenuty try a AppFactory restartovala container.

Firma requestu se pocita jednou. attachAccess da do req.access, co uzivatel smi, a tenantOrDeny z toho odvodi firmu. Kazda route, ktera si to pocitala sama, to delala trochu jinak.

Filtr na firmu je povinny argument. listTickets, listPeople i listAutomations vyzaduji tenantIds. Zapomenuty filtr tak neznamena "vse", ale nezkompiluje se. Podrobnosti v 07-firmy-a-prava.md.

Prava se nikdy nedovozuji na klientovi. Server vraci GET /api/dashboard/access s tim, co uzivatel smi. Kdyby si to klient pocital sam, pocitalo by se to na dvou mistech a jednou se to rozejde.

Resitel neni uzivatel. Uzivatel se prihlasuje do portalu, resitel ma u sebe tickety. Technik muze mit tickety a ucet nikdy nemit. Spojka je e-mail, podrobnosti v 06-tickety.md.

Filtrovani ticketu dela server. Klient posila query parametry a dostane hotovy seznam. Kdyby filtroval sam, ukazoval by jina cisla nez prehled vytizeni.

Krok vidi jen to, co je pred nim. Parametry spoustece plus vystupy predchozich kroku. Vetev podminky nepridava nic do sekvence za podminkou, protoze nemusela probehnout. Vypocet je v flowScope.ts, priklady v 06-tickety.md.

Sablony odkazuji jmenem, ne ID. Opak podminek, a je to zamer: {{subject}} uzivatel napise a precte, {{f_42}} ne. Rozbite odkazy po prejmenovani se hlasi jako nedodelek.

Zadna ticha selhani. Kazdy catch loguje a uzivatel se o chybe dozvi.