@mostajs/teams
v0.1.0
Published
Annuaire d'organisation transverse : équipes, appartenances (rôle DANS l'équipe) et affectation d'une équipe à une cible générique {type,id} (rôle SUR la cible). Cœur headless, persistance injectée, aligné SCIM 2.0 Group. N'accorde aucun droit — l'autoris
Downloads
172
Maintainers
Readme
@mostajs/teams — l'annuaire d'organisation
Auteur : Dr Hamid MADANI [email protected] · Licence AGPL-3.0-or-later · N1, zéro dépendance
Équipes, appartenances (le rôle dans l'équipe) et affectations d'une équipe à une cible
générique {type, id} (le rôle sur la cible). Cœur headless, aucune I/O : la persistance est
injectée. Il répond à « qui travaille sur quoi », et à rien d'autre.
L'invariant fondateur — il n'accorde aucun droit
Aucun can(), aucune importation de @mostajs/rbac, aucun type de cible connu d'avance. Il livre
scopesOf(userId) ; c'est l'application qui construit le pont vers son moteur d'autorisation et
qui décide. Fondement : RFC 7643 §4.2 — un Group porte un displayName et des members[],
et la sémantique des autorisations y est explicitement hors périmètre. Un test le garde (T13).
Savoir qui appartient à quoi et décider ce qui est permis sont deux métiers. Les fondre donne un annuaire qui distribue des pouvoirs en silence.
Installer
npm i @mostajs/teamsComposer
import { createTeams, createMemoryRepositories } from '@mostajs/teams';
const teams = createTeams({
repositories: createMemoryRepositories(), // en production : vos dépôts (data-plug côté app)
roles: ['owner', 'dev', 'tester', 'member'], // le vocabulaire MÉTIER est déclaré par l'app
});
const noyau = await teams.create({ key: 'noyau', name: 'Équipe noyau' });
await teams.members.add(noyau.id, 'u-42', 'dev');
await teams.assignments.assign(noyau.id, { type: 'projet', id: 'collabtrax' }, 'owner');
await teams.peopleOfTarget({ type: 'projet', id: 'collabtrax' });
// → [{ userId:'u-42', teamKey:'noyau', teamRole:'dev', assignmentRole:'owner', … }]La clé d'une équipe est stable à vie : la renommer est refusé. Les liens, les exports et les historiques qui la citent restent vrais — un identifiant qui bouge périme tout ce qui le référence.
Le vocabulaire des rôles est une donnée, pas du code
Le moteur ne possède aucun mot : il impose la règle (« un rôle hors vocabulaire est refusé »).
Le défaut est un seed minimal — ['owner','member'] et ['owner','contributor','observer'] — vrai
dans tout domaine. Livrer dev et tester rendrait ce module implicitement « informatique », alors
qu'un chantier dira chef et exécutant.
import { MINIMAL_ROLES } from '@mostajs/teams/seed-roles';Interopérer
toScimGroup / fromScimGroup traduisent une équipe en SCIM Group (RFC 7643) : un annuaire
d'entreprise peut donc alimenter ou lire l'organisation sans que le module connaisse son dialecte.
Ce qu'il ne fait pas
Autoriser → @mostajs/rbac et rbac-tenant, côté app · identifier les personnes → users
(injecté, il hydrate members.list) · notifier → notifications (injecté ; une notification qui
échoue ne casse pas un ajout) · stocker → les dépôts que vous injectez.
Contrat des dépôts (N0/N1) : create · findById · update · find(predicate) · delete · all.
En N2+ et dans les apps, l'autre convention règne (BaseRepository / FilterQuery de
@mostajs/orm) : l'adaptation appartient à l'application, jamais au module.
Tests
npm test # 16/16