Commit Graph
12 Commits
Author SHA1 Message Date
JiriUhlirandClaude Opus 5 3279dd7dac Cele chybove hlaseni u konektoru i skriptu
U odpovedi 401 nebo 400 je duvod napsany v tele odpovedi sluzby, ne v tom, ze
prislo 401. Dosud se telo zkracovalo na 400 znaku a u overeni konektoru se
zahazovalo cele - zbyla veta "Pristup zamitnut", podle ktere se neda hledat.

- ScriptError nese `request` (metoda a cesta) a `detail` s celou odpovedi
  sluzby, zkracenou az na SCRIPT_ERROR_DETAIL_BYTES (vychozi 8 kB). Chyby jsou
  vzacne, takze objem neroste jako u logu uspesnych kroku
- do detailu jde surove telo, ne prochazene pres JSON.stringify. U chyby chceme
  presne to, co sluzba poslala, vcetne HTML nebo prosteho textu
- u chyby spojeni se pridava i `cause`, u neocekavane vyjimky zasobnik volani
  (mimo produkci, stejne jako u centralniho error handleru)
- overeni konektoru vraci `detail`, `status` i `request`
- cely detail jde i do logu serveru, at je to dohledatelne bez portalu
- do chyby se dava jen cesta, ne cela adresa: v query muze byt tajemstvi
- nova komponenta ErrorDetail: rozbaleni cele odpovedi a tlacitko Kopirovat vse

Overeno: npm run typecheck prochazi na serveru i webu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:38:43 +02:00
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
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
JiriUhlirandClaude Opus 5 6f6b287d7e Skripty konektoru: vykonna cast s manifestem a kontrolou parametru
Konektory dostaly vykonnou cast. Jeden skript je jeden soubor, ktery nese
manifest (vstupni a vystupni parametry) i kod. Diky manifestu s nim umi
pracovat strom automatizace, aniz by o kodu cokoliv vedel.

Soubory jsou zamerne obycejny JavaScript, ne TypeScript. TypeScript by se
musel prelozit a to je presne to otaceni, ktere tady nema byt. Registr
sleduje cas zmeny souboru, takze uprava v portalu, rucni uprava souboru
i novy soubor ve slozce funguji stejne a bez restartu.

Pridano:
- scripts/ se skripty konektoru, nazev souboru je zaroven ID operace
- kontrola vstupu i vystupu proti manifestu, jedna funkce pro obe strany.
  Chybejici povinny vystup je chyba skriptu, ne uzivatele - jinak by strom
  veril parametru, ktery nikdy nedosel
- 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. Cizi API rado vraci prijaty
  token v chybove zprave a log ticketu vidi klient
- napojeni z environment variables 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 vcetne 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 vyhrava skript
- ConnectorOperation ma implementation a scriptId
- ApiError na klientovi nese cele telo odpovedi a umi z nej vytahnout issues
- Dockerfile kopiruje scripts/ do vysledneho image

Ukladani nemuze rozbit fungujici skript: kod se nejdriv zapise do docasneho
souboru, ten se nacte a overi, a az pak prepise puvodni.

K tomu tri dokumenty navrhu dalsich kroku: 09 datove modely a prava,
10 runtime a rozpocet na 150 klientu, 11 popis skriptu konektoru.

Overeno: npm run typecheck prochazi na serveru i webu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 13:37:58 +02:00
JiriUhlir bbc2236c0d dashboard widgets 2026-08-03 13:10:41 +02:00
JiriUhlirandClaude Opus 5 2a3d75c85e Firmy a prava: tenance napric portalem
Portal nemel zadnou tenanci. Kterykoliv prihlaseny uzivatel videl vsechny
tickety vsech firem i cely seznam resitelu, requireRole se nikde nevolal.

Tenant je hranice viditelnosti, tenantId na ticketu, resiteli i automatizaci.
Uzivatel muze patrit do vic firem, v kazde s jinou roli. Pristup napric firmami
je zvlast jako platformAdmin.

Tri pohledy na tickety: all, tenant, mine. Admin mezi nimi prepina vcetne
vyberu firmy. O pravech rozhoduje jedine data/access.ts, klient si nic
nedovozuje a bere je z GET /api/dashboard/access.

Filtr na firmu je v ulozistich povinny argument, takze zapomenuty filtr
neznamena vse, ale nezkompiluje se. Cizi firma vraci 403 nebo 404, nikdy
tise zuzeny vysledek.

Prirazeni jen v ramci firmy. Prehazovat praci mezi lidmi smi jen admin,
agent si smi vzit ticket na sebe.

Zmena prihlasovani: ucet klient@firma.cz zanikl, demo ucty jsou nove.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:59:30 +02:00
JiriUhlirandClaude Opus 5 dd021b5f69 Obsah ticketu, nastaveni kroku a vystupy kroku
Ticket dostal telo (body) a odkaz na zdrojovou zpravu. Predmet je shrnuti,
telo je cely text pozadavku.

Akce maji nastavitelna pole (inputs) se sablonami {{parametr}}. Zatim ticket,
kanaly, CRM a AI, ostatni maji jen napovedu.

Krok vidi parametry spoustece plus vystupy kroku pred nim, takze jde vlozit
predvalidaci a vetvit se podle jejiho vysledku. Vetev podminky nepridava nic
do sekvence za podminkou.

Nove konektory Facebook Messenger a Instagram, nova akce RAYNET Dohledat firmu.

Ctyri vzorove automatizace v rozdeleni jedna na kanal pro prijem
a jedna spolecna pro smerovani na resitele.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:29:26 +02:00
JiriUhlir 52b190bfbc updated tickets 2026-08-03 11:45:35 +02:00
JiriUhlir 9a0c67af08 Odstraneni docasnych souboru z testovaciho behu 2026-07-31 17:05:01 +02:00
JiriUhlir e177ca2087 Oprava: aplikace padala pri startu v produkcnim rezimu
Dockerfile nastavuje NODE_ENV=production a config.ts pri chybejicim
JWT_SECRET vyhazoval vyjimku. AppFactory tu promennou nastavenou nema,
takze se container po startu ukoncil a sluzba byla nedostupna (502).

Chybejici JWT_SECRET uz start neshodi. Vygeneruje se nahodny klic platny
do restartu containeru a do logu jde varovani. Klic zapsany v kodu se
nepouziva, aby nevznikla bezpecnostni dira.

Dusledek: bez nastavene promenne prestanou po restartu platit vydane
tokeny. JWT_SECRET se ma nastavit jako promenna aplikace v AppFactory.
2026-07-31 17:04:32 +02:00
JiriUhlir 7b045a9f20 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/.
2026-07-31 17:00:37 +02:00
AppFactory Bot 46f2f0b07e Initial Node.js TypeScript service 2026-07-31 14:42:26 +00:00