{"id":"c0161","filename":"c0161_vetra_produkcija_evalidator_bridge.dok.json","weise3_id":"","tip":"plan","naziv":"c0161 — vetra.live Produkcija + evalidator KrunicaChain Bridge","kreator":"Ivan Brtan + CC","datum":"2026-05-08","snippet":"","status":"ZAVRSENO","prev_weise3":"","bunker_l":"#00d4ff","full":{"tip":"plan","naziv":"c0161 — vetra.live Produkcija + evalidator KrunicaChain Bridge","sto_treba":"1. Pokrenuti vetra.live u produkciju (BILLING_ENABLED, email, Stripe). 2. Spojiti KrunicaChain: jedna istina za vetra.live i evalidator.eu — svaki VetraDocument kreira DokArh entry.","kreator":"Ivan Brtan + CC","datum":"2026-05-08","prioritet":"P0 paralelno s c0160","ne_dira":["sati.ink worktime","fina-connect","arhiva PWA"],"kontekst":{"vetra_stanje":"LIVE (upravo startana 2026-05-08, bila inactive 2 dana). 3 tenanta, 57 dok, 5 KrunicaChain blokova.","billing":"BILLING_ENABLED=False u .env — naplata isključena, plan upgrades ne rade","email":"smtp.gmail.com:587 konfiguriran s fina.connect.online@gmail.com, ali EMAIL_HOST_PASSWORD nije u .env — nedostaje","evalidator_dokarh":"DokArh model postoji u fenix-v3/evalidator/models.py (1 zapis). Ima payload_hash, envelope_hash, chain integrity, Polygon fields.","krunica_chain":"vetra.live ima vlastiti KrunicaChain (5 blokova, zasebna baza). evalidator.eu ima ChainBlockPOE (76 blokova). NISU SPOJENI.","veza_konjik":"vetra.live billing ide kroz Konjik d.o.o. (OIB 37590751921, IBAN HR8223900011101356183) — VEĆ implementirano u billing/views.py"},"faze":[{"id":"V0","naziv":"Vetra EMAIL aktivacija (blocker za sve ostalo)","opis":"Bez emaila ne rade: registracija, invite, billing obavijesti.","koraci":["Gmail App Password: Ivan otvori myaccount.google.com → Security → 2-Step Verification → App Passwords → kreirati za 'vetra-live-smtp'","Upisati u /var/www/vetra/.env: EMAIL_HOST_PASSWORD=<app_password>","Test: cd /var/www/vetra && venv/bin/python3 manage.py shell -c \"from django.core.mail import send_mail; send_mail('vetra test', 'radi', 'noreply@vetra.live', ['nolimit.vladislavci@gmail.com'])\"","systemctl restart gunicorn-vetra.service"],"blokira":"Registracija novih korisnika, billing obavijesti, invite flow"},{"id":"V1","naziv":"BILLING_ENABLED = True","opis":"Uključi naplatu. Konjik d.o.o. SEPA model (bez Stripe — commitment document protokol).","koraci":["/var/www/vetra/.env: BILLING_ENABLED=True","Provjeri da Plan Prices u billing/models.py odgovaraju: free=0, starter=19, pro=79, enterprise=custom","Test: tenant upgrade flow na http://127.0.0.1:8003/dashboard/billing/upgrade/","Provjeri da VetraCommitment kreira .dok bundle s Ed25519 + ML-DSA potpis","Provjeri SEPA reference format: HR99-{seal[:8]}","systemctl reload gunicorn-vetra.service"],"napomena":"Stripe = buduće. Sada je SEPA commitment document — Konjik šalje PDF račun, klijent uplaćuje, admin potvrđuje VetraPaymentProof."},{"id":"V2","naziv":"status.vetra.live SSL certifikat","opis":"status.vetra.live nginx redirect radi ali nema SSL. Treba DNS A zapis + certbot.","koraci":["IVAN: Dodati DNS A zapis za status.vetra.live → 37.27.248.86 (isti IP kao server)","Čekati DNS propagaciju (~5 min)","certbot --nginx -d status.vetra.live","nginx restart","Test: https://status.vetra.live/ → mora raditi bez SSL warning"],"ivan_akcija":"DNS A zapis status.vetra.live → 37.27.248.86"},{"id":"V3","naziv":"evalidator KrunicaChain Bridge — arhitektura","opis":"Svaki zapečaćeni dokument na vetra.live automatski kreira DokArh entry na evalidator.eu. Jedna istina za oba sustava.","arhitektura":{"trigger":"Nakon VetraDocument seal (status=done) → async task → evalidator bridge","flow":["1. VetraDocument.status = 'done' → Celery task: sync_to_evalidator.delay(doc_id)","2. Task čita VetraDocument: sha3_256, seal, file_name, tenant, ocr data","3. HTTP POST na https://evalidator.eu/api/v1/archive/ingest/ s API key","4. evalidator kreira DokArh: dok_type='archive_entry', payload_hash=sha3_256, issuer_name=tenant.name","5. evalidator vraća: dok_id, weise3_id, chain_block_num, verify_url","6. VetraDocument.evalidator_dok_id = dok_id (novo polje)","7. VetraDocument.chain_block_num = chain_block_num (novo polje — alias na evalidator chain)"],"jedna_istina":"vetra.live KrunicaChain ostaje za interne pozicije. evalidator ChainBlockPOE = javna istina. VetraDocument.evalidator_dok_id je most."}},{"id":"V4","naziv":"evalidator novi API endpoint /archive/ingest/","opis":"Fenix-v3 evalidator app dobiva novi javni API endpoint koji prima dokumente od vanjskih sustava (vetra, sati.ink, genesispos, tahograf).","koraci":["ZAKON 3 OBAVEZNO: Nakon DokArh.objects.create() ODMAH pozovi get_trojna().pohrani_async() — bez toga dokument nije u lancu!","fenix-v3/evalidator/views.py: nova klasa ArchiveIngestView","Auth: API key u Authorization header (EvalidatorKey model već postoji!)","Request: POST /api/v1/archive/ingest/ → payload_hash(sha3_256), file_name, dok_type, issuer_name, amount, currency, country","Response: {dok_id, weise3_id, chain_block_num, verify_url, bunker_seal_id}","DokArh.weise3_id: SHA3-256('WEISE3::{payload_hash}::{issuer_name}::archive::FENIX2026') — ZAKON 27","DokArh.bunker_seal_id: kreirati BunkerSeal L0-L8 za dokument","DokArh.prev_dok_hash: atomičan sequence_num + link na prethodni DokArh","Registrirati u config/urls.py: path('api/v1/archive/ingest/', ArchiveIngestView.as_view())","Rate limit: 100 req/min po API key-u (nginx zone ili Django throttle)","ZAKON 32: commit mora imati cNNNN chain entry"],"migracija":"ALTER TABLE evalidator_dokarh ADD COLUMN weise3_id VARCHAR(64) DEFAULT ''; ADD COLUMN bunker_seal_id VARCHAR(64) DEFAULT ''; (ZAKON 27 polja — trenutno nedostaju!)","ZAKON_3_OBAVEZNO":{"upozorenje":"SVAKI objects.create() MORA imati get_trojna().pohrani_async() — ZAKON 3. Baza = sjena. Krunica = istina.","kod_primjer":["from services.krunica_dvorac_sync import get_trojna","rez = get_trojna().pohrani_sync(weise3_id, podaci, sadrzaj=payload_hash, kreator=issuer_name, tip='archive_ingest', prev_hash=dok.prev_dok_hash or '', kljuc=None)","assert rez['sve_ok'], f'Trojna pohrana pala V4: {rez[\"noge\"]}'"],"napomena":"Ako je async view: pohrani_async(). Ako je sync view: pohrani_sync() ili Celery task koji se okida odmah."}},{"id":"V5","naziv":"vetra.live Celery task: sync_to_evalidator","opis":"Async bridge task koji se okida pri svakom uspješnom sealu.","koraci":["fenix-v3/vetra/ NE — task ide u /var/www/vetra/archive/tasks.py (ZAKON 0 — fizička izolacija!)","Novi task: @shared_task def sync_to_evalidator(doc_id: str)","Čita EVALIDATOR_API_URL i EVALIDATOR_API_KEY iz settings/env","HTTP POST na evalidator endpoint s httpx (async) ili requests (sync)","Na uspjeh: VetraDocument.evalidator_dok_id = response['dok_id']","Na grešku: log warning, retry 3x s exponential backoff — NIKAD ne blokira seal","Okidač: archive/tasks.py SealView.post() na kraju → task.delay(str(doc.id))","Celery Beat: nije potreban — event-driven (na seal)"]},{"id":"V6","naziv":"VetraDocument model — nova polja za bridge","opis":"Dodati evalidator_dok_id na VetraDocument model.","migracija":["evalidator_dok_id = models.UUIDField(null=True, blank=True, db_index=True) — DokArh.dok_id","evalidator_verify_url = models.CharField(max_length=200, blank=True, default='') — verify URL","evalidator_weise3_id = models.CharField(max_length=64, blank=True, default='') — WeisE3 ID","makemigrations archive && migrate"],"ui":["verify/{seal}/ template: dodati 'Also verified on eValidaTor' badge s linkom na evalidator verify URL","dashboard: VetraDocument lista → nova kolona 'eValidator' s ✅ ili ⏳"]},{"id":"V7","naziv":"Retroaktivna sinkronizacija — 57 postojećih dokumenata","opis":"57 VetraDocument koji su već zapečaćeni trebaju biti i u evalidator DokArh.","koraci":["management/commands/sync_all_to_evalidator.py","Iterira VetraDocument.objects.filter(status='done', evalidator_dok_id__isnull=True)","Poziva sync_to_evalidator za svaki","python3 manage.py sync_all_to_evalidator --dry-run (provjeri prvi)","python3 manage.py sync_all_to_evalidator (pravi run)"]},{"id":"V8","naziv":"Public Explorer — jedna stranica za oba lanca","opis":"evalidator.eu/chain/ prikazuje dokumente i s vetra.live i s internih Fenix tokova.","koraci":["Modificirati evalidator/views.py PublicChainExplorerView: uz ChainBlockPOE prikazi i DokArh s dok_type='archive_entry'","Badge: 'Vetra Sealed' ako DokArh ima evalidator_dok_id vezan na VetraDocument","Filter: ?source=vetra ili ?source=fenix ili sve"]}],"commit_plan":["fix(vetra): V0 aktivirati Gmail SMTP email","feat(vetra): V1 BILLING_ENABLED=True + commitment doc test","feat(evalidator): V4 novi /api/v1/archive/ingest/ endpoint + DokArh ZAKON 27 migracija","feat(vetra): V5+V6 sync_to_evalidator Celery task + nova polja na VetraDocument","feat(vetra): V7 retroaktivna sinkronizacija 57 dokumenata","feat(evalidator): V8 Public Explorer unified view","docs(chain): c0161 vetra-evalidator bridge DONE"],"ivan_akcije":["Gmail App Password za fina.connect.online@gmail.com → staviti u /var/www/vetra/.env EMAIL_HOST_PASSWORD","DNS A zapis status.vetra.live → 37.27.248.86","Stripe API key (kad bude — za budući payment flow, nije bloker za sad)"],"vetra_online_odmah":{"sto_radi_sad":["POST /api/v1/scan/ — prima fajl, pečati, vraća seal ✅","GET /verify/{seal}/ — javna stranica verifikacije ✅","Widget.js — embed gumb na bilo koji web ✅","Dashboard — 3 tenanta, 57 dokumenata, KrunicaChain ✅","Trial 14 dana za nove registracije ✅","Python SDK v1.0.0 u sdk/ direktoriju ✅"],"blokeri_za_klijente":["Email (registracija ne šalje verification email) — V0","Billing (plan upgrade UI radi, ali SEPA flow ne šalje email) — V0+V1"]},"zakon":"ZAKON 0 (fizicka izolacija), ZAKON 2 (sve kroz Brsljani), ZAKON 3 (TROJNA POHRANA — svaki objects.create MORA imati get_trojna()!), ZAKON 17 (PULL only), ZAKON 27 (Model Trinity)","KRITICNO_ZA_CC":{"poruka":"ZAKON 3 — TROJNA POHRANA NIJE OPCIJA. Svaki model.objects.create() koji pohranjuje poslovne podatke MORA odmah pozvati get_trojna(). PostgreSQL = brzi upiti = SJENA. Krunica = jedina istina.","greska_koju_cc_pravi":"CC pise objects.create() i smatra da je pohrana gotova. NIJE. Bez get_trojna() dokument postoji samo u bazi, nije u Krunicu ni Brsljanu.","provjera":"grep -n 'objects.create' views.py — svaki redak mora imati odgovarajuci get_trojna() call ispod"},"ispravak":{"datum":"2026-05-08","sto":"ZAKON 3 dodan u zakon polje — originalno izostavljen. V4 koraci vec imaju ZAKON_3_OBAVEZNO sekciju s primjerom koda."},"status":"ZAVRSENO","zavrseno_datum":"2026-05-08","faze_status":{"V0":"DONE - Gmail SMTP aktivan","V1":"DONE - BILLING_ENABLED=True, load_dotenv(override=True) fix","V2":"PENDING - Let's Encrypt maintenance (retry loop aktivan, nije nas bloker)","V3":"DONE - arhitektura dokumentirana","V4":"DONE - POST /api/v1/archive/ingest/ + ZAKON 3 Trojka (Genesis N1 + Brsljani N3)","V5":"DONE - sync_to_evalidator Celery task, 3x retry, httpx","V6":"DONE - VetraDocument: evalidator_dok_id + evalidator_verify_url + evalidator_weise3_id, migration 0007","V7":"DONE - 57/57 retroaktivno sinkronizirano, commit 88fc600","V8":"DONE - /lanac/ unified explorer: ?source=all|fenix|vetra + JSON API"},"kljucni_commitovi":["88fc600 (V7 retroaktivni sync)","migration 0007 (V6 polja)"]}}