feat(backend): ajoute les comptes applicatifs et l'amorçage du premier admin

Table `app_user`, son dépôt, et la commande `create-admin`. Le nom évite
`user`, mot réservé de PostgreSQL, et rappelle qu'il s'agit d'un compte
applicatif, par opposition au rôle PostgreSQL qui portera le
cantonnement des accès ETL et ML.

`credentials_changed_at` couvre à elle seule le changement de mot de
passe, le changement de rôle et la désactivation : tout jeton émis avant
cet instant sera refusé, sans attendre son expiration.

La configuration refuse désormais de démarrer sur cinq erreurs
silencieuses : secret trop court ou laissé à sa valeur d'exemple, `debug`
en production, joker CORS, origines vides hors local, et cookie
`SameSite=None` sans `Secure`. Les fixtures de test et les deux
`.env.example` suivent, sans quoi rien ne démarrerait.

Le mot de passe de l'admin ne transite jamais par `argv`, visible de tout
`ps` : il est saisi par `getpass` ou tiré au sort. Une révision Alembic
qui insérerait ce compte graverait son empreinte dans Git pour toujours.
This commit is contained in:
Johan LEROY
2026-09-15 14:30:05 +02:00
parent 53af7a76d8
commit a8f59e6e76
14 changed files with 615 additions and 21 deletions
+14 -11
View File
@@ -2,15 +2,15 @@ BACKEND := apps/backend
.DEFAULT_GOAL := help
.PHONY: help install dev lint format typecheck test test-cov test-integration check \
docker-build db-up db-down db-reset db-logs db-psql migrate
docker-build db-up db-down db-reset db-logs db-psql migrate bootstrap-admin
help: ## Liste les cibles disponibles
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
install: ## Installe les dependances du backend
install: ## Installe les dépendances du backend
cd $(BACKEND) && uv sync --all-groups
dev: ## Lance l'API en rechargement a chaud
dev: ## Lance l'API en rechargement à chaud
cd $(BACKEND) && uv run uvicorn app.main:create_app --factory --reload --host 0.0.0.0 --port 8000
lint: ## Analyse statique du backend
@@ -19,31 +19,31 @@ lint: ## Analyse statique du backend
format: ## Formate et corrige le backend
cd $(BACKEND) && uv run ruff format . && uv run ruff check --fix .
typecheck: ## Verifie le typage du backend
typecheck: ## Vérifie le typage du backend
cd $(BACKEND) && uv run mypy app
test: ## Execute les tests backend ne demandant pas de base
test: ## Exécute les tests backend ne demandant pas de base
cd $(BACKEND) && uv run pytest --cov-fail-under=85
test-cov: ## Rapports de couverture HTML et XML, plus les resultats au format JUnit
test-cov: ## Rapports de couverture HTML et XML, plus les résultats au format JUnit
cd $(BACKEND) && uv run pytest --cov-fail-under=85 --cov-report=html \
--cov-report=xml --junitxml=test-results/junit.xml
test-integration: ## Execute les tests exigeant une base joignable
test-integration: ## Exécute les tests exigeant une base joignable
cd $(BACKEND) && uv run pytest -m integration
check: lint typecheck test ## Chaine de verification complete
check: lint typecheck test ## Chaîne de vérification complète
docker-build: ## Construit l'image du backend
docker build -t enervision-backend:local $(BACKEND)
db-up: ## Demarre la base PostgreSQL TimescaleDB
db-up: ## Démarre la base PostgreSQL TimescaleDB
docker compose up -d db
db-down: ## Arrete la base en conservant ses donnees
db-down: ## Arrête la base en conservant ses données
docker compose stop db
db-reset: ## Detruit la base et rejoue db/init
db-reset: ## Détruit la base et rejoue db/init
docker compose down -v && docker compose up -d db
db-logs: ## Suit les journaux de la base
@@ -54,3 +54,6 @@ db-psql: ## Ouvre une session psql sur la base applicative
migrate: ## Applique les migrations Alembic
cd $(BACKEND) && uv run alembic upgrade head
bootstrap-admin: ## Crée le premier administrateur, mot de passe saisi au clavier
cd $(BACKEND) && uv run python -m app.cli create-admin --email $${EMAIL:?EMAIL=... requis}