# @mostajs/socle **Auteur** : Dr Hamid MADANI · **Licence** : AGPL-3.0-or-later **Niveau** : N1 · **25 tests** · Amorçage de l'application à partir de ses modules. `socle` est le **BIOS de la plateforme** @mostajs. Au démarrage, il découvre les modules installés, valide leurs dépendances, les charge **dans le bon ordre**, et **recueille ce que chacun déclare** — schémas à installer en base, dépôts, permissions, rôles, routes, pages, menus, thèmes, i18n, seeds. Puis il remet le tout à l'application, exactement comme le BIOS passe la main à l'init de l'OS. ``` wire.json (POST) validation + ordre register() de chaque module découverte des modules → topologique + priorité → collecte des contributions → « booted » ``` ## Ce qu'il fait, précisément | Étape | Méthode | Promesse (prouvée) | |---|---|---| | **Découverte** | `discoverModules(rootDir)` | lit chaque `node_modules/@mostajs/*/wire.json` | | **Validation** | `validateDependencies()` | détecte dépendance manquante ET cycle | | **Ordre** | `resolveLoadOrder()` | tri topologique ; à égalité, la `priority` départage | | **Amorçage** | `bootstrap(config)` | enchaîne tout, appelle `register()`, marque `booted` | | **Collecte** | `ModuleRegistry` | agrège schémas / dépôts / permissions / routes / pages / menus | Le registre construit aussi le **rôle `admin` automatiquement** : l'union de TOUTES les permissions de TOUS les modules. Personne ne le maintient — un module qui ajoute une permission la donne à l'admin. ## Le flux est DESCENDANT (et c'est le point d'architecture) ``` application (init OS) ├── dépend de socle ── collecte les déclarations └── dépend de orm ── crée les schémas collectés ``` L'application dépend de socle **et** d'orm, et c'est **elle** qui les câble. `orm` ne connaît pas socle ; `socle` ne connaît pas orm. Leur seul point commun est le **contrat** — et il vit sous les deux, en N0. ## Le contrat n'est PAS ici — il est en N0 Les types que remplit un module pour se déclarer (`ModuleRegistration`, `WireManifest`, `SocleConfig`…) vivent dans **[`@mostajs/module-contract`](../mosta-module-contract)** (N0, zéro dépendance). `socle` les ré-exporte pour compatibilité, mais il les **implémente**, il ne les possède pas. > **Pourquoi ?** Tant que le contrat vivait dans socle (N1), toute primitive N0 qui voulait se > déclarer — `orm`, `ui`, `themes` — devait importer depuis l'orchestrateur : une dépendance **vers > le haut**. La règle d'architecture avait dû inscrire socle sur une liste blanche pour tolérer > l'inversion (§5.bis.1). Déplacer le contrat en N0 a supprimé et l'inversion, et la dérogation. ## Module « présence seule » Un module d'infrastructure (comme `orm` ou `ui`) ne contribue **rien** — ni schéma, ni route. Il n'a donc **pas** de `register()` : son `wire.json` sans champ `register` suffit à le faire figurer dans le graphe de dépendances. `socle` l'accueille sans exiger de code. C'est ce qui permet à ces primitives de ne plus jamais importer l'orchestrateur. ## Usage ```js import { bootstrap } from '@mostajs/socle'; const registry = await bootstrap({ appName: 'mon-app' }); // registry.getSchemas() → à créer en base // registry.getAllRoles() → à provisionner (dont admin auto-construit) // registry.resolveRoute(['users','42'], 'GET') → { handler, permission, params:{id:'42'} } ``` ## Tests ```bash npm test # 25 tests — chaque promesse est EXÉCUTÉE, pas décrite ```