Files
archicratie-edition/docs/ROADMAP.md
archicratia 60d88939b0
All checks were successful
CI / build-and-anchors (push) Successful in 1m25s
SMOKE / smoke (push) Successful in 11s
CI / build-and-anchors (pull_request) Successful in 1m20s
Seed from NAS prod snapshot 20260130-190531
2026-01-31 10:51:38 +00:00

222 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ROADMAP — CI (Gitea Actions Synology) + Ancrages (aliases build-time)
But : permettre à un successeur de reprendre sans rien deviner.
Ce document décrit :
- létat stable actuel (baseline)
- les invariants à ne pas casser
- les prochaines étapes “mission principale” (ancrages primaires robustes + CI durable)
- la méthode de debug rapide
---
## 0) État actuel (baseline VALIDÉE)
### CI (Gitea Actions)
- ✅ Job dans un container Node 22 (conforme `engines`)
- ✅ Checkout **sans actions GitHub**, depuis `workflow/event.json`
- ✅ Zéro `apt-get` dans le workflow
-`npm ci` + build + tests anchors + validation schema aliases
- ✅ Injection daliases au postbuild confirmée en logs
### Runner (DS220+)
-`container.network: host` dans `/data/config.yaml` du runner
-`NODE_OPTIONS=--dns-result-order=ipv4first` passé aux containers de job
-`--add-host=gitea.archicratie.trans-hands.synology.me:192.168.1.20`
Raison : le DNS du bridge Docker (127.0.0.11) est instable sur cette infra → EAI_AGAIN / ESERVFAIL (npm, debian).
Référence : `docs/CI-BASELINE.md` + `docs/CI-WORKFLOW.md` + `docs/HANDOFF-SESSION.md`.
---
## 1) Invariants (NE PAS “optimiser”)
Ces points sont des garde-fous. Si on les retire, on revient aux mêmes pannes.
1) Runner :
- garder `container.network: host` (tant que linfra DNS bridge nest pas corrigée)
- garder `-e NODE_OPTIONS=--dns-result-order=ipv4first`
2) Workflow :
- ne pas réintroduire `apt-get`
- ne pas dépendre de `actions/checkout@...`
- garder un container Node 22 tant que `package.json engines` impose `>=22 <23`
3) Ancrages :
- le fichier canonique : `src/anchors/anchor-aliases.json`
- injection build-time : `scripts/inject-anchor-aliases.mjs`
- test anchors : `scripts/check-anchors.mjs`
- validation schema aliases : `scripts/check-anchor-aliases.mjs`
---
## 2) Mission principale (raccrochage)
Objectif “métier” :
- préserver les liens profonds (ancrages) malgré lédition (déplacements, insertions, corrections)
- éviter les résolutions “par index” (fragiles)
- rendre la migration dancrages **déterministe, versionnée, testée**
Traduction technique :
- quand un `newId` remplace un `oldId`, on versionne `oldId -> newId` **par page**
- au build, on injecte un alias DOM invisible portant lancien `id` avant lélément ciblé
---
## 3) Prochains jalons (ordre recommandé)
### Jalons A — Verrouillage qualité (court terme, “béton”)
A1) CI : prouver linjection (pas seulement “build ok”)
- ajouter un test qui parcourt `src/anchors/anchor-aliases.json` et vérifie dans `dist/<route>/index.html` :
- présence de `<span id="oldId" ...>`
- présence de lélément `id="newId"`
- et idéalement : alias placé “juste avant” la cible (proximité)
A2) CI : interdire les IDs en double (risque SEO/DOM)
- dans les pages `dist`, détecter les doublons dattribut `id="..."`
A3) CI : artefacts / logs actionnables
- quand un test échoue : afficher `route`, `oldId`, `newId`, extrait HTML et ligne
### Jalons B — Ergonomie éditeur (moyen terme)
B1) `apply-ticket.mjs` : renforcer le mode `--alias`
- si un paragraphe est remplacé : écrire lalias automatiquement
- si conflit : message clair “oldId déjà mappé / newId introuvable”
B2) `check-anchors.mjs` : suggestion daliases
- lorsquil détecte “removed X / added Y” avec même préfixe `p-8-...`
- générer une proposition, option `--write-aliases` (ou sortie patch)
### Jalons C — Robustesse long terme (ops)
C1) Runner : réduire le risque “host network”
- isoler le runner sur LAN (réseau dédié/pare-feu)
- limiter les labels/queues aux repos nécessaires
- documenter comment restaurer `/data/config.yaml`
C2) Versionner les décisions
- tout changement CI/runner : documenté dans `docs/` + commit (pas de “magic fix” non tracé)
---
## 4) Procédure standard (dev -> PR -> merge)
### Ajouter/modifier du contenu
1) modifier les sources (docx/import etc.)
2) si des IDs de paragraphes changent :
- appliquer `scripts/apply-ticket.mjs --alias` si possible
- sinon éditer `src/anchors/anchor-aliases.json` (par route)
### Vérifier en local
- `npm test`
- ou au minimum :
- `npm run build`
- vérifier injection : `grep -n "para-alias" dist/<route>/index.html`
### PR & merge
- une PR = un ticket logique
- CI doit passer
- merge seulement quand anchors + aliases sont cohérents
---
## 5) Debug express (quand ça casse)
### CI échoue “DNS / npm”
Symptômes typiques :
- `EAI_AGAIN`, `ESERVFAIL`, `Temporary failure resolving`
Actions :
1) vérifier runner config : `/data/config.yaml` contient bien `network: host`
2) vérifier job container : logs montrent `network="host"`
3) smoke test NAS :
- `docker run --rm --network host mcr.microsoft.com/devcontainers/javascript-node:22-bookworm bash -lc "npm ping --registry=https://registry.npmjs.org"`
### CI échoue “EBADENGINE”
- Node pas 22 → corriger limage du job (Node 22)
### CI échoue “MODULE_NOT_FOUND scripts/...”
- fichier non commité
- `git status --porcelain` puis `git add/commit/push`
### Injection dalias absente
- vérifier que `postbuild` appelle bien `inject-anchor-aliases.mjs`
- vérifier que `src/anchors/anchor-aliases.json` respecte le schéma (par route)
---
## 6) Définition de “DONE” (quand on peut dire “mission accomplie”)
1) CI stable sur 30+ runs consécutifs (push + PR + merge)
2) Toute modification de paragraphes qui casse des anchors produit :
- soit un alias automatique via tooling
- soit un échec CI explicite (avec patch proposé)
3) Aliases injectés testés (preuve dans dist) + pas de doublons dIDs
4) Documentation à jour (baseline + décisions + procédures)
---
## P2 — UX / Front “lecture outillée” (verrouillé)
- [x] Scroll unique dans le panneau gauche (TOC global + local).
- [x] Bandeau H1/H2/H3 aligné au reading + offsets dancres cohérents.
- [x] Boucle “Proposer” rétablie : modal 2 étapes (type + category) puis ouverture Gitea en nouvel onglet.
- [x] Bookmarks + reprise de lecture + citation copiable.
- [x] Procédure de diagnostic (terminal + dist + DevTools Firefox).
______________________________________
Dernière mise à jour : 2026-01-29
---
## ✅ Réalisé (socle solide)
### A) Ancrages stables (anti-casse)
- Aliasing dancres à la build (déterministe) :
- mapping versionné (ex: `docs/anchor-aliases.json`)
- injection dans `dist/**/index.html` via `scripts/inject-anchor-aliases.mjs`
- Audit dist : détection des IDs dupliqués (sans faux positifs JS/CSS) via `scripts/audit-dist.mjs`
- Vérification “aliases réellement présents dans dist” via `scripts/verify-anchor-aliases-in-dist.mjs`
### B) Qualité CI
- Suite de tests `npm test` (build + audit + anchors + inline JS)
### C) ✅ Production DS220+ (DSM 7.3) — Blue/Green
- Build Astro en image Docker (Node Debian) + runtime Nginx statique
- 2 slots :
- `web_blue` → 127.0.0.1:8081
- `web_green` → 127.0.0.1:8082
- Reverse Proxy DSM :
- bascule port 8081/8082 = bascule prod (rollback ~10s)
- Variables `PUBLIC_GITEA_*` injectées au build → “Proposer” fonctionne end-to-end
- Smoke test + healthcheck opérationnels
Docs :
- `DEPLOY_PROD_SYNOLOGY_DS220.md`
- `OPS_COCKPIT.md`
---
## ⏭️ Prochaines actions “futées” (à très forte valeur)
### 1) Automatiser le cycle blue/green (sans complexifier)
- Script `scripts/deploy-slot.sh green` :
- build --no-cache
- up --force-recreate
- smoke + health
- imprime “OK pour bascule DSM vers 8082”
- Script `scripts/which-live.sh` :
- compare 8081/8082 avec le domaine public
### 2) Durcir lhygiène “transfert macOS → NAS”
- `.dockerignore` contre `PaxHeader/`, `._*`, `.DS_Store`
- (optionnel) script `scripts/clean-macos-artifacts.sh`
### 3) Observabilité minimale
- page “/healthz” (statique) ou check `/pagefind/pagefind.js`
- journalisation Nginx : garder 23 jours, rotation simple (optionnel)
### 4) Sécurité reverse proxy
- confirmer headers (HSTS si voulu, CSP si nécessaire)
- sassurer que 8081/8082 restent local-only (127.0.0.1)
Fin.