# deployment.read — Lire l'état d'un déploiement, sa cause de fin et la durée de chacune de ses étapes.

> Engendrée depuis le registre. Ne pas modifier à la main.

C'est ce qu'on interroge après un échec. Un agent qui déclenche un déploiement n'avait aucun moyen d'en apprendre l'issue : la création rend un identifiant, et rien ne le relisait.

| Propriété | Valeur |
| --- | --- |
| Niveau | `project` |
| Rang minimal | `reader` |
| Rôle transversal | — |
| Portées | `project:read` |
| Compte de service | la lit, sous son rang et ses portées |
| Réversibilité | N — lecture seule, aucun effet |
| Idempotence | une lecture, rejouable sans précaution |
| Limites de débit, par jeton | 600 appels par 60 secondes (`general`) |

## API

`GET /v1/projects/{projectId}/deployments/{deploymentId}` — succès en `200`.

| Paramètre | Où | Type | Requis | Description |
| --- | --- | --- | --- | --- |
| `projectId` | chemin | texte, motif `^prj_[0-9A-HJKMNP-TV-Z]{26}$` | oui | Identifiant de projet |
| `deploymentId` | chemin | texte, motif `^dep_[0-9A-HJKMNP-TV-Z]{26}$` | oui | Identifiant de déploiement |
| `diagnose` | requête | booléen | non | Rendre aussi le diagnostic déterministe : trois hypothèses classées, avec indice de confiance et action suivante, sur le dernier épisode d'anomalie ou la dernière minute. |
| `episode` | requête | texte, motif `^[0-9]{1,18}$` | non | Avec diagnose : relire cet épisode (son anomaly.id) plutôt que le plus récent. |

La réponse :

| Champ | Type | Description |
| --- | --- | --- |
| `id` | texte |  |
| `projectId` | texte, motif `^prj_[0-9A-HJKMNP-TV-Z]{26}$` | Identifiant de projet |
| `environmentId` | texte, motif `^env_[0-9A-HJKMNP-TV-Z]{26}$` | Identifiant de environnement |
| `state` | l'un de `queued`, `building`, `built`, `provisioning`, `healthy`, `superseded`, `failed`, `cancelled`, `skipped` |  |
| `commitSha` | texte, ou nul | Le commit déployé. Vaut null quand la demande a été faite par référence (« HEAD », un nom de branche) et que la récupération ne l'a pas encore résolu : voir resolvedCommitSha. |
| `url` | texte, format uri, ou nul |  |
| `startedAt` | texte, format date-time |  |
| `finishedAt` | texte, format date-time, ou nul |  |
| `createdBy` | objet (`accountId`, `serviceTokenId`, `agentSession`, `channel`), ou nul |  |
| `support` | objet (`niveau`, `phrase`) |  |
| `failureReason` | texte, ou nul |  |
| `failureReport` | objet (`untrusted`, `source`, `content`), ou nul |  |
| `failureCode` | texte, ou nul |  |
| `failureCatalog` | objet (`cause`, `action`, `quiCorrige`, `lieu`), ou nul |  |
| `resolvedCommitSha` | texte, ou nul | Le commit RÉELLEMENT construit, lu par « git rev-parse » à la récupération. Distinct de commitSha, qui porte ce que la demande désignait — une intention, pas un résultat. |
| `buildPlan` | objet (`framework`, `etage`, `sha256`) ou objet ou objet (`framework`, `etage`), ou nul |  |
| `imageConstat` | objet, ou nul |  |
| `cancelReason` | texte, ou nul |  |
| `skipReason` | texte, ou nul |  |
| `steps` | liste — chaque élément : objet (`state`, `at`, `durationMs`) |  |
| `environnement` | objet (`genre`, `nom`) |  |
| `ref` | objet (`untrusted`, `source`, `content`), ou nul | La référence déployée : la branche d'une poussée, ou celle demandée à la création (la branche de l'environnement par défaut). Nulle pour un déploiement qui n'en a pas inscrit. |
| `commitMessage` | objet (`untrusted`, `source`, `content`), ou nul | Le titre du commit déployé (sa première ligne), lu à la récupération du code et borné à 300 caractères. Écrit dans le dépôt, donc non fiable. Nul tant que le code n'est pas récupéré, et pour les déploiements antérieurs à la migration 0260. |
| `releaseId` | texte, motif `^rel_[0-9A-HJKMNP-TV-Z]{26}$`, ou nul | La release que ce déploiement a construite. Nulle tant qu'il n'en a pas, ou s'il a échoué ou été annulé avant. |
| `enAttente` | booléen | Construit et non servi : demandé (stage) ou retenu par un contrôle obligatoire. |
| `promotedFrom` | texte, motif `^dep_[0-9A-HJKMNP-TV-Z]{26}$`, ou nul | Déploiement dont la release est reprise sans reconstruction ; nul sinon. |
| `imageDigest` | texte, motif `^sha256:[0-9a-f]{64}$`, ou nul | Empreinte de l'image ; celle d'une promotion égale la construction d'origine. |
| `checks` | liste de 20 éléments au plus — chaque élément : objet (`id`, `required`, `state`) | Contrôles exigés par la release (.bastide/controles.yaml). |
| `diagnosis` | objet (`source`, `anomaly`, `window`, `rulesVersion`, `measures`, `dominantRoute`, `recentLog`, `hypotheses`) | Le diagnostic, présent sous diagnose: true. Aucun appel de modèle (EX-OBS-370). |

En-têtes de la réponse : `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, `RateLimit-Policy`.

Autres réponses : `400`, `401`, `403`, `404`, `409`, `429`, `500`, `503` — communes à toute opération.

## Ligne de commande

`bastide deployment read --project-id <valeur> --deployment-id <valeur>`

| Option | Type | Requise | Défaut | Description |
| --- | --- | --- | --- | --- |
| `--project-id` | texte | oui | — | Identifiant de projet |
| `--deployment-id` | texte | oui | — | Identifiant de déploiement |
| `--diagnose` | booléen | non | — | Rendre aussi le diagnostic déterministe : trois hypothèses classées, avec indice de confiance et action suivante, sur le dernier épisode d'anomalie ou la dernière minute. |
| `--episode` | texte | non | — | Avec diagnose : relire cet épisode (son anomaly.id) plutôt que le plus récent. |

La commande s'exécute sans confirmation.

## MCP

Outil `deployment_read`.

| Propriété | Valeur |
| --- | --- |
| Lecture seule | oui |
| Destructif | non |
| Idempotent | non |
| Monde ouvert | non |
| Confirmation en deux temps | non |
| Budget de jetons du résultat | 1200 |

## Erreurs

Aucun code propre à cette opération.

S'y ajoutent les refus communs à toute opération — entrée invalide, authentification, autorisation, cible introuvable, conflit, limite de débit, indisponibilité — que le catalogue des erreurs décrit.

## Exemples

Lire l'état d'un déploiement et la durée de chacune de ses étapes :

```json
{
  "projectId": "prj_01JQ8ZK4M7NP2RSTVWXYZ34567",
  "deploymentId": "dep_01JQ8ZK4M7NP2RSTVWXYZ34567"
}
```
