Files
csbot-prototype/documentation/04-api.md
T
JiriUhlirandClaude Opus 5 8ad91a6c28 Rozdeleni na sluzby a konektory, pristupove udaje do konektoru
Slovo "konektor" v kodu znamenalo katalog toho, co umime. Ted znamena napojeni
jedne firmy, tedy to, co tim mysli i uzivatel. Popis modelu je
v documentation/12-sluzby-a-konektory.md.

Tri vrstvy:
- Sluzba: ze iDoklad existuje, co umi a co potrebuje k napojeni. Nase.
- Skript: kod, ktery jednu operaci sluzby opravdu vykona. Nas.
- Konektor: ucet firmy vcetne jejich pristupovych udaju. Firemni.

Pristupove udaje se prestaly cist z environment variables. Cela instance by
mela jedny udaje spolecne a dve firmy by fakturovaly z jednoho uctu. Napojeni
je vlastnost firmy, ne prostredi. Z prostredi zustava jen SERVICES_BASE_URL.

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, zapis do logu
- viditelnost sluzby: vsichni, jen uvedene firmy a lide, nebo jen spravce
  platformy. Neviditelna sluzba se z API nevraci vubec, ne se stavem 403 -
  firma nema poznat, ze takova sluzba existuje
- src/data/connectorStore.ts: konektory za firmu vcetne hodnot udaju. Hodnoty
  se z API nikdy nevraci, jen filled a missing. Prazdne pole hodnotu nemeni,
  takze ulozeni formularu bez tajnych hodnot nic nepresepe
- FlowStep.connectorId: krok rika, pod kterym napojenim volat. null = vychozi
  konektor firmy, diky tomu je vzorovy strom prenositelny mezi firmami
- overeni konektoru pres verifyPath, tedy cteci volani vyzadujici autorizaci.
  U sluzby bez nej se overi jen dostupnost a odpoved to rekne nahlas, jinak by
  zeleny vysledek uzivateli lhal
- stranky /dashboard/sluzby a /dashboard/konektory vcetne formularu udaju
- endpointy /api/dashboard/services a CRUD /api/dashboard/connectors ve Swaggeru
- predvyplnene prihlaseni spravcem platformy a prepinac demo uctu na login
  strance, kvuli testovani prototypu

Zmeneno:
- stav "napojeno" se prestal cist z katalogu a zacal pocitat z konektoru firmy.
  Sluzba ma jen available nebo planned
- validace stromu overuje i konektor. Cizi konektor je chyba, chybejici
  napojeni nedodelek - rozdelana prace se nezahazuje
- 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

Overeno: npm run typecheck prochazi na serveru i webu.

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

9.6 KiB

04 - API

Interaktivni dokumentace je na /apps/<app-id>/docs. Tenhle soubor popisuje to, co ze Swaggeru neni videt.

Endpointy

Verejne:

Metoda Cesta Popis
GET /health health check
GET /docs Swagger UI
GET /openapi.json OpenAPI definice
POST /api/auth/login prihlaseni, vraci JWT
POST /api/contact poptavka z webu
POST /webhook/:token prijem dat do automatizace

Vyzaduji Authorization: Bearer <token>:

Metoda Cesta
GET /api/auth/me
POST /api/auth/logout
GET /api/dashboard/access
GET /api/dashboard/widgets
GET /api/dashboard/layout
PUT /api/dashboard/layout
DELETE /api/dashboard/layout
GET /api/dashboard/summary
GET /api/dashboard/people
GET /api/dashboard/tickets
GET /api/dashboard/tickets/workload
GET /api/dashboard/tickets/:id
POST /api/dashboard/tickets/:id/assign
POST /api/dashboard/tickets/:id/status
POST /api/dashboard/tickets/:id/comment
GET /api/dashboard/incidents
GET /api/dashboard/services
GET /api/dashboard/connectors/services
GET /api/dashboard/connectors
POST /api/dashboard/connectors
GET /api/dashboard/connectors/:id
PATCH /api/dashboard/connectors/:id
DELETE /api/dashboard/connectors/:id
POST /api/dashboard/connectors/:id/test
GET /api/dashboard/scripts
GET /api/dashboard/scripts/:id
PUT /api/dashboard/scripts/:id
POST /api/dashboard/scripts/:id/test
POST /api/dashboard/scripts/reload
GET /api/dashboard/stream
GET /api/dashboard/automations
POST /api/dashboard/automations
GET /api/dashboard/automations/:id
PUT /api/dashboard/automations/:id
DELETE /api/dashboard/automations/:id
POST /api/dashboard/automations/:id/webhook/regenerate
POST /api/simulate

Format chyb

Jednotny pro cele API:

{ "error": "validation_error", "message": "Zadejte platny e-mail." }
HTTP error Kdy
400 validation_error vstup neprosel schematem
401 unauthorized chybi nebo neplatny token
401 invalid_credentials spatny e-mail nebo heslo
403 forbidden nedostatecna role
404 not_found zaznam nebo endpoint neexistuje
409 ruzne operace nedava v danem stavu smysl
500 internal_error neodchycena chyba, detail jen mimo produkci

message je vzdy cesky a je urcena k zobrazeni uzivateli.

Autentizace

Hesla se hashuji bcryptem, plaintext se nikde neuklada. Login vraci JWT podepsany JWT_SECRET s platnosti JWT_EXPIRES_IN.

Spatne heslo i neexistujici e-mail vraci stejnou odpoved, aby se neprozradilo, ktere ucty existuji. Pokus se loguje bez hesla.

Token si drzi klient v localStorage. Pro produkci je cilovy stav httpOnly cookie se Secure a SameSite plus CSRF token.

