Le dépôt des textes créé par Yvv sur git.open.us.org (2026-10-21) : séparé du code, pour que la clé du serveur n'écrive jamais dans yvv/decision et que le dépôt se transfère d'un bloc à l'ouverture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 lines
6.4 KiB
Markdown
102 lines
6.4 KiB
Markdown
# 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**.
|
||
- **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, presets), edit (coquille vs fond,
|
||
# diff), assist (découpage, similarité, longueur), compose (adoption, aperçus)
|
||
trustin-access/ # règles d'accès de trustinWallet : sees / opens / manages_access, groupes par défaut
|
||
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, signaler,
|
||
# traduire) · adoption.rs (balayage, verrou) · publish.rs (file → git) · wot.rs (W
|
||
# sur la chaîne) · seed.rs · web.rs (sert web/build)
|
||
tests/api.rs # scénarios bout en bout
|
||
seeds/ # acte-engagement-certification.json (trilingue, 33 articles, I1/E1/E2 en vigueur)
|
||
web/src/
|
||
lib/i18n/ # fr.ts SOURCE (types Key) · en.ts · es.ts — parité testée
|
||
lib/components/ # Sidebar, DocPanel, VoteView, ProposeView, UnitBlock, DeepList, Seal, Stamp…
|
||
routes/ # / · connexion · invitation · equipe · groupes · g/[group] · g/[group]/docs/[doc] (lecteur,
|
||
# panneau dans l'URL ?onglet=&article=) · acces (trustinWallet) · decisions/mandats/
|
||
# protocoles (à venir)
|
||
web/e2e/ # Playwright C1–C12 + M1 ; serve.sh = serveur jetable /tmp/ld-e2e sur :8092
|
||
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 : 13 contrôles
|
||
|
||
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** : une seule voix ne fait jamais passer un texte (C = 50 pour Monnaie libre) ;
|
||
une coquille ne demande pas de vote, un changement de fond si ; un signalement de
|
||
contradiction bloque ; l'inertie se vote au cran au-dessus ; le groupe d'essai ne publie jamais.
|
||
- **É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, ambiances `pierre` / `nuit`
|
||
(`data-mood`, posé avant le premier rendu), sceau hexagramme 井 #48 en SVG (`Seal`, `Stamp` —
|
||
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).
|