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>
This commit is contained in:
JiriUhlir
2026-08-12 14:11:50 +02:00
co-authored by Claude Opus 5
parent 6f6b287d7e
commit 8ad91a6c28
37 changed files with 3006 additions and 776 deletions
+2 -1
View File
@@ -17,7 +17,7 @@ React aplikaci ze slozky `dist/public`.
| Dashboard | hotovo | prehled, tickety, incidenty, automatizace, nastaveni |
| Zivy dashboard pres SSE | hotovo | zmeny se projevi bez obnoveni stranky |
| Simulace provozu | hotovo | tlacitko v postrannim menu portalu |
| Katalog konektoru | hotovo | 29 sluzeb, 9 kategorii |
| Katalog sluzeb | hotovo | 29 sluzeb, 7 kategorii vcetne Obecne |
| Builder automatizaci | hotovo | strom akci, vetveni podminkou |
| Webhook s registrovanou adresou | hotovo | token generuje server, verejny endpoint validuje data |
| Tickety na konkretni lidi | hotovo | resitel, filtr moje, prehled vytizeni tymu |
@@ -31,6 +31,7 @@ React aplikaci ze slozky `dist/public`.
| Firmy a prava | hotovo | tri pohledy, uzivatel muze byt ve vic firmach |
| Nastavitelny dashboard | hotovo | widgety, sirky a poradi, ulozene za uzivatele a firmu |
| Skripty konektoru | hotovo | manifest, kontrola parametru, hot reload, iDoklad |
| Konektory za firmu | hotovo | pristupove udaje v konektoru, overeni napojeni |
| Sprava clenstvi z portalu | chybi | memberships jdou zmenit jen v kodu |
| Bugs a wishes | chybi | vyvojarska agenda, samostatna evidence vedle ticketu |
| Beh automatizaci | chybi | ulozeny strom se nevykonava, neni runtime |
+23
View File
@@ -36,7 +36,14 @@ Vyzaduji `Authorization: Bearer <token>`:
| 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` |
@@ -171,6 +178,22 @@ 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](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](11-skripty-konektoru.md), tady jen API.
+22 -27
View File
@@ -5,7 +5,7 @@ v [09-navrh-rozsireni.md](09-navrh-rozsireni.md), bod 9.
## Co to je
Skript je **vykonna cast konektoru**. Jeden soubor, ktery nese dve veci:
Skript je **vykonna cast sluzby**. Jeden soubor, ktery nese dve veci:
- **manifest** - jak se operace jmenuje, co potrebuje na vstupu, co vraci na vystupu,
- **kod** - co se ma opravdu udelat.
@@ -24,7 +24,7 @@ scripts/ soubory skriptu, obycejny JavaScript
src/scripts/types.ts co je skript, zod schema manifestu
src/scripts/values.ts kontrola vstupu a vystupu
src/scripts/util.ts pomocne funkce pro skripty, redakce tajemstvi
src/scripts/connections.ts kam se vola a cim se to autorizuje
src/scripts/connections.ts kam se vola a cim se to autorizuje (podle konektoru)
src/scripts/http.ts HTTP klient predany skriptu
src/scripts/manifest.ts overeni manifestu, prevod na operaci katalogu
src/scripts/registry.ts nacitani ze souboru, hot reload, ukladani
@@ -53,19 +53,19 @@ Uprava tedy funguje trema cestami a vzdy stejne:
## Nazev souboru je ID
Soubor se jmenuje `<konektor>.<operace>.js` a `manifest.id` musi byt stejne.
Soubor se jmenuje `<sluzba>.<operace>.js` a `manifest.id` musi byt stejne.
Nesoulad je chyba, ne varovani - jinak by se skript ulozil pod jednim jmenem
a nacetl pod druhym.
```
scripts/idoklad.get-issued-invoice.js
\_____/ \________________/
konektor operace
sluzba operace
```
Z ID se dopocita, do ktereho konektoru operace patri, takze se to nepise
dvakrat. Konektor **musi existovat** v `src/data/connectors.ts`, jinak se skript
ohlasi jako problem.
Z ID se dopocita, do ktere sluzby operace patri, takze se to nepise dvakrat.
Sluzba **musi existovat** v `src/data/services.ts`, jinak se skript ohlasi
jako problem.
## Manifest
@@ -178,27 +178,23 @@ existovat runtime automatizaci, bude tohle jeho jediny vstupni bod na kroku.
## Napojeni
Zatim jedno napojeni na konektor, sestavene z environment variables. Cilovy stav
je napojeni za firmu v databazi, viz bod 9 navrhu. Az to bude, prepise se vnitrek
`resolveConnection` a nic dalsiho.
Skript se k pristupovym udajum nedostane. Adresu i hlavicky doplnuje runtime
podle **konektoru** firmy, popis je v [12-sluzby-a-konektory.md](12-sluzby-a-konektory.md).
Z environment variables uz nechodi zadne pristupove udaje, jen provozni
nastaveni:
| Promenna | K cemu |
| --------------------------- | --------------------------------------------------- |
| `SERVICES_BASE_URL` | zaklad adres, vychozi `https://services.csbot.cz/apps` |
| `<KONEKTOR>_BASE_URL` | presmerovani jednoho konektoru |
| `IDOKLAD_CLIENT_ID` | povinne pro iDoklad, jde do `X-ClientId` |
| `IDOKLAD_CLIENT_SECRET` | povinne pro iDoklad, jde do `X-ClientSecret` |
| `IDOKLAD_APPLICATION_ID` | jen partnerske aplikace |
| `<SLUZBA>_BASE_URL` | presmerovani jedne sluzby |
| `SCRIPTS_DIR` | jina slozka se skripty |
| `SCRIPT_TIMEOUT_MS` | vychozi strop na beh, 15000 |
| `SCRIPT_MAX_RESPONSE_BYTES` | strop na velikost odpovedi, 1000000 |
| `ALLOW_PRIVATE_TARGETS` | povoli volani na localhost, **jen pro lokalni vyvoj** |
Autorizace konektoru je popsana v `authSpecs` v `src/scripts/connections.ts`.
Novy konektor s pristupovymi udaji znamena jeden zaznam v teto tabulce.
**Hodnoty se z API nikdy nevraci.** `GET /api/dashboard/scripts` posila jen jmena
chybejicich promennych a jmena vyplnenych hlavicek, nikdy hodnoty (AGENTS.md).
Co ktera sluzba vyzaduje, je v `credentials` u sluzby v `src/data/services.ts`.
Hodnoty patri konektoru a zadavaji se v portalu.
## Redakce tajemstvi
@@ -226,16 +222,16 @@ o skriptech.
## Napojeni do katalogu
Skript se domeri do katalogu konektoru jako akce s `implementation: 'script'`
Skript se domeri do katalogu sluzeb jako akce s `implementation: 'script'`
a `scriptId`. Kdyz nese ID operace, ktera uz v katalogu je, **skript vyhrava** -
staticky zapis je popis toho, co umime, skript je to, co se opravdu stane.
Prekryv drzi `src/data/connectors.ts` (`setScriptActions`, `actionsFor`).
Prekryv drzi `src/data/services.ts` (`setScriptActions`, `actionsFor`).
Je to zamerne tam, protoze vsechno ostatni se uz pta pres `findOperation`.
Tim se skripty naraz objevi ve validaci stromu, ve vypoctu toho, co je v kterem
kroku videt, i v sablonach - bez toho, aby se to psalo trikrat.
V portalu jsou operace se skriptem oznacene ikonou v katalogu konektoru.
V portalu jsou operace se skriptem oznacene ikonou v katalogu sluzeb.
## API
@@ -292,13 +288,13 @@ cele je.
## Jak pridat skript
1. Zkopirovat `scripts/_sablona.js` na `<konektor>.<operace>.js`.
1. Zkopirovat `scripts/_sablona.js` na `<sluzba>.<operace>.js`.
2. Srovnat `manifest.id` s nazvem souboru.
3. Vyplnit `inputs` a `outputs`.
4. Napsat `run`.
5. Kdyz konektor jeste neni v `src/data/connectors.ts`, pridat ho.
6. Kdyz potrebuje pristupove udaje, pridat zaznam do `authSpecs`
v `src/scripts/connections.ts`.
5. Kdyz sluzba jeste neni v `src/data/services.ts`, pridat ji.
6. Kdyz potrebuje pristupove udaje, popsat je v `credentials` u te sluzby.
Hodnoty pak zada firma v konektoru.
Katalog, builder i stranka skriptu si ho vezmou samy. Nic se nerestartuje.
@@ -306,7 +302,6 @@ Katalog, builder i stranka skriptu si ho vezmou samy. Nic se nerestartuje.
| Chybi | Poznamka |
| ---------------------------- | --------------------------------------------------- |
| Napojeni za firmu | zatim jedno na konektor z environment variables |
| Skripty od zakazniku | potrebuji sandbox a vlastni vlakno, viz vyse |
| Verzovani skriptu | uprava prepise soubor, historie je jen v gitu |
| Vykonavani ze stromu | runner je hotovy, ale runtime automatizaci neni |
+216
View File
@@ -0,0 +1,216 @@
# 12 - Sluzby a konektory
Naprogramovano. Popis vykonne casti sluzeb je
v [11-skripty-konektoru.md](11-skripty-konektoru.md).
## Tri vrstvy a co je co
Slovo "konektor" driv v kodu znamenalo katalog toho, co umime. Ted znamena
napojeni jedne firmy. Rozdeleni je takove:
| Vrstva | Co to je | Kdo to vlastni |
| ----------- | --------------------------------------------------- | -------------- |
| **Sluzba** | ze iDoklad existuje, co umi a co potrebuje k napojeni | my |
| **Skript** | kod, ktery jednu operaci sluzby opravdu vykona | my |
| **Konektor**| ucet firmy vcetne jejich pristupovych udaju | firma |
Sluzba tedy rika "iDoklad chce hlavicky `X-ClientId` a `X-ClientSecret`",
konektor rika "a tohle jsou nase".
```
Sluzba iDoklad definujeme my
| credentials: X-ClientId, X-ClientSecret
| skripty: get-issued-invoice, create-issued-invoice, ...
|
+-- Konektor "iDoklad Celo" zaklada si firma Celo
| values: clientId=..., clientSecret=...
|
+-- Konektor "iDoklad Delo" jina firma, jine udaje
```
Krok automatizace pak nese oboji: **kterou operaci** (`serviceId` plus
`operationId`) a **pod cim ji zavolat** (`connectorId`).
## Pristupove udaje patri konektoru, ne prostredi
Driv se cetly z environment variables. To bylo spatne: cela instance by mela
jedny udaje spolecne a dve firmy by fakturovaly z jednoho uctu. Napojeni je
vlastnost firmy, ne prostredi.
Z prostredi proto zustava jen `SERVICES_BASE_URL`, tedy zaklad adres. Zadne
pristupove udaje.
Pravidla, ktera se u toho nesmi porusit:
- **Hodnoty se z API nikdy nevraci.** Odpoved nese `filled` (co je vyplnene)
a `missing` (ktera povinna pole chybi), nikdy hodnoty. Tajne pole se z portalu
jen zapisuje.
- **Prazdne pole hodnotu nemeni.** Ulozeni formulare, ktery tajne hodnoty
neposila, tedy nic nepresepe. Smazat hodnotu jde poslanim prazdneho retezce.
- **Volani vzdy dela server.** Z prohlizece by to znamenalo poslat pristupove
udaje do prohlizece, a stejne by to neproslo - sluzby kontroluji IP.
- **Redakce v logu.** Nez cokoliv skonci v logu nebo v chybe, projde nahradou
znamych tajnych hodnot za hvezdicky.
- **Zmena udaju rusi predchozi overeni.** Konektor se vrati na `untested`,
jinak by zelena znacka lhala.
## Obecne sluzby
Kategorie `obecne`, priznak `general: true`. Jsou dostupne vsem, nepotrebuji
konektor a viditelnost se u nich neresi:
| Sluzba | K cemu |
| ----------------- | ------------------------------------------ |
| Webhook | prijem pozadavku zvenci |
| Planovac | spousteni podle casu |
| Rucni spusteni | tlacitko |
| Webovy formular | odeslani formulare |
| Tickety | servicedesk: zalozit, priradit, komentovat |
| Transformace dat | premapovani a cisteni mezi kroky |
| HTTP pozadavek | zavolani API, ktere vlastni sluzbu nema |
| Pauza | cekani |
| Zapis do logu | zaznam pro ladeni |
Duvod, proc je to zvlast kategorie a ne jen priznak: v builderu i v katalogu
je chce clovek videt pohromade a hned. Nejsou to integrace, jsou to stavebni
kameny.
## Viditelnost sluzby
```ts
interface ServiceVisibility {
mode: 'everyone' | 'restricted' | 'admin';
tenantIds: string[]; // jen u restricted
userIds: string[]; // jen u restricted, konkretni lide bez ohledu na firmu
}
```
| Mode | Kdo vidi |
| ------------ | ---------------------------------------------- |
| `everyone` | vsichni prihlaseni |
| `restricted` | uvedene firmy a jmenovite uvedeni lide |
| `admin` | jen spravce platformy |
Spravce platformy vidi vzdy vsechno. Obecne sluzby vidi vzdy vsichni.
**Sluzba, kterou uzivatel nevidi, se nevraci vubec.** Ne se stavem "nemate
pravo" - firma nema z odpovedi poznat, ze takova sluzba existuje. Je to stejne
pravidlo jako u ticketu v [07-firmy-a-prava.md](07-firmy-a-prava.md).
V katalogu je jako ukazka `polstryn-sap`, ktery vidi jen LogiTrans. Ostatni
firmy ho v odpovedi nedostanou.
## Stav se prestal cist a zacal pocitat
Driv byl v katalogu `status: 'connected' | 'available' | 'planned'`. Prvni
hodnota tam nepatrila: jestli je sluzba napojena, je vlastnost **firmy**, ne
sluzby.
Sluzba proto ma jen `available` nebo `planned` a portal si stav dopocita:
| Co uzivatel vidi | Kdy |
| ------------------ | -------------------------------------------------- |
| Napojeno | obecna sluzba, nebo firma ma aspon jeden konektor |
| Muzete napojit | sluzbu umime, firma konektor nema |
| Na roadmape | `status: 'planned'` |
| nic | sluzbu uzivatel nevidi, v odpovedi neni |
`GET /api/dashboard/connectors/services` proto vraci `connectorCount`.
## Vychozi konektor
Firma muze mit dva ucty teze sluzby. Krok stromu proto nese `connectorId`, ale
smi byt `null`:
- **`null`** znamena vychozi konektor firmy pro tuhle sluzbu. Diky tomu je
vzorovy strom prenositelny - kazde firme se dosadi jeji vlastni napojeni.
- **Vyplnene** je potreba, kdyz firma ma dva ucty a zalezi na tom, ktery.
Prvni konektor na sluzbu se stane vychozim sam. Kdyz vychozi zmizi, prevezme to
prvni zbyly - jinak by kroky bez vyberu prestaly fungovat, aniz by se cokoliv
jineho zmenilo.
## Validace stromu
| Situace | Vysledek |
| ------------------------------------------- | --------- |
| Krok odkazuje na neexistujici sluzbu/operaci | chyba 400 |
| Krok odkazuje na cizi konektor | chyba 400 |
| Konektor patri jine sluzbe nez krok | chyba 400 |
| Sluzba neni obecna a firma nema konektor | nedodelek |
| Konektor existuje, ale chybi mu udaje | nedodelek |
Cizi konektor je chyba, ne nedodelek: strom, ktery by volal cizim jmenem, se
nesmi ulozit. Chybejici napojeni je naopak nedodelek - rozdelana prace se
nezahazuje, jen automatizace nepujde zapnout.
## Overeni konektoru
Sluzba muze deklarovat `verifyPath`, tedy levne **cteci** volani vyzadujici
autorizaci. iDoklad ma `/account/agenda`.
Kdyz ho sluzba nema, overi se jen `/health`. Odpoved to v `checked` rekne
nahlas - test, ktery projde i se spatnymi udaji, by uzivateli rikal nepravdu.
Neuspesne overeni **neni chyba API**. Vraci se 200 s `ok: false` a popisem,
protoze vysledek "nefunguje to" je platna odpoved na otazku "funguje to?".
## API
| Metoda | Cesta | Popis |
| ------ | ----------------------------------------- | ---------------------------- |
| GET | `/api/dashboard/services` | katalog pro builder |
| GET | `/api/dashboard/connectors/services` | katalog ocima firmy |
| GET | `/api/dashboard/connectors` | konektory firmy |
| POST | `/api/dashboard/connectors` | zalozit |
| GET | `/api/dashboard/connectors/:id` | detail |
| PATCH | `/api/dashboard/connectors/:id` | upravit |
| DELETE | `/api/dashboard/connectors/:id` | smazat |
| POST | `/api/dashboard/connectors/:id/test` | overit napojeni |
## Stranky portalu
```
/dashboard/sluzby katalog: co umime, co uz mate napojene
/dashboard/konektory napojeni teto firmy, formulare udaju, overeni
/dashboard/skripty vykonna cast sluzeb
```
## Jak pridat sluzbu
1. Zaznam do `services` v `src/data/services.ts`: kategorie, ikona, `general`,
`appId`, `visibility`, `credentials`, pripadne `verifyPath`.
2. Pokud pouziva novou ikonu, doplnit klic do `web/src/lib/serviceIcons.ts`.
3. Skripty operaci do `scripts/<sluzba>.<operace>.js`, viz
[11-skripty-konektoru.md](11-skripty-konektoru.md).
Katalog, builder, stranka Sluzby i zakladani konektoru si ji vezmou samy.
## Co se prejmenovalo
Kdo se v kodu orientoval podle stareho pojmenovani:
| Driv | Ted |
| ----------------------------- | ------------------------------ |
| `src/data/connectors.ts` | `src/data/services.ts` |
| `Connector`, `ConnectorOperation` | `Service`, `ServiceOperation` |
| `connectorCategories` | `serviceCategories` |
| `findConnector` | `findService` |
| `FlowStep.connectorId` | `FlowStep.serviceId` |
| `GET /api/dashboard/connectors` | `GET /api/dashboard/services` |
| `web/src/lib/connectorIcons.ts` | `web/src/lib/serviceIcons.ts` |
| stranka Konektory (katalog) | stranka Sluzby |
`Connector` a `connectorId` v kodu ted znamenaji napojeni firmy, tedy to, co
tim mysli i uzivatel.
## Co chybi
| Chybi | Poznamka |
| ---------------------------- | ----------------------------------------------------- |
| Databaze a sifrovani udaju | hodnoty jsou v pameti procesu, restart je smaze |
| Nastaveni viditelnosti z portalu | `visibility` jde zmenit jen v kodu |
| Zamek pri soubeznem overovani| dva testy tehoz konektoru si prepisou stav |
| Historie zmen konektoru | kdo kdy prepsal udaje, se nikde neuklada |
| OAuth toky | zatim jen hlavicky, obnovovani tokenu resi sluzba |
| Vyber konektoru v builderu | krok uz `connectorId` nese, UI ho zatim nenabizi |
+42
View File
@@ -2,6 +2,48 @@
Nejnovejsi nahore.
## 2026-08-12 - sluzby a konektory
Rozdeleni na sluzbu a konektor. Popis
v [12-sluzby-a-konektory.md](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