docs(livrables): charte EnerVision sur les rapports EC02 et EC04, chaîne md2pdf versionnée
Les deux PDF sont régénérés avec la chaîne Markdown vers HTML vers CSS de pagination vers PDF, désormais versionnée dans docs/livrables/outils (script, CSS, logo). Le CSS reprend les tokens du frontend (vert primaire, neutres, Lato en substitut de Segoe UI, tableaux sans filet vertical, badges d'état pour les marqueurs Prouvé, Constaté, Absent). Le rapport collectif EC02 perd sa section « Écarts entre conception (EC01) et réalisation » : les dossiers EC01 sont individuels et différents d'un membre à l'autre, il n'existe pas une conception collective à comparer. Les sections suivantes sont renumérotées ; le rapport passe de 12 à 10 pages.
This commit is contained in:
@@ -258,43 +258,7 @@ imparti, et **RPA avancé**, au-delà de l'orchestration Airflow.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Écarts entre conception (EC01) et réalisation
|
## 6. Usage de l'intelligence artificielle
|
||||||
|
|
||||||
Le guide d'évaluation le dit : **les écarts entre conception et réalisation font partie du
|
|
||||||
compte rendu d'activité**. Chaque écart ci-dessous porte sa trace.
|
|
||||||
|
|
||||||
| # | Choix du dossier EC01 (14/09) | Réalisé au gel | Verdict |
|
|
||||||
|---|---|---|---|
|
|
||||||
| 1 | FastAPI / Python pour l'API | FastAPI, contrat OpenAPI versionné et testé | ✅ Tenu |
|
|
||||||
| 2 | PostgreSQL 17 + TimescaleDB | Identique, relevés en hypertable (ADR 0001) | ✅ Tenu |
|
|
||||||
| 3 | JWT + Argon2id, RBAC à 3 rôles | Identique, plus rotation du jeton de rafraîchissement (ADR 0002, 0003) | ✅ Tenu |
|
|
||||||
| 4 | Une valeur nulle n'est jamais effacée | Qualité de donnée et imputation tracées, gravées par une contrainte `CHECK` | ✅ Tenu |
|
|
||||||
| 5 | Contrats d'interface figés | Contrat OpenAPI testé, table `prediction` comme frontière ML | ✅ Tenu |
|
|
||||||
| 6 | Docker Compose plutôt que Kubernetes | Compose, un projet par environnement (ADR 0009, 0017) | ✅ Tenu |
|
|
||||||
| 7 | On-premise plutôt que cloud public | Machine de l'école, aucune ressource cloud | ✅ Tenu |
|
|
||||||
| 8 | Traefik en terminaison TLS | Nginx par stack (ADR 0007) et frontal SNI (ADR 0018) | 🔁 Substitué |
|
|
||||||
| 9 | Prophet + IsolationForest | LightGBM, un modèle global (ADR 0005), alertes internes par règles, dérive surveillée (ADR 0013) | 🔁 Substitué |
|
|
||||||
| 10 | APScheduler pour l'ETL | Airflow, 7 DAGs : imports, entraînement, scoring, alertes, dérive, rétention | 🔁 Substitué |
|
|
||||||
| 11 | MinIO, couche bronze | Garage par environnement (ADR 0019) | 🔁 Substitué |
|
|
||||||
| 12 | Ansible, durcissement et déploiement | Terraform et script rejouable (ADR 0010) ; durcissement non automatisé | ⚠️ Partiel |
|
|
||||||
| 13 | SOPS + age pour les secrets | Secrets générés sur la machine, hors de Git | ❌ Non fait |
|
|
||||||
| 14 | Trivy, Bandit, gitleaks en CI | Bandit (#121) et un DAST ZAP non prévu (#140) ; Trivy et gitleaks hors CI | ⚠️ Partiel |
|
|
||||||
| 15 | Prometheus, Grafana, Loki | Prometheus, Alertmanager, Grafana actifs en production (ADR 0016) ; pas de Loki | ⚠️ Partiel |
|
|
||||||
| 16 | Runner auto-hébergé, déploiement automatique | `deploy.yml` sur runner auto-hébergé, sept déploiements de production | ✅ Tenu |
|
|
||||||
| 17 | Deux réseaux Docker, données jamais exposées | Un seul composant exposé, le frontal ; tout le reste sur la boucle locale | 🔁 Intention tenue, autre moyen |
|
|
||||||
|
|
||||||
**Décompte sur les 17 choix du dossier : 8 tenus, 5 substitués, 3 partiels, 1 non fait.** Au
|
|
||||||
23/09, il était de 8 tenus, 4 substitués, 3 partiels et 2 non faits : MinIO est passé de « non
|
|
||||||
fait » à « substitué » par Garage.
|
|
||||||
|
|
||||||
**Hors de cette liste**, le dashboard était prévu en React / Vite ; il est en **Angular 22**
|
|
||||||
depuis son initialisation le 14/09 (commit `49f4697`, PR #52). Sans effet sur le reste de
|
|
||||||
l'architecture, puisque le frontend ne connaît que le contrat d'API. Motif : choix de Valentin, développeur
|
|
||||||
full stack de l'équipe, qui maîtrisait Angular ; aucune objection dans le cadre du projet.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Usage de l'intelligence artificielle
|
|
||||||
|
|
||||||
Déclaration exigée par le formateur : outils utilisés, tâches réalisées, valeur ajoutée,
|
Déclaration exigée par le formateur : outils utilisés, tâches réalisées, valeur ajoutée,
|
||||||
limites constatées, vérifications humaines.
|
limites constatées, vérifications humaines.
|
||||||
@@ -316,7 +280,7 @@ tâches, valeur ajoutée, limites, vérifications.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Licences logicielles
|
## 7. Licences logicielles
|
||||||
|
|
||||||
**Licence du dépôt** : aucun fichier `LICENSE` au gel. Faute de licence explicite, le code reste
|
**Licence du dépôt** : aucun fichier `LICENSE` au gel. Faute de licence explicite, le code reste
|
||||||
sous le régime par défaut : tous droits réservés à ses auteurs, aucune réutilisation accordée.
|
sous le régime par défaut : tous droits réservés à ses auteurs, aucune réutilisation accordée.
|
||||||
@@ -348,7 +312,7 @@ notamment sa licence AGPL, que Garage partage ; les autres raisons de l'ADR rest
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Anonymisation et conformité RGPD
|
## 8. Anonymisation et conformité RGPD
|
||||||
|
|
||||||
- **Les données du projet sont synthétiques.** Les séries de consommation proviennent des CSV
|
- **Les données du projet sont synthétiques.** Les séries de consommation proviennent des CSV
|
||||||
fournis par l'organisme de formation et de l'API Mock simulée. Aucune donnée de consommation
|
fournis par l'organisme de formation et de l'API Mock simulée. Aucune donnée de consommation
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,70 @@
|
|||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 17mm 16mm 19mm 16mm;
|
||||||
|
@bottom-left {
|
||||||
|
content: string(doctitle);
|
||||||
|
font: 8pt Lato, "Liberation Sans", Arial, sans-serif;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
@bottom-right {
|
||||||
|
content: counter(page) " / " counter(pages);
|
||||||
|
font: 8pt Lato, "Liberation Sans", Arial, sans-serif;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--ink: #1f2937;
|
||||||
|
--muted: #6b7280;
|
||||||
|
--label: #374151;
|
||||||
|
--accent: #16a34a;
|
||||||
|
--accent-dark: #15803d;
|
||||||
|
--accent-light: #dcfce7;
|
||||||
|
--rule: #e5e7eb;
|
||||||
|
--border: #d1d5db;
|
||||||
|
--soft: #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
html { font: 10pt/1.48 Lato, "Liberation Sans", Arial, sans-serif; color: var(--ink); background: #fff; }
|
||||||
|
body { margin: 0; }
|
||||||
|
|
||||||
|
.brand { display: flex; align-items: center; justify-content: space-between; padding-bottom: 3mm; margin-bottom: 5mm; border-bottom: 0.3mm solid var(--rule); }
|
||||||
|
.brand .lockup { display: flex; align-items: center; gap: 3mm; }
|
||||||
|
.brand img { height: 9mm; width: 9mm; }
|
||||||
|
.brand .name { font-size: 14pt; font-weight: 700; color: var(--ink); }
|
||||||
|
.brand .meta { font-size: 8pt; font-weight: 700; letter-spacing: 0.12em; color: var(--accent-dark); text-transform: uppercase; }
|
||||||
|
|
||||||
|
h1 { string-set: doctitle content(); font-size: 20pt; line-height: 1.2; color: var(--ink); margin: 0 0 5mm; }
|
||||||
|
h1::after { content: ""; display: block; width: 14mm; height: 1mm; background: var(--accent); margin-top: 3mm; }
|
||||||
|
h2 { font-size: 13.5pt; color: var(--ink); margin: 7mm 0 3mm; padding-bottom: 1.2mm; border-bottom: 0.3mm solid var(--rule); break-after: avoid; }
|
||||||
|
h3 { font-size: 11pt; color: var(--label); margin: 5mm 0 2mm; break-after: avoid; }
|
||||||
|
h4 { font-size: 10.2pt; margin: 4mm 0 1.5mm; break-after: avoid; }
|
||||||
|
p, li { orphans: 3; widows: 3; }
|
||||||
|
a { color: var(--accent-dark); text-decoration: none; }
|
||||||
|
strong { font-weight: 700; }
|
||||||
|
|
||||||
|
code { font: 8.4pt "Noto Sans Mono", "DejaVu Sans Mono", monospace; background: var(--soft); padding: 0 1mm; border-radius: 1mm; }
|
||||||
|
pre { background: var(--soft); padding: 3mm; border-radius: 0 2mm 2mm 0; border-left: 1mm solid var(--accent); overflow-wrap: anywhere; white-space: pre-wrap; break-inside: avoid; }
|
||||||
|
pre code { background: none; padding: 0; }
|
||||||
|
|
||||||
|
table { border-collapse: collapse; width: 100%; margin: 3mm 0 4mm; font-size: 8.6pt; break-inside: auto; }
|
||||||
|
thead { display: table-header-group; }
|
||||||
|
tr { break-inside: avoid; }
|
||||||
|
th, td { padding: 1.5mm 2.2mm; text-align: left; vertical-align: top; border-bottom: 0.25mm solid var(--rule); }
|
||||||
|
th { font-size: 7.4pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); border-bottom: 0.4mm solid var(--border); }
|
||||||
|
|
||||||
|
thead:has(th:empty + th:empty) { display: none; }
|
||||||
|
table:has(thead th:empty + th:empty) { border-collapse: separate; border-spacing: 0 0.6mm; margin-top: 0; }
|
||||||
|
table:has(thead th:empty + th:empty) td { background: var(--soft); border: none; padding: 1.8mm 2.5mm; }
|
||||||
|
table:has(thead th:empty + th:empty) td:first-child { border-radius: 2mm 0 0 2mm; width: 24mm; font-size: 7.4pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); padding-top: 2.2mm; }
|
||||||
|
table:has(thead th:empty + th:empty) td:first-child strong { color: var(--muted); }
|
||||||
|
table:has(thead th:empty + th:empty) td:last-child { border-radius: 0 2mm 2mm 0; }
|
||||||
|
|
||||||
|
blockquote { margin: 3mm 0; padding: 2mm 4mm; border-left: 1mm solid var(--accent); background: var(--soft); border-radius: 0 2mm 2mm 0; }
|
||||||
|
hr { border: none; border-top: 0.3mm solid var(--rule); margin: 6mm 0; }
|
||||||
|
img { max-width: 100%; }
|
||||||
|
|
||||||
|
.badge { display: inline-block; font-size: 6.8pt; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; border-radius: 99mm; padding: 0.3mm 1.8mm; line-height: 1.5; vertical-align: 0.3mm; white-space: nowrap; }
|
||||||
|
.badge.ok { background: var(--accent); color: #fff; }
|
||||||
|
.badge.warn { background: #fef9e7; color: #92400e; border: 0.25mm solid #f9a825; }
|
||||||
|
.badge.no { background: #fef2f2; color: #b91c1c; border: 0.25mm solid #dc2626; }
|
||||||
Executable
+35
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Réf : consigne formateur, version figée d'un livrable = Markdown -> HTML -> CSS de pagination -> PDF.
|
||||||
|
# Usage : md2pdf.sh "fichier.md" [sortie.pdf]. Sans sortie, le PDF est écrit à côté du .md.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
src="$1"
|
||||||
|
out="${2:-${src%.md}.pdf}"
|
||||||
|
here="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
work="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$work"' EXIT
|
||||||
|
|
||||||
|
title="$(grep -m1 '^# ' "$src" | sed 's/^# //; s/&/\&/g; s/</\</g')"
|
||||||
|
css_title="$(grep -m1 '^# ' "$src" | sed 's/^# //; s/\\/\\\\/g; s/"/\\"/g')"
|
||||||
|
logo="$(base64 -w0 "$here/logo-icon.png")"
|
||||||
|
|
||||||
|
npx --yes marked@18 --gfm -i "$src" -o "$work/body.html"
|
||||||
|
sed -i 's/ \([:;?!»]\)/\xc2\xa0\1/g; s/« /«\xc2\xa0/g' "$work/body.html"
|
||||||
|
# Les marqueurs de preuve du rapport EC04 deviennent des pastilles, comme les badges d'état de l'application.
|
||||||
|
sed -i -E 's#\[Prouvé\]#<span class="badge ok">Prouvé</span>#g; s#\[Constaté\]#<span class="badge warn">Constaté</span>#g; s#\[Absent\]#<span class="badge no">Absent</span>#g; s#<strong>((<span class="badge[^"]*">[^<]*</span> ?)+)</strong>#\1#g' "$work/body.html"
|
||||||
|
|
||||||
|
{
|
||||||
|
printf '<!doctype html>\n<html lang="fr"><head><meta charset="utf-8"><title>%s</title><style>\n' "$title"
|
||||||
|
cat "$here/md2pdf.css"
|
||||||
|
# Piège : Chromium ignore `string-set`, le titre du pied de page est donc écrit en dur ici.
|
||||||
|
printf '\n@page { @bottom-left { content: "%s"; } }\n' "$css_title"
|
||||||
|
printf '\n</style></head><body>\n'
|
||||||
|
printf '<div class="brand"><div class="lockup"><img src="data:image/png;base64,%s" alt=""><span class="name">EnerVision</span></div><div class="meta">EADL 2026 · Groupe 3</div></div>\n' "$logo"
|
||||||
|
cat "$work/body.html"
|
||||||
|
printf '\n</body></html>\n'
|
||||||
|
} > "$work/doc.html"
|
||||||
|
|
||||||
|
chromium --headless --disable-gpu --no-pdf-header-footer \
|
||||||
|
--print-to-pdf="$out" "file://$work/doc.html" 2>/dev/null
|
||||||
|
|
||||||
|
echo "PDF écrit : $out"
|
||||||
Reference in New Issue
Block a user