All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- seed.py : 3 foyers avec codes fixes (DEVTEST2/3/4, RS/RP/PRO) insérés avant les 363 réels ; existing_codes pré-chargé → zéro collision - page citizen : dev hint mis à jour avec les 3 mêmes codes + profils - CLAUDE.md : reformaté en guide de session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
SejeteralO
Plateforme de tarification participative de l'eau pour communes françaises. Les citoyens votent sur la forme de la courbe tarifaire via des éditeurs Bézier interactifs ; le système calcule un tarif à équilibre de recettes en temps réel.
Protocole de début de session
git pull --rebase origin main- Vérifier que
data/existe à la racine — si absent, signaler avant toute opération - Si l'objectif de la session n'est pas précisé, le demander
Stack
- Frontend : Nuxt 4 (Vue 3, TypeScript) + Pinia ; package manager : npm ; port dev : 3009
- Backend : Python FastAPI + SQLAlchemy 2.0 async + SQLite (aiosqlite) ; port dev : 8000
- Déploiement : Docker multi-stage + Traefik (backend + frontend) ; CI Woodpecker
- Pas d'UnoCSS — CSS vanilla avec variables CSS palettes dans
main.css
Structure
frontend/
app/
components/ # composants Vue (dont DisplaySettings.vue — 6 palettes)
layouts/ # layouts Nuxt
pages/
commune/[slug]/index.vue # page principale citoyenne (~1900 lignes)
composables/
useApi.ts # wraps fetch avec Bearer token ; usage : api.get<Type>('/path')
middleware/ # route middleware (auth)
plugins/
auth-restore.client.ts # restaure token depuis localStorage au démarrage
stores/
auth.ts # token, role, communeSlug
commune.ts
utils/
bezier-math.ts # formule Bézier (Cardano + Newton-Raphson) — miroir du backend
nuxt.config.ts # port 3009, apiBase via NUXT_PUBLIC_API_BASE (défaut :8000)
backend/
app/
routers/ # 6 routers : auth, communes, tariff, votes, households, content
engine/
pricing.py # compute_p0(), compute_tariff(), compute_impacts()
integrals.py # coefficients α₁, α₂, β₂ (intégrales Bézier)
median.py # médiane élément par élément des votes
current_model.py # tarif linéaire de référence
models/ # Commune, TariffParams, Household, Vote, AdminUser, CommuneContent
alembic/versions/ # migrations
tests/
seed.py # Commune Saoû, 363 foyers, codes auth 8 chars, comptes admin
data/ # runtime — JAMAIS dans git (voir Données runtime)
docker/
docker-compose.yml # backend + frontend (réseau traefik externe)
backend.Dockerfile
frontend.Dockerfile
docker-compose.dev.yml
Makefile # docker-up, docker-dev
Données runtime (CRITIQUE)
data/à la racine : contenu non géré par git, jamais écrasé par les commits- Volume Docker
backend-datamonté sur/app— contientsejeteralo.db(SQLite) - Avant toute migration de chemin ou écriture sur data/ ou le volume : demander confirmation
- En dev local : la DB SQLite est dans
backend/(chemin relatif./sejeteralo.db) - Seed requis après chaque reset DB :
cd backend && python seed.py
Commandes
# Backend
cd backend && . venv/bin/activate
uvicorn app.main:app --reload --port 8000 --host 0.0.0.0
python -m pytest tests/ -v
python seed.py # Saoû, 363 foyers, admin accounts
# Frontend
cd frontend && npm run dev # :3009
npm run build
# Docker
make docker-up # production
make docker-dev # dev avec hot-reload
Conventions / pièges
- UI français, code anglais — "foyer" = household (facturation), "électeur" = voter (vote)
- Modèle Bézier deux niveaux — 6 paramètres citoyens (vinf, a, b, c, d, e) + p0 auto-calculé :
Implémenté deux fois : backend Python (
p0 = (Recettes − Σabo − Σβ₂) / Σ(α₁ + α₂)engine/pricing.py) et frontend TS (utils/bezier-math.ts) — garder synchronisés - Agrégation votes : médiane élément par élément des votes actifs (pas moyenne)
- Graphiques SVG : axe X inversé (volumes élevés à gauche) — utiliser bindings réactifs
t.*ouvar(--svg-*), jamais de couleurs hex codées en dur dans les SVG - Thème : 6 palettes via
useState('theme-dark'); CSS vars :--color-primary,--color-bg,--color-surface,--color-text,--color-border,--svg-plot-bg,--svg-grid,--svg-text,--svg-text-light;.palette-darksur<html> - Dev hints : classe
.dev-hint+v-if="isDev"; les codes auth doivent exister dans la DB seedée - Port backend : 8000 en local (nuxt.config + uvicorn) — la table globale CLAUDE.md indique 8009 par erreur ; les fichiers de config font foi
- Pas de
ssr: true— CSR uniquement