# Acteurs intégrés

Les cinq acteurs intégrés sont timeacte, audio, vidéo, document et image.

## Déclarations et création

L'enveloppe garde `type: "actor"`. `data.kind` sélectionne `timeacte`, `audio`,
`video`, `image` ou `document`. Les identifiants des exemples sont préfixés
`actor_`; `lineacte` est un mode de `timeacte`, pas une deuxième fabrique.
Les signatures et la forme de `data` ci-dessous sont les choix d'implémentation
concrets du module des acteurs, ajoutés au contrat fonctionnel validé.

```json
{
  "id": "actor_photo",
  "type": "actor",
  "data": {
    "kind": "image",
    "resource": {"id": "photo", "role": "image", "url": "images/photo.png"},
    "config": {"alt": "Description de la photo", "fit": "contain"}
  }
}
```

`resource` peut aussi être une référence à une entité `type: "resource"` déjà
chargée, locale au namespace de l'acteur ou qualifiée `namespace:id`.
L'URL relative est résolue contre le document qui déclare la ressource,
jamais contre la page qui affiche l'acteur. Les références n'entraînent pas
la découverte implicite d'un fichier : déclarer les bibliothèques nécessaires
au chargeur. Les ressources externes nécessitent les autorisations CORS
habituelles du navigateur pour le chargement des documents.

```js
import {createActorContext} from './src/index.js';
// loaded : résultat ready/degraded du chargeur.
const context = createActorContext({loaded});
const result = context.createActor({
  id: 'actor_photo_view', reference: 'mon.projet:actor_photo',
  container: document.getElementById('photo'), config: {width: 320}
});
if (!result.ok) throw new Error(JSON.stringify(result.diagnostics));
const actor = result.value;
const initialized = await actor.init();
if (initialized.ok) await actor.activate();
await actor.command('presentationSet', {alt: 'Autre description'});
await actor.stop();
await actor.activate();
await actor.destroy();
```

Le contexte expose `createActor`, `getActor(id)` et `listActors()`.
Options de création : `id`, `reference`, `namespace?`, `container`, `config?`,
`connections?`, `initialState?`. Les connexions et données JSON génériques
restent celles du cycle de vie ; elles ne déclenchent aucune orchestration automatique.
Le contexte accepte aussi `timeouts` (cycle de vie) et `fetchDocument(url, {signal})`,
qui retourne une réponse de type Fetch (`ok`, `status`, `url`, `text()`).

Chaque acteur expose `id`, `definition`, `kind`, `capabilities`, `status`,
`init()`, `activate()`, `stop()`, `destroy()`, `inspect()`, `stateGet()`,
`command(name, ...args)` et `on(event, callback)` (retourne le désabonnement).
Les commandes rendent une promesse `{ok, value?, diagnostics}` ; elles ne
retournent jamais les objets DOM ou le modèle mutable interne.
Les états retournés sont des copies. `inspect()` réunit diagnostics de cycle
et diagnostics de l'acteur ; les résultats de cycle restent ceux du cycle de vie.

## Cycle de vie et disponibilité

- `init` prépare une instance indépendante, sans montage visible. Image et
  document attendent leur chargement ; médias attendent leurs métadonnées,
  sauf `preload: "none"` qui demande explicitement un chargement différé.
- `activate` monte les éléments et engage les ressources d'activité.
- `stop` du cycle démonte et met les médias en pause, en conservant état et
  position. La réactivation remonte la même instance sans rechargement imposé.
- La commande média `command('stop')` met en pause et revient au début, sans
  arrêter le cycle de vie. Ces deux opérations ont des usages distincts.
- `destroy` retire les seuls éléments possédés, écouteurs et abonnements,
  annule les requêtes et libère les sources des médias. Le contenu extérieur
  au montage est conservé. Les IDs restent réservés dans le contexte d’instances.

Les commandes sont disponibles dans les états `ready`, `active`, `stopped`,
hors transition. `play` exige `active`. Les opérations dépendantes de la
présentation (défilement notamment) sont utiles après activation.
Les délais du cycle bornent les opérations du cycle. Un lecteur injecté ignorant
l'annulation peut continuer son calcul, mais son résultat tardif ne monte
aucun contenu et ne notifie pas les abonnés supprimés.

## Capacités et valeurs par défaut

| Acteur | Commandes |
|---|---|
| `timeacte` | `boundsSet(bounds)`, `move(ratio)`, `zoom(factor, anchor?)`, `center(value)`, `fit()`, `sceneBoundsSet(id, bounds)`, `rideauSet(id, bounds)`, `acteSet(sceneId, acteId, patch)`, `flush()`, `flushAutoSet(boolean)` |
| `audio`, `video` | `play()`, `pause()`, `stop()`, `seek(seconds)`, `volumeSet(0..1)`, `mutedSet(boolean)`, `rateSet(0.0625..16)`, `loopSet(boolean)` |
| `image` | `presentationSet(patch)` |
| `document` | `scrollTo(top, left?)`, `anchor(id)`, `start()` |

Les listes `ACTOR_CAPABILITIES` sont explicites et immuables. Une commande
absente produit `E_ACTOR_CAPABILITY`, sans opération implicite.

