Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13 KiB
13 KiB
Story 6.6: Environment Configuration
Status: done
Story
En tant que Developer, je veux toute la configuration via variables d'environnement, afin que les secrets ne soient jamais dans le code.
Acceptance Criteria
- Étant donné .env.example documente toutes les variables requises
Quand je déploie
Alors tous les secrets proviennent de l'environnement : DATABASE_URL, JWT_SECRET_KEY (ou SECRET_KEY), GOOGLE_API_KEY (ou équivalent), DEEPL_API_KEY, OPENAI_API_KEY, OLLAMA_BASE_URL, REDIS_URL
Et les variables requises manquantes provoquent un échec rapide avec un message d'erreur clair
Et des valeurs par défaut sont fournies pour les variables optionnelles
Tasks / Subtasks
- Task 1 (AC: #1) — Inventaire et .env.example
- 1.1 Vérifier que .env.example (racine ou backend) liste toutes les variables utilisées en production : base de données, auth (JWT, admin), Redis, providers (Google, DeepL, OpenAI, Ollama), Stripe si utilisé, CORS, log level, etc.
- 1.2 Pour chaque variable, indiquer si elle est requise ou optionnelle, un exemple de valeur (sans secret réel), et le comportement si absente (défaut ou fail-fast).
- 1.3 S'assurer qu'aucun secret n'apparaît en clair dans .env.example (placeholders du type
your_secret_here,sk_...,pk_...).
- Task 2 (AC: #1) — Fail-fast pour variables requises
- 2.1 Au démarrage de l'application (main.py ou module config), valider la présence des variables requises pour l'environnement cible (ex. production : DATABASE_URL ou POSTGRES_*, JWT_SECRET_KEY, REDIS_URL, ADMIN_USERNAME + ADMIN_PASSWORD ou ADMIN_PASSWORD_HASH).
- 2.2 Si une variable requise est absente, lever une exception ou sortir avec un message explicite listant les variables manquantes (pas de stack trace générique).
- 2.3 En développement, autoriser des valeurs par défaut ou des avertissements au lieu de fail-fast pour certaines variables (ex. REDIS_URL optionnel si rate limiting désactivé), en documentant le comportement dans .env.example.
- Task 3 (AC: #1) — Défauts pour variables optionnelles
- 3.1 Pour les variables optionnelles (LOG_LEVEL, OLLAMA_BASE_URL, CORS_ORIGINS, timeouts, etc.), définir des valeurs par défaut dans le code ou dans un schéma Pydantic BaseSettings / config centralisée.
- 3.2 Documenter ces défauts dans .env.example pour que le déploiement soit reproductible sans deviner.
- Task 4 — Cohérence backend / frontend
- 4.1 Backend : une seule source de vérité pour la config (ex. core/config.py avec Pydantic BaseSettings chargé depuis os.environ et .env). Éviter les os.getenv dispersés pour les variables critiques.
- 4.2 Frontend : NEXT_PUBLIC_* et autres variables documentées dans .env.local.example ou la section frontend de .env.example ; pas de secrets côté client (NFR10).
- 4.3 Mettre à jour README ou DEPLOYMENT_GUIDE avec la procédure "copier .env.example vers .env et remplir les champs requis".
Dev Notes
- Contexte : Les stories 6-1 à 6-5 ont livré Docker, Redis, structlog, reverse proxy. L'architecture impose que tous les secrets et la configuration sensible passent par l'environnement (NFR10). Le projet dispose déjà d'un .env.example riche à la racine ; cette story vise à s'assurer qu'il est exhaustif, que le démarrage échoue clairement si des variables requises manquent, et que les optionnelles ont des défauts documentés.
- Architecture : [Source: _bmad-output/planning-artifacts/architecture.md] — core/config.py Pydantic BaseSettings ; NFR10 (secrets via env, jamais dans le code). Product brief : centraliser la config dans un module Pydantic BaseSettings.
- NFR10 : Variables d'environnement pour tous les secrets ; jamais de clés ou mots de passe en dur dans le code ni dans le dépôt.
- Fichiers à toucher :
.env.example(racine),config.py(racine — actuellement classe Config + os.getenv, sans fail-fast),main.py(point d'entrée pour validation au démarrage), éventuellementservices/providers/config.pysi centralisation dans un seul module config, README/DEPLOYMENT_GUIDE. Pas decore/config.pyexistant ; créer ou étendre le config actuel selon choix d’architecture.
Project Structure Notes
- Racine :
office_translator/avecconfig.pyà la racine (classeConfig,os.getenvpartout — pas de Pydantic BaseSettings ni fail-fast actuellement).main.pyfaitfrom config import config..env.exampleà la racine (partagé dev/Docker). - Config actuelle :
config.py(racine) +services/providers/config.py(providers). Pas decore/config.py; l’architecture cible peut être soit migrer verscore/config.pyavec BaseSettings, soit ajouter validation fail-fast dans leConfigexistant au démarrage dansmain.py. - Frontend : si présent, documenter
NEXT_PUBLIC_*dans une section dédiée de.env.exampleou.env.local.example.
References
- [Source: _bmad-output/planning-artifacts/architecture.md] — core/config.py, NFR10, Infrastructure & Deployment.
- [Source: _bmad-output/planning-artifacts/epics.md] — Epic 6, Story 6.6, AC.
- [Source: _bmad-output/planning-artifacts/product-brief-office_translator-2026-02-18.md] — Configuration centralisée Pydantic BaseSettings.
- [Source: .env.example] — Variables existantes (Translation, Rate Limiting, Database, Redis, Admin, JWT, Stripe, Logging). S'en servir comme base pour l'exhaustivité et le fail-fast.
Technical Requirements (Architecture Compliance)
- Variables requises (prod) : Au minimum DATABASE_URL (ou POSTGRES_* pour construire l'URL), JWT_SECRET_KEY, REDIS_URL (si rate limiting/cache activés), ADMIN_USERNAME et ADMIN_PASSWORD ou ADMIN_PASSWORD_HASH. Autres secrets (provider keys, Stripe) peuvent être optionnels avec désactivation des features associées.
- Fail-fast : Au tout début du démarrage (avant de monter les routes ou de lancer des workers), vérifier les variables requises et sortir avec un message lisible du type : "Missing required env: JWT_SECRET_KEY, REDIS_URL. Set them in .env or environment. See .env.example."
- Défauts : LOG_LEVEL=INFO, OLLAMA_BASE_URL=http://localhost:11434, CORS_ORIGINS=http://localhost:3000, etc. Documenter dans .env.example ; implémenter dans BaseSettings avec Field(default=...) ou équivalent.
- Un seul point de chargement : Éviter que chaque module fasse son propre os.getenv pour les variables critiques ; passer par un objet Settings chargé une fois (dependency injection ou global après validation).
Architecture Compliance
- Alignement avec architecture.md : config centralisée (Pydantic BaseSettings), secrets uniquement via env.
- Pas de clé API ou mot de passe en dur ; pas de fichier .env commité (vérifier .gitignore).
Library / Framework Requirements
- Pydantic BaseSettings (pydantic-settings) : chargement depuis os.environ et .env, validation des types, optional avec default. Déjà utilisé dans beaucoup de projets FastAPI.
- python-dotenv : optionnel si BaseSettings charge le .env ; sinon utiliser load_dotenv() avant de construire Settings. Pas de lib supplémentaire obligatoire si BaseSettings est déjà en place.
- Côté frontend : Next.js charge automatiquement .env.local ; documenter NEXT_PUBLIC_API_URL et autres dans .env.example.
File Structure Requirements
- .env.example : à la racine du projet. Sections commentées par domaine (Database, Redis, Auth, Providers, etc.). Chaque variable avec commentaire "Required" ou "Optional" et exemple. Déjà présent ; s’assurer exhaustivité et clarté Required/Optional.
- Config centralisée : soit migrer
config.py(racine) vers Pydantic BaseSettings dansconfig.pyoucore/config.py, soit conserver la classe Config actuelle et ajouter une fonction de validation au démarrage qui vérifie les variables requises et appellesys.exit(1)avec message listant les variables manquantes. Éviter de laisser desos.getenvdispersés pour les variables critiques (JWT_SECRET_KEY, DATABASE_URL, etc.) sans validation. - main.py : au tout début du démarrage (avant montage des routes), appeler la validation des variables requises ; en cas d’échec, ne pas démarrer l’app et afficher un message lisible (ex. "Missing required env: JWT_SECRET_KEY, REDIS_URL. Set them in .env. See .env.example.").
Testing Requirements
- Test unitaire ou script : avec un environnement vide (ou sans les variables requises), le démarrage de l'app doit échouer et le message doit mentionner les noms des variables manquantes.
- Test : avec .env complet (ou mock des env), l'app démarre et les endpoints répondent (ex. GET /health).
- Vérifier que .env.example ne contient aucun secret réel (grep ou revue manuelle).
Previous Story Intelligence (6-5 Reverse Proxy)
- Fichiers concernés : Docker Compose prod, config Nginx/Traefik, README/DEPLOYMENT_GUIDE. Pas de changement des variables d'environnement applicatives ; le proxy utilise ses propres config (certificats, etc.).
- Pour 6-6 : les variables ENABLE_HSTS, CORS_ORIGINS, et les URLs (FRONTEND_URL, NEXT_PUBLIC_API_URL) sont déjà dans .env.example ; s'assurer qu'elles sont documentées comme requises/optionnelles et que l'app les charge depuis la config centralisée. Pas de duplication de logique entre 6-5 et 6-6 : 6-5 = infra proxy, 6-6 = config applicative via env.
Git Intelligence Summary
- Le dépôt contient déjà .env.example à la racine avec de nombreuses variables. Vérifier qu'aucun fichier .env (sans .example) n'est versionné et que .gitignore exclut bien .env et .env.local.
Latest Tech Information
- pydantic-settings (Pydantic v2) : SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore"). Pour rendre un champ obligatoire : pas de default ; pour optionnel : Field(default=...). Validation au chargement ; MissingEnvVarError ou ValidationError avec détails des champs manquants.
- Fail-fast : appeler Settings() dans main.py ou dans un lifespan ; en cas de ValidationError, logger l'erreur et sys.exit(1) avec message listant les variables manquantes (err.errors() contient les détails).
Project Context Reference
- Aucun fichier project-context.md trouvé. Contexte : architecture.md (config, NFR10), epics.md (Story 6.6), .env.example existant, product-brief (config centralisée).
Story Completion Status
- Status : ready-for-dev
- Completion note : Contexte et guide développeur complets — prêt pour implémentation.
Dev Agent Record
Agent Model Used
{{agent_model_name_version}}
Debug Log References
- Fail-fast testé en dev (validate_required_env retourne []) et en prod simulée (liste des variables manquantes). Tests dans tests/test_config_env.py.
Completion Notes List
- Task 1 : .env.example mis à jour avec légende Required/Optional, comportement si absent, TRANSLATION_SERVICE et section Frontend (NEXT_PUBLIC_API_URL). Placeholder ADMIN_PASSWORD=your_admin_password_here (plus de secret en clair).
- Task 2 : config.validate_required_env() ajouté dans config.py ; appel au démarrage dans main.py avec sys.exit(1) et message listant les variables manquantes. Fail-fast uniquement en ENV=production ; en dev retourne [].
- Task 3 : Défauts déjà présents dans config.py et services/providers/config.py ; documentés dans .env.example (Optional. Default: ...).
- Task 4 : Procédure « copier .env.example → .env et remplir les champs requis » ajoutée dans README.md et DEPLOYMENT_GUIDE.md. Section Frontend dans .env.example.
- Code review (AI): HIGH/MEDIUM corrigés — main.py une seule source de vérité (config.LOG_FORMAT, config.ENV, config.LOG_LEVEL, config.RATE_LIMIT_, config.MAX_MEMORY_PERCENT, config.ENABLE_HSTS, config.CORS_ORIGINS_RAW) ; support POSTGRES_ dans config.get_database_url() et injection dans os.environ ; fail-fast déplacé en tête de main.py (avant tout autre import) ; test démarrage exit 1 + test POSTGRES* ; table Required Variables complétée dans DEPLOYMENT_GUIDE ; .env.example CLEANUP_INTERVAL Default: 5 + doc POSTGRES_* ; README note CORS dev-only. File List complétée avec .env.production.
File List
- .env.example
- .env.production
- config.py
- main.py
- tests/test_config_env.py
- README.md
- DEPLOYMENT_GUIDE.md
Change Log
| Date | Author | Action | Notes |
|---|---|---|---|
| 2026-03-14 | dev-story | Implement | Story 6.6: .env.example exhaustif + fail-fast (config + main), tests, README/DEPLOYMENT_GUIDE. Status → review. |
| 2026-03-14 | code-review (AI) | Fix HIGH/MEDIUM | Single source of truth (main→config), POSTGRES_* support, fail-fast before imports, tests startup exit 1 + POSTGRES_*, DEPLOYMENT_GUIDE + .env.example + README. Status → done. |