Zivy stream

GET /api/dashboard/stream je Server-Sent Events. Po pripojeni posle potvrzeni a poslednich par udalosti, pak uz jen nove. Kazdych 25 sekund jde komentarovy radek, aby spojeni neuspalo proxy.

Typy udalosti: ticket.created, ticket.updated, ticket.assigned, ticket.resolved, incident.started, incident.updated, incident.resolved, automation.created, automation.updated, automation.deleted, automation.run, webhook.received.

Klient se pripojuje pres fetch s hlavickou Authorization, ne pres EventSource. Duvod je v 03-architektura-a-mapa-kodu.md.

Webhook

Verejny endpoint bez prihlaseni. Autorizuje neuhodnutelny token v adrese, 32 znaku z randomBytes(24) v base64url.

Token generuje vyhradne server. Hodnota webhookToken poslana klientem se ignoruje, jinak by si sel nastavit predvidatelnou adresu.

Situace Odpoved
vse v poradku 202
neznamy token 404
automatizace je pozastavena 409
chybi povinny parametr, spatny typ 400

Parametry navic se neodmitaji, jen loguji. Odesilatele bezne posilaji i vlastni data a odmitat je by rozbijelo integrace.

curl -X POST https://services.csbot.cz/apps/<app-id>/webhook/<token> \
  -H "Content-Type: application/json" \
  -d '{"customer":"Nordis","score":18}'

Prototyp pozadavek prijme, zvaliduje a zapocita do metrik, ale strom akci nevykona - runtime neexistuje.

Firmy a pohledy

Prava popisuje 07-firmy-a-prava.md, tady jen API.

Endpointy dashboardu berou scope (all, tenant, mine) a tenantId. GET /api/dashboard/access rekne, co uzivatel smi, aby to klient nedovozoval.

Pozadavek na pohled nebo firmu bez opravneni vraci 403 nebo 404, nikdy tise zuzeny vysledek. Uzivatel nesmi koukat na cizi cisla v domneni, ze jsou spravna.

Tickety

Popis modelu je v 06-tickety.md, tady jen to, co se tyka API.

GET /api/dashboard/tickets bere navic filtry assignee, status, channel. U assignee je zvlastni hodnota unassigned pro frontu bez resitele. U pohledu mine se assignee ignoruje, pohled je silnejsi. Neznama hodnota filtru se zaloguje a ignoruje - je lepsi ukazat vic ticketu nez prazdny seznam bez vysvetleni.

Odpoved nese vedle items jeste meId. Klient podle nej pozna, ktere tickety jsou jeho, a jestli ma vubec smysl nabizet filtr "moje".

Filtrovani dela server, ne klient. Seznam a prehled vytizeni tak nikdy neukazuji jina cisla. Vyhledavaci pole v portalu je jina vec - to jen dohledava v uz nactenem seznamu.

GET /api/dashboard/tickets/:id vraci navic trace, tedy log prubehu vcetne toho, co ktera volana sluzba vratila.

POST /api/dashboard/tickets/:id/assign s telem {"assigneeId": null} vrati ticket do fronty. Neznamy resitel vraci 404, ne tiche odpojeni.

Simulace

POST /api/simulate vyvola provozni udalost pro nahled ziveho dashboardu. Zamerne meni skutecna data, ne jen posila falesnou notifikaci.

Akce: ticket.created, ticket.resolved, incident.started, incident.resolved, automation.run.

U ticket.created urcuje channel (whatsapp, facebook, instagram, email, voice, form, portal), odkud pozadavek prisel, a podle toho se poskladá i log ticketu. knownCustomer: false znamena, ze CRM firmu nedohleda - ticket zustane bez zakaznika i bez resitele a v logu je videt proc.

Nevyplnena pole server doplni ukazkovou hodnotou. U akci s "resolved" se bez zadaneho id pouzije prvni nevyrizeny zaznam.

Sluzby a konektory

Popis modelu je v 12-sluzby-a-konektory.md, tady jen API.

Sluzba je to, co umime. Konektor je napojeni jedne firmy vcetne jejich pristupovych udaju.

Hodnoty pristupovych udaju se nikdy nevraci, jen filled a missing. V PATCH staci poslat jen to, co se meni: prazdny retezec hodnotu smaze, chybejici klic ji nechava.

Sluzba, kterou uzivatel nevidi, se nevraci vubec, ne se stavem 403.

POST /connectors/:id/test vraci 200 i pri neuspechu. checked rika, co se vlastne overilo - u sluzby bez verifyPath jen dostupnost, ne udaje.

Skripty konektoru

Popis modelu je v 11-skripty-konektoru.md, tady jen API.

Cteni smi kazdy prihlaseny, protoze builder potrebuje vedet, co skript umi. Uprava, zkusebni spusteni a vynucene nacteni smi jen spravce platformy - uprava skriptu meni chovani vseho, co ho pouziva.

GET /api/dashboard/scripts vraci vedle manifestu i problems s rozbitymi skripty a connections se stavem napojeni. Hodnoty pristupovych udaju se nevraci nikdy, jen jmena chybejicich environment variables.

PUT /api/dashboard/scripts/:id kod nejdriv nacte a overi a az pak prepise soubor. Rozbita uprava vraci 400 s issues a puvodni skript dal funguje.

POST /api/dashboard/scripts/:id/test vola opravdovou sluzbu. Chyba skriptu neni chyba API, vraci se 200 a popis v error vcetne toho, jestli ma smysl zkusit to znovu.

Pri pridani endpointu

Soucasne aktualizovat src/openapi.ts a tenhle soubor. Swagger musi odpovidat skutecnemu chovani aplikace, jinak je horsi nez zadny.