Create documentation for project architecture, deployment, and usage
Add DAT, DEX, GITEA_TUTO, and WIKI markdown files to the docs directory, and update agent_assets_metadata.toml to include these new documents. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 923ae0e3-a363-4db8-b04a-e8baca2a1330 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 4bb1a658-d577-451e-965c-fa15e2c21ca9 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8af7d2ec-2cc3-4ece-8af3-9f071488d072/923ae0e3-a363-4db8-b04a-e8baca2a1330/RusmVRz Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -6,3 +6,27 @@ id = "x31gBYdQKnMGZriV7IJ1v"
|
||||
uri = "file://DEPLOIEMENT.md"
|
||||
type = "text"
|
||||
title = "Guide d'auto-hébergement RockyLinux"
|
||||
|
||||
[[outputs]]
|
||||
id = "QwHkF1SFkRpZFuyRMNI9h"
|
||||
uri = "file://docs/GITEA_TUTO.md"
|
||||
type = "text"
|
||||
title = "Tutoriel — Récupérer le projet sur Gitea"
|
||||
|
||||
[[outputs]]
|
||||
id = "wdBpdE1lSme8lM2xYd3oJ"
|
||||
uri = "file://docs/DAT.md"
|
||||
type = "text"
|
||||
title = "DAT — Document d'Architecture Technique"
|
||||
|
||||
[[outputs]]
|
||||
id = "NXFvDFOIzX862xNq15Mak"
|
||||
uri = "file://docs/DEX.md"
|
||||
type = "text"
|
||||
title = "DEX — Document d'Exploitation"
|
||||
|
||||
[[outputs]]
|
||||
id = "kJNXgVnYp_LQmPcWr6Osb"
|
||||
uri = "file://docs/WIKI.md"
|
||||
type = "text"
|
||||
title = "Wiki — La Voix du Peuple"
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
# Document d'Architecture Technique — La Voix du Peuple
|
||||
|
||||
**Version** : 1.0
|
||||
**Date** : Avril 2026
|
||||
**Statut** : En production (Replit), prêt pour auto-hébergement
|
||||
|
||||
---
|
||||
|
||||
## 1. Présentation générale
|
||||
|
||||
**La Voix du Peuple** est une plateforme civique permettant à des citoyens de soumettre des propositions politiques. Ces contributions sont :
|
||||
|
||||
1. Filtrées par un agent IA selon le droit international des droits humains
|
||||
2. Synthétisées automatiquement en un résumé clair par thème
|
||||
3. Affichées en temps réel à destination d'élus ou de décideurs
|
||||
|
||||
---
|
||||
|
||||
## 2. Architecture globale
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Navigateur client │
|
||||
│ React + Vite (TypeScript) │
|
||||
└────────────────────────┬────────────────────────────────┘
|
||||
│ HTTP/REST (JSON)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Reverse Proxy — Nginx / HAProxy │
|
||||
│ (rate limiting, TLS, X-Forwarded-For) │
|
||||
└────────────────────────┬────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Backend API — Flask (Python) │
|
||||
│ Port 8080 │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
||||
│ │ app.py │ │ ai_agent.py │ │ database.py │ │
|
||||
│ │ (routes) │──▶│ (filtre + │ │ (PostgreSQL) │ │
|
||||
│ │ │ │ synthèse) │ │ │ │
|
||||
│ └──────────────┘ └──────┬──────┘ └──────┬───────┘ │
|
||||
└─────────────────────────────┼───────────────┼──────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────────┐
|
||||
│ Mistral AI API │ │ PostgreSQL │
|
||||
│ api.mistral.ai │ │ (base DB) │
|
||||
└──────────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Composants
|
||||
|
||||
### 3.1 Frontend — React + Vite
|
||||
|
||||
| Élément | Détail |
|
||||
|---------|--------|
|
||||
| Framework | React 18 + TypeScript |
|
||||
| Build | Vite 7 |
|
||||
| Styles | Tailwind CSS + shadcn/ui |
|
||||
| Routing | Wouter |
|
||||
| État serveur | TanStack Query |
|
||||
| Client API | `@workspace/api-client-react` (généré depuis OpenAPI) |
|
||||
| Police | Bahnschrift (titres), Inter (corps) |
|
||||
|
||||
**Pages** :
|
||||
- `/` — Page principale (formulaire + fil + synthèse)
|
||||
- `/about` — À propos et fondements juridiques
|
||||
- `/transparence` — Fonctionnement technique et données collectées
|
||||
|
||||
**Variables d'environnement** :
|
||||
- `BASE_URL` — Préfixe de chemin (injecté par Vite)
|
||||
- `PORT` — Port du serveur de développement (assigné par Replit)
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Backend — Flask
|
||||
|
||||
| Élément | Détail |
|
||||
|---------|--------|
|
||||
| Framework | Flask 3 (Python 3.11+) |
|
||||
| Serveur WSGI | Gunicorn (production) |
|
||||
| CORS | flask-cors |
|
||||
| Rate limiting | flask-limiter (5 req/min par IP sur POST /api/ideas) |
|
||||
| ORM | psycopg2-binary (requêtes SQL directes) |
|
||||
|
||||
**Endpoints** :
|
||||
|
||||
| Méthode | Route | Description |
|
||||
|---------|-------|-------------|
|
||||
| `GET` | `/api/ideas` | Liste des contributions acceptées |
|
||||
| `POST` | `/api/ideas` | Soumet une nouvelle contribution |
|
||||
| `GET` | `/api/ideas/stats` | Statistiques (acceptées/refusées) |
|
||||
| `GET` | `/api/synthesis` | Texte de synthèse actuel |
|
||||
| `GET` | `/health` | Health check |
|
||||
|
||||
**Réponses** : JSON camelCase, statuts HTTP standard.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Agent IA
|
||||
|
||||
Deux appels distincts à l'API Mistral (compatible OpenAI SDK) :
|
||||
|
||||
#### Filtre de modération
|
||||
|
||||
- **Modèle** : `mistral-small-latest` (configurable via `FILTER_MODEL`)
|
||||
- **Entrée** : Texte brut de la contribution
|
||||
- **Sortie** : JSON `{"accepted": bool, "reason"?: string, "legal_basis"?: string}`
|
||||
- **Référentiel** : DUDH, PIDCP, CEDH, Charte UE, CERD, Statut de Rome
|
||||
- **Max tokens** : 300
|
||||
|
||||
#### Synthèse collective
|
||||
|
||||
- **Modèle** : `mistral-large-latest` (configurable via `SYNTHESIS_MODEL`)
|
||||
- **Entrée** : Liste de toutes les contributions acceptées
|
||||
- **Sortie** : Texte libre structuré par thèmes, destiné aux élus
|
||||
- **Max tokens** : 1200
|
||||
- **Déclencheur** : À chaque nouvelle contribution acceptée (asynchrone)
|
||||
|
||||
**Priorité de configuration du client IA** :
|
||||
1. `MISTRAL_API_KEY` → `https://api.mistral.ai/v1`
|
||||
2. `OPENAI_API_KEY` → API OpenAI standard
|
||||
3. `AI_INTEGRATIONS_OPENAI_*` → Proxy Replit (intégration native)
|
||||
|
||||
---
|
||||
|
||||
### 3.4 Base de données — PostgreSQL
|
||||
|
||||
**Table `ideas`** :
|
||||
|
||||
| Colonne | Type | Description |
|
||||
|---------|------|-------------|
|
||||
| `id` | SERIAL PK | Identifiant |
|
||||
| `content` | TEXT | Texte de la contribution |
|
||||
| `author` | VARCHAR(100) | Pseudonyme (nullable) |
|
||||
| `accepted` | BOOLEAN | Résultat du filtre |
|
||||
| `rejection_reason` | TEXT | Motif de refus (nullable) |
|
||||
| `legal_basis` | TEXT | Base légale du refus (nullable) |
|
||||
| `created_at` | TIMESTAMPTZ | Horodatage de soumission |
|
||||
|
||||
**Table `synthesis`** :
|
||||
|
||||
| Colonne | Type | Description |
|
||||
|---------|------|-------------|
|
||||
| `id` | SERIAL PK | (toujours 1 — ligne unique) |
|
||||
| `text` | TEXT | Dernier texte de synthèse |
|
||||
| `idea_count` | INTEGER | Nombre de contributions intégrées |
|
||||
| `updated_at` | TIMESTAMPTZ | Dernière mise à jour |
|
||||
|
||||
---
|
||||
|
||||
## 4. Variables d'environnement
|
||||
|
||||
| Variable | Obligatoire | Description |
|
||||
|----------|-------------|-------------|
|
||||
| `DATABASE_URL` | ✅ | URL PostgreSQL complète |
|
||||
| `MISTRAL_API_KEY` | ✅ (ou OpenAI) | Clé API Mistral |
|
||||
| `SESSION_SECRET` | ✅ | Secret Flask (sessions) |
|
||||
| `FILTER_MODEL` | — | Modèle de filtrage (défaut : `mistral-small-latest`) |
|
||||
| `SYNTHESIS_MODEL` | — | Modèle de synthèse (défaut : `mistral-large-latest`) |
|
||||
| `OPENAI_API_KEY` | — | Alternative à Mistral |
|
||||
| `MISTRAL_BASE_URL` | — | URL custom Mistral (défaut : `https://api.mistral.ai/v1`) |
|
||||
|
||||
---
|
||||
|
||||
## 5. Infrastructure de déploiement (auto-hébergement)
|
||||
|
||||
```
|
||||
Internet ──▶ HAProxy (TLS, load balancing)
|
||||
└──▶ Nginx (reverse proxy, rate limiting IP)
|
||||
└──▶ Gunicorn × N workers (Flask)
|
||||
└──▶ Fichiers statiques Vite (build)
|
||||
│
|
||||
PostgreSQL (local ou RDS)
|
||||
```
|
||||
|
||||
**Fichiers fournis** :
|
||||
- `deploy/nginx.conf` — Configuration Nginx avec HAProxy support
|
||||
- `deploy/voix-du-peuple-api.service` — Unité systemd pour Gunicorn
|
||||
- `artifacts/voix-du-peuple/vite.config.selfhost.ts` — Build sans plugins Replit
|
||||
|
||||
---
|
||||
|
||||
## 6. Sécurité
|
||||
|
||||
| Mesure | Implémentation |
|
||||
|--------|----------------|
|
||||
| Rate limiting | 5 POST/min par IP (flask-limiter) |
|
||||
| Sanitisation | bleach sur le contenu avant stockage |
|
||||
| CORS | Origines configurées explicitement |
|
||||
| SQL injection | Requêtes paramétrées (psycopg2) |
|
||||
| Secrets | Variables d'environnement uniquement, jamais dans le code |
|
||||
| Données personnelles | Aucune IP stockée, pseudonyme facultatif |
|
||||
|
||||
---
|
||||
|
||||
## 7. Flux de traitement d'une contribution
|
||||
|
||||
```
|
||||
POST /api/ideas
|
||||
│
|
||||
├─ Validation (longueur 10–1000 chars)
|
||||
├─ Sanitisation (bleach)
|
||||
├─ INSERT en base (statut pending)
|
||||
│
|
||||
├─ Appel Mistral (filtre)
|
||||
│ ├─ accepted=true → UPDATE idea, déclenche synthèse async
|
||||
│ └─ accepted=false → UPDATE idea avec motif
|
||||
│
|
||||
├─ [async] Appel Mistral (synthèse) sur toutes contributions acceptées
|
||||
│ └─ UPSERT table synthesis
|
||||
│
|
||||
└─ Réponse JSON 201
|
||||
```
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
# Document d'Exploitation — La Voix du Peuple
|
||||
|
||||
**Version** : 1.0
|
||||
**Date** : Avril 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Démarrage et arrêt des services
|
||||
|
||||
### Sur Replit
|
||||
|
||||
Les services sont gérés par les **Workflows** Replit. Ils démarrent automatiquement.
|
||||
|
||||
| Workflow | Commande | Port |
|
||||
|----------|----------|------|
|
||||
| API Server | `PORT=8080 sh artifacts/flask-api/start.sh` | 8080 |
|
||||
| Frontend | `pnpm --filter @workspace/voix-du-peuple run dev` | auto |
|
||||
|
||||
Pour redémarrer manuellement : onglet **Workflows** → bouton restart.
|
||||
|
||||
---
|
||||
|
||||
### En auto-hébergement (RockyLinux / Debian)
|
||||
|
||||
```bash
|
||||
# Démarrer le backend
|
||||
systemctl start voix-du-peuple-api
|
||||
|
||||
# Arrêter le backend
|
||||
systemctl stop voix-du-peuple-api
|
||||
|
||||
# Redémarrer après mise à jour
|
||||
systemctl restart voix-du-peuple-api
|
||||
|
||||
# Voir le statut
|
||||
systemctl status voix-du-peuple-api
|
||||
|
||||
# Activer au démarrage
|
||||
systemctl enable voix-du-peuple-api
|
||||
```
|
||||
|
||||
```bash
|
||||
# Redémarrer Nginx après modification de la config
|
||||
nginx -t && systemctl reload nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Variables d'environnement
|
||||
|
||||
Fichier de référence : `.env.example` à la racine du projet.
|
||||
|
||||
En production, créer `/etc/voix-du-peuple/.env` :
|
||||
|
||||
```bash
|
||||
# Base de données
|
||||
DATABASE_URL=postgresql://user:password@localhost:5432/voix_du_peuple
|
||||
|
||||
# IA — choisir l'un des deux
|
||||
MISTRAL_API_KEY=sk-...
|
||||
# OPENAI_API_KEY=sk-...
|
||||
|
||||
# Modèles (optionnel — valeurs par défaut ci-dessous)
|
||||
FILTER_MODEL=mistral-small-latest
|
||||
SYNTHESIS_MODEL=mistral-large-latest
|
||||
|
||||
# Sécurité Flask
|
||||
SESSION_SECRET=une-longue-chaine-aleatoire-securisee
|
||||
```
|
||||
|
||||
> **Important** : Après toute modification du fichier `.env`, redémarrer le service API.
|
||||
|
||||
---
|
||||
|
||||
## 3. Mise à jour du code
|
||||
|
||||
```bash
|
||||
# Depuis votre serveur, après un git pull
|
||||
cd /opt/voix-du-peuple
|
||||
|
||||
git pull gitea main
|
||||
|
||||
# Mettre à jour les dépendances Python si requirements.txt a changé
|
||||
pip install -r artifacts/flask-api/requirements.txt
|
||||
|
||||
# Reconstruire le frontend si le code frontend a changé
|
||||
pnpm install
|
||||
pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts
|
||||
|
||||
# Redémarrer l'API
|
||||
systemctl restart voix-du-peuple-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Consultation des logs
|
||||
|
||||
### Sur Replit
|
||||
|
||||
Voir les logs dans l'onglet **Workflows** → cliquer sur le workflow concerné.
|
||||
|
||||
### En auto-hébergement
|
||||
|
||||
```bash
|
||||
# Logs du service systemd (temps réel)
|
||||
journalctl -u voix-du-peuple-api -f
|
||||
|
||||
# 100 dernières lignes
|
||||
journalctl -u voix-du-peuple-api -n 100
|
||||
|
||||
# Logs d'une journée spécifique
|
||||
journalctl -u voix-du-peuple-api --since "2026-04-01" --until "2026-04-02"
|
||||
|
||||
# Logs Nginx
|
||||
tail -f /var/log/nginx/access.log
|
||||
tail -f /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Base de données
|
||||
|
||||
### Connexion directe
|
||||
|
||||
```bash
|
||||
psql "$DATABASE_URL"
|
||||
# ou
|
||||
psql -U voix_user -d voix_du_peuple -h localhost
|
||||
```
|
||||
|
||||
### Requêtes utiles
|
||||
|
||||
```sql
|
||||
-- Nombre de contributions par statut
|
||||
SELECT accepted, COUNT(*) FROM ideas GROUP BY accepted;
|
||||
|
||||
-- Dernières contributions
|
||||
SELECT id, author, left(content, 60), accepted, created_at
|
||||
FROM ideas ORDER BY created_at DESC LIMIT 10;
|
||||
|
||||
-- Contributions refusées avec motif
|
||||
SELECT id, left(content, 60), rejection_reason, created_at
|
||||
FROM ideas WHERE accepted = false ORDER BY created_at DESC;
|
||||
|
||||
-- État de la synthèse
|
||||
SELECT idea_count, left(text, 200), updated_at FROM synthesis;
|
||||
```
|
||||
|
||||
### Sauvegarde
|
||||
|
||||
```bash
|
||||
# Dump complet
|
||||
pg_dump "$DATABASE_URL" > backup_$(date +%Y%m%d_%H%M).sql
|
||||
|
||||
# Restauration
|
||||
psql "$DATABASE_URL" < backup_20260401_0800.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Vérification du bon fonctionnement
|
||||
|
||||
```bash
|
||||
# Health check API
|
||||
curl http://localhost:8080/health
|
||||
|
||||
# Test de soumission
|
||||
curl -X POST http://localhost:8080/api/ideas \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "Test de fonctionnement de la plateforme.", "author": "Admin"}'
|
||||
|
||||
# Lecture de la synthèse
|
||||
curl http://localhost:8080/api/synthesis | python3 -m json.tool
|
||||
|
||||
# Statistiques
|
||||
curl http://localhost:8080/api/ideas/stats
|
||||
```
|
||||
|
||||
Réponse attendue du health check :
|
||||
```json
|
||||
{"status": "ok"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Changement de modèle IA
|
||||
|
||||
Pour basculer vers un modèle différent sans toucher au code :
|
||||
|
||||
```bash
|
||||
# Exemple : passer à mistral-medium
|
||||
# Éditer le .env
|
||||
FILTER_MODEL=mistral-medium-latest
|
||||
SYNTHESIS_MODEL=mistral-medium-latest
|
||||
|
||||
# Redémarrer
|
||||
systemctl restart voix-du-peuple-api
|
||||
```
|
||||
|
||||
Modèles Mistral disponibles (avril 2026) :
|
||||
- `mistral-small-latest` — Rapide, économique (filtre)
|
||||
- `mistral-medium-latest` — Équilibré
|
||||
- `mistral-large-latest` — Meilleure qualité (synthèse)
|
||||
|
||||
---
|
||||
|
||||
## 8. Purge des données
|
||||
|
||||
```sql
|
||||
-- Supprimer toutes les contributions (irréversible)
|
||||
TRUNCATE ideas;
|
||||
TRUNCATE synthesis;
|
||||
|
||||
-- Supprimer uniquement les contributions refusées
|
||||
DELETE FROM ideas WHERE accepted = false;
|
||||
|
||||
-- Forcer une re-synthèse (supprimer le cache)
|
||||
DELETE FROM synthesis;
|
||||
```
|
||||
|
||||
Après une purge, la synthèse se régénère automatiquement à la prochaine contribution acceptée.
|
||||
|
||||
---
|
||||
|
||||
## 9. Dépannage courant
|
||||
|
||||
| Symptôme | Cause probable | Solution |
|
||||
|----------|---------------|----------|
|
||||
| `Service temporairement indisponible` sur soumission | Clé Mistral invalide ou quota dépassé | Vérifier `MISTRAL_API_KEY`, consulter console.mistral.ai |
|
||||
| Synthèse non mise à jour | Erreur silencieuse en arrière-plan | Consulter les logs, vérifier la connexion à l'API IA |
|
||||
| Erreur 500 sur toutes les routes | `DATABASE_URL` incorrect ou PostgreSQL arrêté | `systemctl status postgresql`, vérifier le `.env` |
|
||||
| Frontend vide (page blanche) | Build manquant ou `BASE_URL` incorrect | Relancer le build Vite, vérifier la config Nginx |
|
||||
| Rate limit atteint (429) | Trop de soumissions depuis la même IP | Normal — attendre 1 minute |
|
||||
| Modèle IA introuvable (404) | Nom de modèle incorrect dans `FILTER_MODEL` | Corriger le nom, redémarrer le service |
|
||||
|
||||
---
|
||||
|
||||
## 10. Contacts et ressources
|
||||
|
||||
- Documentation Mistral : https://docs.mistral.ai
|
||||
- PostgreSQL : https://www.postgresql.org/docs/
|
||||
- Flask : https://flask.palletsprojects.com
|
||||
- Guide de déploiement complet : `DEPLOIEMENT.md`
|
||||
- Architecture : `docs/DAT.md`
|
||||
@@ -0,0 +1,156 @@
|
||||
# Récupérer le projet sur Gitea
|
||||
|
||||
Ce tutoriel explique comment pousser le code de **La Voix du Peuple** depuis Replit vers votre instance Gitea, et comment vous synchroniser ensuite à votre rythme.
|
||||
|
||||
---
|
||||
|
||||
## Prérequis
|
||||
|
||||
- Une instance Gitea accessible (ex. `https://git.mondomaine.fr`)
|
||||
- Un compte avec les droits de création de dépôt
|
||||
- Git installé localement (si vous travaillez aussi depuis votre poste)
|
||||
|
||||
---
|
||||
|
||||
## Étape 1 — Créer le dépôt sur Gitea
|
||||
|
||||
1. Connectez-vous à votre Gitea
|
||||
2. Cliquez sur **+ New Repository**
|
||||
3. Nom suggéré : `voix-du-peuple`
|
||||
4. Laissez-le **vide** (pas de README, pas de .gitignore)
|
||||
5. Notez l'URL du dépôt — elle ressemble à :
|
||||
- SSH : `git@git.mondomaine.fr:vous/voix-du-peuple.git`
|
||||
- HTTPS : `https://git.mondomaine.fr/vous/voix-du-peuple.git`
|
||||
|
||||
---
|
||||
|
||||
## Étape 2 — Ajouter Gitea comme remote depuis Replit
|
||||
|
||||
Dans le shell Replit (onglet **Shell**) :
|
||||
|
||||
```bash
|
||||
# Vérifier les remotes actuels
|
||||
git remote -v
|
||||
|
||||
# Ajouter votre Gitea comme remote (choisissez SSH ou HTTPS)
|
||||
git remote add gitea git@git.mondomaine.fr:vous/voix-du-peuple.git
|
||||
# ou en HTTPS :
|
||||
git remote add gitea https://git.mondomaine.fr/vous/voix-du-peuple.git
|
||||
|
||||
# Vérifier
|
||||
git remote -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Étape 3 — Configurer l'authentification
|
||||
|
||||
### Option A — SSH (recommandé)
|
||||
|
||||
Générez une clé SSH dans le shell Replit si vous n'en avez pas :
|
||||
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -C "replit-voix-du-peuple"
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
Copiez la clé publique affichée et ajoutez-la dans Gitea :
|
||||
**Paramètres → Clés SSH → Ajouter une clé**
|
||||
|
||||
Testez la connexion :
|
||||
|
||||
```bash
|
||||
ssh -T git@git.mondomaine.fr
|
||||
```
|
||||
|
||||
### Option B — HTTPS avec token
|
||||
|
||||
Dans Gitea : **Paramètres → Applications → Générer un token**
|
||||
|
||||
Utilisez l'URL avec token :
|
||||
|
||||
```bash
|
||||
git remote set-url gitea https://VOTRE_TOKEN@git.mondomaine.fr/vous/voix-du-peuple.git
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Étape 4 — Pousser le code
|
||||
|
||||
```bash
|
||||
# Premier push (établit le tracking)
|
||||
git push -u gitea main
|
||||
|
||||
# Pour les push suivants
|
||||
git push gitea main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Étape 5 — Récupérer les mises à jour depuis Replit
|
||||
|
||||
Chaque fois que vous voulez synchroniser votre Gitea avec l'état actuel du projet Replit :
|
||||
|
||||
```bash
|
||||
# Depuis le shell Replit
|
||||
git push gitea main
|
||||
```
|
||||
|
||||
Si vous avez également modifié des fichiers directement sur Gitea :
|
||||
|
||||
```bash
|
||||
git pull gitea main --rebase
|
||||
git push gitea main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Étape 6 — Cloner depuis Gitea sur votre serveur de production
|
||||
|
||||
Sur votre serveur RockyLinux / Debian :
|
||||
|
||||
```bash
|
||||
git clone git@git.mondomaine.fr:vous/voix-du-peuple.git
|
||||
cd voix-du-peuple
|
||||
|
||||
# Copier et adapter les variables d'environnement
|
||||
cp .env.example .env
|
||||
nano .env # Renseignez DATABASE_URL, MISTRAL_API_KEY, SESSION_SECRET
|
||||
|
||||
# Suivre ensuite le guide DEPLOIEMENT.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Résumé des commandes utiles
|
||||
|
||||
```bash
|
||||
# Voir l'état du dépôt
|
||||
git status
|
||||
git log --oneline -10
|
||||
|
||||
# Synchroniser vers Gitea
|
||||
git push gitea main
|
||||
|
||||
# Récupérer depuis Gitea
|
||||
git pull gitea main
|
||||
|
||||
# Voir les remotes configurés
|
||||
git remote -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Structure des branches
|
||||
|
||||
| Branche | Usage |
|
||||
|---------|-------|
|
||||
| `main` | Code de production, stable |
|
||||
| `replit-agent` | Branche de travail de l'agent Replit (interne) |
|
||||
|
||||
> Il est conseillé de ne travailler que sur `main` et de ne jamais pousser `replit-agent` vers votre Gitea.
|
||||
|
||||
```bash
|
||||
# Pousser uniquement main
|
||||
git push gitea main
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
# La Voix du Peuple — Page wiki
|
||||
|
||||
**Type** : Plateforme civique numérique
|
||||
**Stack** : Python / Flask · React / Vite · PostgreSQL · Mistral AI
|
||||
**Hébergement** : Replit (dev) / Auto-hébergeable (RockyLinux, Debian)
|
||||
**Dépôt** : `voix-du-peuple` (Gitea)
|
||||
**Statut** : Actif — avril 2026
|
||||
|
||||
---
|
||||
|
||||
## Qu'est-ce que c'est ?
|
||||
|
||||
Un outil permettant à des citoyens de soumettre des propositions politiques en texte libre. Ces propositions sont :
|
||||
|
||||
- **filtrées** automatiquement par une IA selon les textes internationaux des droits humains (DUDH, PIDCP, CEDH…)
|
||||
- **synthétisées** en un résumé structuré par thèmes, destiné à des élus ou décideurs
|
||||
- **affichées** en temps réel sur la page principale
|
||||
|
||||
L'objectif est de fournir aux représentants politiques un document clair et utilisable issu des préoccupations citoyennes, sans intermédiaire.
|
||||
|
||||
---
|
||||
|
||||
## Fonctionnement en 5 points
|
||||
|
||||
1. Un citoyen saisit une proposition sur la page principale
|
||||
2. L'IA (Mistral Small) vérifie que le contenu respecte les droits fondamentaux
|
||||
3. Si la contribution est acceptée, elle s'ajoute à la base et déclenche une re-synthèse
|
||||
4. L'IA (Mistral Large) relit toutes les contributions et produit un résumé thématique
|
||||
5. Le résumé s'affiche en temps réel à droite de l'écran
|
||||
|
||||
---
|
||||
|
||||
## Pages de l'application
|
||||
|
||||
| URL | Contenu |
|
||||
|-----|---------|
|
||||
| `/` | Formulaire de soumission + contributions récentes + synthèse |
|
||||
| `/about` | Description du projet et fondements juridiques |
|
||||
| `/transparence` | Fonctionnement de l'IA, données collectées, limites |
|
||||
|
||||
---
|
||||
|
||||
## Stack technique
|
||||
|
||||
| Couche | Technologie |
|
||||
|--------|-------------|
|
||||
| Frontend | React 18 + TypeScript + Vite 7 + Tailwind CSS |
|
||||
| Backend | Python 3.11 + Flask 3 + Gunicorn |
|
||||
| Base de données | PostgreSQL |
|
||||
| IA | Mistral AI (API OpenAI-compatible) |
|
||||
| Modération | `mistral-small-latest` |
|
||||
| Synthèse | `mistral-large-latest` |
|
||||
| Police | Bahnschrift (titres), Inter (corps) |
|
||||
|
||||
---
|
||||
|
||||
## Variables d'environnement clés
|
||||
|
||||
```
|
||||
DATABASE_URL — URL PostgreSQL
|
||||
MISTRAL_API_KEY — Clé API Mistral
|
||||
SESSION_SECRET — Secret Flask
|
||||
FILTER_MODEL — Modèle de modération (optionnel)
|
||||
SYNTHESIS_MODEL — Modèle de synthèse (optionnel)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Données collectées
|
||||
|
||||
- Texte de la contribution
|
||||
- Pseudonyme (facultatif, choisi par l'utilisateur)
|
||||
- Horodatage
|
||||
- Résultat du filtre IA (accepté / refusé + motif)
|
||||
|
||||
**Non collecté** : adresse IP, compte utilisateur, cookies de suivi.
|
||||
|
||||
---
|
||||
|
||||
## Liens
|
||||
|
||||
- Tutoriel Gitea → [`docs/GITEA_TUTO.md`](./GITEA_TUTO.md)
|
||||
- Architecture technique → [`docs/DAT.md`](./DAT.md)
|
||||
- Exploitation → [`docs/DEX.md`](./DEX.md)
|
||||
- Guide déploiement → [`DEPLOIEMENT.md`](../DEPLOIEMENT.md)
|
||||
- Fonctionnement technique (in-app) → `/transparence`
|
||||
Reference in New Issue
Block a user