Web i domovina-api
Registrar, web tok, baza
# 4. Promjene u webu i u domovina-api
Izmjena 26. 9. 2026.: Astro je odbačen; web ostaje Vite + Cloudflare Worker
maksimir(odluka). Redoslijed spajanja, zastavica i prijelaz s faze 1 su u 08. Sva kriptografija koju web treba već postoji uchain/client/i testirana je.
# Registrar (domovina-api)
Jedini novi poslužiteljski dio. Nova edge funkcija, npr. maksimir-register:
POST /functions/v1/maksimir-register (Authorization: Bearer <sesija nakon eOsobne>)
{ "commitment": "…" }
→ { "commitment", "deadline", "signature", "contract", "chainId" }
- Sesija mora imati red u
identity_verifications(eOsobna ili mobile.ID). - Jednom po osobi: nova tablica
maksimir_chain_registrations(oib_hash unique, commitment, created_at). Drugi zahtjev iste osobe vraća isti potpis za isti commitment, a za drugi commitment vraća greškualready_registered. Zato izgubljen ključ ne donosi drugi glas. - Potpis:
registerTypedData({ chainId, contract, commitment, deadline })izchain/client/ballot.ts(viemsignTypedData, radi i u Denou), rok 1 h. - Tajna
MAKSIMIR_REGISTRAR_KEYpostoji samo u edge funkciji.
Registrar ne šalje transakciju. Potpis vraća pregledniku, a preglednik ga šalje relayeru ili sam.
# Web (nakon Astro migracije)
# Ključ
Isti Semaphore ključ kao u fazi 1 (maksimir-zk-identity u localStorage + preuzimanje
datoteke). Tko ga već ima, registrira njegov commitment. Ključ se nudi za preuzimanje prije
prve predaje, jer bez njega nema izmjene listića (06).
# Predaja listića
import { encodePoints, proveBallot, registerTypedData, toJson } from "chain/client/ballot";
import { fetchGroup } from "chain/client/group";
// 1. jednom: pravo glasa
const reg = await fetch(REGISTRAR_URL, { method: "POST", headers: auth, body: toJson({ commitment: id.commitment }) }).then((r) => r.json());
await fetch(`${RELAYER_URL}/register`, { method: "POST", body: toJson(reg) });
// 2. svaki put: listić → dokaz → relayer
const group = await fetchGroup(publicClient, SEMAPHORE, GROUP_ID, DEPLOY_BLOCK);
const points = encodePoints(nacrt); // {ŠIFRA: bodovi}, zbroj 100
const revision = (await ballotOf(nullifier)).revision + 1;
const proof = await proveBallot(id, group, { chainId, contract, revision, points });
await fetch(`${RELAYER_URL}/cast`, { method: "POST", body: toJson({ revision, points, proof }) });
- Nullifier za „moj listić” daje
ballotNullifier(id, group). Pamti se lokalno, a iz njega se čitajuballotOfi revizija. - Gumb „preuzmi paket” uz „predaj” daje isti JSON za slanje bez našeg relayera.
- Relayerova greška 409
BadRevisionznači da je listić već predan s drugog uređaja. Tada se ponovno pročitaballotOfi izradi nova revizija.
# Rezultati i provjera
- Rezultati:
results()sa svih verzija izchain/deployments/(danas samo V1), zbrojeni. - Stranica „Kako radi”: poveznice na verificiran izvor, zadnje
BallotCastdogađaje i na 06. web/src/docs.tsje ručni manifest dokumenata.docs/blockchain/*.mdondje treba dodati da se prikažu na#/dokumenti, u obliku koji Astro migracija uvede.
# Konfiguracija
Adresa ugovora, chainId, blok deploya, groupId, URL relayera i registrara. Sve osim URL-ova
čita se iz chain/deployments/<mreža>/v1.json.
# Faza 1 u bazi
- Nakon prelaska
maksimir_cast_ballotse zatvara (closes_at= trenutak prelaska ili nova zastavica). Zadnji satni snapshot ide u Bitcoin kao završno stanje faze 1. - Javne objave s imenom (
/g/<id>) ostaju u bazi, jer ime nikad ne ide na lanac. Za objavu listića s lancamaksimir_set_publicbilježi nullifier umjestovoter_id. Nullifier tada postaje javno povezan s imenom, ali samo po izboru glasača.