`timeacte` : `config.mode` fixé à la création (`lineacte` par défaut),
`renderer` (`dom-full` par défaut, ou `dom-shadow`), `deb`, `fin` requis,
`flushAuto: true`. `data.scenes` contient des sources spécialisées existantes
`{id, deb, fin, actes: [...]}` ou des références à des entités `scene` déjà
chargées dont `data` contient cette forme. Les représentations sont construites
par instance : aucune duplication du moteur et aucune mutation de la définition.
Les dates gardent la forme structurée existante, par exemple `{an: 0}`.
Les réglages dynamiques portent sur fenêtres, rideaux et présentation des actes.
Le remplacement global de la déclaration/source demande une nouvelle instance.

Le rendu utilise `init`, `mount`, `invalidate`, `flush`, `unmount`, `destroy`.
`actionAdd` reste compatible avec les fabriques de la gestion des instances ;
les deux rendus livrés exposent désormais `invalidate` directement.

`audio`/`video` : `autoplay: false`, `controls: true`, `volume: 1`, `muted: false`,
`rate: 1`, `loop: false`, `preload: "metadata"`. La vidéo ajoute `fit: "contain"`,
`position: "50% 50%"`, `width?`, `height?` (pixels) et `poster?` (URL relative
à la déclaration de l'acteur). Les limites effectives de codecs, de vitesse,
d'autoplay et de seek dépendent du navigateur et de la ressource : les refus
sont diagnostiqués. Autoplay refusé ne fait pas échouer le montage.

État média : position en secondes, durée finie ou `null`, pause, fin, volume,
sourdine, vitesse, boucle, disponibilité et `readyState` natif.
Événements : `loading`, `available`, `play`, `pause`, `ended`, `position`,
`waiting`, `volume`, `rate`, `error`. Une réponse HTTP reçue ne suffit pas :
les événements de disponibilité viennent du décodeur natif.

`image` : `<img>`, `alt: ""`, `fit: "contain"`, `position: "50% 50%"`, dimensions
optionnelles en pixels. `presentationSet` modifie la présentation, pas la source.
État : disponibilité, dimensions affichées et naturelles, présentation.
Événements : `loading`, `available`, `error`. Aucune commande temporelle.

`document` : HTML chargé via Fetch, défilement local, ancres par `id`, hauteur
optionnelle `config.height` en pixels. Sans hauteur, le contenu détermine la
hauteur ; fixer une hauteur pour obtenir une zone de défilement interne.
État : disponibilité, défilements `top`/`left`. Événements : `loading`,
`available`, `scroll`. Une erreur de chargement est disponible dans les
résultats de cycle et `inspect()`, sans prétendre que le contenu est affiché.

## HTML documentaire

Le HTML est analysé dans un template inerte, puis reconstruit depuis une liste
positive de balises de texte, sections, tableaux, liens, images et details/summary.
Aucun arbre HTML brut n'est connecté à la page. Scripts, formulaires, médias
imbriqués, iframe, objets, SVG/MathML, templates, CSS et attributs d'événements
sont retirés. Les liens et images relatifs utilisent l'URL finale de la réponse.
Les ancres `#id` sont résolues dans l'instance et leur clic ne navigue pas la page.
Les suppressions produisent un avertissement `E_ACTOR_CONTENT`.

Chaque document a un Shadow DOM propre : IDs et styles internes sont isolés.
Ce n'est pas un navigateur embarqué : les applications HTML nécessitant leurs
scripts ou leurs styles ne sont pas prises en charge par cet acteur.
URLs admises pour les ressources : HTTP(S), blob ; données raster base64 pour
les images et données audio/vidéo base64 pour les médias. Les URLs exécutables
`javascript:`, données HTML et SVG inline sont refusées. Les blob URL fournies
par l'appelant restent sa propriété : l'acteur ne les révoque pas.

## Diagnostics et vérification

Champs inconnus de `data`/`config` : avertissements `E_UNKNOWN_FIELD` conservant
la donnée. Une valeur connue invalide est une erreur ; seul un champ absent
reçoit son défaut. Les sources spécialisées gardent leur validation.

| Code | Contexte |
|---|---|
| `E_ACTOR_CONFIG` | Configuration, mode, valeur ou cible spécialisée invalide |
| `E_ACTOR_CAPABILITY` | Commande absente des capacités |
| `E_ACTOR_STATE` | Cycle incompatible avec la commande |
| `E_ACTOR_RESOURCE` | Référence, URL, chargement ou décodage indisponible |
| `E_ACTOR_OPERATION` | Refus d'une opération native |
| `E_ACTOR_CONTENT` | HTML filtré ou ancre introuvable |
| `E_ACTOR_LISTENER` | Exception d'un abonné, isolée des autres abonnés |

`npm test`, `npm run check`, `npm run test:browser` et l'exemple
`examples/actors/` fournissent les vérifications. Les fixtures incluent PNG,
WAV et WebM créés localement et du HTML volontairement non conforme pour
vérifier son filtrage. Les tests n'utilisent aucun hébergement de médias tiers.

L’assemblage des compositions et la coordination sont décrits dans [composition.md](../common/composition.md).
OpenLayers, canvas et iframe ne sont pas des acteurs intégrés.
Le vérificateur déclaratif est décrit dans [verification.md](../common/verification.md).
