Wiki/docs/14-repo-structure-gitops.md
Corentin JOGUET 668576cdc4 chore: initial commit — formation-hub conception phase
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)
2026-05-07 12:16:19 +02:00

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 node
  • fix(baserow): correct rollup cache invalidation on annulation
  • ops(ci): add SAST scan with semgrep
  • sec(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 error severity
  • Dependency check (npm audit) zero CVE high ou critical
  • 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 main actives
  • Required reviewers configures sur production env

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 ?