@mostajs/training 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +12 -0
  3. package/docs/00-PROPOSITION-PLAN-TRAINING-18062026.md +13 -0
  4. package/docs/01-ETUDE-ETAT-ART-TRAINING-18062026.md +216 -0
  5. package/docs/01-ETUDE-ETAT-ART-TRAINING-18062026.pdf +0 -0
  6. package/docs/03-PLAN-DEV-TRAINING.md +117 -0
  7. package/docs/03-PLAN-DEV-TRAINING.pdf +0 -0
  8. package/docs/04-PLAN-TESTS.md +82 -0
  9. package/docs/04-PLAN-TESTS.pdf +0 -0
  10. package/docs/05-PLAN-SUIVI-MONITORING.md +49 -0
  11. package/docs/05-PLAN-SUIVI-MONITORING.pdf +0 -0
  12. package/docs/PROPOSITION-MODULE-TRAINING.md +136 -0
  13. package/docs/PROPOSITION-MODULE-TRAINING.pdf +0 -0
  14. package/docs/old-dpf/01-ETUDE-ETAT-ART-TRAINING-18062026.pdf +0 -0
  15. package/docs/old-dpf/03-PLAN-DEV-TRAINING.pdf +0 -0
  16. package/docs/old-dpf/04-PLAN-TESTS.pdf +0 -0
  17. package/docs/old-dpf/05-PLAN-SUIVI-MONITORING.pdf +0 -0
  18. package/docs/old-dpf/PROPOSITION-MODULE-TRAINING.pdf +0 -0
  19. package/docs/results-training-20260618/01-lms.json +42 -0
  20. package/docs/results-training-20260618/02-sis.json +42 -0
  21. package/docs/results-training-20260618/10-catalog.json +42 -0
  22. package/docs/results-training-20260618/11-cefr.json +42 -0
  23. package/docs/results-training-20260618/20-sessions.json +42 -0
  24. package/docs/results-training-20260618/30-enroll.json +42 -0
  25. package/docs/results-training-20260618/40-centre.json +42 -0
  26. package/docs/results-training-20260618/41-centre-fr.json +42 -0
  27. package/docs/results-training-20260618/50-incub.json +42 -0
  28. package/docs/results-training-20260618/51-incub-fr.json +42 -0
  29. package/docs/results-training-20260618/60-standards.json +42 -0
  30. package/docs/results-training-20260618/70-ao.json +42 -0
  31. package/docs/results-training-20260618/71-agrement.json +42 -0
  32. package/docs/results-training-20260618/80-acad-lms.json +1 -0
  33. package/docs/results-training-20260618/81-acad-sched.json +1 -0
  34. package/docs/results-training-20260618/SOURCES.md +48 -0
  35. package/docs/results-training-20260618/academic-only.csv +2 -0
  36. package/docs/results-training-20260618/all-results.csv +130 -0
  37. package/docs/results-training-20260618/vendors-only.csv +11 -0
  38. package/docs/scripts-recherche-training-18062026.sh +84 -0
  39. package/docs/scripts-recherche-training-portable-18062026.sh +74 -0
  40. package/examples/cohorte/run.mjs +13 -0
  41. package/llms.txt +14 -0
  42. package/package.json +26 -0
  43. package/src/index.js +4 -0
  44. package/src/memory-repo.js +8 -0
  45. package/src/schemas.js +17 -0
  46. package/src/training.js +61 -0
  47. package/test-scripts/unit/training.test.mjs +45 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog — @mostajs/training
