Revize projektu: prava, vykon, runtime, portal a ARES
Prava a bezpecnost: spravce firmy uz nemuze nastavit priznak spravce platformy ani clenstvi v cizi firme; pozvanky, konektory a automatizace kontroluji sve pravo; cizi firma v query je 404; zivy stream posila udalosti jen firmam, kterych se tykaji; akce nad ticketem maji kontrolu prava za firmu ticketu a strop viditelnosti; tokeny se nelogujou; limit pokusu na prihlaseni, kontakt a pozvanky; bezpecnostni hlavicky; zachyceni chyb v async handlerech; timing-safe porovnani tokenu. Vykon: audit neskenuje celou kolekci pri kazdem zapisu a konecne maze firemni zaznamy; ticket se uklada jednou misto trikrat; zapisy do Postgresu jsou serializovane podle ID; prava se pocitaji jednou na request; widgety nacitaji tickety jednou; strankovani seznamu; worker je pool misto kol; na webu udalost ze streamu neodmontuje stranku, dotazy maji spolecny debounce a cache, ciselniky drzi typovany sklad. Runtime: opakuji se jen chyby oznacene retryable; smycka nenarazi na strop 50 kroku (novy strop 1000 akci); podminka nad datem funguje; vystup MCP nastroje neprepisuje spoustec; sandbox skriptu firmy nejde opustit; MCP session id se drzi mezi volanimi; incident z kroku patri firme; jedno rozhodnuti o rezimu uloziste; snapshot neprepise soubor po chybe cteni. Refaktory: sdilene typy API v src/shared (web nic nekopiruje, osm rozjetych tvaru sjednoceno); spolecny modul net/guard pro volani ven; formularova vrstva ui/form; rozdeleni Connectors a FlowCanvas; jeden helper pro firmu z query, validaci a CRUD udalosti; pomucky ctx.util pro skripty konektoru; i18n verejneho webu vcetne anglictiny. Nova funkce: zalozeni firmy z registru ARES v Nastaveni (IC nebo nazev, dotazeni IC, DIC, sidla a pravni formy, vyber soucasnych statutarnich zastupcu a prokury, ucty spravce firmy s nahradnim e-mailem IC-poradi@placeholder.cz). Dokumentace: zaznam v 99-zmeny.md a aktualizace 15 dalsich dokumentu. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0c405ea55a
commit
104ae36783
@@ -1,21 +1,26 @@
|
||||
# 14 - Databaze
|
||||
|
||||
Naprogramovano a overeno. Zatim se ukladaji **konektory**, tedy pristupove udaje
|
||||
k sluzbam. Zbytek je v pameti procesu, poradi dalsich kroku je na konci.
|
||||
Naprogramovano a overeno. Uklada se vsechno: konektory, tickety, automatizace,
|
||||
incidenty, rozlozeni dashboardu, entity nastaveni, audit a notifikace.
|
||||
|
||||
Ukladat jde tremi zpusoby a rezim se vybira sam podle toho, co je k dispozici.
|
||||
|
||||
## Tri rezimy, jedno rozhrani
|
||||
## Tri rezimy, jedno rozhrani, jedno rozhodnuti
|
||||
|
||||
Rozdil se resi **na jednom miste**, v `src/data/connectorStore.ts`. Nikde jinde
|
||||
se nezjistuje, ktery rezim jede - kdyby se to rozlezlo po kodu, jedno misto by
|
||||
se zapomnelo a chovalo by se pak jinak nez zbytek.
|
||||
Rozdil se resi **na jednom miste**, v `initStores` v `src/data/store/index.ts`.
|
||||
Nikde jinde se nezjistuje, ktery rezim jede - kdyby se to rozlezlo po kodu,
|
||||
jedno misto by se zapomnelo a chovalo by se pak jinak nez zbytek.
|
||||
|
||||
| Rezim | Kdy | Prezije restart | Prezije redeploy |
|
||||
| ---------- | --------------------------------- | --------------- | ---------------- |
|
||||
| `postgres` | je `DATABASE_URL` i `SECRETS_KEY` | ano | ano |
|
||||
| `file` | neni databaze, ale je `DATA_DIR` | ano | **ne** |
|
||||
| `memory` | ani jedno, nebo nejde zapsat | ne | ne |
|
||||
Presne to se stalo: konektory mely vlastni rozhodnuti v `connectorStore.ts`
|
||||
s jinymi podminkami nez zbytek, takze konektory mohly jet z databaze a tickety
|
||||
ze souboru. Ted `connectorStore` jen vola `initStores` a rezim je **jeden pro
|
||||
vsechna uloziste**.
|
||||
|
||||
| Rezim | Kdy | Prezije restart | Prezije redeploy |
|
||||
| ---------- | --------------------------------------------------------- | --------------- | ---------------- |
|
||||
| `postgres` | je `DATABASE_URL`, migrace prosly a je cim sifrovat (`SECRETS_KEY`) | ano | ano |
|
||||
| `file` | neni databaze, ale je `DATA_DIR` | ano | **ne** |
|
||||
| `memory` | ani jedno, nebo nejde zapsat | ne | ne |
|
||||
|
||||
Rezim `file` je pro mockup. Filesystem containeru je docasny, takze soubor
|
||||
prezije restart procesu i containeru, ale nove nasazeni ho smaze. Je to
|
||||
@@ -87,8 +92,38 @@ Kdyby to byly dve implementace, jedna by se casem opravila a druha ne.
|
||||
| Slucovani zapisu | deset uprav za sebou znamena jeden zapis na disk |
|
||||
| Zapis pri ukonceni | `SIGTERM` dokonci rozepsany zapis, jinak by se posledni zmena ztratila |
|
||||
| Rozbity soubor | prejmenuje se na `.broken`, zaloguje a jede se s prazdnymi daty. Aplikace, ktera nenastartuje, je pro AppFactory nefunkcni sluzba |
|
||||
| Necitelny soubor | jen `ENOENT` je prvni start. Jina chyba cteni (prava, plny disk) **zamkne zapisy** a zaloguje se - jinak by se soubor s daty prepsal prazdnym |
|
||||
| Sifrovani | tajne hodnoty jsou v souboru zasifrovane, plaintext nikdy |
|
||||
|
||||
Rozdil mezi poslednimi dvema radky je zamer. Rozbity JSON je zalozeny bokem
|
||||
a nic se neztrati. Chyba cteni ale neznamena, ze data neexistuji - a start
|
||||
s prazdnem, ktery by je pri prvnim zapisu prepsal, je jedina cesta, jak
|
||||
o ne v rezimu `file` opravdu prijit.
|
||||
|
||||
## Vrstvy nad ulozistem
|
||||
|
||||
Dve obalky, kazda pro jiny druh dat (podrobne
|
||||
v [17-nastaveni-a-prava.md](17-nastaveni-a-prava.md)):
|
||||
|
||||
**`withCache`** pro entity, ktere se ctou pri kazdem requestu a meni zridka.
|
||||
Kopie v pameti, `byId` je `Map`. Vsechny cache jsou v registru
|
||||
(`src/data/store/cached.ts`): `refreshCache(kind)` obnovi jednu,
|
||||
`refreshAllCaches()` vsechny. Route nastaveni driv po kazdem zapisu obnovovala
|
||||
vsechny cache, ted jen entitu, do ktere psala (`bootstrapDataRefresh(route)`
|
||||
v `src/data/refresh.ts`). `listByTenant(tenantIds, sortBy)` je jeden filtr
|
||||
a razeni misto sedmi kopii v modulech.
|
||||
|
||||
**`withMirror`** pro provozni data: meni se v pameti, po zmene se zapise cely
|
||||
zaznam. Zapisy tehoz ID jsou **serazene za sebou** retezem promise. Bez toho
|
||||
mohl Postgres potvrdit dva `put` tehoz ticketu v opacnem poradi, nez prisly,
|
||||
a v tabulce zustala starsi verze - v pameti to nebylo videt, po restartu ano.
|
||||
Tickety navic slucuji vic zmen v jednom tiku do jednoho zapisu
|
||||
(`persist` / `flushPersist`).
|
||||
|
||||
**Audit** se jen pripisuje a oreza se davkou (`removeMany`) po 50 zapisech
|
||||
nebo nejvys jednou za minutu. Prvni verze mazala jen radky platformy
|
||||
(`tenantId: null`) a audit firem rostl donekonecna.
|
||||
|
||||
### Klic mimo databazi
|
||||
|
||||
Bez `SECRETS_KEY` si aplikace v rezimu `file` vygeneruje klic do
|
||||
@@ -221,10 +256,7 @@ Proti Postgresu 16 v kontejneru:
|
||||
|
||||
| Chybi | Poznamka |
|
||||
| ------------------------------------ | ----------------------------------------------------------------------------- |
|
||||
| Automatizace v ulozisti | dalsi na rade, je to to, co si clovek nastavi. Pujde do souboru i do databaze |
|
||||
| Rozlozeni dashboardu | male a samostatne, hned po automatizacich |
|
||||
| Tickety a incidenty | naposled, dnes je generuje simulace |
|
||||
| Uzivatele, firmy, resitele | v prototypu je to spis konfigurace nez data |
|
||||
| Fronta nad Postgresem | vyber behu je v pameti jedne instance, chce to `SKIP LOCKED` |
|
||||
| Sbernice udalosti pres LISTEN/NOTIFY | dnes `EventEmitter` v pameti jedne instance |
|
||||
| Vymena klice (rotace) | `v` je pripravene, prevod dat napsany neni |
|
||||
| Retence a partitionovani | az u tabulek behu, viz dokument 10 |
|
||||
|
||||
Reference in New Issue
Block a user