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>
This commit is contained in:
Yvv
2026-10-30 20:52:47 +01:00
co-authored by Claude Opus 5.5
parent a576b68570
commit 3541e1b1a6
19 changed files with 2595 additions and 105 deletions
+9 -2
View File
@@ -1,16 +1,19 @@
//! libreDecision server.
//!
//! One binary serves the JSON API under `/api`, the compiled Svelte interface,
//! and runs two background workers: the electorate refresher (size of the Ğ1
//! web of trust) and the publisher (adopted texts pushed to the git repository
//! and runs four background workers: the electorate refresher (size of the Ğ1
//! web of trust), the adoption sweeper, the ballot watcher (votes signed on the
//! Ğ1 chain, confirmed on the indexer) and the publisher (adopted texts pushed to the git repository
//! that client applications read).
pub mod access;
pub mod adoption;
pub mod auth;
pub mod ballots;
pub mod config;
pub mod docs;
pub mod error;
pub mod indexer;
pub mod inertia_amend;
pub mod overview;
pub mod participation;
@@ -116,6 +119,9 @@ pub fn api_router() -> Router<AppState> {
.route("/docs/{id}/preview", get(docs::preview))
.route("/docs/{id}/assist", post(proposals::assist))
.route("/docs/{id}/proposals", post(proposals::create))
.route("/docs/{id}/votes", post(ballots::vote_many))
.route("/docs/{id}/ballots", post(ballots::create))
.route("/ballots/{id}", get(ballots::status))
.route("/proposals/{id}", get(proposals::detail).patch(proposals::edit))
.route("/proposals/{id}/submit", post(proposals::submit))
.route("/proposals/{id}/withdraw", post(proposals::withdraw))
@@ -211,6 +217,7 @@ pub async fn run() -> anyhow::Result<()> {
tokio::spawn(wot::refresher(state.clone()));
tokio::spawn(publish::worker(state.clone()));
tokio::spawn(adoption::sweeper(state.clone()));
tokio::spawn(ballots::watcher(state.clone()));
let listener = tokio::net::TcpListener::bind(&state.cfg.bind).await?;
tracing::info!(bind = %state.cfg.bind, build = %state.cfg.build, "libreDecision listening");