forked from yvv/decision
v3 : serveur des objections, des coquilles validées et de la messagerie (lot F)
Objections « redit » / « contredit » à la place des signalements : la dernière arrivée des deux versions n'est plus votable (repli, panier, chaîne : un vote déjà scellé est gardé mais ne la fait pas entrer) ; un texte en vigueur ne l'est jamais. L'auteur répond en modifiant l'article visé (proposition liée) ou en reformulant ; la personne qui objecte lève ou réitère depuis ses messages ; sans réponse sous 3 jours, l'objection est levée. Un administrateur peut lever. Coquilles : la sienne passe tout de suite ; celle d'un autre attend l'auteur (valider / refuser), passe seule au bout de 3 jours, et l'auteur garde la main tant que le texte n'est pas en vigueur. En vigueur, seule une coquille validée corrige (auteur de la version, administrateur pour un texte semé). Deux coquilles en attente : la seconde se mesure au texte voté ; à l'application, celle qui ne colle plus est périmée. Messagerie dans l'application (boîte, non-lus, gestes, échéance), chaque personne ne lit que les siens. Échéances par le balayage existant, avec rattrapage au démarrage et horloge injectable (route de dev). Migration 0008 additive : les signalements deviennent des « contredit », sans perte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,19 +2,24 @@
|
||||
//!
|
||||
//! One binary serves the JSON API under `/api`, the compiled Svelte interface,
|
||||
//! 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).
|
||||
//! web of trust), the adoption sweeper (with the deadlines of three days of
|
||||
//! objections and typo fixes), 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 clock;
|
||||
pub mod config;
|
||||
pub mod deadlines;
|
||||
pub mod docs;
|
||||
pub mod error;
|
||||
pub mod indexer;
|
||||
pub mod inertia_amend;
|
||||
pub mod messages;
|
||||
pub mod objections;
|
||||
pub mod overview;
|
||||
pub mod participation;
|
||||
pub mod proposals;
|
||||
@@ -22,6 +27,7 @@ pub mod publish;
|
||||
pub mod seed;
|
||||
pub mod seed_amend;
|
||||
pub mod team;
|
||||
pub mod typos;
|
||||
pub mod util;
|
||||
pub mod web;
|
||||
pub mod wot;
|
||||
@@ -50,6 +56,8 @@ pub struct AppState {
|
||||
pub publish_wake: Arc<Notify>,
|
||||
/// What is coming in the tools of each group (`seeds/upcoming/`), read at start.
|
||||
pub upcoming: Arc<overview::Upcoming>,
|
||||
/// The clock of the deadlines of three days (objections, typo fixes); tests move it.
|
||||
pub clock: clock::Clock,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -59,7 +67,14 @@ impl AppState {
|
||||
.user_agent(concat!("libreDecision/", env!("CARGO_PKG_VERSION")))
|
||||
.build()?;
|
||||
let upcoming = Arc::new(overview::Upcoming::load(&cfg.seed_dir).await?);
|
||||
Ok(Self { db, cfg: Arc::new(cfg), http, publish_wake: Arc::new(Notify::new()), upcoming })
|
||||
Ok(Self {
|
||||
db,
|
||||
cfg: Arc::new(cfg),
|
||||
http,
|
||||
publish_wake: Arc::new(Notify::new()),
|
||||
upcoming,
|
||||
clock: clock::Clock::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,9 +142,17 @@ pub fn api_router() -> Router<AppState> {
|
||||
.route("/proposals/{id}/withdraw", post(proposals::withdraw))
|
||||
.route("/proposals/{id}/split", post(proposals::split))
|
||||
.route("/proposals/{id}/vote", post(proposals::vote))
|
||||
.route("/proposals/{id}/signals", post(proposals::signal))
|
||||
.route("/proposals/{id}/objections", post(objections::raise))
|
||||
.route("/proposals/{id}/translations/{lang}", put(proposals::translate))
|
||||
.route("/signals/{id}/lift", post(proposals::lift_signal))
|
||||
.route("/objections/{id}/lift", post(objections::lift))
|
||||
.route("/objections/{id}/reiterate", post(objections::reiterate))
|
||||
.route("/typos/{id}/validate", post(typos::validate))
|
||||
.route("/typos/{id}/refuse", post(typos::refuse))
|
||||
.route("/messages", get(messages::list))
|
||||
.route("/messages/unread", get(messages::unread))
|
||||
.route("/messages/read", post(messages::read_all))
|
||||
.route("/messages/{id}/read", post(messages::read))
|
||||
.route("/dev/clock", post(deadlines::dev_clock))
|
||||
.route("/units/{id}/inertia", post(proposals::propose_inertia))
|
||||
.route("/feedback", post(access::send_feedback))
|
||||
.route("/access", get(access::overview))
|
||||
@@ -210,6 +233,12 @@ pub async fn run() -> anyhow::Result<()> {
|
||||
tracing::warn!(error = %e, "usual participation");
|
||||
}
|
||||
auth::bootstrap(&state).await?;
|
||||
// A deadline passed while the server was stopped is dealt with now.
|
||||
match deadlines::sweep(&state).await {
|
||||
Ok(s) if s != deadlines::Swept::default() => tracing::info!(?s, "deadlines passed while stopped"),
|
||||
Ok(_) => {}
|
||||
Err(e) => tracing::warn!(error = %e, "deadlines"),
|
||||
}
|
||||
if let Err(e) = publish::ensure_key(&state).await {
|
||||
tracing::warn!(error = %e, "publication key");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user