Wiki/examples/acadenice-formation-hub/seed-baserow.md
Corentin JOGUET 2ed73fa948
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
feat(bridge): R1 refactor proxy generique style Notion
Pivot strategique : DocAdenice = produit Notion-like generique. Le bridge
est livre vide a un user qui cree ses tables Baserow comme il veut. Code
sans aucune ontologie metier.

Suppressions :
- 9 entites domain metier (Personne, Formation, Bloc, Module, Attribution,
  Client, Projet, Tache, Intervention) + types.ts (Role, statuts)
- baserow-repo.ts (mega-fichier 554 LOC avec 9 repos heritant BaseRepo)
- 6 routes metier (personnes, formations, projets, modules, interventions,
  attributions) + tests associes
- Lookup PersonneRepo.findByEmail dans middleware auth
- Mapping DEFAULT_ROLE_SCOPES dans middleware/scopes.ts
- Cascade rollup metier dans webhooks/baserow-handler.ts

Ajouts :
- Domain generique : Table, Row, Field, View + schemas zod refondus
- 4 repos generiques : tables / rows / fields / views
- Route unique routes/tables.ts avec 9 endpoints REST CRUD generiques
- Claim JWT acadenice_permissions[] lu directement dans le middleware auth
  (alimente par RBAC dynamique cote DocAdenice en R2)
- examples/acadenice-formation-hub/ : README + seed-baserow.md schema
  9 tables + example-roles.md (Formateur, Developpeur, Direction, Support,
  Admin avec permissions generiques)

Refactors :
- BaserowClient etendu : listTables, getTable, listFields, listViews,
  getGridViewRows
- middleware/auth.ts : extractPermissions(payload), AuthenticatedUser
  remplace roles[] par permissions[]
- middleware/scopes.ts : computeOidcScopes(groups, permissions, map)
- webhooks/baserow-handler.ts : invalidation generique
  bridge:tables:<tableId>:* sans cascade cross-table
- lib/cache.ts : invalidateEntity -> invalidateTable(redis, tableId, rowId?)
- container.ts : drop tableIds, RepoSet={tables, rows, fields, views}
- 501 NOT_IMPLEMENTED si DB token sur endpoints /tables qui exigent JWT

Tests : 250/250 verts (depuis 319). Coverage : domain 98.9%, adapters 89%,
auth 97.08%, rate-limit 100%, cache 100%, webhooks 100%.

Quality gates verts : typecheck, lint biome, vitest, coverage thresholds.

Refs: R1 dans le pivot strategique DocAdenice Notion-like generique.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:12:32 +02:00

10 KiB
Raw Permalink Blame History

Seed Baserow — schema formation-hub Acadenice

Schema reference des 9 tables Baserow pour cet exemple metier.

Ce document decrit le modele que l'utilisateur cree dans son Baserow. Le bridge ne sait rien de tout cela : il proxie generique. Le code de seeding (Python ou autre) peut venir plus tard ; c'est la mise en oeuvre typique de la doc 19 Bridge API design (cas Acadenice).

Database

  • Workspace : Acadenice
  • Database : formation-hub
  • 9 tables au singulier

Table Personne

Pivot multi-roles. Capacite annuelle d'heures splittee entre formation et agence.

Field name Type Notes
personne_nom text (primary)
personne_prenom text
personne_email text (email) Unique. Lie au sub Authentik via DocAdenice.
personne_telephone text Optionnel.
personne_capacite_annuelle number Heures annuelles theoriques (ex 1500).
personne_split_formation_pct number 0-100. Doit sommer 100 avec split_agence.
personne_split_agence_pct number 0-100.
personne_roles multi_select Choix : formateur, developpeur, admin, direction, support
personne_statut single_select actif / inactif
personne_heures_attribuees_formation formula (rollup sum attributions) Auto.
personne_heures_attribuees_agence formula (rollup sum interventions) Auto.
personne_heures_restantes_formation formula capacite × split_formation_pct - heures_attribuees

