v3 : déploiement (image unique, produit à la racine, maquette en sous-domaine) et documentation du chantier

- docker/app.Dockerfile : une image Rust + Svelte, la construction rejoue toute
  la boucle (fmt, clippy -D warnings, tests, svelte-check, vitest) ; utilisateur
  non-root, volume /data. docker/app-compose.yml pour sonic (fabio).
- .woodpecker/app.yml : produit sur decision.librodrome.org, attend la maquette,
  écarte tout conteneur qui revendique encore la racine, healthcheck du commit.
- .woodpecker/maquette.yml (ex .woodpecker.yml) : la maquette v2 telle quelle,
  sur maquette.decision.librodrome.org, mêmes volumes.
- .env.example de la maquette rangé dans maquette/ ; celui de la v3 à la racine.
- Docs : README, CONTRIBUTING (travail à deux), CLAUDE.md v3, HANDOFF,
  docs/chantiers (feuille de route, fiche, contrôles, onboarding de Chiara,
  demande à poka), docs/adr 0001–0006.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-21 03:50:44 +02:00
co-authored by Claude Opus 5.5
parent c2669a3d0b
commit 1f9c241b41
24 changed files with 1187 additions and 281 deletions
+74 -73
View File
@@ -1,11 +1,10 @@
# libreDecision
Boîte à outils de la première démocratie — décider ensemble, du trio à la population.
Rendre possible la décision collective — en fonction du contexte, processus et modalités,
boîte à outils.
libreDecision fait de la décision un geste quotidien : chaque question tient en une phrase,
l'outil propose le chemin le plus court — jamais plus lourd que l'enjeu — et tout ce qui est
décidé reste révisable, mesuré, consigné. Le même outil sert un trio d'amis, une association,
une coopérative ou la toile de confiance Ğ1 (marque blanche par construction).
En ligne : **https://decision.librodrome.org** (le produit, v3) · la maquette v2, conservée pour
présenter le projet : https://maquette.decision.librodrome.org (`maquette/`).
## Manifeste
@@ -24,90 +23,92 @@ une coopérative ou la toile de confiance Ğ1 (marque blanche par construction).
> Autonomie, Équilibre, Liaison. Du trio d'amis à la toile Ğ1 : le même geste, dix secondes,
> et l'observatoire qui apprend de nous. La ville change, le puits demeure.
## Les 6 routes de décision
## Les quatre outils
Le triage (moteur pur, toujours expliqué en une phrase, toujours contournable) oriente chaque
décision vers l'une de six routes :
| Outil | Ce qu'il fait | État |
|---|---|---|
| **Décisions** | funnel assisté pour choisir les modalités, journal des décisions | à venir |
| **Docs de référence** | acte d'engagement, licence, charte, constitution… sous vote permanent | **actif** |
| **Mandats** | création et révocation de tout mandat | à venir |
| **Protocoles** | workflows sans organe statutaire, rôles tournants, automatisations | à venir |
| Route | Geste |
|---|---|
| **solo** | « Personne d'autre n'est concerné — décide. » 2 gestes, moins de 10 secondes, trace facultative |
| **record** | « Déjà tranché — je le consigne. » L'observatoire en un geste, adopté immédiatement |
| **mandate** | « Ton mandat couvre — décide, c'est tracé. » Trace obligatoire + fenêtre d'objection 48 h |
| **transmit** | « Le mandat d'un autre couvre — transmets-lui. » (ou conteste le mandat) |
| **advice** | « Réversible et petit cercle — demande leur avis, puis décide. » 72 h |
| **collective** | « Nous décidons. » Formulation, liste des concernés arrêtée, session de vote |
Le produit avance **un chantier à la fois**, chacun livré complet et en production avant le
suivant — feuille de route : [`docs/chantiers/README.md`](docs/chantiers/README.md).
Chantier en cours : **Acte d'engagement Certification** (Monnaie libre), en binôme Yvv + Chiara.
Dérogation asymétrique : alourdir est libre (1 tap journalisé) ; alléger exige une note motivée
et une fenêtre d'objection.
## Comment marche un doc de référence
## Les 5 modalités
- On arrive sur **le texte en vigueur**, seul, lisible. Trois gestes contextuels : consulter le
vote, voir les propositions, proposer une modification.
- Chaque article est sous **vote permanent** : une proposition qui atteint son seuil (formule
inertielle Ğ1, plancher C de votants « pour ») **remonte en vigueur** et remplace la version
en place — si elle tient une marge plus large. Les textes de départ sont des *seeds a minima*,
à zéro vote.
- **Corriger n'est pas voter** : une coquille se corrige sans vote ; un changement de fond
ouvre une nouvelle révision, dont les votes antérieurs sont à reconfirmer.
- Deux propositions qui **se contredisent** ne passent pas ensemble : un signalement bloque la
seconde tant qu'il n'est pas levé.
- L'**inertie** de chaque article se vote aussi (par défaut : un cran au-dessus).
- Tout ce qui entre en vigueur est **publié automatiquement** dans un dépôt git
(fr/en/es + JSON) lu par les applications clientes.
Chaque protocole est nommé et référencé par une clause du Pacte — le modifier, c'est amender
le Pacte.
1. **Consentement** — « Ça me va / J'objecte » : zéro objection maintenue = adopté. Le repli
universel : tout collectif en a un (invariant).
2. **Nuancé 6 niveaux** — de « Pas du tout » à « Tout à fait », jamais « contre » ;
histogramme visible, commentaire obligatoire sur les niveaux bas.
3. **Paramétrique** — décider au curseur : faisceau des positions, médiane vivante, carte
« Pour moi » ; la cristallisation finale est un geste humain daté du garant, jamais un
automatisme.
4. **Élection** — réservée aux mandats et aux problématiques d'échelle (6 méthodes de
nomination, vote blanc, jamais de départage par l'outil).
5. **Binaire inertiel** — le seuil `C + B^W + (M + (1−M)(1−(T/W)^G))·max(0, T−C)`, héritage
Ğ1 remis à sa place : l'outil de dernier recours des très grands corps. L'Atelier des
formules (`/textes/formules`) reste son école.
## Local-first
- **Aucun serveur requis** : tout l'état vit dans le navigateur (IndexedDB via idb-keyval,
une clé par collectif).
- **Export / import** de bundles JSON — la fédération, c'est l'échange de bundles, jamais une
table.
- **Seeds** livrés et importés par le même chemin que l'import utilisateur :
- `duniter-g1.bundle.json` — la toile Ğ1 : 33 clauses Certification + 59 clauses Forgeron
(textes votés intacts, provenance et décomptes conservés), protocoles, 3 mandats ;
- `atelier-du-canal.bundle.json` — association fictive de 12 membres, le test permanent de
marque blanche : décisions à tous les états, paramétrique vivant, épreuve du réel due.
- **7 gabarits** de collectif à la création (`/creer`) : page blanche, informel, association,
coopérative, commune, monnaie libre, institution symétrique.
Le détail, les décisions et leurs raisons : [`docs/chantiers/acte-certification/CHANTIER.md`](docs/chantiers/acte-certification/CHANTIER.md)
et [`docs/adr/`](docs/adr/).
## Stack
- **Frontend** : Nuxt 4 (SPA, SSR off) + Vue 3 + TypeScript + Nuxt UI v3 + Pinia + UnoCSS ;
npm ; port **3002**
- **Moteurs purs** : `frontend/app/engine/` — triage, machine à états, seuils, médiane
paramétrique, nuancé, périmètres — zéro dépendance Nuxt, testés vitest (**342 tests**)
- **Backend v1** (FastAPI + SQLAlchemy async) : conservé dans `backend/` pour la future
synchronisation multi-appareils — non requis pour utiliser ou développer le frontend
- **Serveur** : Rust (edition 2024, toolchain 1.99 épinglée) — axum 0.8, sqlx/SQLite, tokio.
Trois crates : `ld-engine` (moteur pur : seuils, édition, assistant, composition),
`trustin-access` (règles d'accès de trustinWallet), `ld-server` (API + publication + service
de l'interface).
- **Interface** : SvelteKit 2 / Svelte 5 (runes), SPA statique servie par le serveur ;
trilingue fr · en · es dès le départ (le français fait foi).
- **Déploiement** : une seule image Docker, Woodpecker → sonic (fabio), volume de données nommé.
## Démarrage
## Démarrer
```bash
cd frontend
npm install
npm run dev # http://localhost:3002
npm test # vitest — 342 tests
npm run build # build de production
export PATH=$HOME/.cargo/bin:$PATH
cd web && npm ci && npm run build && cd .. # l'interface compilée
LD_DEV_LOGIN=1 cargo run -p ld-server # API + interface sur :8002
cd web && npm run dev # interface à chaud sur :3002 (proxy /api → :8002)
```
## Structure v2
`LD_DEV_LOGIN=1` ouvre une connexion de développement (sans clé, membre de tous les groupes) —
jamais en production. Toutes les variables : [`.env.example`](.env.example).
## Vérifier (la boucle)
```bash
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
```
Les contrôles d'usage (C1–C10, M1) sont décrits dans
[`docs/chantiers/acte-certification/CONTROLES.md`](docs/chantiers/acte-certification/CONTROLES.md) ;
les tests de Chiara en sont la version humaine.
## Structure
```
frontend/app/
engine/ # moteurs purs (barrel index.ts — seul point d'import)
data/ # persistence.ts (IndexedDB), templates.ts (7 gabarits), seeds/*.bundle.json
stores/ # collective.ts (le tenant) + decisions.ts (façade d'actions)
composables/ # useMood, useFeed, useSearch
components/ # par domaine : chemin/ decisions/ votes/ texts/ mandates/ feed/ onboarding/ common/
pages/ # 14 routes : / decider decisions(+id, vote, observatoire)
# textes(+slug, formules) mandats(+id, nouveau) creer donnees
lexicon.ts # source unique des libellés FR + test anti-lexique
types/domain.ts # le noyau du modèle
docs/dev/BLUEPRINT-V2.md # la référence produit
crates/
ld-engine/ # moteur pur, sans I/O : threshold, edit, assist, compose
trustin-access/ # qui voit, qui ouvre, qui gère les accès
ld-server/ # axum : auth Ğ1 + invitations, docs, propositions, votes, adoption, publication
migrations/ # schéma SQLite (données runtime : jamais réécrites)
tests/api.rs # scénarios bout en bout de l'API
seeds/ # documents de départ (JSON trilingue), instanciés une seule fois par groupe
web/
src/lib/ # api, session, i18n (fr source, en, es), composants
src/routes/ # accueil, groupes, lecteur du texte, trustinWallet (/acces)…
e2e/ # Playwright : C1–C10, M1
docker/ # app.Dockerfile + app-compose.yml (sonic)
.woodpecker/ # app.yml (le produit) · maquette.yml (la maquette)
docs/ # chantiers/, adr/, dev/ (blueprint v2), recherche/
maquette/ # la v2 Nuxt + FastAPI, telle quelle
```
## Licence
Logiciel libre. Le fichier LICENSE sera posé avant la première publication.
Logiciel libre — la licence reste à choisir (question ouverte à Yvv) ; le fichier LICENSE sera
posé avant toute publication du code.