Multi-tržište: razdvojiti ili nastaviti? — plenum 5 stručnjaka (2026-08-19)
Bilko multi-tržište — plenum 5 stručnjaka: razdvojiti ili nastaviti? (2026-08-19)
Pitanje CEO-a: "Ovo s multi-tržištima će nas ujesti za guzicu. Pogledaj odluke o tome kako smo odlučili da dijelimo backend i što nas taj plan sad ubija. Odvajanje ili nastavak?"
Presuda: NE RAZDVAJATI. Jednoglasno, 5/5.
Sjedišta: arhitekt (Petter Graff, autor ADR-015) · HR porez i fiskalizacija · HR računovodstvo ·
podaci i distribuirani sistemi (Martin Kleppmann) · đavolji advokat.
Svi su radili nezavisno, s identičnim briefom, bez međusobnog dogovaranja.
Brief: ~/system/evidence/107158/plenum-brief-multimarket.md · nalazi: plenum-1..5-*.md
1. Brief je bio pogrešan i svih pet sjedišta ga je oborilo
Tvrdio sam da plugin arhitektura (ADR-015) postoji kao ljuštura koju niko ne koristi.
Netačno. Mjereno na azdo/main @ 0e3dcd04:
| provjera | rezultat |
|---|---|
git grep -l "CountryPlugin" |
30 fajlova |
git grep -l "PluginRegistry" |
24 fajla |
InvoiceService.kt |
8 pogodaka, pluginRegistry.resolve(country) na 4 mjesta |
ComplianceCalendarService.kt |
3 pogotka, HR PDV rokovi isključivo kroz PluginHR |
DI.kt 226–238 |
svih 5 jurisdikcija registrovano kroz Koin |
Greška je nastala jer je ispis skraćen na prvih osam redova — vidjeli su se samo pluginovi sami.
Brojanje umjesto čitanja, ista klasa greške kao s boot.sh dan ranije. Zabilježeno jer je to
obrazac koji se ponavlja, ne jednokratni previd.
2. Stvarni kvar je uzak, ne strukturni
PausalService.kt je goli Koin singleton izvan registryja. Napisan 2026-08-13 — tri mjeseca
poslije ADR-015, šest dana prije plenuma. Nije zatečeni legacy nego nov rad koji je zaobišao
mehanizam koji radi.
Ruta /compliance/pausal/* nema country-gate, a isti obrazac (SUPPORTED_COMPLIANCE_COUNTRIES)
postoji ~150 linija niže u istom fajlu za deadline rute.
Zašto ga ništa nije zaustavilo: ADR-015 §3.1 obećava Detekt CI pravilo protiv when(country)
grananja u servisima.
ISPRAVKA 2026-08-19 (poslije objave). Prvobitno je ovdje pisalo da
grep -i detekt azure-pipelines.ymldaje 0 pogodaka i da kapija ne postoji. To je netačno. Mjereno naazdo/main: 16 pogodaka zadetekt, 30 zaMC #106879, 10 zakover. Detekt je ožičen kao stvaran blokirajući korak (Gate: Detekt (MC #106879),Detekt static analysis (blocking, detekt-baseline.xml suppresses pre-existing debt)). Isto važi i zaintegrationTest known-failures baseline check (MC #106879, blocking)— živ je i radi: oborio je build 1180 na PR-u 367 zbog 11 stvarnih regresija.Greška je nastala jer je grep izveden nad glavnim checkoutom, koji je na grani druge sesije i zastario. Ista klasa greške koju je ovaj plenum ispravio u §1 — mjerenje nad pogrešnim stablom. MC #106879 jeste
paused, ali status zadatka ne opisuje stanje pipeline-a.
Prava, uža rupa: Detekt radi s aktivnim skupovima pravila potential-bugs i coroutines.
Pravilo koje bi uhvatilo baš ovaj slučaj — tržišna logika izvan PluginRegistry — nije napisano
kao Detekt pravilo. Sam pipeline to i kaže: CrossTenantNotChecked iz detekt.yml "is NOT a
real Detekt RuleSetProvider". Dakle nedostaje jedno custom pravilo, ne cijela kapija.
Petter Graff: "Razdvajanje liječi pogrešan organ."
3. Zašto razdvajanje (opcija B) nije odgovor
- Regulatorno ga ne traži nijedan propis. HR poreski stručnjak nije našao odredbu (Zakon o
računovodstvu, EN16931) koja zahtijeva odvajanje izvornog koda po jurisdikciji — reguliše se
revizijski trag transakcija, ne arhitektura softvera. eRačun kod je već fajlovski odvojen
(
country/hr/*vscountry/rs/*). - Baza nije rizik nego najbolje uređen dio sistema. 64 tabele imaju RLS, dvoslojno se provodi
(app
SET LOCAL app.current_org_id+ RLS). Nema nijednog cross-jurisdiction stranog ključa — nema šta da se "presiječe". Stvarni diskriminator jeorganizations.country, necountry_code. - Cijena je nesrazmjerna: org ima jedan self-hosted CI slot — tri backenda znače 3–5× serijalizaciju, uz umnoženu repo-nehigijenu.
- Tržišta pravno ne postoje odvojeno: nema HR pravnog entiteta (nema OIB), HR plaćanja idu preko ALAI Holding AS.
4. Šta je plenum iskopao usput — hitnije od arhitekture
a) Hrvatski eRačun je ISKLJUČEN na produkciji.
az containerapp show -n bilko-api-demo -g rg-bilko-demo → SVERACUN_HR_LIVE=false.
Obavezni B2B eRačun u HR važi od 2026-01-01 — sedam i po mjeseci. PluginHR kdoc i dalje navodi
provisioning prod tajni kao neriješen blokator.
Nesklad koji treba razriješiti: memo iz juna tvrdi da je vrijednost bila true i CEO-potvrđena,
uz napomenu "ne gasi je". Danas je false. Ko i kad — nepoznato, ne nagađa se.
b) Registracija ne kreira kontni plan.
AuthService.register() radi Organizations.insert i Users.insert, ali nikad Accounts.insert
(provjereno grepom, nula pogodaka). Punjenje postoji u CountryService iza CountryRoutes, ali nije
dio registracije. Ako ga onboarding ne zove, prvi sendInvoice() novog korisnika pada.
c) Revizija RLS-a je bila djelimična. 64 tabele imaju RLS; revidirane su 22. Fail-open rupa
zatvorena jutros (notifications, V104→V165, MC #106958) nađena je unutar tih 22 — 42 tabele niko
nije pregledao. Politike su i dalje PERMISSIVE, nikad prebačene na RESTRICTIVE.
d) Računovođin portal (AccountantContext.kt, X-Accountant-Org) ožičen je na ~10 ruta, a
vlastita dokumentacija kaže da je sigurnosna revizija obavezna prije produkcije. To je jedino
mjesto gdje identitet stvarno prelazi granicu organizacije. Curenje tamo nema vidljiv trag i može
otići u nepovratne eRačune prema FINA/SEF.
e) Dodatni servisi van registryja (nalaz đavoljeg advokata): CountryService (5 metoda s
when(country)), ReportingRoutes (when(orgMeta.country)), ReportService (0 pogodaka na
CountryPlugin). Dakle PausalService nije jedini — ali jeste jedini koji je procurio korisniku.
5. Odluka i redoslijed
Arhitektura se ne dira. Radi se opcija A — dovršiti ADR-015.
- Country-gate na
/compliance/pausal/*— obrazac postoji u istom fajlu (sati, ne dani) → URAĐENO isti dan: PR 367. KapijaintegrationTestga je oborila zbog 11 postojećih testova pisanih prije gate-a; popravka u toku. Odblokirati MC #106879 (Detekt CI gate)→ premašeno stvarnošću, vidi ispravku u §2. Detekt i integrationTest kapije su već žive i blokirajuće. Preostaje napisati jedno custom Detekt pravilo koje prijavljuje tržišno-specifičnu logiku izvanPluginRegistry.HrPausalServiceizaPluginHRs podacima iz NN (razredi 1–7, stopa 12%, prag 60.000 EUR — potvrđeno iz 5 NN dokumenata, dva nezavisna lanca)- Zamrznuti peto tržište dok kapija nije zelena u CI-u
- Prije svega gore: razriješiti
SVERACUN_HR_LIVEi kontni plan pri registraciji
6. Metodološka bilješka
Vrijednost plenuma nije bila u odgovoru na postavljeno pitanje — nego u tome što je pitanje bilo pogrešno postavljeno, i što je pet nezavisnih provjera to pokazalo prije nego je iko potrošio sedmice na razdvajanje.
Đavolji advokat je dobio izričit zadatak da obori brief i orkestratora, i uspio je u oba. Da je brief prihvaćen na riječ, danas bi počela reorganizacija arhitekture koja bi zaobišla stvarni uzrok: nedostajuću kapiju u CI-u, ne dijeljeni backend.
No comments to display
No comments to display