Kontrakt webhooku: objekt jde vybrat a odmitnuti je videt

Parametr spoustece `data` byl deklarovany jako type string a povinny, zatimco
odesilatel ho posila jako objekt a v prvni zprave hovoru ho jeste nema. Kazde
volani proto skoncilo na 400 a automatizace hodinu nedelala nic.

Za tim byly tri veci, kazda sama o sobe malicherna:

- rucne pridany parametr byl vychozi povinny, zatimco parametr odvozeny
  z ukazkoveho tela nepovinny. Dve ruzna vychozi nastaveni pro tutez vec
  v jednom formulari. Nove je nepovinny i rucne pridany: povinny znamena
  "odmitni volani" a do toho nema nikdo spadnout omylem
- objekt a seznam neslo vybrat. declarableFieldTypes nabizel jen string, number,
  boolean a date, a TriggerConfig.tsx mel jeste treti kopii toho seznamu.
  Deklarovat data jako objekt tedy neslo, i kdyz matchesType objekt umi
  a operatorsByType pro nej ma operatory
- odmitnuti nebylo nikde videt. Skoncilo jako console.warn v logu kontejneru:
  zadna udalost, zadny beh, nic na detailu automatizace

Ten treti bod je ten podstatny. Chybu v kontraktu udela ten, kdo ho psal, ale
400 dostane odesilatel - a ten s tim nic nenadela, casto je to cizi sluzba,
ktera volani neopakuje. Majitel automatizace se nedozvi nic a v portalu vypada
vsechno v poradku.

Detail automatizace proto ukazuje poslednich deset volani: cas, jestli proslo
nebo ne, a u odmitnutych duvod. Telo se schvalne neuklada, duvod uz rika, co je
spatne, a drzet payloady by znamenalo mit v pameti kopie zakaznickych dat.
Seznam je v pameti, restart ho zahodi. Incident se z toho nezaklada
a upozorneni se neposila: staci radek, implementator se ozve sam.

Vzorova automatizace ma data opravene na object a nepovinne.

Do navrhu 25 jsou zapsana rozhodnuti z diskuze: "moje tickety" jsou tickety
prirazene mne, v helpdesku ty, ktere jsem zalozil ja, a helpdeskove pozadavky
vidi lide podle teze hierarchie jako tickety. Sekce 6 popisuje tuhle zmenu.

