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)
516 lines
17 KiB
Markdown
516 lines
17 KiB
Markdown
# 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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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
|
|
|
|
```markdown
|
|
## 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
|
|
```markdown
|
|
## 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
|
|
```markdown
|
|
## 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
|
|
|
|
```bash
|
|
# 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 ?
|