# Données et déclarations

Entrée publique `alloframe/declarations`, également réexportée depuis `alloframe`.
Modules ES purs sous `src/declarations/`, fondés sur `src/common/`.
Aucun accès DOM, réseau, disque, import dynamique ni exécution de déclaration.

## Interfaces

| Fonction | Rôle |
|---|---|
| `parseDeclarationJson(text, {source}?)` | Analyse syntaxique JSON, valeur brute |
| `normalizeDocument(object, options?)` | Vérification structurelle, copie et normalisation |
| `normalizeProjectManifest(object, options?)` | Raccourci `kind: 'project'` |
| `normalizeLibraryManifest(object, options?)` | Raccourci `kind: 'library'` |
| `normalizeEntityDocument(object, options?)` | Raccourci `kind: 'entities'` |
| `normalizeCompositionDocument(object, options?)` | Raccourci `kind: 'composition'` |
| `parseVersion(text)` | Version stricte, composantes sous forme de chaînes |
| `parseVersionConstraint(text)` | Comparaisons combinées par ET |
| `checkVersionCompatibility(version, constraint)` | Succès vrai ou diagnostics d'échec |
| `verifyDeclarations(entries, options?)` | Contrôles croisés sur les seuls documents fournis |

Options de normalisation : `kind` (défaut `entities`), `source` (URL du document,
par défaut `null`), `namespace` (contexte explicite de repli), `frameworkVersion`.
Autres kinds : `decor`, `staging`, `scenario`, `actor`, `director`, `choreography`.

Toutes les fonctions retournent `{ok, value, diagnostics}` en succès, ou
`{ok:false, diagnostics}` sans `value` en échec. Un avertissement ne fait pas échouer
la validation. Un succès de normalisation ne garantit pas qu'une représentation
peut être exécutée.

La valeur normalisée contient :

- `kind`, `source`, `document` : déclaration copiée, défauts appliqués ;
- `identities` : identité, catégorie et origine de chaque entité ;
- `references` : référence brute, identité qualifiée, namespace déclarant, catégorie attendue et origine ;
- `locations` : chemins/URL déclarés, origine et URL résolue si possible ;
- `deferred` : contrôles qui exigent des informations supplémentaires.

Les chemins de diagnostic utilisent `$`, les noms de propriétés et les indices de tableaux.
La provenance figure dans `scope.source` et `scope.path`. L'ordre d'entrée est conservé.
Les propriétés inconnues sont copiées et produisent `E_UNKNOWN_FIELD` / `warning` / `none`.
Les valeurs présentes invalides ne sont jamais remplacées par un défaut.
Les objets JS non JSON (fonctions, accesseurs, cycles, Date, undefined, etc.) sont rejetés.

## Structures prises en charge

### Manifestes

`alloframe.manifest.json` : `format_version` obligatoire, `project`, `requires`,
`libraries` par défaut `{}`, `compositions` obligatoire et non vide.
Chaque entrée nommée de `compositions` comprend `composition` (chemin obligatoire),
`decor` (`null`), `scenarios` (`[]`) et `staging` (`null`). Ces chemins restent
relatifs au manifeste qui les déclare, sans sélection implicite d'une composition.

`alloframe.library.json` : `format_version` obligatoire, `library`, `requires`,
`libraries` par défaut `{}`, `contributions` obligatoire, tableau de chemins non vides
pouvant être vide. Les contributions s'additionnent sans fusion d'entités homonymes.

`libraries` est une table d'alias : chaque entrée contient `manifest` obligatoire
et éventuellement `requires_version`. Les métadonnées `project`/`library` admettent
`id`, `name`, `description`, `version`, sans version inventée.
`requires.framework` exprime la contrainte du framework ; elle ne remplace pas
la contrainte de version d'une bibliothèque.

### Entités et compositions

Document d'entités : `format_version`, `namespace` facultatif, `entities` obligatoire.
Les documents acceptent aussi `libraries`, par défaut `{}`.
Une entité possède `id`, `type`, `namespace` propre ou hérité, `name` (défaut `id`),
`description` (défaut `""`), `data` (défaut `{}`). Une identité nécessite un namespace
fourni par l'entité, le document ou explicitement par l'appelant.

Un document spécialisé contient une entité sous la clé correspondant à son kind
(`composition`, `decor`, etc.), ainsi que `entities` facultatif, par défaut `[]`.
L'entité principale doit porter la catégorie attendue.

