# @mostajs/socle

**Auteur** : Dr Hamid MADANI <drmdh@msn.com> · **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
```