Overeno na bezici instanci s vlastnim DATA_DIR: telo s data jako objektem
projde, prvni zprava hovoru s data null projde, telo bez callSid se dal odmita,
a vsechna tri jsou videt v seznamu poslednich volani.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-09-02 10:14:48 +02:00
co-authored by Claude Opus 5
parent 72da07debe
commit e8bb4d6e54
8 changed files with 302 additions and 41 deletions
+78 -27
View File
@@ -1,8 +1,9 @@
# 25 - Navrh: pristupny portal a viditelnost
**Navrh, ne popis stavu. Nic z toho zatim neni naprogramovane.** Az se cast
udela, prepise se do prislusneho souboru dokumentace a odsud zmizi. Stejne
pravidlo jako u [09-navrh-rozsireni.md](09-navrh-rozsireni.md).
**Navrh, ne popis stavu.** Jedina hotova cast je sekce 6, ostatni zatim
naprogramovane neni. Az se cast udela, prepise se do prislusneho souboru
dokumentace a odsud zmizi. Stejne pravidlo jako
u [09-navrh-rozsireni.md](09-navrh-rozsireni.md).
Popis soucasneho stavu je v [01-prehled-a-stav.md](01-prehled-a-stav.md), prava
a pohledy v [07-firmy-a-prava.md](07-firmy-a-prava.md), widgety
@@ -390,6 +391,19 @@ jinak -> moje tickety
Posledni radka je rozhodnuti, ne odvozeni: bez ni nema vedouci co rozdelovat,
protoze neprirazeny ticket nepatri nikomu.
**"Moje" znamena prirazene mne.** Nic vic: ne zalozene mnou, ne komentovane
mnou. Ticket, ktery clovek zapsal po telefonu a predal dal, uz neni jeho -
prave o tom predani slo.
V **helpdesku** je to naopak: tam jsou "moje" ty pozadavky, ktere jsem **zalozil
ja**. Neni to vyjimka z pravidla, je to tentyz pohled z druhe strany. Zadavatel
pozadavek nikdy nema prirazeny, protoze ho resi nekdo jiny, a helpdeskove
pozadavky se automaticky vazou na hlavni firmu.
Kdo pozadavky v helpdesku vidi, se ridi **toutez hierarchii** jako u ticketu:
firemni priznak, pak skupiny, jinak svoje. Helpdesk tedy nema vlastni pravidlo
viditelnosti, jen jinou definici toho, co je "moje".
### Past: dve identity
Projekt ma **uzivatele** (kdo se prihlasi) a **resitele** (na koho jde ticket),
@@ -474,6 +488,58 @@ nem neda nic overit do hloubky.
---
## 6 - Kdyz kontrakt nesedi na data (hotovo)
Jedina cast, ktera uz naprogramovana **je**. Je tady proto, ze patri ke stejne
tride problemu jako zbytek: konfigurace je formalne v poradku a pritom nesedi na
skutecna data.
### Jak to vypadalo
Parametr spoustece `data` byl deklarovany jako `type: string, required: true`,
zatimco odesilatel ho posila jako objekt a v prvni zprave hovoru ho jeste nema.
Kazde volani proto skoncilo na 400 a automatizace hodinu nedelala nic.
Za tim byly tri veci a kazda z nich sama o sobe malicherna:
1. **Rucne pridany parametr byl vychozi povinny**, zatimco parametr odvozeny
z ukazkoveho tela nepovinny. Dve ruzna vychozi nastaveni pro tutez vec
v jednom formulari.
2. **Objekt a seznam neslo vybrat.** `declarableFieldTypes` je nabizel jen
`string`, `number`, `boolean` a `date`, a klient mel jeste svoji treti kopii
toho seznamu. Deklarovat `data` jako objekt tedy neslo, i kdyz `matchesType`
objekt umi a `operatorsByType` pro nej ma operatory.
3. **Odmitnuti nebylo nikde videt.** Skoncilo jako `console.warn` v logu
kontejneru: zadna udalost, zadny beh, nic na detailu automatizace.
Ten treti bod je ten podstatny. Chybu v kontraktu udela ten, kdo ho psal, ale
**400 dostane odesilatel** - a ten s tim nic nenadela, casto je to cizi sluzba,
ktera volani neopakuje. Majitel automatizace se nedozvi nic a v portalu vypada
vsechno v poradku.
### Co se zmenilo
- **Novy parametr je nepovinny.** Povinny znamena "odmitni volani" a do toho
nema nikdo spadnout omylem. Zaskrtnout to jde vzdycky.
- **Objekt a seznam jdou vybrat.** `declarableFieldTypes` je ma a klient si uz
nedrzi vlastni kopii, bere sdileny seznam.
- **Poslednich deset volani je videt na detailu automatizace.** Cas, jestli
proslo nebo ne, a u odmitnutych duvod.
Telo se **schvalne neuklada**. Duvod odmitnuti uz rika, co je spatne ("Parametr
data ma mit typ string"), a drzet payloady by znamenalo mit v pameti kopie
zakaznickych dat, aniz by o tom kdokoliv vedel. Seznam volani se drzi v pameti,
restart ho zahodi - je to diagnostika posledni hodiny, ne historie.
### Co se tim nedela
Nezaklada se incident, neposila se upozorneni. Staci radek: kdyz se
implementator ozve, ze mu neco nesedi, je tady videt co. Rozsirit se to da
pozdeji, ale kazda dalsi vrstva stoji za to az ve chvili, kdy tenhle seznam
prestane stacit.
---
## Poradi praci
1. **Formularove primitivy** a rozdeleni dvou formularu (ticket, helpdesk). Nic
@@ -500,34 +566,19 @@ Postgres kdykoliv mezi tim, nezavisle na ostatnim.
- **Strankovani seznamu ticketu** zmeni chovani dnesniho klientskeho hledani. Musi
jit ruku v ruce se serverovym hledanim, ne pred nim.
## Rozhodnuto
- **"Moje tickety" jsou tickety prirazene mne.** V helpdesku ty, ktere jsem
zalozil ja. Podrobnosti v sekci 4, cast "Vypocet stropu".
- **Helpdeskove pozadavky vidi lide podle teze hierarchie** jako tickety, tedy
firemni priznak, pak skupiny, jinak svoje.
- **Odmitnuta volani webhooku maji byt videt na automatizaci**, staci radek
s casem a duvodem. Uz je to hotove, viz sekce 6.
## Otevrene otazky
U kazde jde o rozhodnuti, ktere se z modelu neda odvodit.
### A - Co znamena "moje tickety" pro strop
Tri odpovedi, lisi se v tom, kdy clovek o ticket prijde z dohledu:
| Varianta | Dusledek |
| ---------------------------------- | --------------------------------------------------------------- |
| jen prirazene mne | pracovnik zalozi ticket po telefonu, preda ho a hned o nem nevi |
| prirazene plus zalozene mnou | vidi i to, co poslal dal |
| prirazene, zalozene i komentovane | vidi vse, ceho se dotkl |
Ticket dnes nenese, kdo ho zalozil rucne (`automationId` je jen u automatickych),
takze druha a treti varianta znamenaji nove pole na ticketu.
### B - Helpdesk a strop
Firma A posle pozadavek firme B. Zadavatel u firmy A ho vidi pres
`helpdeskSourceId`, i kdyz ticket vlastni firma B. Zadavatel neni resitel a neni
v zadne skupine, takze strop na nej nesedi.
Nabizi se, ze helpdeskovy pohled ma vlastni pravidlo ("vidim, co moje firma
poslala") a strop se na nej nevztahuje. Otazka je, **kdo z firmy A to vidi**:
kazdy clen firmy, nebo jen ten, kdo pozadavek poslal? U firmy o peti lidech je
odpoved jina nez u firmy o padesati.
### C - Hledani v udalostech
Udalosti nesou cele prijate telo webhooku. Hledat v nem znamena hledat v datech,
+38
View File
@@ -2,6 +2,44 @@
Nejnovejsi nahore.
## 2026-09-02 - Kontrakt webhooku: objekt jde vybrat a odmitnuti je videt
Parametr spoustece `data` byl deklarovany jako `type: string, required: true`,
zatimco odesilatel ho posila jako objekt a v prvni zprave hovoru ho jeste nema.
Kazde volani proto skoncilo na 400 a automatizace hodinu nedelala nic.
Za tim byly tri veci, kazda sama o sobe malicherna:
- **Rucne pridany parametr byl vychozi povinny**, zatimco parametr odvozeny
z ukazkoveho tela nepovinny. Dve ruzna vychozi nastaveni pro tutez vec
v jednom formulari. Nove je nepovinny i rucne pridany: povinny znamena
"odmitni volani" a do toho nema nikdo spadnout omylem.
- **Objekt a seznam neslo vybrat.** `declarableFieldTypes` nabizel jen `string`,
`number`, `boolean` a `date`, a `TriggerConfig.tsx` mel jeste treti kopii toho
seznamu. Deklarovat `data` jako objekt tedy neslo, i kdyz `matchesType` objekt
umi a `operatorsByType` pro nej ma operatory. Ted jsou v nabidce oba a klient
si vlastni kopii nedrzi.
- **Odmitnuti nebylo nikde videt.** Skoncilo jako `console.warn` v logu
kontejneru: zadna udalost, zadny beh, nic na detailu automatizace.
Ten treti bod je ten podstatny. Chybu v kontraktu udela ten, kdo ho psal, ale
**400 dostane odesilatel** - a ten s tim nic nenadela, casto je to cizi sluzba,
ktera volani neopakuje. Majitel automatizace se nedozvi nic a v portalu vypada
vsechno v poradku.
Detail automatizace proto ukazuje **poslednich deset volani**: cas, jestli
proslo nebo ne, a u odmitnutych duvod. Telo se schvalne neuklada, duvod uz rika,
co je spatne, a drzet payloady by znamenalo mit v pameti kopie zakaznickych dat.
Seznam je v pameti, restart ho zahodi - je to diagnostika posledni hodiny, ne
historie. Incident se z toho nezaklada a upozorneni se neposila: staci radek,
protoze implementator se ozve sam a tady je videt co.
Vzorova automatizace ma `data` opravene na `type: 'object', required: false`.
Overeno na bezici instanci s vlastnim DATA_DIR: telo s `data` jako objektem
projde, prvni zprava hovoru s `data: null` projde, telo bez `callSid` se dal
odmita - a vsechna tri jsou videt v seznamu poslednich volani.
## 2026-09-02 - Navrh: pristupny portal a viditelnost
Novy [25-navrh-pristupny-portal.md](25-navrh-pristupny-portal.md). Je to navrh,