Nahrazeni sablony kompletnim webem a klientskym portalem

Web a portal Automia v jednom containeru. Express obsluhuje API
i zbuildovanou React aplikaci z dist/public.

Obsah:
- verejny web: homepage, sluzby, o nas, kontakt, 404
- prihlaseni pres JWT, demo ucty
- portal: prehled s grafem, tickety, incidenty, automatizace, konektory
- builder automatizaci: strom akci, vetveni podminkou
- katalog 25 konektoru v 8 kategoriich
- webhook s registrovanou adresou, token generuje server
- zivy dashboard pres SSE vcetne simulace provozu
- Swagger UI na /docs a OpenAPI na /openapi.json

Soulad s AGENTS.md:
- ROOT_PATH z prostredi, prefix proxy nikde nehardcodovan
- mount na koren i na prefix, funguje s handle_path i bez nej
- base tag a window.__BASE_PATH__ vkladane do index.html za behu
- OpenAPI servers obsahuje prefix, Try it out vola spravnou adresu
- povinne /health a /docs, port 3000, naslouchani na 0.0.0.0
- secrets jen z environment variables, nikdy v logu

Dokumentace ve slozce documentation/.
This commit is contained in:
JiriUhlir
2026-07-31 17:00:37 +02:00
parent 46f2f0b07e
commit 7b045a9f20
100 changed files with 15409 additions and 35 deletions
+124
View File
@@ -0,0 +1,124 @@
# 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/summary` |
| GET | `/api/dashboard/tickets` |
| GET | `/api/dashboard/incidents` |
| GET | `/api/dashboard/connectors` |
| 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:
```json
{ "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.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](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.
```bash
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.
## 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`.
Nevyplnena pole server doplni ukazkovou hodnotou. U akci s "resolved" se bez
zadaneho id pouzije prvni nevyrizeny zaznam.
## Pri pridani endpointu
Soucasne aktualizovat `src/openapi.ts` a tenhle soubor. Swagger musi odpovidat
skutecnemu chovani aplikace, jinak je horsi nez zadny.