@mostajs/diplomation
v0.14.0
Published
Parcours académique encadré menant à un acte officiel : types de parcours en configuration (diplôme-startup, PFE, master, thèse), dossier à jalons gardés, livrables versionnés à cycles de révision, encadrants désignés avec autorité de validation, soutenan
Maintainers
Readme
@mostajs/diplomation
Auteur : Dr Hamid MADANI [email protected] · AGPL-3.0-or-later · niveau N3 Produit : DiplomaFlow
Le parcours académique encadré qui mène à un acte officiel : dossier à jalons gardés, livrables versionnés à cycles de correction, encadrants désignés avec autorité de validation, soutenance, actes signés.
Le type de parcours est une donnée de configuration : startup-label (diplôme-startup,
arrêté 1275), pfe, master, these — et tout ce que vous déclarez. Ajouter un parcours ne
touche aucune ligne de code.
Ce que le module ne fait pas
C'est aussi important que ce qu'il fait. Tout est consommé par ports injectés :
| Besoin | Module | Le module ne contient donc… |
|---|---|---|
| Jury, vote, quorum, PV | @mostajs/deliberation | aucune logique de scrutin |
| Notes, moyennes, barèmes | @mostajs/gradebook | aucun calcul de note |
| Fichiers, versions d'octets | @mostajs/ged | aucun stockage |
| Certificats, PDF signés | @mostajs/certificates + pdf-sign | aucun rendu de document |
| Présences | @mostajs/attendance | aucune règle de pointage |
| Contenu pédagogique | @mostajs/training, elearning | aucun catalogue |
@mostajs/diplomation n'importe aucun autre module @mostajs — c'est ce qui évite le couplage
latéral entre N3 et le rend testable seul.
Installation
npm i @mostajs/diplomationAucune dépendance de production : dépôts, ports, audit, horloge et numérotation sont injectés.
Exemple minimal
import { createDiplomation, createMemoryRepositories, STARTUP_LABEL } from '@mostajs/diplomation';
const d = createDiplomation({ repositories: createMemoryRepositories(), ports });
await d.types.register(STARTUP_LABEL);
const j = await d.journeys.open({ studentId: 'etu-18', kind: 'startup-label', tenantId: 'univ-boumerdes' });
await d.milestones.plan(j.id);
await d.journeys.transition(j.id, 'submitted'); // avance d'UNE étape, gardes comprises
await d.supervision.assign({ journeyId: j.id, supervisorId: 'ens-bmc', scope: 'bmc' });
await d.deliverables.submit({ journeyId: j.id, kind: 'bmc', fileRef: 'ged:doc-1' });
await d.deliverables.requestRevision({ journeyId: j.id, kind: 'bmc', by: 'ens-bmc', reason: '…' });
await d.deliverables.accept({ journeyId: j.id, kind: 'bmc', by: 'ens-bmc' });
await d.defense.schedule({ journeyId: j.id, body: 'jury-1' }); // ouvre une séance via deliberation
await d.defense.record({ journeyId: j.id, grade: 17.5 });
await d.defense.publish({ journeyId: j.id }); // refusé tant que le PV n'est pas scelléDeux exemples exécutables : npm run example — diplôme-startup complet, puis PFE sans aucune
notion de startup. Même moteur, seule la configuration change.
API
| Groupe | Méthodes |
|---|---|
| types | register · get · list |
| journeys | open · get · list · transition · history |
| milestones | plan · list · complete |
| deliverables | submit · requestRevision · accept · history · current |
| supervision | assign · revoke · of · history |
| defense | schedule · record · publish · get |
Cœur pur réutilisable seul : supervisorOf, canValidate, nextStage, isLegalTransition,
deliverablesAccepted, currentVersion.
Les quatre règles qui font le module
On avance d'une étape à la fois. Sauter une étape est un défaut de dossier, pas un raccourci.
transition() refuse tout ce qui n'est pas l'étape immédiatement suivante.
Les gardes sont déclaratives. Une étape porte requires: 'training-complete' |
'deliverables-accepted' | 'defense-sealed'. Une garde non satisfiable (port absent) lève une
erreur : mieux vaut échouer bruyamment que laisser passer sans vérifier.
Chaque dépôt est une version, jamais un remplacement. La suite des versions — avec son motif de révision et son auteur — est la traçabilité des corrections exigée par le dossier.
L'autorité de validation suit la désignation. Seul l'encadrant désigné sur ce périmètre valide : l'encadreur du BMC n'a rien à dire sur le BP. Révoquer n'efface rien, on clôt.
Cloisonnement multi-établissement
journeys.get(id, { tenantId }) renvoie null hors périmètre — jamais un refus, qui
confirmerait l'existence du dossier d'une autre université. journeys.list({ tenantId }) filtre ;
sans tenantId, la vue est complète (usage central).
Tests
npm test — 16 cas, alignés un à un sur les exigences de
docs/DEVTEST-PLAN.diplomation.json (format
mostajs-devtest/1, ingéré par MostaQatraxFlow).
