Files
decision/CLAUDE.md
T
YvvandClaude Opus 5.5 fd19dbf4ec v3 : liens d'équipe, publication sur git.open.us.org, huitième relecture
Liens d'équipe (Yvv, 2026-10-21) : un lien réutilisable jusqu'à une date
et pour un nombre de personnes, révocable. Chaque ouverture demande un nom
et crée sa propre identité d'invitation, jamais administratrice ; un nom
déjà pris est refusé ; une personne déjà connectée reçoit les groupes.
trustinWallet montre par quel lien chaque identité est venue, et donne un
nouveau lien de connexion à une personne invitée (autre appareil).
Migration additive 0002 (table team_links, colonne identities.team_link).

Publication : yvv/libredecision-textes sur git.open.us.org, pour
l'instant (un dépôt pour l'ouverture, puis le dépôt officiel, viendront).

Huitième relecture (c3d6bf8 : ok), points corrigés :
- une négation n'est jamais coupée ni formée par collage (« ja mais ») ;
- caractères invisibles : tout l'ensemble Unicode des ignorables et les
  contrôles autres que saut de ligne et tabulation ;
- sauts de ligne et indentation font partie de la forme (listes) ;
- un titre tient sur une ligne.

Boucle : 65 tests Rust, svelte-check, 9 vitest, e2e 13/13 (C12 ajouté).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 08:12:21 +02:00

102 lines
6.4 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**.
- **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/libredecision-textes`
(provisoire : puis un dépôt pour l'ouverture, puis le dépôt officiel pour les textes en vigueur).