2
+ ## [0.1.0] — 2026-06-18
3
+ ### Added
4
+ - Catalogue (Course/Level CEFR) + sessions (open/code/cancel) + inscriptions (capacité, full/open, idempotence). Compose numbering/notifications.
5
+ - EXTRACTION du modèle course-builder iquesta. 7 tests + exemple §12 (cohorte ATC Anglais A1).
package/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # @mostajs/training
2
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com> · **Licence** : AGPL-3.0-or-later · **Statut** : 0.1.0 (7 tests verts)
3
+ > Catalogue formations à niveaux + sessions/groupes + inscriptions (capacité). Extraction iquesta. Compose numbering/notifications/booking.
4
+ ```js
5
+ import { createTraining, createMemoryRepositories } from '@mostajs/training';
6
+ const t = createTraining({ repositories: createMemoryRepositories() });
7
+ const c = await t.catalog.createCourse({ title:'Anglais', category:'langues' });
8
+ await t.catalog.addLevel(c.id,{ order:1, label:'A1' });
9
+ const s = await t.sessions.open({ courseId:c.id, capacity:12 });
10
+ await t.enrollments.enroll(s.id, learnerId); // throw CapacityReached si plein
11
+ ```
12
+ Lancer : `node test-scripts/unit/training.test.mjs && node examples/cohorte/run.mjs`
@@ -0,0 +1,13 @@
1
+ # @mostajs/training — DEVRULES de bout en bout (§4 + #3 + #4 condensés)
2
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com> · **Date** : 2026-06-18 · **Statut** : cas C (P0, commun P1+P2)
3
+ **Principe** : EXTRACTION du modèle course-builder d'iquesta-dev (Formation/Activity → Course/Level/Session/Enrollment).
4
+ Étude #1 détaillée + protocole §8 : `mosta-training/docs/01-ETUDE-ETAT-ART-TRAINING-18062026.md`.
5
+ ## §4 / §3
6
+ Catalogue de formations à **niveaux** (CEFR généralisé) + **sessions/groupes** + **inscriptions** (contrôle de capacité).
7
+ DB-agnostique. **Compose** : booking (planning séances), numbering (code session), notifications. **Délègue** : éval→gradebook,
8
+ paiement→payment/subscriptions, présence→attendance, contenu→elearning/media. **Frontière** : booking=créneau ; training=quoi/qui.
9
+ **API** : `createTraining({repositories,numbering?,notifications?,booking?})` → `catalog.{createCourse,addLevel,listLevels,listCourses}`,
10
+ `sessions.{open,setInstructor,schedule,run,close,cancel,listOpen}`, `enrollments.{enroll(capacité),cancel(libère),complete,listBySession,listByLearner,seats}`.
11
+ **Jalons** : 0.1 catalogue+niveaux · 0.2 sessions(code)+inscriptions(capacité) · 0.3 booking(planning) · 1.0 14 livrables.
12
+ ## §4 (tests)
13
+ catalogue/niveaux ordonnés, code session, capacité→full, annulation→open, idempotence, refus si non ouverte, notifications. (7 verts)
@@ -0,0 +1,216 @@
1
+ # 01 — Étude de l'état de l'art — `@mostajs/training`
2
+
3
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com>
4
+ **Date** : 2026-06-18
5
+ **Statut** : proposition à discuter (livrable §9 #1 — DEVRULES). **Précède le scaffold.**
6
+ **Protocole reproductible associé** : `scripts-recherche-training-18062026.sh` (gabarit googler §8) **+ runner portable exécuté** `scripts-recherche-training-portable-18062026.sh` (DuckDuckGo HTML + APIs académiques, car googler/ddgr absents de la machine)
7
+ **Proposition module** : `PROPOSITION-MODULE-TRAINING.md` · **Consommateurs** : P1 Hadhinat, P2 ATC.
8
+ **Convention sources** : `[A]` académique/standard · `[V]` vendeur/produit · `[T]` tiers. Consultées le 2026-06-18.
9
+
10
+ > ✅ **Reproductibilité (§8) — protocole EXÉCUTÉ le 2026-06-18**. Le gabarit googler étant non installable ici,
11
+ > un **runner portable versionné** (`scripts-recherche-training-portable-18062026.sh`, mêmes axes) a produit
12
+ > `results-training-20260618/` : **130 résultats** dédupliqués, dont `vendors-only.csv` (11) et `academic-only.csv`.
13
+ > Les sources ci-dessous (§3, §7, §10) sont **issues de ce rejeu**, horodatées 2026-06-18. Relancer : `./scripts-recherche-training-portable-18062026.sh all`.
14
+
15
+ ---
16
+
17
+ ## 1. Résumé
18
+
19
+ Le domaine « gestion de formation » est couvert par deux familles d'outils : les **LMS** (Learning Management Systems — diffusion de contenu, suivi pédagogique) et les **SIS** (Student Information Systems — inscriptions, sections, scolarité). La plupart sont des **applications monolithiques** (Moodle, Open edX, Canvas), riches mais lourdes, difficiles à **composer** dans un autre logiciel métier. Pour `@mostajs/training`, le besoin n'est **ni un LMS complet ni un SIS complet** : c'est une **brique de domaine mince** « **catalogue de formations à niveaux + sessions/groupes + inscriptions** », **DB-agnostique** et **composable**, qui **délègue** contenu (→ futur `@mostajs/elearning`), évaluation (→ `gradebook`/`questa`), planning (→ `booking-stack`), paiement (→ `payment`/`subscriptions-plan`), présence (→ `attendance`) et certificats (→ `certificates`). Les **standards** (OneRoster, LTI, SCORM/xAPI, QTI, CEFR) servent de **vocabulaire de mapping**, pas d'implémentation à recopier.
20
+
21
+ ---
22
+
23
+ ## 2. Axes de recherche (cf. script §8)
24
+
25
+ - **Verticaux** : (1) plateformes LMS/SIS open source, (2) modèle catalogue/curriculum/niveaux, (3) sessions/cohortes/planning, (4) inscriptions/capacité/liste d'attente.
26
+ - **Horizontaux** : (5) centres de formation & écoles de langues, (6) programmes d'accompagnement/incubateurs.
27
+ - **Standards** : (7) interopérabilité 1EdTech/IMS (OneRoster, LTI, QTI), e-learning (SCORM, xAPI), langues (CEFR).
28
+ - **Demande/opportunités (§8.4)** : (9) appels d'offres, agréments centres de formation (Algérie), RFP SIS.
29
+
30
+ ---
31
+
32
+ ## 3. État de l'art des outils à implémentation commune (et leurs limites)
33
+
34
+ ### 3.1 LMS — diffusion & suivi pédagogique
35
+ | Outil | Type | Forces | Limites pour notre besoin |
36
+ |---|---|---|---|
37
+ | **Moodle** `[V][A]` | LMS PHP open source, dominant | Très complet (cours, quiz, SCORM/xAPI, rôles) | Monolithe PHP, modèle pédagogique imposé ; **non composable** comme librairie TS ; lourd pour « juste catalogue+sessions+inscriptions » |
38
+ | **Open edX** `[V]` | LMS MOOC (Python/Django) | Échelle, parcours, certificats | Très lourd à opérer ; orienté contenu en ligne, pas gestion de groupes présentiels |
39
+ | **Canvas** (Instructure) `[V]` | LMS (Ruby) | UX moderne, LTI natif | Produit applicatif, pas une brique ; couplage fort |
40
+ | **Chamilo / Sakai** `[V]` | LMS open source | Présentiel + e-learning | Monolithes ; intégration par API externe seulement |
41
+ | **Frappe LMS** `[V]` | LMS sur framework Frappe | Léger, code ouvert | Couplé à Frappe/ERPNext (Python) ; hors stack TS/MostaORM |
42
+
43
+ ### 3.2 SIS — scolarité, inscriptions, sections
44
+ | Outil | Type | Forces | Limites |
45
+ |---|---|---|---|
46
+ | **Gibbon** `[V]` | SIS écoles (PHP) | Inscriptions, classes, emploi du temps | Monolithe scolaire ; modèle « école » rigide |
47
+ | **OpenSIS / Fedena** `[V]` | SIS établissements | Gestion complète scolarité | Applications fermées sur leur domaine ; non réutilisables en module |
48
+
49
+ **Constat** : aucun de ces outils n'est une **librairie de domaine composable**. Ils imposent leur app, leur DB, leur UI. Réutiliser l'un d'eux dans Hadhinat **ou** ATC reviendrait à **intégrer un système entier** pour un sous-besoin — l'inverse de la philosophie `@mostajs/*` (petit, focalisé, composable — DEVRULES §0).
50
+
51
+ > Détail confirmé au rejeu : **Moodle** publie un plugin dédié *Waitlist enrolment* `[V]` (moodle.org/plugins/enrol_waitlist) — preuve que **capacité + liste d'attente** est un besoin standard (valide notre `Enrollment`/contrôle de capacité, TC-ENR-02).
52
+
53
+ ### 3.4 Marché concurrent — applications de gestion de centre de formation (FR / Algérie)
54
+ Repéré au rejeu (axe 5) : **Algeriasm** `[V]` (algeriasm.net — **acteur algérien** « gestion des formations »), **Dendreo** `[V]` (centres FR), **MyScol** `[V]`, **Class Manager**, **Skooly**, panorama **Appvizer « TOP 12 logiciels centre de formation »** `[T]`. Tous sont des **SaaS applicatifs fermés** (par utilisateur/mois), **non composables** dans un autre logiciel métier — ce qui **confirme l'espace** d'une **brique** `@mostajs/training` réutilisable (vs un produit de plus). À instruire pour le positionnement commercial (#10) et la veille AO (§7).
55
+
56
+ ### 3.3 Standards d'interopérabilité (vocabulaire de référence)
57
+ | Standard | Rôle | Usage pour `training` |
58
+ |---|---|---|
59
+ | **1EdTech OneRoster** `[A]` | Échange roster : *org, course, class, enrollment, term* | **Aligner notre modèle** (Course/Session/Enrollment) sur un vocabulaire éprouvé ; export futur |
60
+ | **1EdTech LTI** `[A]` | Lancement d'outils pédagogiques externes | Pertinent pour `elearning`, pas `training` (frontière) |
61
+ | **SCORM / xAPI (Tin Can)** `[A]` | Paquet & traçage d'activités e-learning | Délégué à `@mostajs/elearning` |
62
+ | **QTI** `[A]` | Items/tests interopérables | Délégué à `gradebook`/`questa` |
63
+ | **CEFR (CECRL)** `[A]` | Niveaux de langue **A1→C2** | **Modèle direct** des `Level` (P2 ATC : langues) ; généralisable (niveaux 1→N) |
64
+
65
+ ---
66
+
67
+ ## 4. Description des capacités retenues (périmètre `training`)
68
+
69
+ De cet état de l'art, on **retient et isole** la seule couche **non couverte et réutilisable** :
70
+ - **Catalogue** : `Course` (formation) + `Level` ordonnés avec prérequis (modèle CEFR généralisé).
71
+ - **Sessions/groupes** : `Session` = instance datée d'une formation (animateur, capacité, salle, planning récurrent **délégué à `booking-stack`**), avec **machine d'états** simple (`draft→open→full→running→closed`, déléguée à `statemachine`).
72
+ - **Inscriptions** : `Enrollment` avec **contrôle de capacité** et statuts (`pending→confirmed→cancelled→completed`).
73
+
74
+ On **écarte explicitement** (frontières — délégation, §10) : contenu/vidéo (`elearning`), évaluation/notes (`gradebook`/`questa`), présence (`attendance`), paiement (`payment`/`subscriptions-plan`), certificats (`certificates`), planning bas niveau (`booking-stack`).
75
+
76
+ ---
77
+
78
+ ## 5. Motif de sélection (quel mécanisme pour quel usage)
79
+
80
+ - **Modèle aligné OneRoster** (course/class/enrollment/term) → interopérabilité & familiarité, sans en dépendre.
81
+ - **Niveaux façon CEFR** → couvre directement P2 (A1→C2) et se généralise (calcul mental 1→10, accompagnement incubés par paliers).
82
+ - **Délégation systématique** plutôt que monolithe → conforme §0/§10 ; évite de réimplémenter booking/éval/paiement déjà modularisés.
83
+ - **DB-agnostique (repos injectés)** → un seul module sert P1 (MongoDB/ORM) et P2 sans réécriture.
84
+
85
+ ---
86
+
87
+ ## 6. Application localisée
88
+
89
+ - **P2 ATC** : `Course` = Anglais ; `Level` = A1…C2 ; `Session` = groupe « ENG-A1-01 » (Mme X, samedi 14h, salle, capacité 12) ; `Enrollment` = élève inscrit. La gestion des groupes (spec F3) et le catalogue (F2) **sont** ce module.
90
+ - **P1 Hadhinat** : `Course` = « Monter son business plan » ; `Session` = cohorte d'incubés ; `Enrollment` = entreprise incubée inscrite. Le module « Formation & accompagnement » **est** ce module.
91
+
92
+ ---
93
+
94
+ ## 7. Veille de la demande — appels d'offres & agréments (§8.4)
95
+
96
+ > Axe 9 **exécuté** le 2026-06-18 → résultats classés dans `Entreprise/appels-d-offres/formation/` (un répertoire par thème, §8.4).
97
+
98
+ - **Agréments — CONFIRMÉ** : les **établissements privés de formation** en Algérie relèvent d'un **agrément MFEP** (Ministère de la Formation et de l'Enseignement Professionnels) avec **cahier des charges**. Sources : guide *Agrément MFEP* `[T]` (beeform.dz/agrement-mfep-algerie), *Cahier des charges école privée / DFP* `[T]` (Scribd), **Journal Officiel** arrêtés `[A]` (joradp.dz — JO 2002/067 ; arrêté du 4 août, invest.caci.dz). → un logiciel **conforme au cahier des charges** (registres élèves, attestations, traçabilité) est un **différenciateur d'appel d'offres**.
99
+ - **Appels d'offres — CONFIRMÉ** : portail officiel **BOMOP / ANEP** `[T]` (bomop.anep.dz) avec une rubrique dédiée **« Consultation, formation et certification »**, **portail des marchés publics** `[A]` (marches-publics.gov.dz), agrégateurs **AlgérieMarchés** `[T]` (algeriemarches.com), **RhinoTenders** `[T]`.
100
+ - **Marché — CONFIRMÉ** : concurrents SaaS (Algeriasm/Dendreo/MyScol/Skooly, cf. §3.4) → demande réelle ; espace pour une **brique composable** + conformité MFEP locale.
101
+
102
+ **Livrable §8.4 produit** : `Entreprise/appels-d-offres/formation/{README.md, ETAT-DES-LIEUX-AO-18062026.md}` (état des lieux classé/argumenté).
103
+
104
+ ---
105
+
106
+ ## 7-bis · Audit `iquesta-dev` — implémentation de référence & extraction de modules (création des cours)
107
+
108
+ > Ajout 2026-06-18. `SolutionCh/iquesta-dev` (« plateforme questionnaire magic-link + **course-builder** »,
109
+ > ex-orphin, prod `iquesta.amia.fr`) contient **déjà** une grande partie de la **création des cours** que
110
+ > `@mostajs/training` doit modulariser. C'est donc à la fois une **source d'extraction** (règle d'or §0 :
111
+ > ne pas réécrire ce qui existe) et le **terrain d'audit** de l'existant (§9 #2). *(Fichiers `MONTORING*.md`
112
+ > du projet = journaux de reprise, lus mais NON modifiés — DEVRULES §5.)*
113
+
114
+ ### A. Avancement de `iquesta-dev` (source : `docs/Audit iquesta dev état.md` 2026-05-30 + `docs/ROADMAP.md` 2026-06-02)
115
+
116
+ | Couche | Avancement | Verdict |
117
+ |---|---|---|
118
+ | Schémas de données (Formation/Activity/Dependency/Attachment/Snapshot) | **~95 %** | ✅ fondation excellente |
119
+ | Plateforme événements / Q-bank / inscription / paiement | **~90 %** | ✅ en prod, durcie |
120
+ | Éditeur visuel formation (course-builder) | **~68 %** | 🟢 fonctionnel (React Flow + dagre, undo/redo, optimistic locking, snapshots) |
121
+ | Backend / persistance formation (server actions, diff/upsert 3 niveaux, snapshots SHA256) | **~75 %** | 🟢 solide |
122
+ | Runtime apprenant | **~40 %** | 🟡 prototype |
123
+ | **Intégration média / recording** | **~5 %** | 🔴 **non démarrée — principal reste** |
124
+ | Tests | **~0 %** | 🔴 1 smoke `.mjs` |
125
+
126
+ **Reste à faire = essentiellement l'intégration du module média** (cf. §E) + runtime serveur (suivi/scoring persistés, certificats PDF) + tests.
127
+
128
+ ### B. Modèle « création des cours » à extraire vers `@mostajs/training`
129
+
130
+ iquesta modélise **Formation → (Module/Section) → Activity** avec **10 kinds** (`module, lesson, video, audio, reading, quiz, submission, live, external, certificate`), **dépendances en DAG** (détection de cycle DFS), **snapshots/versioning** (bundle JSON + SHA256), **attachments** formation↔projet, **optimistic locking**. C'est **exactement** le cœur catalogue/structure visé par `@mostajs/training` (§4-§6) — **déjà implémenté à ~75-95 %**. → **À extraire**, pas à réécrire.
131
+
132
+ ### C. Extraction des modules — logique codée en dur dans iquesta (cas B/C, règle d'or §0)
133
+
134
+ iquesta consomme **12 modules `@mostajs/*`** (audit, auth, config, mailer, menu, orm, payment, pwa-scan, qrpanel, rbac, subscriptions-plan, url — *versions un peu anciennes : qrpanel 0.4→0.5, payment 0.5.3→0.8, subscriptions-plan 0.3.6→0.4*). Mais des **capacités réutilisables restent codées dans l'app** → candidates d'extraction :
135
+
136
+ | Logique in-app (schemas + lib + components) | Module cible | Cas | Note |
137
+ |---|---|---|---|
138
+ | `formation*`, `activity*`, `section`, `components/formation/*` (FormationEditor, Tree/Canvas/Props, React Flow, dagre, snapshots) | **`@mostajs/training`** (modèle) **+ `@mostajs/course-builder`** (éditeur visuel) | **C** | **extraction prioritaire** — fonde le plan de dev #3 |
139
+ | `question`, `answer`, `respondent`, `template`, `template-chain*`, `scoring.ts`, `questions.ts` | **`@mostajs/questa`** | **C/B** | questa est **0.0.0 (design seul)** → iquesta en est l'**implémentation de référence** |
140
+ | `scoring.ts`, `weight/passingScore/maxAttempts` | **`@mostajs/gradebook`** (proposé) | **C** | alimente le module éval commun |
141
+ | `magic-link*`, `anon-token`, `invite-token`, `agent-invite` | **module `@mostajs/magic-link`** (ou `auth-flow`) | **C** | **non sélectionné avant** (cf. §D) |
142
+ | `registration*` (cascade/mailer/status/validate), `cohort-mailer` | **`@mostajs/registration`** (+ enrôlement `training`) | **C** | inscription événement/cohorte |
143
+ | `archive*`, `tombstone*`, `import-actions` (jszip, `.iquesta-archive.zip`) | **composer `@mostajs/ixarchive`** | **B** | remplacer le code maison par le module existant |
144
+ | `pdf-respondent.ts` (pdfkit) | **composer `@mostajs/file-export`** | **B** | reçus/attestations PDF |
145
+ | `app-mode.ts`, `demo-actions`, `demo-seed` (4 modes dev/test/demo/prod + commission) | **`@mostajs/app-mode`** (petit) | **C** | **non sélectionné avant** (cf. §D) |
146
+
147
+ ### D. Modules **non sélectionnés** dans les cartographies P1/P2/P3 (révélés par iquesta)
148
+
149
+ 1. **`@mostajs/course-builder`** — éditeur **visuel** de formation (React Flow + dagre + undo/redo + optimistic locking + snapshots). **Distinct** de `training` (modèle de domaine) : c'est l'**UI d'édition**. Les cartographies disaient « training » sans isoler l'éditeur — iquesta prouve que c'est une **préoccupation à part entière** (~68 %, réutilisable). **Nouveau cas C.**
150
+ 2. **`@mostajs/questa` (à matérialiser)** — référencé partout comme « utilisable » alors qu'il est **design-only (0.0.0)** ; iquesta fournit le **code réel** (questions/réponses/scoring/templates/chaînes/respondents). À **remplir par extraction**, pas à présumer prêt.
151
+ 3. **`@mostajs/magic-link`** — accès **anonyme/par lien** (respondent, invitation agent). Très réutilisable : formulaires bénéficiaires **P3 ASSO-SEL**, portail parents **P2 ATC**, questionnaires **P1**. **Non identifié avant.**
152
+ 4. **`@mostajs/registration`** — inscription **événement/cohorte** + relances (cohort-mailer) + QR check-in. Recoupe l'enrôlement `training` mais l'**événementiel** (scan QR, badges) est une préoccupation propre.
153
+ 5. **`@mostajs/app-mode`** — modes **dev/test/démo/commission** (entrée 1-clic, reset, bandeau) : capacité **commerciale/démo** transverse, utile à tout produit vitrine. **Non identifié avant.**
154
+
155
+ > Ces 5 entrées **complètent** la liste « modules métier génériques » (roadmap Phase 8) issue de la confrontation P1/P2/P3.
156
+
157
+ ### E. Le reste d'iquesta = **intégration & utilisation du module média** (principal levier)
158
+
159
+ Le seul grand chantier restant du course-builder est l'**intégration média** (Track B, ~5 %). La **brique amont est prête et éprouvée** (`@mostajs/media@2.4.0` + `@mostajs/media-server@0.2.3` + `@mostajs/storage@0.1.2`, déjà en prod via *camera-studio*). Plan (réf. `docs/MEDIA-INTEGRATION-COURSE-BUILDER.md` + `ROADMAP.md` Axe 3) :
160
+
161
+ | # | Item | Effort |
162
+ |---|---|---|
163
+ | M1 | Bootstrap deps + `lib/media-bootstrap.ts` + `lib/storage-bootstrap.ts` | ~0.5 j |
164
+ | M2 | Schéma **`Media`** en DB (`Activity.mediaId` pointe déjà dessus) | ~0.5 j |
165
+ | M3 | Routes `app/api/admin/media/recordings` (upload) + `[id]` (GET) | ~0.5 j |
166
+ | M4 | `<CourseBuilderMediaSlot>` = `<MultiTakeRecorder>` (5 modes) + repli `<MediaPicker>` URL | ~1.5 j |
167
+ | M5 | *(stretch)* kind `live` → `<LiveActivityPanel>` SFU/WHIP | ~1 j |
168
+
169
+ **État actuel** : les activités `video/audio` stockent un `externalUrl` libre, **pas** un `mediaId` (table `Media` absente). L'intégration média **débloque** captation reprenable (multi-take), stockage **souverain RGPD** (self-hosted, §11.3 informative) et le kind `live`. **Règle §10** : ce slot **compose** `@mostajs/media` + `@mostajs/storage`, il ne recode **aucune** capture/transcodage.
170
+
171
+ ### F. Conséquences pour `@mostajs/training` (plan de dev #3)
172
+
173
+ - **Source de code** : le plan de dev #3 doit **partir de l'extraction iquesta** (schemas + actions + éditeur), pas d'une feuille blanche — gain de temps majeur (~75-95 % du modèle existe).
174
+ - **Découpage** confirmé : `training` (modèle/sessions/inscriptions) **+** `course-builder` (éditeur visuel) **+** `questa` (questionnaires/quiz) **+** `gradebook` (scoring) **+** `media`/`storage` (contenu) — composition, pas monolithe (§10).
175
+ - **Dépendance média** : le kind `video/audio/live/certificate` de `training`/`course-builder` **compose** `@mostajs/media`+`storage` (le chantier restant d'iquesta = le **patron d'intégration** à généraliser dans le module).
176
+
177
+ ---
178
+
179
+ ## 8. Discussion / projection
180
+
181
+ `@mostajs/training` se positionne comme **brique de domaine** réutilisable par **tout** logiciel de formation/scolarité de l'écosystème (P1, P2, MostaJS-Académie, futurs centres). Couplé à `elearning` + `gradebook` + `attendance` + `certificates`, il **reconstitue par composition** un LMS/SIS complet — mais **à la carte**, sans le poids d'un monolithe. Projection : un **stack `@mostajs/campus-stack`** dont `training` est le cœur catalogue/sessions.
182
+
183
+ ---
184
+
185
+ ## 9. Conclusion
186
+
187
+ Aucun outil existant n'offre une **brique composable** « catalogue+sessions+inscriptions » en TS/MostaORM : les LMS/SIS sont des **applications**, pas des **modules**. La création de `@mostajs/training` (cas C) est **justifiée**, **réutilisable sur ≥ 2 projets** dès maintenant, et **alignable** sur les standards (OneRoster, CEFR) sans en hériter le poids. → Passage au **plan de dev §9 #3**.
188
+
189
+ ---
190
+
191
+ ## 10. Références
192
+
193
+ **Standards** (axe 7, consultés 2026-06-18)
194
+ - `[A]` **1EdTech — OneRoster v1.1 Final Specification** : https://www.imsglobal.org/oneroster-v11-final-specification
195
+ - `[A]` **1EdTech — OneRoster & LTI Advantage (K-12)** : https://www.imsglobal.org/about/k12/oneroster-and-lti-advantage
196
+ - `[A]` **1EdTech — QTI Specification Documents** : https://www.1edtech.org/standards/qti/index · **Specifications** : https://www.1edtech.org/specifications
197
+ - `[A]` **ADL SCORM / xAPI** : https://adlnet.gov/ , https://xapi.com/ · panorama standards (SCORM/xAPI/cmi5/LTI/OneRoster/Ed-Fi) `[T]` aristeksystems.com/blog/elearning-standards
198
+ - `[A]` **CEFR / CECRL** (Conseil de l'Europe) — niveaux A1–C2 : https://www.coe.int/lang-cefr
199
+
200
+ **Outils** (axes 1/2/3, consultés 2026-06-18)
201
+ - `[V]` **Moodle** (dont plugin *Waitlist enrolment* moodle.org/plugins/enrol_waitlist) · **Open edX** · **Canvas/Instructure** · **Chamilo** · **Sakai** · **Frappe LMS**
202
+ - `[V]` SIS : **Gibbon** (docs.gibbonedu.org) · **openSIS** (opensis.com + Community SourceForge) · **Fedena** (github.com/projectfedena/fedena)
203
+
204
+ **Académique** (axe 8, Semantic Scholar/arXiv/ResearchGate, 2026-06-18)
205
+ - `[A]` *A Comparison of Open-Source Learning Management Systems Used for Distance Education in HEI* — ResearchGate pub. 387491743
206
+ - `[A]` *Course-Prerequisite Networks for Analyzing and Understanding Academic Curricula* — arXiv:2210.01269 *(appui direct du modèle `Level.prerequisiteLevelId`)*
207
+
208
+ **Demande / appels d'offres — Algérie** (axe 9, 2026-06-18 → `Entreprise/appels-d-offres/formation/`)
209
+ - `[T]` **BOMOP / ANEP** : https://bomop.anep.dz/ (rubrique *Consultation, formation et certification*) · `[A]` **Marchés publics** : https://marches-publics.gov.dz/ · `[T]` algeriemarches.com · rhinotenders.com/bomop
210
+ - `[T]` **Agrément MFEP** : beeform.dz/agrement-mfep-algerie · *Cahier des charges* établissement privé de formation (Scribd) · `[A]` **JORADP** (JO 2002/067 ; arrêté 4 août — invest.caci.dz)
211
+
212
+ > Sources brutes horodatées : `results-training-20260618/{all-results.csv, academic-only.csv, vendors-only.csv}` (rejouables via le runner portable versionné).
213
+
214
+ ---
215
+
216
+ **Fin de l'état de l'art `@mostajs/training`.**
@@ -0,0 +1,117 @@
1
+ # 03 — Plan de développement — `@mostajs/training`
2
+
3
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com>
4
+ **Date** : 2026-06-18
5
+ **Statut** : proposition à discuter (livrable §9 #3 — DEVRULES). **Précède toute ligne de code métier (§0/§4).**
6
+ **Amont** : `PROPOSITION-MODULE-TRAINING.md` (§4) · `01-ETUDE-ETAT-ART-TRAINING-18062026.md` (§9 #1)
7
+ **Consommateurs** : P1 Hadhinat (accompagnement incubés) · P2 ATC (catalogue + groupes).
8
+
9
+ ---
10
+
11
+ ## 1. Périmètre & responsabilité unique
12
+
13
+ **Catalogue de formations à niveaux + sessions/groupes + inscriptions** — domaine **mince**, **DB-agnostique** (repos injectés), **composable**. Tout le transverse est **délégué** (cf. §6).
14
+
15
+ **Hors périmètre (frontières — délégué)** : contenu/e-learning (`elearning`), évaluation/notes (`gradebook`/`questa`), présence (`attendance`), paiement (`payment`/`subscriptions-plan`), certificats (`certificates`), planning bas niveau (`booking-stack`), apprenant/enseignant (ids opaques → `school`/`incubator`/`staff`).
16
+
17
+ ---
18
+
19
+ ## 2. Entités (schémas)
20
+
21
+ | Entité | Champs clés | Notes |
22
+ |---|---|---|
23
+ | **Course** | `id`, `title`, `category`, `description`, `active` | formation/programme |
24
+ | **Level** | `id`, `courseId`, `order`, `label`, `prerequisiteLevelId?` | CEFR généralisé (A1…C2 / 1…N) |
25
+ | **Session** | `id`, `courseId`, `levelId?`, `code`, `instructorId?`, `room?`, `capacity`, `startDate`, `endDate?`, `scheduleRef?`, `status` | instance datée ; `scheduleRef`→`booking-stack` ; `status`→`statemachine` |
26
+ | **Enrollment** | `id`, `sessionId`, `learnerId`, `status`, `enrolledAt` | contrôle de **capacité** à l'inscription |
27
+
28
+ États `Session` : `draft → open → full → running → closed` (+ `cancelled`).
29
+ États `Enrollment` : `pending → confirmed → cancelled → completed`.
30
+
31
+ ---
32
+
33
+ ## 3. Services (API cible)
34
+
35
+ ```
36
+ createTraining({ repositories, booking?, numbering?, notifications?, statemachine?, i18n?, now? }) -> Training
37
+ Training.catalog.createCourse / updateCourse / addLevel / listCourses / getCourse
38
+ Training.sessions.open / close / cancel / setInstructor / setSchedule / listOpen / get
39
+ Training.enrollments.enroll(sessionId, learnerId) // refuse si capacity atteinte → throws CapacityReached
40
+ Training.enrollments.cancel / complete / listBySession / listByLearner
41
+ createMemoryRepositories() -> TrainingRepositories // tests ; prod via @mostajs/repository
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 4. Composition (DEVRULES §10) — capacités consommées
47
+
48
+ | Capacité | Module | Mode | Obligatoire |
49
+ |---|---|---|---|
50
+ | Persistance | `@mostajs/repository` (`data-plug`/`orm`) | DI repos | oui |
51
+ | Planning/salles des séances | `@mostajs/booking-stack` | DI (peer) | non (v0.2) |
52
+ | États de session | `@mostajs/statemachine` | DI | non (fallback interne) |
53
+ | N° de session/inscription | `@mostajs/numbering` | DI | non |
54
+ | Notifications (ouverture, confirmation, rappel) | `@mostajs/notifications` | DI | non |
55
+ | Libellés FR/AR/EN | `@mostajs/i18n` | DI | non |
56
+ | Config (.env/profils) | `@mostajs/config` | runtime | oui |
57
+
58
+ > Le plan **cite explicitement** ces capacités (exigence §10) ; aucune n'est réimplémentée.
59
+
60
+ ---
61
+
62
+ ## 5. Versions (jalons)
63
+
64
+ > **Amont d'extraction (≠ feuille blanche)** : le modèle « création des cours » existe déjà à **~75-95 %** dans
65
+ > `SolutionCh/iquesta-dev` (schemas `formation/activity/dependency/snapshot`, server actions, éditeur visuel).
66
+ > Les versions ci-dessous **partent de l'extraction** de ce code (cf. étude #1 §7-bis), pas d'une réécriture.
67
+ > Découpage : `training` (modèle) **+** `@mostajs/course-builder` (éditeur visuel, roadmap #40) **+** `questa`/`gradebook`
68
+ > (quiz/scoring) **+** `media`/`storage` (contenu). Le **kind média compose** `@mostajs/media`+`storage` (§10).
69
+
70
+
71
+ | Version | Contenu | Portes §11 | DoD |
72
+ |---|---|---|---|
73
+ | **0.1.0** | Catalogue : `Course` + `Level` (CRUD, prérequis) ; repos mémoire ; `llms.txt` (#6) ; `CHANGELOG` (#7) | §11.1 build/tests | tests verts catalogue |
74
+ | **0.2.0** | `Session` (open/close, capacité, statut) + planning via `booking-stack` | §11.1 | session schedulable |
75
+ | **0.3.0** | `Enrollment` (enroll/cancel/complete) + **contrôle de capacité** + notifications | §11.1 | inscription bout-en-bout |
76
+ | **0.4.0** | i18n statuts/niveaux ; export aligné **OneRoster** ; adaptateurs `@mostajs/repository` (prod) | §11.1 + §11.5 (i18n) | P1 **et** P2 branchés |
77
+ | **1.0.0** | 14 livrables §9 complets + portes §11 + **exemple §12** + **article #17** | toutes portes applicables | publiable npm |
78
+
79
+ ---
80
+
81
+ ## 6. Risques & mitigations
82
+
83
+ | Risque | Mitigation |
84
+ |---|---|
85
+ | Périmètre qui déborde (devenir un LMS) | Frontières strictes §1 ; délégation §4 ; revue à chaque version |
86
+ | Couplage `booking-stack` | `scheduleRef` opaque + DI optionnelle ; v0.1 sans booking |
87
+ | Divergence P1/P2 | API unique pilotée par config ; ids opaques learner/instructor |
88
+ | Modèle de niveaux trop « langue » | `Level.order`+`label` générique (1→N), CEFR = cas particulier |
89
+
90
+ ---
91
+
92
+ ## 7. Portes §11 applicables (déclaration — exigée par §11)
93
+
94
+ - **§11.1 qualité (BLOQUANTE)** : build/typecheck/lint + tests verts, couverture cœur ≥ 80 %.
95
+ - **§11.5 i18n** : FR/AR/EN + RTL (libellés statuts/niveaux) dès v0.4.
96
+ - **§11.2 / §11.3 (INFORMATIVES)** : données traitées = inscriptions (peu sensibles) ; pas d'IA ; pas de tiers. Portée **faible** → **déclarées non critiques**, documentées pour information à l'usage (#15/#16 légers). *Elles n'empêchent pas le développement.*
97
+ - **§11.8 SemVer** : strict ; `CHANGELOG` dès 0.0.1.
98
+ - Non applicables (déclarées) : §11.4 budget LLM (pas d'IA), §11.6 SBOM (au build 1.0).
99
+
100
+ ---
101
+
102
+ ## 8. Jalons livrables §9
103
+
104
+ `#1` état de l'art ✅ (ce dossier) · `#2` audit (proposition §4 + cartographies P1/P2) · **`#3` ce plan** · `#4` plan de test (→ `04-PLAN-TESTS.md`) · `#5` plan de suivi (→ `05-PLAN-SUIVI-MONITORING.md`) · `#6` `llms.txt` dès 0.1 · `#7` `CHANGELOG` · `#8`–`#14` à la publication · **§12 exemple AVANT #17 article**.
105
+
106
+ ---
107
+
108
+ ## 9. Questions ouvertes (validation demandée)
109
+
110
+ 1. Nom `training` confirmé (vs `courses`/`learning`) ?
111
+ 2. `Session` porte-t-elle la salle, ou tout délégué à `booking-stack` ?
112
+ 3. Export **OneRoster** dès 0.4 ou reporté ?
113
+ 4. `gradebook` séparé confirmé (training ne porte aucune note) ?
114
+
115
+ ---
116
+
117
+ **Fin du plan de dev `@mostajs/training`.**
Binary file
@@ -0,0 +1,82 @@
1
+ # 04 — Plan de test — `@mostajs/training`
2
+
3
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com>
4
+ **Date** : 2026-06-18
5
+ **Statut** : proposition à discuter (livrable §9 #4 — DEVRULES). Rend la porte **§11.1** vérifiable.
6
+ **Amont** : `03-PLAN-DEV-TRAINING.md` · **Emplacement des tests** : `test-scripts/` (JAMAIS `/tmp` — §5), rejouables & committés.
7
+
8
+ ---
9
+
10
+ ## 1. Stratégie
11
+
12
+ - **Unitaires** (cœur de domaine, repos mémoire) — l'essentiel ; **sans I/O**, déterministes (`now` injecté).
13
+ - **Intégration** : adaptateurs `@mostajs/repository` + `booking-stack` (mock/DI) + `numbering`/`notifications` (spies).
14
+ - **Exemple §12** (`examples/`) : scénario headless `*.mjs` qui exerce l'API réelle et **`assert`** (DoD).
15
+ - **Cible de couverture** : cœur métier **≥ 80 %** lignes/branches (§11.1).
16
+
17
+ ---
18
+
19
+ ## 2. Matrice de couverture (T-cases)
20
+
21
+ | ID | Domaine | Cas | Attendu |
22
+ |---|---|---|---|
23
+ | **TC-CAT-01** | Catalogue | créer Course | persisté, `active=true` |
24
+ | **TC-CAT-02** | Catalogue | addLevel ordonné | `order` croissant, `label` libre |
25
+ | **TC-CAT-03** | Catalogue | prérequis (Level→prerequisiteLevelId) | chaîne cohérente, pas de cycle |
26
+ | **TC-CAT-04** | Catalogue | listCourses(filter category) | filtre correct |
27
+ | **TC-SES-01** | Session | open(course, capacity) | statut `open`, `code` via numbering |
28
+ | **TC-SES-02** | Session | setInstructor / setSchedule | instructorId + scheduleRef posés |
29
+ | **TC-SES-03** | Session | transition draft→open→running→closed | machine d'états respectée |
30
+ | **TC-SES-04** | Session | cancel | statut `cancelled`, inscriptions notifiées |
31
+ | **TC-SES-05** | Session | passage auto `open`→`full` à capacité | déclenché par enroll |
32
+ | **TC-ENR-01** | Inscription | enroll sous capacité | `Enrollment` `confirmed` |
33
+ | **TC-ENR-02** | Inscription | **enroll à capacité atteinte** | **throws `CapacityReached`** |
34
+ | **TC-ENR-03** | Inscription | double enroll même learner/session | refus/idempotent |
35
+ | **TC-ENR-04** | Inscription | cancel libère une place | session repasse `full`→`open` |
36
+ | **TC-ENR-05** | Inscription | complete | statut `completed` |
37
+ | **TC-ENR-06** | Inscription | listByLearner / listBySession | filtres corrects |
38
+ | **TC-I18N-01** | i18n | libellés statuts/niveaux FR/AR/EN | clés résolues, fallback |
39
+ | **TC-CMP-01** | Composition | sans booking/numbering (DI absente) | fallback interne, pas d'erreur |
40
+ | **TC-CMP-02** | Composition | notifications spy à open/enroll/cancel | events émis une fois (idempotent) |
41
+ | **TC-OR-01** | Export | mapping OneRoster (course/class/enrollment) | structure conforme (v0.4) |
42
+ | **TC-P1-01** | Scénario P1 | cohorte incubés : course→session→enroll | bout-en-bout vert |
43
+ | **TC-P2-01** | Scénario P2 | ENG-A1-01 : Anglais/A1, capacité 12 | bout-en-bout vert |
44
+
45
+ ---
46
+
47
+ ## 3. Cas limites & robustesse
48
+
49
+ - Capacité 0 ou négative → rejet à `open`.
50
+ - enroll sur session `closed`/`cancelled` → rejet.
51
+ - Level d'une autre Course → rejet.
52
+ - `now` injecté pour dates (pas de `Date.now()` non maîtrisé).
53
+ - Concurrence enroll (course pleine) → contrôle atomique côté repo (test d'intégration).
54
+
55
+ ---
56
+
57
+ ## 4. Scripts & emplacement
58
+
59
+ ```
60
+ mosta-training/
61
+ ├── test-scripts/
62
+ │ ├── unit/ # TC-CAT/SES/ENR/I18N/CMP (repos mémoire)
63
+ │ ├── integration/ # repository + booking + numbering (DI)
64
+ │ └── .out*/ # sorties (gitignorées)
65
+ └── examples/
66
+ ├── p1-incubateur/ # scénario headless *.mjs + assert (§12)
67
+ └── p2-ecole-langues/
68
+ ```
69
+
70
+ - Rejouables : `node test-scripts/unit/*.mjs` ; **committés** ; sorties dans `.out*` (gitignorées) — §5.
71
+ - CI : `build + typecheck + lint + tests` (porte §11.1) — bloquant avant tag/publish.
72
+
73
+ ---
74
+
75
+ ## 5. Critère de Definition of Done (test)
76
+
77
+ - Toutes les T-cases **vertes** ; couverture cœur **≥ 80 %**.
78
+ - **Exemple §12 exécuté** (`examples/*/run.mjs`) avec assertions vertes → **prérequis de l'article #17**.
79
+
80
+ ---
81
+
82
+ **Fin du plan de test `@mostajs/training`.**
Binary file
@@ -0,0 +1,49 @@
1
+ # 05 — Plan de suivi (KPIs & observabilité) — `@mostajs/training`
2
+
3
+ **Auteur** : Dr Hamid MADANI <drmdh@msn.com>
4
+ **Date** : 2026-06-18
5
+ **Statut** : proposition à discuter (livrable §9 #5 — DEVRULES). Avant 1.0.
6
+ **Amont** : `03-PLAN-DEV-TRAINING.md` · `04-PLAN-TESTS.md`.
7
+
8
+ ---
9
+
10
+ ## 1. KPIs produit (valeur métier)
11
+
12
+ | KPI | Définition | Source | Consommateur |
13
+ |---|---|---|---|
14
+ | Taux de remplissage des sessions | inscriptions confirmées / capacité | enrollments/sessions | direction P1/P2 |
15
+ | Sessions ouvertes vs réalisées | `running`+`closed` / total | états session | pilotage |
16
+ | Taux d'annulation d'inscription | `cancelled` / total | enrollments | qualité offre |
17
+ | Progression de niveau | `completed` par Level (A1→A2…) | enrollments+levels | pédagogie |
18
+ | Délai ouverture→première inscription | timestamps | events | marketing |
19
+
20
+ > Ces KPIs **alimentent `@mostajs/reporting`** (module commun P1/P2/P3) — `training` **expose les événements**, il n'embarque pas de dashboard (frontière §10).
21
+
22
+ ## 2. Observabilité runtime
23
+
24
+ - **Logs structurés** : `course.created`, `session.opened/closed/cancelled`, `enrollment.created/cancelled/completed`, `enrollment.rejected{reason:capacity}`.
25
+ - **Métriques** : compteurs par event ; histogramme capacité/remplissage ; erreurs `CapacityReached`.
26
+ - **Audit** : composer `@mostajs/audit` (traçabilité des actions sensibles : open/cancel/enroll).
27
+ - **Santé** : pas de service propre (librairie) ; les events sont consommés par l'app hôte.
28
+
29
+ ## 3. Alertes (côté app hôte)
30
+
31
+ | Condition | Seuil | Action |
32
+ |---|---|---|
33
+ | Session quasi pleine | remplissage ≥ 90 % | notifier gestionnaire (via `notifications`) |
34
+ | Session sous-remplie proche du début | < 30 % à J-3 | alerte marketing/relance |
35
+ | Pic de `CapacityReached` | > N/jour | suggérer ouverture session supplémentaire |
36
+
37
+ ## 4. Tableaux de bord (délégués)
38
+
39
+ Construits dans **`@mostajs/reporting`** à partir des events `training` — jamais dans `training` lui-même. Cohérent avec la confrontation P1/P2 (reporting = module commun).
40
+
41
+ ## 5. Rattachement aux portes §11
42
+
43
+ - §11.7 observabilité : logs/métriques/taxonomie d'erreurs **par défaut**.
44
+ - §11.1 : les events sont **testés** (TC-CMP-02).
45
+ - §11.2/§11.3 (**informatives**) : volumétrie de données personnelles faible (ids opaques) → suivi RGPD léger, **pour information à l'usage**, non bloquant.
46
+
47
+ ---
48
+
49
+ **Fin du plan de suivi `@mostajs/training`.**