La lecture de l'environnement dans Forge¶
Ce document décrit comment Forge lit la variable APP_ENV.
APP_ENV désigne l'environnement actif d'une application Forge, dev par défaut et prod en production.
Plusieurs gardes du framework en dépendent, et une lecture approximative les désarme silencieusement.
Le fichier de code correspondant est core/app/env.py.
1. Rôle¶
Trois écritures de la même lecture coexistaient dans le dépôt.
Une lecture sans normalisation, une avec .lower() seul, et une avec .strip().lower().
Les deux premières laissaient APP_ENV=Prod échouer une comparaison à prod.
Deux gardes de sécurité cessaient alors de se déclencher, sans le dire.
L'API IoT s'enregistrait sans jeton en production, ce que SEC-IOT-TOKEN-PROD-001 interdit.
La commande fixtures:load --run acceptait de peupler la base de production sans --force, ce que l'ADR-074 interdit.
Ce module est la seule lecture officielle, conformément au principe 11.
2. Vue d'ensemble rapide¶
| Élément | Valeur |
|---|---|
| Module Python | core.app.env |
| Couche | bootstrap applicatif |
| Rôle | lire et normaliser APP_ENV |
| Dépend de | os et collections.abc seulement |
| API publique | normalize_app_env, read_app_env, is_prod |
| Constantes publiques | APP_ENV_VAR, DEFAULT_APP_ENV, PROD |
| Effet de bord | aucun, read_app_env lit os.environ sans l'écrire |
Le module ne dépend d'aucun autre module de Forge.
Il est donc importable au tout début du démarrage, y compris par la configuration du squelette.
3. Règle de normalisation¶
La forme canonique retire les blancs de bord et met en minuscules.
| Valeur lue | Forme canonique | Production |
|---|---|---|
"prod" |
prod |
oui |
"Prod" |
prod |
oui |
" PROD " |
prod |
oui |
"dev" |
dev |
non |
"" |
dev |
non |
| absente | dev |
non |
"staging" |
staging |
non |
Une valeur absente, vide ou blanche vaut dev.
C'est le côté sûr, car un environnement inconnu ne doit jamais être pris pour la production.
La normalisation porte sur la forme, jamais sur le sens.
production reste distinct de prod, parce qu'inventer un synonyme serait de la magie cachée que le principe 3 refuse.
4. API¶
normalize_app_env(value)¶
Rend la forme canonique d'une valeur quelconque.
Accepte object, car la valeur peut venir du registre core.forge, qui n'est pas typé.
from core.app.env import normalize_app_env
normalize_app_env(" Prod ") # "prod"
normalize_app_env(None) # "dev"
read_app_env(environ=None)¶
Rend l'environnement actif, lu depuis l'environnement du processus.
Le paramètre environ permet de lire une autre source, ce dont les tests ont besoin sans toucher au processus.
from core.app.env import read_app_env
read_app_env() # lit os.environ
read_app_env({"APP_ENV": "Prod"}) # "prod"
is_prod(value)¶
Répond si la valeur désigne la production, une fois normalisée.
À préférer à une comparaison écrite à la main, car c'est l'écriture à la main qui avait laissé passer Prod.
from core.app.env import is_prod
if is_prod(app_env):
raise RuntimeError("configuration interdite en production")
5. Garde-fou¶
Le fichier tests/meta/test_app_env_normalisation_001.py refuse deux choses.
Une lecture de APP_ENV dans l'environnement du processus, hors de ce module.
Une comparaison à prod ou dev portant sur une lecture non normalisée.
Le détecteur travaille sur l'arbre syntaxique et non par expression régulière.
Un grep sur prod remonte le mot produire, et c'est exactement ce faux positif qui avait fait conclure à tort que forge-mvc-fixtures n'avait aucune garde.
6. Le cœur tolère, le pré-vol exige¶
Le cœur et le pré-vol de déploiement ne jouent pas le même rôle, et ils ne traitent pas Prod de la même façon.
Le cœur est permissif, parce qu'une garde de sécurité ne doit jamais rater une production à cause d'une majuscule.
is_prod("Prod") répond donc oui, et l'API IoT refuse de s'ouvrir.
La commande forge deploy:check est stricte, parce qu'elle vérifie une déclaration écrite par un exploitant dans env/prod.
Elle refuse APP_ENV=Prod et demande la forme canonique, pour qu'il n'existe qu'une seule écriture officielle, comme le veut le principe 11.
Les deux comportements se complètent.
Le pré-vol pousse vers la forme canonique avant le déploiement, et le cœur protège quand même si une variante passe.
7. Ce que le module ne fait pas¶
Il ne valide pas la liste des environnements autorisés.
forge run --env s'en charge pour son propre argument, et une application reste libre de nommer ses environnements.
Il ne charge aucun fichier env/.
C'est le rôle de la configuration du projet, qui utilise la valeur normalisée pour choisir le fichier à charger.