forked from yvv/decision
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>
52 lines
3.0 KiB
SQL
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;
|