Conception complete (Phase 0) pour formation-hub Acadenice : - 19 docs Merise Agile + UML + GitOps + plans (tests/deploy/ops/api) cf docs/00-readme.md pour l'index complet - Stack Docker compose (Docmost + Baserow + Postgres + Redis + MinIO local FS) compose.yml + compose.staging.yml + compose.prod.yml - CI/CD GitHub Actions skeleton (ci, deploy-staging, deploy-prod) - Bridge service skeleton (Hono + TS + Biome + Vitest + zod + pino) - Templates GitHub : PR + 3 issue types + CODEOWNERS + dependabot.yml - Scripts ops : healthcheck, backup quotidien, smoke-test post-deploy - LICENSE AGPL-3.0 + SECURITY.md + CONTRIBUTING.md + CHANGELOG.md - Diagramme drawIO archi infra (XML importable dans diagrams.net) Decisions structurelles enregistrees : - Scope CFA + Agence avec entite PERSONNE pivot multi-roles (ADR-001) - Stack composite Docmost AGPL + Baserow MIT + bridge custom (ADR-001) - Path B : UX quasi-unified via Tiptap node-views custom (ADR-002) - Monorepo trunk-based development (ADR-003) - Postgres separe Docmost/Baserow (ADR-004) - Bridge stack Node 22 + Hono (ADR-005) - Repo neuf prefere a fork Docmost - Prod-like des le jour 1 (pas MVP)
17 KiB
Repo Structure & GitOps
Specification du monorepo GitHub : arborescence, branching, CI/CD, DevOps, SecOps, quality gates. A valider avant creation du repo public. Audience : Corentin (DevOps owner), Yan, freelance ponctuel.
1. Principes
| Principe | Pourquoi |
|---|---|
| Monorepo | Tout versionne ensemble (infra, donnees, code custom, docs) — un tag = etat coherent |
| Trunk-based development | Branches courtes (max 2-3j), merge direct sur main apres review + CI |
| Infra as code | Tout ce qui touche a l'infra (compose, traefik labels, makefile, ci) versionne |
| Secrets exclus du versioning | Variables d'env via .env ignore + GitHub Secrets pour CI/CD |
| Quality gates obligatoires | Pas de merge sans CI vert (lint + tests + security scan) |
| Reproductibilite | git clone + .env + make up = stack identique, partout |
2. Arborescence cible du repo
formation-hub/
├── .github/
│ ├── workflows/
│ │ ├── ci.yml # tests + lint + security scan a chaque push/PR
│ │ ├── deploy-staging.yml # deploy automatique sur push main
│ │ ├── deploy-prod.yml # deploy sur tag v*
│ │ └── nightly-backup-test.yml # test mensuel restauration backup
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── feature_request.md
│ │ └── security.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── CODEOWNERS # qui review quoi
│ └── dependabot.yml # auto bumps deps
│
├── docs/ # documentation projet (push aussi sur Outline)
│ ├── 01-discovery-recap.md
│ ├── 02-scope-etendu-cfa-agence.md
│ ├── 03-decision-record.md # ADR
│ ├── 04-cahier-des-charges-techniques.md
│ ├── 05-data-dictionary.md
│ ├── 06-merise-mcd.md
│ ├── 07-merise-mld.md
│ ├── 08-merise-mct.md
│ ├── 09-merise-mot.md
│ ├── 10-state-diagrams.md
│ ├── 11-uml-use-cases.md
│ ├── 12-uml-class-diagram.md
│ ├── 13-uml-activity-diagrams.md
│ ├── 14-repo-structure-gitops.md # CE DOC
│ ├── 15-baserow-mpd.md
│ ├── 16-plan-tests.md
│ ├── 17-plan-deployment.md
│ └── 18-plan-operations.md
│
├── compose.yml # stack locale dev
├── compose.staging.yml # override staging (labels Traefik staging)
├── compose.prod.yml # override prod (labels prod, replicas, healthcheck strict)
│
├── docmost/
│ ├── README.md # specifique a la branche Docmost
│ ├── patches/ # diffs upstream (Phase 2+ si fork)
│ └── Dockerfile.fork # Phase 2+ si custom build
│
├── baserow/
│ ├── README.md
│ ├── schemas/ # JSON exports des tables (versionnes)
│ │ ├── personne.json
│ │ ├── formation.json
│ │ ├── ...
│ ├── seed/
│ │ ├── seed.py # script idempotent setup initial
│ │ └── fixtures/ # data de test
│ └── migrations/ # migrations versionnees (apres setup initial)
│
├── bridge/ # service Node TS Phase 2+
│ ├── README.md
│ ├── package.json
│ ├── tsconfig.json
│ ├── biome.json # lint + format Biome (rapide, no config)
│ ├── Dockerfile
│ ├── src/
│ │ ├── index.ts
│ │ ├── domain/ # domain models (Personne, Module, Tache, ...)
│ │ ├── adapters/ # baserow-client, docmost-client, redis-cache
│ │ ├── routes/ # API endpoints
│ │ ├── webhooks/ # baserow webhook handlers
│ │ └── lib/ # utils
│ ├── tests/
│ │ ├── unit/
│ │ ├── integration/
│ │ └── e2e/
│ └── .env.example
│
├── traefik/ # config Traefik si versionnee (sinon reseau Docker existant)
│ ├── README.md
│ └── dynamic-config.yml
│
├── scripts/
│ ├── backup.sh # appele par cron host
│ ├── restore.sh # restauration assistee
│ ├── healthcheck.sh # check rapide endpoints
│ └── seed-baserow.sh # wrapper du baserow/seed/seed.py
│
├── .gitignore
├── .editorconfig
├── .env.example
├── Makefile # commandes ops standardisees
├── LICENSE # AGPL-3.0 (compatible avec Docmost AGPL)
├── SECURITY.md # politique de divulgation
├── CONTRIBUTING.md # convention commits, PR, branches
├── CHANGELOG.md # tenu a jour par release
└── README.md # quickstart + lien vers docs/
3. Branching strategy
Trunk-based development simplifie :
main (protege)
├── feat/saisie-heures-ui (max 2-3j vie)
├── fix/baserow-rollup-cache (max 1j vie)
├── chore/bump-deps (auto via dependabot)
└── ...
| Aspect | Regle |
|---|---|
| Branche par defaut | main |
Protection main |
Required reviews 1+, CI must pass, no force push |
| Convention nom branche | <type>/<description-kebab> ou type = feat | fix | chore | docs | refactor | test |
| Duree de vie max d'une branche | 3 jours (rebase ou drop si plus vieux) |
| Squash merge | Oui, un commit propre par PR |
| Tags | v<MAJOR>.<MINOR>.<PATCH> (semver) declenche deploy prod |
4. Convention de commits
Format : <type>(<scope>): <description>
| Type | Usage |
|---|---|
feat |
Nouvelle fonctionnalite |
fix |
Bug fix |
docs |
Documentation seulement |
refactor |
Refactor sans changement comportement |
test |
Ajout/modif tests |
chore |
Maintenance, deps, tooling |
ops |
Infra, CI/CD, ops |
sec |
Security fix ou hardening |
Exemples :
feat(bridge): add formateur mention tiptap nodefix(baserow): correct rollup cache invalidation on annulationops(ci): add SAST scan with semgrepsec(deps): bump postgres to 16.4 for CVE-2026-XXXX
Pas d'emoji dans les commits, pas de signature Claude (regle Acadenice).
5. CI/CD GitHub Actions
5.1 Workflow ci.yml (a chaque push + PR)
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx biome check bridge/
type-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: cd bridge && npm ci && npm run typecheck
test:
runs-on: ubuntu-latest
services:
postgres: { image: postgres:16-alpine, env: { POSTGRES_PASSWORD: test }, ports: ["5432:5432"] }
redis: { image: redis:7-alpine, ports: ["6379:6379"] }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: cd bridge && npm ci && npm run test
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Secret scanning
uses: trufflesecurity/trufflehog@main
- name: SAST
uses: returntocorp/semgrep-action@v1
- name: Dependency check
run: cd bridge && npm audit --audit-level=high
- name: License check
run: cd bridge && npx license-checker --failOn 'GPL-3.0;AGPL-3.0' --excludePackages 'bridge'
docker-build:
runs-on: ubuntu-latest
needs: [lint, type-check, test, security]
steps:
- uses: actions/checkout@v4
- run: docker compose build
- run: docker compose up -d
- run: ./scripts/healthcheck.sh
- run: docker compose down -v
5.2 Workflow deploy-staging.yml (sur push main)
name: Deploy Staging
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Build & push images
run: |
docker build -t registry.acadenice.fr/formation-hub/bridge:${{ github.sha }} bridge/
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login registry.acadenice.fr -u "${{ secrets.REGISTRY_USER }}" --password-stdin
docker push registry.acadenice.fr/formation-hub/bridge:${{ github.sha }}
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.STAGING_HOST }}
username: ${{ secrets.STAGING_USER }}
key: ${{ secrets.STAGING_SSH_KEY }}
script: |
cd /opt/formation-hub
git pull
docker compose -f compose.yml -f compose.staging.yml pull
docker compose -f compose.yml -f compose.staging.yml up -d
./scripts/healthcheck.sh
5.3 Workflow deploy-prod.yml (sur tag v*)
Identique a staging mais cible prod, requiert approbation manuelle (environment: production avec required reviewers dans GitHub UI).
5.4 Workflow nightly-backup-test.yml (mensuel)
Restauration automatique d'un backup recent sur env isole + verification integrite. Alerte si fail.
6. DevOps — environnements
| Env | Host | Domain | Branche source | Auto deploy |
|---|---|---|---|---|
| local | machine de dev | localhost:3000/8080/4000 |
n'importe | manuel via make up |
| staging | VPS Hetzner staging | wiki.staging.acadenice.fr etc. |
main |
oui sur push |
| prod | VPS Hetzner prod | wiki.acadenice.fr etc. |
tags v* |
oui mais avec approval review |
Differences env
| Aspect | local | staging | prod |
|---|---|---|---|
| Donnees | seed fixtures | data realiste anonymisee | data reelle |
| Backups | aucun | quotidien local | quotidien local + S3 distant |
| Healthchecks | optional | active | strict + alerting |
| Replicas | 1 | 1 | 1 (peut passer a 2 si charge) |
| Logs | stdout | persisted 7j | persisted 90j + push central |
| Monitoring | aucun | uptime basique | uptime + perf + alerting |
7. Secret management
Exclus de git, sans exception.
| Type secret | Stockage |
|---|---|
| Local dev | .env (gitignored) |
| GitHub Actions | GitHub Secrets (env-scoped : staging, production) |
| Staging/Prod runtime | .env.staging / .env.prod sur le serveur, ownership root, perms 600 |
| API tokens longue duree (Outline, etc.) | Vault / pass / 1Password en interne — exclus du disque non-encrypted |
| Backup encryption key | Hors git, hors GitHub, conserve dans coffre-fort hors-bande |
Rotation : tokens API rotates annuellement, secrets sensibles (DB, JWT) rotates trimestriellement.
8. SecOps
8.1 Quality gates avant merge
Tous obligatoires (PR bloquee si rouge) :
- CI lint vert (Biome)
- Type-check vert (tsc)
- Tests unit + integration verts
- Coverage >= 70% sur fichiers modifies (decision a affiner)
- Secret scanning (TruffleHog) zero hit
- SAST (Semgrep) zero finding
errorseverity - Dependency check (npm audit) zero CVE
highoucritical - License check (license-checker) pas de GPL/AGPL non-compatibles
- Docker build OK + healthcheck stack passe
- Review humaine 1+ approval
8.2 Outils SecOps
| Outil | Role | Frequence |
|---|---|---|
| TruffleHog | Secret scanning dans le code | A chaque push |
| Semgrep | SAST (Static Application Security Testing) | A chaque push |
| npm audit | CVE deps Node | A chaque push |
| Dependabot | Auto-bump deps + security alerts | Auto, hebdomadaire |
| Trivy ou Grype | Scan vulnerabilities images Docker | Avant push registry |
| OWASP ZAP | DAST sur staging (Phase 2+) | Hebdomadaire |
| Falco ou logs analysis | Runtime intrusion detection | Continu prod |
8.3 Politique de divulgation (SECURITY.md)
- Email contact : security@acadenice.fr
- Reponse sous 48h ouvrees
- Disclosure responsable, embargo coordonne
- CVE assignee si publique
8.4 Audit log applicatif
Operations sensibles loggees avec :
- Acteur (personne_id)
- Action (creation/modification/suppression/partage_externe)
- Cible (entity_type + entity_id)
- Timestamp
- IP source
- Justification (si fournie)
Stockage : table dediee audit_log ou journal append-only fichier (a trancher MPD).
Retention : 5 ans (Qualiopi-compatible).
9. PR template
## Description
<!-- Quoi et pourquoi -->
## Type de changement
- [ ] feat
- [ ] fix
- [ ] docs
- [ ] refactor
- [ ] test
- [ ] chore
- [ ] ops
- [ ] sec
## Issue liee
Closes #...
## Tests realises
- [ ] Tests unit ajoutes/modifies
- [ ] Tests integration ajoutes/modifies
- [ ] Test manuel local
## Checklist
- [ ] CI vert
- [ ] Pas de secret commit (verifier diff)
- [ ] Doc mise a jour si necessaire
- [ ] Migration data si schema change
- [ ] Changelog mis a jour si user-facing
10. Issue templates
Bug report
## Description
<!-- Quoi -->
## Etapes pour reproduire
1. ...
## Comportement attendu
<!-- ... -->
## Comportement observe
<!-- ... -->
## Env (local/staging/prod)
- Version (commit SHA ou tag) :
- Browser/device :
## Logs / screenshots
<!-- ... -->
Feature request
## Probleme metier
<!-- Quoi resoudre -->
## Solution proposee
<!-- Comment -->
## Alternatives considerees
<!-- Autres options -->
## Impact estime
<!-- Effort + valeur -->
Security
Privee par defaut. Reporting via email security@acadenice.fr.
11. Release process
1. Merge PRs sur main → deploy staging auto
2. Tester sur staging (qualif metier + smoke tests)
3. Si OK :
- Update CHANGELOG.md (section "Unreleased" → version)
- Tag : git tag -a v1.2.3 -m "Release v1.2.3"
- git push origin v1.2.3
4. GitHub Action deploy-prod se declenche
5. Approval manual review (Yan ou Corentin)
6. Deploy prod execute
7. Post-deploy : surveiller logs + metriques 30 min
8. Si issue : execute rollback (cf section 12)
Convention semver :
- MAJOR : breaking changes (migration data forcee, rupture API)
- MINOR : nouvelle feature, backward-compatible
- PATCH : bug fix, security fix
12. Rollback process
| Scenario | Action |
|---|---|
| Bug critique en prod (data loss / down) | Re-deploy version precedente : git checkout v1.2.2 && deploy-prod.yml |
| Schema migration foireuse | Restore Postgres depuis backup precedant le deploy + redeploy version stable |
| Compromission credentials | Rotate secrets immediate + audit logs + isoler env si necessaire |
| Bug minor en staging | Hotfix sur main, redeploy staging, ne pas tag prod |
Runbook detaille dans 18-plan-operations.md (a venir).
13. CODEOWNERS
# Default
* @corentin
# Infra & ops
/.github/workflows/ @corentin @yan
/compose*.yml @corentin
/Makefile @corentin
/scripts/ @corentin
# Code custom
/bridge/ @corentin
# Docs
/docs/ @corentin
14. Quickstart pour nouveau dev
# 1. Clone
git clone git@github.com:acadenice/formation-hub.git
cd formation-hub
# 2. Setup
cp .env.example .env
# editer .env avec secrets (cf SECURITY.md)
# 3. Up
make up
# 4. Acces
# - Docmost : http://localhost:3000
# - Baserow : http://localhost:8080
# - Bridge : http://localhost:4000 (Phase 2)
# 5. Workflow contribution
git checkout -b feat/ma-feature
# code, test
git commit -m "feat(bridge): description"
git push origin feat/ma-feature
# Ouvrir PR sur GitHub, attendre CI vert + review
15. Etapes avant creation du repo public
Checklist Corentin avant git init + git push -u origin main :
- LICENSE (AGPL-3.0 par alignement avec Docmost)
- SECURITY.md
- CONTRIBUTING.md
- README.md (quickstart + liens docs)
- .gitignore complet (verifie pas de fichier sensible)
- .env.example commite, .env exclu
- Workflows CI/CD
.github/workflows/prets (au moins ci.yml) - PR template + issue templates
- CODEOWNERS
- dependabot.yml configure
- GitHub Secrets configures (
REGISTRY_*,STAGING_*,PROD_*) - Branch protection rules sur
mainactives - Required reviewers configures sur
productionenv
Une fois tout vert : push main, configure Dependabot, enable security alerts. Le repo est pret.
16. Questions a trancher
- Repo public (open-source) ou prive ? Implications RGPD si etudiants/clients dans audit logs visible.
- Self-host GitLab interne plutot que GitHub (souverainete) ? Pas le cas aujourd'hui mais a noter.
- Registry images Docker : GitHub Container Registry, Harbor self-host, ou registry.acadenice.fr (a deployer) ?
- Couverture tests minimum : 70% / 80% / autre ? Strictesse vs vitesse.
- Tooling lint/format : Biome (rapide, all-in-one) vs ESLint+Prettier classique ?