Files
decision/crates/ld-server/migrations/0006_ballots.sql
T
YvvandClaude Opus 5.5 3541e1b1a6 v3 : le vote par la chaîne Ğ1, côté moteur et serveur
Le bulletin scellé (ld1: + blake2b-256 du bulletin canonique, sel de 128 bits),
l'ordre de la chaîne (bloc, puis rang de l'événement : le dernier fait foi), les
adresses SS58 comparées par clé (ld-engine, pur). trustin-access : Monnaie libre
vote par la chaîne, les groupes gérés sur le serveur ; le droit de vote se lit à
la confirmation. Serveur : bulletins en attente, confirmation sur l'indexeur
(virement, auteur, identité, membre), identité idty:<index> créée au besoin,
tâche de fond toutes les 10 s, expiration à 24 h, vote groupé en une écriture
dans les groupes gérés. Migration additive 0006. Sans LD_VOTE_ACCOUNT, le vote
par la chaîne est éteint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 20:52:47 +01:00

52 lines
3.0 KiB
SQL

-- The vote on the Ğ1 chain (2026-10-30, ADR 0008). Additive only: nothing is
-- rewritten, every vote of before stays as it was (source 'server').
--
-- A ballot is asked by a session, sealed by the server (salt, digest H) and
-- signed by a wallet: one transaction, a transfer to the vote account and the
-- remark `ld1:<H>`. The server confirms it by reading the indexer, then writes
-- each of its lines into `votes` for the Ğ1 identity of the signer — unless a
-- more recent ballot of that identity, in the order of the chain, already
-- decided that proposal (the last one stands).
CREATE TABLE ballots (
id TEXT PRIMARY KEY,
doc_id TEXT NOT NULL REFERENCES documents(id),
requested_by TEXT NOT NULL REFERENCES identities(id), -- the identity of the session that asked
author TEXT, -- the account bound to sign (Ğ1 address), when the page knew it
salt TEXT NOT NULL, -- 128 random bits, 32 hex digits
digest TEXT NOT NULL UNIQUE, -- H = blake2b-256 of the canonical ballot
remark_hash TEXT NOT NULL UNIQUE, -- 0x + blake2b-256 of `ld1:<H>`: what the indexer finds it by
account TEXT NOT NULL, -- the vote account at the time (Ğ1 address)
amount INTEGER NOT NULL, -- cents of Ğ1 asked
status TEXT NOT NULL, -- pending | confirmed | refused | expired
reason TEXT, -- refused: no_identity | not_member | transfer
voter_id TEXT REFERENCES identities(id), -- idty:<index> of the signer, once confirmed
signer TEXT, -- the account that signed (Ğ1 address)
block INTEGER, -- where the remark sits on the chain
event_index INTEGER,
event_id TEXT,
entered TEXT, -- JSON: what entered into force at the confirmation
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
checked_at TEXT, -- last reading of the indexer
settled_at TEXT -- confirmed, refused or expired
);
CREATE INDEX ballots_pending ON ballots(status, created_at);
CREATE INDEX ballots_requested ON ballots(requested_by);
CREATE INDEX ballots_voter ON ballots(voter_id);
CREATE TABLE ballot_lines (
ballot_id TEXT NOT NULL REFERENCES ballots(id),
proposal_id TEXT NOT NULL REFERENCES proposals(id),
revision INTEGER NOT NULL, -- the revision voted: counted only while it is the proposal's
choice TEXT NOT NULL, -- for | against | none (withdraws)
PRIMARY KEY (ballot_id, proposal_id)
);
CREATE INDEX ballot_lines_proposal ON ballot_lines(proposal_id);
-- Where a vote comes from, and for a vote of the chain, where it sits on it.
ALTER TABLE votes ADD COLUMN source TEXT NOT NULL DEFAULT 'server'; -- server | chain
ALTER TABLE votes ADD COLUMN block INTEGER;
ALTER TABLE votes ADD COLUMN event_index INTEGER;
ALTER TABLE votes ADD COLUMN ballot_id TEXT;