`composition.data.scenes` est obligatoire, tableau vide autorisé. Chaque utilisation :
`ref`, `instance_id` facultatif, `config` par défaut `{}`. Les références locales
se qualifient dans le namespace de l'entité déclarante ; elles ne vérifient pas
à elles seules l'existence d'une cible.

`decor.data.presentations` (défaut `[]`) contient `target`, éventuellement `renderer`
et `template`, et `config` (défaut `{}`). Les noms de rendu/template restent des
identifiants opaques ; aucun moteur n'est choisi ni appelé.

`staging.data` comprend `actors`, `scenarios`, `choreographies` (défaut `[]`) et
`director` (défaut `null`). Acteurs, directeur et chorégraphies utilisent la forme
`ref`/`instance_id`/`config`. Les acteurs ajoutent `bindings` (défaut `{}`).
Chaque association de scénario contient `actor` (instance d'acteur) et `scenario`
(utilisation avec `ref`, `instance_id`, `config`). Les instances d'une mise en scène
partagent un contrôle d'unicité. Une association vers un acteur absent est rejetée.

Une entité `resource` place `role`, `type` et `url` dans `data` ; son `id` provient
de l'enveloppe. Les autres catégories et leurs données métier restent extensibles :
l'enveloppe est vérifiée, le contenu métier nécessite le contrat de la catégorie.
Ce contrôle est explicitement différé, et non annoncé comme réussi.

## Versions

Versions strictes `MAJEURE.MINEURE.CORRECTIVE`, sans zéros initiaux. Contraintes :
version exacte, `=`, `>`, `>=`, `<`, `<=`, séparées par des espaces et combinées par ET.
Exemple : `>=1.0.0 <2.0.0`. Comparaison exacte, y compris pour de grandes composantes.
Pas de `^`, `~`, jokers, OU, préversions ou métadonnées de build dans ce sous-ensemble.
Un format inconnu est rejeté ; seule la version de format `1.0.0` est implémentée.
L'absence de version d'une bibliothèque sous contrainte est une erreur. Hors
contrainte, une bibliothèque sans version reste valide.

## Vérification d'ensemble

```js
import { verifyDeclarations } from 'alloframe/declarations';
const result = verifyDeclarations([
  { kind: 'entities', source: 'https://example.test/entities.json', document: {
    format_version: '1.0.0', namespace: 'demo',
    entities: [{ id: 'scene_main', type: 'scene' }]
  } },
  { kind: 'composition', source: 'https://example.test/composition.json', document: {
    format_version: '1.0.0', namespace: 'demo', composition: {
      id: 'main', type: 'composition', data: { scenes: [{ ref: 'scene_main' }] }
    }
  } }
], { complete: true, frameworkVersion: '1.0.0' });
```

Chaque descripteur contient `document`, `kind`, et éventuellement `source`, `namespace`.
`complete:false` par défaut : les cibles non fournies sont différées. Avec
`complete:true`, les cibles absentes du jeu déclaré complet sont des erreurs.
Cela ne signifie jamais que le réseau ou des fichiers externes ont été vérifiés.
Sans URL source absolue, les chemins relatifs restent à résoudre explicitement.

Le contrôle compare les identités toutes catégories et contributions confondues,
les catégories de références, les types de documents liés, les versions requises,
les instances et les cibles de décor/bindings lorsque le manifeste fournit les
liens vers la composition et la mise en scène. Une référence de ressource n'entraîne
pas de vérification de présence du média dans ce jeu de documents.

La sortie comprend `documents`, `identities`, `deferred`, `scope`. Aucun registre
persistant n'est créé. Deux appels ne partagent pas d'état.

## Choix techniques de cette API

Les noms des fonctions, le module `src/declarations/`, les métadonnées latérales,
les codes supplémentaires et les chemins `$...` sont des choix d'implémentation.
Les identifiants générés suivent `categorie_position` (position à partir de 1),
avec suffixe numérique en cas de collision avec une valeur explicite. Leur génération
est déterministe ; les identifiants explicites ne sont jamais réécrits.
Les alias et noms de compositions suivent la grammaire d'identifiant local du socle.
`bindings` est traité comme une table nom de liaison → identifiant d'instance ;
la validité de chaque liaison métier nécessite le contrat de l'acteur.


## Portée et vérification

`npm run test:declarations` contrôle les documents conformes et non conformes.
Cette API vérifie les documents fournis sans accéder à leurs dépendances.
Voir [loading.md](loading.md) pour charger le graphe et [verification.md](verification.md)
pour les contrôles statiques des acteurs, ressources et compositions.
