# Intégration iframe – Spécification de messagerie Ce document définit les échanges entre un site hôte et `ihm_client` intégré en iframe, via `window.postMessage`. Aucun exemple de code exécutable n’est inclus. ## Principes - Canal: postMessage entre la page parente et l’iframe `ihm_client`. - Découverte: `ihm_client` émet `LISTENING` pour signaler la disponibilité des listeners (côté iframe). En mode E2E (`?e2e=1`) et seulement lorsque l’app tourne en iframe, `LISTENING` est émis périodiquement (jusqu’à 100 fois) pour éviter les courses de tests. Hors E2E, pas d’émission périodique. - Sécurité: - Utiliser la cible `event.origin` pour les réponses. - De nombreuses opérations exigent un `accessToken` valide (lié à `origin`). - `messageId` recommandé pour corréler requêtes/réponses. - Pré-requis: pour la plupart des actions de processus, l’appareil doit être appairé. ## Types de message Référence: `src/models/process.model.ts` (enum `MessageType`). ### LISTENING - Émis par `ihm_client` au parent pour signaler la disponibilité des listeners. - Réception côté parent (aucune requête attendue). Pas de payload spécifique. --- ### REQUEST_LINK (Requête) - Objet: ouverture d’un consentement utilisateur pour lier l’hôte à l’appareil. - Requête (parent → iframe): - `type`: `REQUEST_LINK` - `messageId`: string (optionnel mais recommandé) - Réponses (iframe → parent): - Succès: `type`: `LINK_ACCEPTED`, `accessToken`: string, `refreshToken`: string, `messageId` - Erreur: `type`: `ERROR`, `error`: string, `messageId` ### VALIDATE_TOKEN (Requête) - Objet: vérifier la validité du couple `{accessToken, refreshToken}`. - Requête: `type`, `accessToken`, `refreshToken`, `messageId` - Réponse: `type`: `VALIDATE_TOKEN`, `isValid`: boolean, `accessToken`, `refreshToken`, `messageId` ### RENEW_TOKEN (Requête) - Objet: obtenir un nouveau `accessToken` depuis un `refreshToken`. - Requête: `type`, `refreshToken`, `messageId` - Réponses: - Succès: `type`: `RENEW_TOKEN`, `accessToken`, `refreshToken`, `messageId` - Erreur: `ERROR` --- ### CREATE_PAIRING (Requête) - Objet: initier l’appairage de l’appareil. - Pré-requis: `accessToken` valide; appareil non appairé. - Requête: `type`, `accessToken`, `messageId` - Réponses: - Succès: `type`: `PAIRING_CREATED`, `pairingId`: string, `messageId` - Erreur: `ERROR` ### GET_PAIRING_ID (Requête) - Objet: récupérer l’identifiant d’appairage utilisateur. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `accessToken`, `messageId` - Réponse: `type`: `GET_PAIRING_ID`, `userPairingId`: string, `messageId` --- ### GET_MY_PROCESSES (Requête) - Objet: lister les processus auxquels l’utilisateur participe. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `accessToken`, `messageId` - Réponse: `type`: `GET_MY_PROCESSES`, `myProcesses`: string[] | null, `messageId` ### GET_PROCESSES (Requête) - Objet: récupérer tous les processus connus localement. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `accessToken`, `messageId` - Réponse: `type`: `PROCESSES_RETRIEVED`, `processes`: Record, `messageId` --- ### RETRIEVE_DATA (Requête) - Objet: déchiffrer et retourner les attributs autorisés d’un état de processus. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `processId`: string, `stateId`: string (32 bytes hex), `accessToken`, `messageId` - Réponse: `type`: `DATA_RETRIEVED`, `data`: Record, `messageId` ### DECODE_PUBLIC_DATA (Requête) - Objet: décoder des données publiques encodées. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `accessToken`, `encodedData`: number[], `messageId` - Réponse: `type`: `PUBLIC_DATA_DECODED`, `decodedData`: any, `messageId` --- ### CREATE_PROCESS (Requête) - Objet: créer un nouveau processus. - Pré-requis: appairé + `accessToken` valide. - Requête: - `type` - `processData`: Record (données brutes à répartir en public/privé) - `privateFields`: string[] (liste des nouveaux champs à forcer en privé) - `roles`: Record - `accessToken`, `messageId` - Réponse succès: `type`: `PROCESS_CREATED`, `processCreated`: { `processId`: string, `process`: Process, `processData`: Record }, `messageId` - Réponse erreur: `ERROR` ### UPDATE_PROCESS (Requête) - Objet: créer un nouvel état avec des mises à jour (champs publics/privés déterminés automatiquement, `privateFields` pour les nouveaux champs privés). - Pré-requis: appairé + `accessToken` valide + processus existant avec état committé. - Requête: `type`, `processId`, `newData`: Record, `privateFields`: string[], `roles` (ou null pour conserver), `accessToken`, `messageId` - Réponse: `type`: `PROCESS_UPDATED`, `updatedProcess`: Process, `messageId` --- ### NOTIFY_UPDATE (Requête) - Objet: demander l’émission d’un PRD Update pour un état précis. - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId` - Réponse: `type`: `UPDATE_NOTIFIED`, `messageId` ### VALIDATE_STATE (Requête) - Objet: valider un état (selon règles/permissions WASM). - Pré-requis: appairé + `accessToken` valide. - Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId` - Réponse: `type`: `STATE_VALIDATED`, `validatedProcess`: Process, `messageId` --- ### HASH_VALUE (Requête) - Objet: obtenir le hash d’un blob (document) pour un engagement donné. - Requête: `type`, `accessToken`, `commitedIn`: string, `label`: string, `fileBlob`: { type: string; data: Uint8Array }, `messageId` - Réponse: `type`: `VALUE_HASHED`, `hash`: string, `messageId` ### GET_MERKLE_PROOF (Requête) - Objet: récupérer la preuve Merkle d’un attribut dans un état. - Requête: `type`, `accessToken`, `processState`: ProcessState, `attributeName`: string, `messageId` - Réponse: `type`: `MERKLE_PROOF_RETRIEVED`, `proof`: MerkleProofResult, `messageId` ### VALIDATE_MERKLE_PROOF (Requête) - Objet: valider une preuve Merkle pour un document donné. - Requête: `type`, `accessToken`, `merkleProof`: string (JSON sérialisé), `documentHash`: string, `messageId` - Réponse: `type`: `MERKLE_PROOF_VALIDATED`, `isValid`: boolean, `messageId` --- ## Erreurs communes (`ERROR`) - Conditions typiques: - `Device not paired` (opération nécessitant appairage) - `Invalid or expired session token` - `Failed to ...` (création/lecture/validation) - `Invalid state id` / `Process not found` - Payload générique: `{ type: 'ERROR', error: string, messageId?: string }` ## Bonnes pratiques d’intégration - Toujours préciser et propager `messageId` pour tracer les échanges. - Conserver `origin` côté parent et utiliser la même valeur dans les requêtes suivantes. - Renouveler régulièrement le `accessToken` via `RENEW_TOKEN`. - Séparer données publiques/privées dès la création d’un processus. - Valider les formats (ids hex 32 bytes, structures de rôles) avant envoi.