Skip to content

Configuration du projet — l'inventaire complet

Tous les points de configuration d'ElectriCore, en un seul endroit. Quand tu cherches « où se règle X », c'est ici. Trois registres de savoir (ADR-0024) : le runtime (cette section 1, module runtime.py), le structurel (code/modèles) et le réglementaire (taux régulés, section 2).

1. Variables d'environnement — registre runtime (.env à la racine, gitignoré)

Lues par un seul module canonique, electricore/config/runtime.py (pydantic-settings,

141, ADR-0025). Un domaine indépendant

par groupe (sftp, aes, duckdb, api, bot, odoo), accédé par accessor mis en cache (runtime.sftp(), …). Précédence env-système > .env (native pydantic-settings) : en Docker, le bloc environment: du compose prime sur env_file: .env. Validation fail-fast par point d'entrée via runtime.valider(*domaines) (l'API ne valide jamais le bot ; le runner valide sftp+aes+duckdb).

Ingestion (mouvement des flux)

variable rôle défaut
SFTP__URL URL SFTP Enedis (sftp://user:pass@host/chemin ou file:///... pour des zips locaux) — (requis)
AES__TROUSSEAU__<label>__KEY (+ __IV optionnel) une clé AES (hex) du trousseau ; 16 octets (AES-128) ou 32 (AES-256) ; <label> parlant choisi par l'opérateur (aes256_2026, aes128_2024…). __IV optionnel (ADR-0040) : présent ⇒ schéma IV-fixe ; absent ⇒ schéma IV-préfixé (AES-256) — (≥ 1 __KEY requis)

Le délimiteur __ est l'env_nested_delimiter natif de pydantic-settings : AES__TROUSSEAU__aes256_2026__KEY → entrée trousseau["aes256_2026"].key. Le trousseau accepte un nombre arbitraire de clés ; la bonne est sélectionnée par essai au déchiffrement (oracle PKCS7 + magic bytes ZIP), sans date ni protocole (ADR-0037). Garder les anciennes clés préserve l'accès aux archives passées. Le support .dlt/secrets.toml a été retiré (#141) — les clés vivent en variables d'environnement uniquement.

Bases de données

variable rôle défaut
DUCKDB__PATH la base DuckDB de production — résolue par le domaine duckdb du registre (runtime.duckdb().chemin, issue #146), consommé par les loaders core, l'API, le runner d'ingestion et les tools (reset_incremental_state). En Docker : /data/flux_enedis_pipeline.duckdb (volume) electricore/ingestion/flux_enedis_pipeline.duckdb (absolu, ancré sur le dépôt — indépendant du CWD)
DBT_DUCKDB_PATH chemin vu par dbt (ingestion/dbt/profiles.yml) — seul pont os.environ (ADR-0025), positionné par le runner autour de l'invocation dbt (scopé try/finally) ; ne se règle pas à la main suit runtime.duckdb().chemin via le runner

Schémas dans la base : flux_raw (brut JSON), flux_enedis (tables typées, lues par les loaders — figé dans ingestion/dbt/profiles.yml).

API

Domaine api du registre (runtime.api()) ; electricore/api/config.py n'est plus qu'une façade de compatibilité (settings) déléguant au registre.

variable rôle défaut
API__TROUSSEAU__<consommateur>__KEY trousseau de clés d'authentification (X-API-Key), une par consommateur — révocation ciblée + attribution (ADR-0046 §4)
API__TITLE / API__DESCRIPTION / API__VERSION métadonnées OpenAPI version du paquet
INSTANCE_SLUG identifiant d'instance (multi-déploiements) ""

Bot Telegram

variable rôle
BOT__TOKEN token du bot
BOT__ALLOWED_USERS allowlist d'IDs utilisateurs
BOT__NOTIFY_CHAT_ID chat des alertes proactives (échec d'un job d'ingestion, scheduler compris) ; vide = désactivé

API_BASE_URL a été supprimée (#141/ADR-0025) : le bot tourne dans le processus de l'API et la joint en interne (localhost:8001) — aucune variable requise.

Odoo (intégration)

Domaine odoo du registre (runtime.odoo()) — bloc unique read-only ODOO__{URL,DB,USERNAME,PASSWORD} (#439, ADR-0046 §5) ; charger_config_odoo() reste une façade déléguant au registre. Plus de sélecteur test/prod (#190 clos) : une variable absente lève ConfigurationManquante au boot (no-ERP servi tant que le bloc est entièrement absent).

2. Fichiers de configuration versionnés

fichier rôle quand y toucher
electricore/ingestion/config/flux.yaml mouvement des flux : file_pattern (glob SFTP), format (xml/json), file_regex (fichiers extraits des zips) nouveau flux Enedis, changement de nommage des zips
electricore/ingestion/dbt/profiles.yml connexion dbt→DuckDB (path via env), schéma cible flux_enedis jamais ou presque
electricore/ingestion/dbt/dbt_project.yml matérialisations (staging=view, flux=table) jamais ou presque
electricore/ingestion/dbt/models/sources.yml déclaration des tables brutes raw_* nouveau flux
electricore/ingestion/dbt/models/flux/schema.yml data tests not_null (joués à chaque build) durcir le filet, nouveau flux
electricore/config/turpe_rules.csv règles tarifaires TURPE (fixe + variable) publication CRE
electricore/config/accise_rules.csv barème accise (TICFE) loi de finances
electricore/config/cta_rules.csv taux CTA évolution réglementaire

La sélection/typage des flux (ex-DSL de flux.yaml) n'est plus de la configuration : ce sont les modèles SQL ingestion/dbt/models/ — voir ingestion.md.

3. Déploiement (deploy/docker/)

fichier rôle
docker-compose.yml services api/bot/ingestion-scheduler ; env_file: .env + environment: (DUCKDB__PATH=/data/..., TZ=Europe/Paris) ; volume duckdb_data
crontab (copié de crontab.example) planning : /ingestion/run all à 02:00 via l'API, backup à 03:30
Caddyfile (copié de .example) reverse proxy TLS
backup_duckdb.sh sauvegarde quotidienne de la base
Dockerfile image unique, uv sync --extra ingestion --extra dbt

4. Outillage développeur (config de dev, pas de runtime)

fichier rôle
pyproject.toml dépendances + extras (ingestion, dbt, viz), ruff, mypy (périmètre strict), pytest (markers), coverage
.pre-commit-config.yaml ruff check/format + détection de secrets (et pytest en pre-push)
.github/workflows/ci.yml lint, typecheck, tests py3.12/3.13 avec extras ingestion+dbt

Régénérables (pas de la config, mais souvent cherchés ici)

  • Fixtures XSD et golden : tests/fixtures/flux/generer_fixtures_xsd.py (exige les XSD Enedis en local) et generer_golden.py (oracle = chemin dbt).
  • État incrémental dlt : ~/.dlt/ + tables _dlt_* — purge via ingestion.py resync.