Wiki/docs/03-decision-record.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

4.9 KiB

ADR — Architecture Decision Records

Format Architecture Decision Record. Une entree par decision structurelle.


ADR-001 — Stack composite : Docmost (wiki) + Baserow (DBs)

Statut : Accepte le 2026-05-07 Decideurs : Le user (AdminSys/DevOps) + BYAN (consulting)

Contexte

Aucun projet OSS unique ne couvre :

  • Users illimites self-host (out : AFFiNE 10-seat, AppFlowy 1-user)
  • Bidirec + DBs multi-vues + team workspaces simultanement
  • Budget recurrent zero (out : AFFiNE Team License)

Decision

Combiner deux outils OSS matures :

  • Docmost pour le wiki collaboratif (AGPL, users illimites, team workspaces, share links natifs)
  • Baserow pour les DBs structurees (MIT core, users illimites, vues multiples, rollups, relations)

Et construire un bridge service custom Node TS pour unifier l'UX de surface (l'UI Baserow reste cachee cote utilisateur final).

Alternatives ecartees

  1. AFFiNE Team License paid : ~2200€/an recurrent, lock-in vendor.
  2. Custom DB engine sur Docmost : 4-6 mois dev (~30-60k€), reinvention de la roue.
  3. Notion (cloud) : pas self-host.
  4. Outline + add bidirec custom : license BSL bloque usage commercial.
  5. AppFlowy paid : disqualifie pour stack Flutter (recrutement difficile, pas web-first).

Consequences

Positives

  • Zero recurrent licensing cost (juste l'infra ~30€/mois VPS)
  • Stack mainstream TS/NestJS/React/Tiptap pour Docmost et Python/Django pour Baserow
  • Decouplage permet de remplacer Docmost ou Baserow sans tout refaire
  • Baserow couvre les besoins DBs du cas (multi-vues, relations, rollups, formules) parmi les Airtable-likes OSS evalues

Negatives

  • Deux services a maintenir au lieu d'un
  • Bridge service = code custom a ecrire et maintenir
  • Performance : appels HTTP entre Docmost et Baserow (mitige par cache Redis)
  • Risque scope creep sur le bridge (tentation de reproduire 100% de Notion)

A surveiller

  • Si Docmost ajoute des DBs natives (pas dans roadmap actuelle), reevaluer la valeur de Baserow
  • Si AFFiNE OSS leve sa limite 10-seat, reevaluer le path A

ADR-002 — Path B (UX quasi-unified) plutot que Path A (deux mondes)

Statut : Accepte le 2026-05-07

Contexte

Path A (cross-link URL externe entre Docmost et Baserow) demande 2-4 semaines mais expose l'UI Baserow aux utilisateurs (jonglage entre deux applis).

Path B (Tiptap nodes custom + API Baserow) demande 2-3 mois pour un fullstack senior, 4-6 mois pour AdminSys/DevOps solo mais offre une UX unifiee.

Decision

Path B retenu. Le user accepte la courbe d'apprentissage Tiptap/React et la timeline plus longue contre une UX qui ne disrupt pas l'experience metier.

Consequences

  • Phase 1 (Mois 1) : stack vanilla utilisable telle quelle, l'equipe peut commencer a alimenter le wiki et les DBs sans bridge
  • Phase 2 (Mois 2-6) : iteration progressive sur les nodes Tiptap custom selon la douleur reelle des utilisateurs
  • Risque : tentation d'aller direct au "tout brillant" sans valider l'usage. Garde-fou : Phase 1 obligatoire avant tout code custom.

ADR-003 — Monorepo Git

Statut : Accepte le 2026-05-07

Decision

Monorepo unique formation-hub/ versionne ensemble :

  • Compose files (compose.yml, overrides staging/prod)
  • Bridge service (bridge/)
  • Schemas Baserow (baserow/schemas/)
  • Patches Docmost (docmost/patches/) si fork phase 2+
  • Docs (docs/)
  • CI/CD (.github/workflows/)

Pourquoi

  • Couplage fort entre infra, donnees, code custom — versionne ensemble = atomique
  • Releases coordonnees (un tag = une version coherente du systeme)
  • Un seul repo a cloner pour reproduire l'environnement

Consequences

  • Repo va grossir avec patches Docmost. Acceptable (pas de binaires lourds).
  • CI/CD doit etre intelligent (ne build que ce qui a change).

ADR-004 — Postgres separe Docmost / Baserow

Statut : Accepte le 2026-05-07

Decision

Chaque service a son propre Postgres (deux containers) en local dev. Possibilite de partager une instance physique en prod via deux databases logiques si besoin perf.

Pourquoi

  • Isolation : un dump de Docmost n'affecte pas Baserow
  • Versions Postgres potentiellement differentes selon les exigences
  • Migration upstream de Docmost ou Baserow ne risque pas de casser l'autre

Consequences

  • Plus de RAM consommee (~200 Mo overhead par instance)
  • Plus de complexite ops (deux backups distincts) — compense par scripts Makefile

ADR-005 — Stack technique du bridge (Phase 2)

Statut : Provisoire — sera confirme avant Phase 2

Hypothese

  • Runtime : Node 22 LTS
  • Framework : Hono (rapide, leger, TypeScript-first)
  • HTTP client : ofetch ou native fetch
  • Cache : Redis (memoire partagee avec Docmost ou dedie)
  • Validation : zod
  • Tests : vitest

A confirmer en Phase 2

  • Si on adopte Bun runtime au lieu de Node (perf + TS native)
  • Si le bridge stocke un etat propre (Postgres dedie) ou reste stateless