INVARIANTS — Pense-bête
0) Rôle du document
Ce document fixe les invariants techniques, structurels, métier, visuels et ergonomiques du projet Pense-bête.
Il sert de source de vérité pour :
- l’infrastructure locale et serveur
- les conventions Docker / Compose
- la structure Django / React
- les variables d’environnement
- les règles frontend/backend
- la cohérence visuelle avec les autres applications existantes
- les consignes à respecter par Codex et tout autre agent
En cas de conflit entre une proposition de code et ce document, ce document prévaut.
1) Identité du projet
1.1 Nommage canonique
- Nom humain :
Pense-bête - Nom dépôt Git :
pense_bete - Slug technique :
pb - Répertoire DEV :
~/projets/pense_bete - Répertoire PROD :
/opt/apps/pb
1.2 Variables d’identité
Les variables suivantes sont obligatoires :
APP_NAME=Pense-bête
APP_DEPOT=pense_bete
APP_SLUG=pb
APP_ENV=dev|prod
APP_NO=<entier unique>1.3 Rôle de APP_NO
APP_NO est l’identifiant numérique unique de l’application dans l’écosystème local.
Il sert à dériver les ports hôte en DEV.
2) Principes d’architecture
2.1 Stack imposée
Le projet utilise exclusivement :
- PostgreSQL
- Django + Django REST Framework
- SimpleJWT
- React + Vite
- Docker Compose
- Traefik comme frontal unique côté serveur
2.2 Interdictions
Il est interdit de :
- remplacer PostgreSQL par SQLite
- remplacer Django par un autre backend
- remplacer Vite/React par une autre stack frontend
- exposer directement les apps en PROD sur 80/443
- contourner Traefik
- introduire une seconde architecture concurrente
- modifier les noms canoniques des services Compose
- stocker des secrets dans les fichiers
.env.devou.env.prod
2.3 Objectif du projet
Pense-bête est une application de capture rapide et de suivi léger.
Ce n’est pas un agenda centré sur l’heure.
L’application est conçue pour :
- noter rapidement une idée ou une tâche
- suivre un dossier ouvert
- revoir des choses à penser ou à relancer
- distinguer ce qui est à faire, en attente, à acheter ou à revoir
3) Répertoires, nommage Docker et conventions système
3.1 Répertoires
- DEV :
~/projets/${APP_DEPOT} - PROD :
/opt/apps/${APP_SLUG}
3.2 Nommage Docker
- Containers :
${APP_SLUG}_<service>_${APP_ENV} - Réseau par défaut :
${APP_SLUG}_appnet - Volume DB recommandé :
${APP_SLUG}_db_data
3.3 Services Compose canoniques
Les services autorisés et attendus sont :
dbbackendvitefrontend
Ces noms sont stables et ne doivent pas être renommés.
4) Ports dérivés de APP_NO
4.1 Règle canonique
Si APP_NO = N, alors en DEV :
DEV_DB_PORT = 5432 + N
DEV_API_PORT = 8001 + N
DEV_VITE_PORT = 5173 + N4.2 Ports internes fixes
Les ports internes des conteneurs sont toujours :
- DB :
5432 - backend :
8000 - vite :
5173
Seuls les ports hôte varient via APP_NO.
4.3 Exemple pour Pense-bête
Si APP_NO=5, alors :
DEV_DB_PORT=5437
DEV_API_PORT=8006
DEV_VITE_PORT=51785) Environnements et secrets
5.1 Fichiers canoniques
Fichiers versionnés :
.env.dev.env.prod.env.local.example
Fichier non versionné :
.env.local
Symlink canonique :
.env -> .env.$(APP_ENV)5.2 Règles de secrets
Interdit dans .env.dev et .env.prod :
POSTGRES_PASSWORDDJANGO_SECRET_KEYADMIN_USERNAMEADMIN_EMAILADMIN_PASSWORD- tout autre secret réel
Autorisé dans .env.local seulement :
POSTGRES_PASSWORDDJANGO_SECRET_KEYADMIN_USERNAMEADMIN_EMAILADMIN_PASSWORD
5.3 Exemples
.env.dev
APP_ENV=dev
APP_NAME=Pense-bête
APP_DEPOT=pense_bete
APP_SLUG=pb
APP_NO=5
POSTGRES_USER=${APP_SLUG}_pg_user
POSTGRES_DB=${APP_SLUG}_pg_db
DEV_DB_PORT=5437
DEV_API_PORT=8006
DEV_VITE_PORT=5178
VITE_API_BASE=/api.env.prod
APP_ENV=prod
APP_NAME=Pense-bête
APP_DEPOT=pense_bete
APP_SLUG=pb
APP_NO=5
APP_HOST=pb.mon-site.ca
POSTGRES_USER=${APP_SLUG}_pg_user
POSTGRES_DB=${APP_SLUG}_pg_db
VITE_API_BASE=/api.env.local.example
POSTGRES_PASSWORD=change_me
DJANGO_SECRET_KEY=change_me
ADMIN_USERNAME=admin
ADMIN_EMAIL=admin@example.test
ADMIN_PASSWORD=change_me6) Postgres — invariants de connexion
6.1 Invariants
- Host compose :
db - Port interne :
5432 - Utilisateur :
${POSTGRES_USER}=${APP_SLUG}_pg_user - Base :
${POSTGRES_DB}=${APP_SLUG}_pg_db
6.2 Accès hors conteneur
En DEV, si publication activée :
localhost:${DEV_DB_PORT}En PROD :
- ne pas publier la DB publiquement
- privilégier un tunnel SSH ponctuel si nécessaire
6.3 Commandes psql canoniques
Depuis le conteneur backend :
docker compose --env-file .env.dev -f docker-compose.dev.yml exec backend \
psql -h db -p 5432 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c '\\dt'Depuis l’hôte si port publié :
psql -h localhost -p "$DEV_DB_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c 'select 1;'7) Conteneurisation (Compose)
7.1 Règles générales
- utiliser exclusivement
docker compose - toujours fournir
--env-file - conserver deux fichiers :
docker-compose.dev.yml
docker-compose.prod.yml7.2 Services
db: Postgresbackend: Django APIvite: serveur dev frontendfrontend: build statique / service web selon le mode
7.3 Healthchecks et dépendances
backenddépend dedbhealthyvitepeut dépendre debackenden DEV- le système doit démarrer sans ordre implicite fragile
7.4 PROD et exposition réseau
En PROD :
- ne jamais publier 80/443 depuis l’application
- Traefik reste le frontal unique
- un bind local
127.0.0.1:PORT->8000peut exister pour debug/health local seulement
8) Backend Django (API)
8.1 Règles générales
- commande DEV :
python manage.py runserver 0.0.0.0:8000 - toutes les routes backend sont sous le préfixe
/api/ - auth JWT via SimpleJWT
- API REST via DRF
- base de données PostgreSQL uniquement
8.2 Règles d’auth
JWTAuthenticationdoit être activé- les endpoints JWT doivent exister
- une route
whoamidoit exister - l’API doit être utilisable via le proxy Vite
/api - l’application doit être protégée par authentification
8.3 Structure recommandée
backend/
├── api/
│ ├── migrations/
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── serializers.py
│ ├── permissions.py
│ ├── urls.py
│ ├── views.py
│ ├── views_auth.py
│ └── views_login.py / views_logout.py
├── pb/
│ ├── settings.py
│ ├── urls.py
│ ├── asgi.py
│ └── wsgi.py
├── Dockerfile.dev
├── Dockerfile.prod
├── manage.py
└── requirements.txt8.4 Permissions
Chaque utilisateur ne voit que ses propres objets.
Règles :
- filtrer les querysets par
request.user - object-level permissions strictes
- pas de fuite de données inter-utilisateurs
9) Métier — modèle central
9.1 Entité principale
L’entité principale est Item.
Un Item représente :
- tâche
- achat
- suivi
- appel
- question
- idée
- document à obtenir
9.2 Champs métier minimaux
Le modèle Item doit prévoir au minimum :
titledetailskindstatusprioritycontextcontact_namedue_datereview_atcompleted_atcreated_atupdated_atuser
9.3 Types (kind)
Valeurs minimales :
taskbuyfollowupcallquestionideadocument
9.4 Statuts (status)
inboxnextwaitingscheduleddonearchived
9.5 Priorité (priority)
lownormalhigh
9.6 Distinction importante
due_date et review_at ne doivent pas être confondus.
due_date= échéance réellereview_at= moment où l’item doit revenir dans l’attention
9.7 Historique
Prévoir une entité ItemEvent pour tracer :
- création
- modification
- changement de statut
- report de revue
- marquage terminé
10) API métier
10.1 Endpoints minimaux
GET /api/items/POST /api/items/GET /api/items/{id}/PATCH /api/items/{id}/DELETE /api/items/{id}/
10.2 Endpoints utiles
/api/items/inbox//api/items/today//api/items/waiting//api/items/buy//api/items/review//api/items/overdue/
10.3 Actions rapides
POST /api/items/{id}/mark_done/POST /api/items/{id}/move_to_inbox/POST /api/items/{id}/set_waiting/POST /api/items/{id}/reschedule_review/
10.4 Recherche / filtres
GET /api/items/ doit permettre de filtrer par :
statuskindpriorityq
11) Frontend React / Vite
11.1 Stack frontend
- React
- Vite
- proxy
/apivershttp://backend:8000 VITE_API_BASE=/api
11.2 Règles frontend
- ne jamais coder une base API absolue
- utiliser
VITE_API_BASE - passer par le proxy Vite
11.3 Structure recommandée
frontend/src/
├── api.js
├── App.jsx
├── main.jsx
├── styles.css
├── components/
│ ├── QuickCapture.jsx
│ ├── ItemForm.jsx
│ ├── ItemList.jsx
│ ├── ItemCard.jsx
│ ├── ItemFilters.jsx
│ ├── StatusBadge.jsx
│ └── ToastProvider.jsx
└── pages/
├── LoginPage.jsx
├── InboxPage.jsx
├── TodayPage.jsx
├── WaitingPage.jsx
├── BuyPage.jsx
├── AllItemsPage.jsx
└── ItemDetailPage.jsx11.4 Token frontend
Clé recommandée :
pb.jwt11.5 Intercepteur
Un intercepteur 401 peut rediriger vers la page de login.
12) Vues fonctionnelles minimales
- Login
- Inbox
- Aujourd’hui
- En attente
- Achats
- Tous
- Détail item
13) Invariants UX
Principe fondamental
La capture rapide est la fonctionnalité centrale.
Créer un item simple doit être plus rapide qu’ouvrir un formulaire classique.
Règles
- capture immédiate
- champs obligatoires minimaux
- tri possible après création
14) Invariants UI / visuels
Objectif
L’application doit rester cohérente avec les autres applications existantes.
Principes :
- interface sobre
- lisibilité
- hiérarchie claire
- composants homogènes
15) Fragments normatifs
Vite proxy
proxy: {
'/api': {
target: 'http://backend:8000'
}
}16) Makefile — cibles attendues
- help
- envlink
- ensure-env
- up
- down
- restart
- ps
- logs
- logs-backend
- logs-frontend
- logs-db
- makemigrations
- migrate
- createsuperuser
- psql
17) Vérification des invariants
Script recommandé :
scripts/verifier-invariants.sh18) Checklist avant merge
- invariants vérifiés
- proxy Vite OK
- JWT configuré
- secrets hors repo
- cohérence UI
19) Emplacement du document
Chemin recommandé :
docs/INVARIANTS.md20) Consignes permanentes pour Codex
- relire ce document
- respecter les invariants
- proposer des snippets prêts à copier
- maintenir la cohérence cross-apps
21) Extension cross-apps
Ce document est une déclinaison du template commun des applications :
- conventions Docker
- conventions API
- conventions
.env - cohérence frontend