v3 : points de la relecture indépendante — une personne une voix, ordre de déploiement, durcissements
- Dans Monnaie libre (électorat = toile de confiance), seuls les membres de la toile votent (trustin_access::votes_in) ; une identité d'invitation y lit, propose et signale. L'interface le dit à la place des boutons (fr/en/es). - Un lien d'invitation ne vise jamais une identité Ğ1 ; le lien est réservé avant de créer l'identité (deux acceptations simultanées : une seule passe). - Un nombre n'est jamais une coquille (« 50 » → « 5,0 », « 1 5 » → « 15 »). - Redirection après connexion : caractères de contrôle refusés. - En-têtes : X-Frame-Options DENY, frame-ancestors 'none', nosniff, Referrer-Policy. - Déploiement : le produit passe en premier ; la maquette attend son succès. Les conteneurs, même arrêtés, qui revendiquent encore la racine sortent de « restart: always » (ils reviendraient au redémarrage de Docker). - Tests : 57 Rust (dont 14 scénarios d'API), e2e 12 / 12 avec C11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,9 @@
|
||||
//! - a group opens only to its members; Monnaie libre's members are the
|
||||
//! members of the Ğ1 web of trust, the others are granted one by one;
|
||||
//! - everything is open to a member except access management, which belongs
|
||||
//! to trustinWallet's administrators.
|
||||
//! to trustinWallet's administrators;
|
||||
//! - where the electorate is the web of trust (Monnaie libre), only its members
|
||||
//! vote (2026-10-21, independent review: one person, one vote).
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -99,6 +101,18 @@ pub fn opens(identity: &Identity, group: &Group, granted: bool) -> bool {
|
||||
is_member(identity, group, granted)
|
||||
}
|
||||
|
||||
/// Can this identity vote in the group? Where the electorate is the Ğ1 web of
|
||||
/// trust (policy `G1Members`), only its members vote: the threshold is computed
|
||||
/// on the size of the web, and an invitation identity next to a Ğ1 identity
|
||||
/// would give one person two votes. Development identities stand in for members
|
||||
/// (local only: the dev login is never enabled in production).
|
||||
pub fn votes_in(identity: &Identity, group: &Group, granted: bool) -> bool {
|
||||
opens(identity, group, granted)
|
||||
&& (group.policy != GroupPolicy::G1Members
|
||||
|| identity.kind == IdentityKind::Dev
|
||||
|| (identity.kind == IdentityKind::G1 && identity.g1_member))
|
||||
}
|
||||
|
||||
/// Access management stays with trustinWallet's administrators.
|
||||
pub fn manages_access(identity: &Identity) -> bool {
|
||||
identity.admin
|
||||
@@ -176,6 +190,18 @@ mod tests {
|
||||
assert!(!opens(&admin, &group("essai"), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_wot_members_vote_where_the_electorate_is_the_web_of_trust() {
|
||||
let ml = group("monnaie-libre");
|
||||
assert!(votes_in(&who(IdentityKind::G1, true, false), &ml, false));
|
||||
let invited = who(IdentityKind::Invite, false, true);
|
||||
assert!(opens(&invited, &ml, true), "an invitation may open Monnaie libre to read and propose");
|
||||
assert!(!votes_in(&invited, &ml, true), "but its votes would not be web-of-trust votes");
|
||||
assert!(!votes_in(&who(IdentityKind::G1, false, false), &ml, true), "a former member reads, does not vote");
|
||||
assert!(votes_in(&invited, &group("essai"), true), "managed groups: every member votes");
|
||||
assert!(!votes_in(&invited, &group("essai"), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_atelier_du_canal() {
|
||||
assert!(default_groups().iter().all(|g| !g.slug.contains("atelier")));
|
||||
|
||||
Reference in New Issue
Block a user