Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
Workflows (playbooks markdown) pour orchestrer les 4 agents specialises : - README.md : index + conventions communes + integration BYAN web futur - build-story.md : cycle complet livrer 1 story Phase 2 (bridge-dev → bridge-tester → review → CI → deploy staging → validation metier) - sync-bidirec.md : sync Docmost ↔ Baserow event-driven (idempotence + anti-loop X-Bridge-Origin) - release.md : process release semver (E2E staging → tag → approval → deploy prod → watch 30min) - incident.md : SEV1/2/3 response + post-mortem blameless + runbooks - bump-deps.md : Dependabot PRs + major bumps + Docmost/Baserow upstream Chaque workflow specifie : trigger, acteurs (agents + humains), sequence ordonnee avec outputs, gates humains bloquants, rollback, comm templates. Workflows = playbooks declaratifs pour Claude main qui orchestre les agents via Agent tool sequentiel. A migrer plus tard vers BYAN web workflow runs quand le runtime BYAN sera fix. Equipe complete pour formation-hub : - 4 agents specialises (bridge-dev, bridge-tester, acadenice-devops, docmost-fork-dev) - 5 workflows orchestrant leur collaboration
144 lines
6.3 KiB
Markdown
144 lines
6.3 KiB
Markdown
# Workflow : SYNC BIDIREC Docmost ↔ Baserow
|
|
|
|
Orchestration de la synchronisation bidirectionnelle entre Docmost (wiki) et Baserow (DBs). Phase 2 — necessite que le bridge service soit deploye et operationnel.
|
|
|
|
Equivalent BYAN-natif : event-driven workflow avec idempotence.
|
|
|
|
## Trigger
|
|
|
|
L'un des suivants :
|
|
- Webhook Baserow `row.created` / `row.updated` / `row.deleted` sur table donnee
|
|
- Webhook Docmost `page.created` (si configure cote Docmost custom)
|
|
- Action explicite admin : "Sync forcee projet 42 → Docmost"
|
|
- Cron periodique de reconciliation (Phase 3+)
|
|
|
|
## Acteurs
|
|
|
|
- **bridge-dev** (handler webhook + sync logic)
|
|
- **acadenice-devops** (config webhooks + monitoring)
|
|
- **bridge-tester** (validation idempotence + anti-loop)
|
|
- **Corentin** (alerte si depassement capacite)
|
|
|
|
## Sequence — type webhook Baserow row.created sur table 'projet'
|
|
|
|
```
|
|
[1] Webhook recu (bridge endpoint POST /api/webhooks/baserow/projet-changed)
|
|
- Verifier signature HMAC X-Baserow-Signature (anti-spoofing)
|
|
- Si invalide : log + 401, ABORT
|
|
- Output : event valide
|
|
|
|
[2] Idempotence check (bridge + Redis)
|
|
- Lire payload event_id
|
|
- Redis : SET bridge:webhook:event:<event_id> "1" EX 86400 NX
|
|
- Si SET retourne null (key existait) : event deja traite, ABORT 200
|
|
- Sinon : continue
|
|
- Output : event nouveau, marque traite
|
|
|
|
[3] Anti-loop check
|
|
- Verifier header X-Bridge-Origin sur la row Baserow
|
|
- Si X-Bridge-Origin == "bridge" : c'est nous qui avons cree la row, ABORT
|
|
- Sinon : c'est un user qui a cree, continue
|
|
- Output : event source legitime
|
|
|
|
[4] Logique metier (bridge service)
|
|
- Pour 'row.created' sur 'projet' :
|
|
* Fetch projet detail depuis Baserow (BaserowClient.getRow)
|
|
* Fetch client lie (BaserowClient.getRow)
|
|
* Calcul nom de page Docmost : "Projet [nom] - [client]"
|
|
* Determiner space cible : "Agence" → fetch space ID
|
|
- Output : payload pour creation Docmost
|
|
|
|
[5] Action Docmost (bridge service via DocmostClient)
|
|
- DocmostClient.createPage({ spaceId, title, content: template_projet(projet) })
|
|
- Header : X-Bridge-Origin: bridge (eviter loop futur)
|
|
- Output : pageId Docmost cree
|
|
|
|
[6] Update Baserow row (bridge service)
|
|
- BaserowClient.updateRow(projet_id, { docmost_page_id: pageId })
|
|
- Header : X-Bridge-Origin: bridge
|
|
- Output : projet Baserow enrichi avec docmost_page_id
|
|
|
|
[7] Cache invalidation (bridge + Redis)
|
|
- RedisCache.invalidatePattern("bridge:projet:*")
|
|
- RedisCache.invalidatePattern("bridge:client:<id>:projets")
|
|
- Output : caches invalides
|
|
|
|
[8] Notif si capacite formateur depassee (cas attribution)
|
|
- Si event = creation 'attribution' :
|
|
* Recalculer Personne.heures_restantes_total
|
|
* Si < 0 : notifier admin via SMTP/Slack
|
|
- Output : notification envoyee si depassement
|
|
|
|
[9] Audit log
|
|
- Log structurel : { event_id, source: 'baserow', target: 'docmost', action: 'createPage', success: true, duration_ms, ... }
|
|
- Output : trace persistee
|
|
|
|
[10] Reponse webhook
|
|
- Return 200 OK { processed: true, page_id: <docmost_page_id> }
|
|
```
|
|
|
|
## Patterns specifiques par event
|
|
|
|
| Trigger | Action sync |
|
|
|---------|-------------|
|
|
| Baserow row.created sur `projet` | Auto-create page Docmost dans space Agence |
|
|
| Baserow row.created sur `formation` | Auto-create collection Docmost (sub-pages par bloc) |
|
|
| Baserow row.updated sur `projet`/`formation` (titre, statut) | Update title/icon page Docmost liee |
|
|
| Baserow row.created sur `intervention` | Check capacite → notify admin si depassement |
|
|
| Baserow row.created sur `attribution` | Notify formateur (email) + check capacite |
|
|
| Docmost page.created (template specifique 'compte-rendu') | Auto-create row dans table `comptes_rendus` Baserow (Phase 3+) |
|
|
| Docmost share.created | Log audit + notify admin (alerte data leak risk) |
|
|
|
|
## Gates humains
|
|
|
|
Aucun gate bloquant — c'est event-driven temps reel. Mais :
|
|
- Notif Corentin sur depassement capacite (asynchrone)
|
|
- Notif Corentin sur erreurs critiques (sync echec apres 3 retry)
|
|
|
|
## Rollback / gestion d'erreurs
|
|
|
|
| Echec | Strategy |
|
|
|-------|----------|
|
|
| Docmost API down | Retry 3x exponential backoff. Si tjrs KO : queue Redis pour retry batch |
|
|
| Baserow row introuvable (race condition) | Fetch retry x2 avec 200ms delay. Sinon : log + skip event |
|
|
| Cache invalidation echec | Log warning, continuer (TTL fallback 5 min) |
|
|
| Notification SMTP fail | Log warning, alerte degraded |
|
|
| Loop detecte (X-Bridge-Origin manquant cote bridge writes) | URGENT : alerte Corentin, audit code bridge |
|
|
|
|
## Anti-loop strategy (CRITICAL)
|
|
|
|
Pour eviter Docmost → bridge → Baserow → bridge → Docmost → ... boucle infinie :
|
|
|
|
1. **Header X-Bridge-Origin** : tous les writes du bridge vers Baserow et Docmost ajoutent ce header
|
|
2. **Detection cote handler** : si l'event provient d'une row/page avec ce flag, ABORT
|
|
3. **Idempotence event_id** : meme si une boucle se forme, max 1 cycle (TTL 24h en Redis)
|
|
4. **Rate limit** : max 1 sync identique / 5 min sur entite (cle: `bridge:sync:<entity>:<id>`)
|
|
5. **Monitoring** : alerter si > 10 events identiques en 1 min (signe de boucle)
|
|
|
|
## Outputs
|
|
|
|
- Pages Docmost crees automatiquement
|
|
- Rows Baserow enrichies avec ids Docmost (lien bidirec)
|
|
- Caches invalides
|
|
- Audit log evenement traite
|
|
- Notifications metier si necessaire
|
|
|
|
## Tests obligatoires
|
|
|
|
- **Test idempotence** : envoyer le meme event 5 fois → un seul effet (bridge-tester)
|
|
- **Test anti-loop** : simuler bridge-write → verifier que webhook ignore (bridge-tester)
|
|
- **Test rate limit** : 100 events identiques en 1 min → verifier que rate limit kick in
|
|
- **Test recovery** : Docmost down 5 min → events queues et processed apres recovery
|
|
- **Test webhook signature invalid** : event avec mauvais HMAC → 401 (bridge-tester)
|
|
|
|
## Exemple invocation
|
|
|
|
Trigger non-manuel — se declenche automatiquement quand Baserow envoie un webhook au bridge. Mais peut etre invoque manuellement pour :
|
|
- Reconciliation : "WF SYNC : force re-sync de tous les projets non-mappes vers Docmost"
|
|
- Debug : "WF SYNC : trace l'event ID xyz pour comprendre pourquoi il a abort"
|
|
|
|
## Notes
|
|
|
|
- Webhooks Baserow : a configurer cote Baserow UI ou API (apres deploy bridge)
|
|
- Endpoint signature secret : `BASEROW_WEBHOOK_SECRET` dans `.env` bridge
|
|
- Logs : toutes les operations sync sont loguees structurellement (Pino) avec event_id pour traceability
|