Files
decision/CLAUDE.md
T

174 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# libreDecision
Rendre possible la décision collective — en fonction du contexte, processus et modalités,
boîte à outils. **v3 : Rust + Svelte**, un chantier à la fois, chacun livré en production avant
le suivant (`docs/chantiers/README.md`).
**Référence du chantier en cours : `docs/chantiers/acte-certification/CHANTIER.md`** — toute
décision de comportement s'y adosse ; les décisions durables dans `docs/adr/`.
La maquette v2 (Nuxt + FastAPI) vit dans `maquette/`, **intacte** (Yvv la présente) — ne pas y
développer.
## Protocole de début de session
1. `git pull --rebase origin main` (puis la branche du chantier : `chantier/acte-certification`)
2. Lire `HANDOFF.md` (où on en est, ce qui attend Yvv)
3. Si l'objectif de la session n'est pas précisé, le demander
## Stack
- **Serveur** : Rust edition 2024, toolchain **1.99** épinglée (`rust-toolchain.toml`) ;
rustup installé sans PATH → `export PATH=$HOME/.cargo/bin:$PATH`. axum 0.8, sqlx 0.8
(SQLite, requêtes runtime + `migrate!`), tokio, reqwest rustls.
- **Interface** : SvelteKit 2 / Svelte 5 (runes), adapter-static SPA, vite 7, vitest,
Playwright ; npm. Polices Literata (textes) + Nunito (interface), fontsource.
- **Ports** : dev interface **3002** (strict, proxy `/api` → 8002) · serveur **8002** ·
serveur jetable des e2e **8092** (sa chaîne Ğ1 simulée prend un port local éphémère).
- **Déploiement** : une image (`docker/app.Dockerfile`), Woodpecker `ci.open.us.org` dépôt
LPK/decision → sonic (fabio). `.woodpecker/app.yml` = le produit sur
**decision.librodrome.org** ; `.woodpecker/maquette.yml` = la maquette sur
**maquette.decision.librodrome.org** (le produit passe en premier et retire de la racine tout conteneur qui la revendique ; la maquette attend un déploiement réussi du produit).
Push sur `prod` (`gitea@git.open.us.org:EHV/decision.git`) branche `main` = déploiement.
## Structure
```
crates/
ld-engine/ # PUR (zéro I/O) : threshold (formule inertielle sur un quorum, judged_voters,
# yes_needed / no_needed), inertia (cinq crans, leurs quorums, bornes, médiane,
# référence, échelle), edit (coquille vs fond, diff), assist (découpage, similarité,
# longueur), compose (adoption, aperçus), ballot (bulletin scellé ld1:, le dernier
# fait foi, jugement d'une transaction), address (SS58, préfixe g1), objection
# (redit / contredit : la dernière arrivée retenue, les tours, l'échéance), correction
# (la coquille d'un autre : attendre, valider, refuser, l'échéance), order (l'ordre
# d'une section : qui en est, complété à la fin, places), pending (modules à voter),
# buffer (le tampon des votes, ADR 0012 : réconciliation, poids des états,
# SIMULATED_ADOPTS)
trustin-access/ # règles d'accès de trustinWallet : sees / opens / manages_access, vote_way (serveur ou
# chaîne), answers_typo, lifts_objection / reiterates_objection, reads_message,
# sets_quorum, casts_simulated (le vote simulé, chaîne fermée), groupes par défaut
# (TEST_GROUP)
ld-server/
migrations/ # schéma SQLite — additif seulement
src/ # lib.rs (routes, csrf, run) · config.rs (LD_*) · auth.rs (connect OAuth2, invitations,
# dev, bootstrap) · team.rs (liens d'équipe) · docs.rs (lecture, aperçus) · proposals.rs (écrire, voter,
# traduire) · objections.rs (faire, lever, réitérer, la version retenue) · typos.rs
# (les coquilles des autres) · messages.rs (la boîte « Messages ») · deadlines.rs
# (les échéances de 3 jours) · clock.rs (horloge injectable) · adoption.rs
# (balayage, verrou) · participation.rs (p̃, une fois par
# jour) · publish.rs (file → git) · wot.rs (W sur la chaîne) · seed.rs ·
# seed_amend.rs / inertia_amend.rs / seed_proposal_amend.rs (amendements gardés ;
# le dernier fait des Propositions seed, ADR 0011) · ballots.rs (vote groupé,
# bulletins de la chaîne Ğ1, le tampon : intention, preuve, réconciliation ; le vote
# simulé, « ton vote ») · simulation.rs (l'acte « supprime » de la fin de la simulation :
# `ld-server discard-simulation [--apply]`, ADR 0012) · indexer.rs (txComments)
# · modules.rs / order.rs / doc_title.rs (les modules, ADR 0009 : l'ordre d'une
# section, le titre du document) · module_amend.rs (ajout gardé) · quorum.rs (le quorum
# d'un article, PUT /units/{id}/quorum ; « un vote existe » : voted_units, ADR 0013) ·
# quorum_amend.rs (les quorums par cran, amendement gardé) · article_amend.rs (un
# article du seed ajouté à un document existant, gardé : E12, lot T4) · retire.rs
# (formule, inertie, ordonnancement sortis du document sans rien effacer :
# units.retired_at, ADR 0014) · web.rs (sert web/build)
tests/ # api.rs (scénarios bout en bout) · ballots.rs (vote par la chaîne, indexeur simulé) ·
# objections.rs · typos.rs (lot F, horloge avancée, migration 0008) · modules.rs (ordre,
# titre, ajout gardé) · seed_proposals.rs (Propositions seed, publication suspendue) ·
# quorum.rs (quorums par cran, la route, « un vote existe », l'amendement) ·
# fixtures/seed-production-2026-11-02/ (le seed que la production fait tourner :
# I1/E1/E2 en vigueur, pour rejouer les amendements sur une base comme elle) ·
# seed_quorum_texts.rs (lots T, T2 et T3 : F1.1, F1.2, N1.1 ; aucun chiffre daté, chaque
# phrase vraie pour tout W et tout quorum ; fixtures/seed-quorum-m6b.json et
# seed-quorum-t2.json, leurs textes depuis M6b et M6c, pour rejouer T2 et T3 sur une
# base comme la production ; depuis T4, sur le seed de M8) · amorce.rs (lot T4 : les
# textes d'Yvv, E12, le retrait ; après M6c et après M8, chaque ligne de chaque table
# gardée, le retour arrière) · fixtures/seed-m8/ (le seed de M8 : les derniers textes
# de formule, inertie, ordonnancement, référence du lot U3)
seeds/ # acte-engagement-certification.json (trilingue, 27 articles, 5 sections, aucun en
# vigueur ; I1/E1/E12/E2 Propositions seed au cran 2 (seed::SEED_PROPOSAL_LEVEL),
# inertie 3 ailleurs ; modules en vigueur sans vote : le titre à 4, l'ordre de chaque
# section à 2 ;
# quorums par cran : 12 · 12 · 50 · 50 · 50 Monnaie libre, 1 partout essai)
# upcoming/<groupe>.json : les « À venir » des outils d'un groupe (fr, en, es), lus au démarrage
web/src/
lib/i18n/ # fr.ts SOURCE (types Key) · en.ts · es.ts — parité testée
lib/components/ # Sidebar, DocPanel, VoteFold (le vote déplié sous l'article), BallotPanel (panier),
# ChainSign (signature, Ğecko), VersionDetails, ProposeView, UnitBlock, DeepList,
# OrderLine / Reorder (l'ordre d'une section : une ligne en fin de section, les poignées
# sur ses articles, sur place), QuorumSetting (le quorum de l'auteur), Crans (l'inertie dessinée),
# TitleBar / TitlePropose (le titre du document), OpeningInfo (« Info ouverture doc de réf. », lot U3), Seal…
lib/wallet/ # injected.ts (portefeuille injectedWeb3, polkadot-api chargé à la signature) · gecko.ts
lib/basket.ts # PUR : sections, tout pour / tout contre, versions en concurrence, versions retenues, modules
lib/objections.ts # où l'auteur répond à une objection · lib/diff.ts : le diff resserré d'une coquille
lib/order.ts # PUR : placer, monter / descendre, ce qui a bougé
lib/opening.ts # PUR : le chapitre d'ouverture, lu dans l'API (cran d'ouverture, Propositions d'amorce, quorums)
routes/ # / (accueil + choix du groupe) · connexion · invitation · equipe · g/[group] (piliers, en cours) ·
# g/[group]/docs · g/[group]/docs/[doc] (lecteur,
# vote déplié ?vote=, panneau sans onglets ?onglet=panier|proposer|details|reglages ;
# l'ancien onglet=propositions déplie le vote ; note : docs/chantiers/acte-certification/UX-lecteur.md)
# · g/[group]/decisions · g/[group]/mandats ·
# g/[group]/protocoles (à venir) · acces (trustinWallet) · messages (la boîte) ;
# /groupes, /decisions… redirigent
web/e2e/ # Playwright C1–C44 + M1, M2 ; serve.sh = serveur jetable /tmp/ld-e2e sur :8092 et
# chain-mock.mjs (nœud et indexeur Ğ1 simulés) ; faux portefeuille dans helpers.ts
docker/ # app.Dockerfile · app-compose.yml (sonic)
.woodpecker/ # app.yml · maquette.yml
docs/ # chantiers/ · adr/ · dev/BLUEPRINT-V2.md (doctrine de la maquette) · recherche/
maquette/ # v2 intacte (frontend Nuxt, backend FastAPI, docker, docs-v1)
```
## Données runtime — jamais écrasées
- **Production** : volume `lpk-libredecision-app_data` (`/data` : `libredecision.db`, `textes/`
= clone du dépôt publié, `keys/` = clé de publication, `bootstrap-admin.txt`). Jamais
`down -v`, jamais recréé.
- **Maquette** : volumes `lpk-decision-main_postgres-data` / `_ipfs-data` (inchangés).
- **Local** : `data/` (gitignoré) — le supprimer repart du seed. Les e2e utilisent `/tmp/ld-e2e`.
- Un document seedé n'est **jamais** réinstancié : dès qu'il existe en base, c'est de la donnée.
## Commandes — la boucle (tout vert = fait)
```bash
export PATH=$HOME/.cargo/bin:$PATH
cargo fmt --all --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace
cd web && npm run check && npm test && npm run build && npm run e2e # e2e : 46 contrôles (48 tests, C25 et C35 en deux)
LD_DEV_LOGIN=1 cargo run -p ld-server # :8002, sert web/build
cd web && npm run dev # :3002 à chaud
docker build -f docker/app.Dockerfile --target production . # rejoue toute la boucle
```
## Conventions / pièges
- **UI français, code anglais** ; **trilingue** : aucune chaîne affichée en dur, tout passe par
`web/src/lib/i18n/fr.ts` puis en/es (test de parité + `FORBIDDEN_UI_TERMS`). Tutoyer ; le sujet
est la personne ou le groupe, jamais le système. Le français du texte voté fait foi.
- **Moteur pur** : une règle de vote / édition / composition s'écrit et se teste dans
`ld-engine` avant d'être câblée. Le serveur ne décide jamais l'accès seul : `trustin-access`.
- **Invariants** : les informations de fonctionnement (formule, inertie, ordonnancement) ne se
votent pas : hors du document, une unité retirée (`units.retired_at`) n'est ni lue, ni votée, ni
comptée, ni publiée, et rien n'est effacé (ADR 0014) ; au départ, aucun article n'est en
vigueur : I1, E1, E12 et E2 sont des Propositions
seed (ouvertes, mises en avant, au cran 2 ; seuls les modules sont des *seeds a minima*), et la
publication d'un document attend son premier texte en vigueur (ADR 0011) ; un quorum par cran
(12 · 12 · 50 · 50 · 50 dans Monnaie libre), que l'auteur d'un article change avant le premier
vote : sous le quorum, les votants qui manquent comptent comme « non », et une seule voix ne fait
jamais passer un texte (quorum ≥ 2), sauf dans le groupe d'essai (quorum 1 ; ADR 0013) ;
une coquille ne demande pas de vote, un changement de fond si ; la coquille d'un autre attend
son auteur (un administrateur pour le seed) ou 3 jours, et en vigueur seule une coquille validée
change le texte ; une objection retient la dernière arrivée jusqu'à sa levée (jamais un texte en
vigueur ; ADR 0010) : elle n'entre pas en vigueur, et on peut y retirer son vote ou passer à
« contre », jamais ajouter un « pour » (Yvv, 01/11/2026 : « Retirer ou "contre" ») ; l'inertie de l'inertie hérite du cran de l'article (cinq crans, ADR 0007) ;
le groupe d'essai ne publie jamais ; dans Monnaie libre, un vote est une transaction Ğ1 et le
dernier fait foi dans l'ordre de la chaîne (ADR 0008) — **jamais de transaction réelle en test**
(chaîne simulée ; un essai réel est un acte « paye » d'Yvv).
- **Écritures** : en-tête `x-requested-with: libredecision` obligatoire (CSRF) ; cookie
`ld_session`. Les tests d'API passent par `Client` (`tests/api.rs`).
- **Pièges vus** : `pkill -f target/debug/ld-server` tue son propre shell → `pkill -x ld-server` ;
un `from_secret` absent fait refuser tout le pipeline Woodpecker ; la route hôte `/*` de fabio
masque le webroot ACME → arrêter le service avant `acme.sh --issue` ; Playwright en locale
`fr-FR` (sinon l'interface part en anglais).
- **Design** : sans bordures, arrondis 16/12/20/14, quatre ambiances `pierre`, `calcaire`
(claires), `nuit`, `ardoise` (sombres) (`data-mood`, posé avant le premier rendu, clé `ld:mood`), logo
« Clé de voûte » (`Logo`, jamais incliné, `--cle` par ambiance), sceau hexagramme 井 #48 en SVG (`Seal` —
jamais le glyphe, qui s'affiche mal). Mouvement réduit respecté.
- **Domaine** : decision.librodrome.org ; dépôt des textes `git.open.us.org/yvv/decision-depot-textes-reference`
(provisoire : puis un dépôt pour l'ouverture, puis le dépôt officiel pour les textes en vigueur).