Table Formation

Field name Type Notes
formation_nom text (primary)
formation_filiere single_select dev, graphisme, marketing, iot, cybersec
formation_heures_totales number
formation_statut single_select draft, actif, termine, archive
formation_date_debut date
formation_date_fin date
formation_heures_attribuees formula Sum rollup blocs.heures_prevues

Table Bloc

Decoupage pedagogique d'une Formation.

Field name Type Notes
bloc_nom text (primary)
bloc_formation link_row -> Formation FK obligatoire.
bloc_heures_prevues number
bloc_ordre number

Table Module

Brique elementaire d'un Bloc, attribuable a une Personne.

Field name Type Notes
module_nom text (primary)
module_bloc link_row -> Bloc
module_heures_prevues number
module_statut single_select a_attribuer, attribue, en_cours, realise, annule
module_heures_attribuees formula Sum rollup attributions.
module_heures_realisees formula Sum rollup attributions.

Table Attribution

Lien Module <-> Personne[role=formateur] avec heures et statut.

Field name Type Notes
attribution_module link_row -> Module
attribution_personne link_row -> Personne role=formateur exige cote DocAdenice
attribution_heures_attribuees number RG-01 : sum <= module.heures_prevues
attribution_heures_realisees number Saisi par le formateur
attribution_date_debut date
attribution_date_fin date
attribution_statut single_select planifie, en_cours, realise, annule

Table Client

Field name Type Notes
client_nom text (primary)
client_contact_principal text
client_contact_email text (email)
client_contact_telephone text
client_secteur text
client_notes long_text
client_statut single_select prospect, actif, inactif, archive

Table Projet

Field name Type Notes
projet_nom text (primary)
projet_client link_row -> Client
projet_type single_select site_web, app_mobile, api, infra, audit, support, autre
projet_charge_heures number Devis valide.
projet_statut single_select devis, en_cours, livre, cloture, abandonne
projet_formation_pedagogique link_row -> Formation Optionnel. Lien projet pedagogique.
projet_heures_realisees formula Sum rollup taches.heures_realisees

Table Tache

Field name Type Notes
tache_titre text (primary)
tache_projet link_row -> Projet
tache_charge_heures number
tache_priorite single_select faible, normale, haute, critique
tache_statut single_select todo, in_progress, review, done, abandoned
tache_heures_realisees formula Sum rollup interventions.heures

Table Intervention

Lien Tache <-> Personne[role=developpeur] avec heures saisies.

Field name Type Notes
intervention_tache link_row -> Tache
intervention_personne link_row -> Personne role=developpeur exige cote DocAdenice
intervention_heures number > 0
intervention_date date
intervention_notes long_text Optionnel.
intervention_statut single_select planifie, realise, annule

Webhooks Baserow vers le bridge

Configurer un webhook par table (ou un seul global selon la version Baserow) qui pointe sur POST /api/webhooks/baserow du bridge avec :

  • header X-Baserow-Signature: <hmac-sha256-hex>
  • secret partage via env BASEROW_WEBHOOK_SECRET du bridge

Le bridge invalidera juste bridge:tables:<tableId>:* — sans cascade metier. Si vous avez besoin de mettre a jour une table parente, posez une formule Baserow qui fait le rollup ; Baserow emettra son propre webhook quand la formule recalcule.

Regles de gestion principales (RG)

Ces regles vivent cote frontend / DocAdenice — pas dans le bridge.

Code Regle
RG-01 Sum(attributions.heures_attribuees) <= module.heures_prevues
RG-02 personne.split_formation_pct + split_agence_pct = 100
RG-03 Attribution exige personne.role contient 'formateur'
RG-04 Intervention exige personne.role contient 'developpeur'
RG-05 personne.heures_attribuees_formation <= capacite × split_formation_pct
RG-06 personne.heures_attribuees_agence <= capacite × split_agence_pct