API v1.1.0 : archives, propriétés de relations, propriétaires d’actifs et scénarios
Une intégration qui synchronise une CMDB, un inventaire cloud ou un portefeuille de projets a besoin des mêmes capacités que l’application : archiver et restaurer, qualifier les relations, nommer les propriétaires des actifs et tester des changements avant de les appliquer. L’API v1.1.0 apporte ces capacités sur /api/v1/, sans changer le préfixe d’URL que vos intégrations utilisent déjà, et permet de créer ou mettre à jour un enregistrement en un seul appel.
Archiver, lister et restaurer
DELETE /assets/{id} a toujours archivé un actif plutôt que de le supprimer. Les lectures montrent désormais cette archive. Chaque réponse d’actif porte archived_at, nul tant que l’actif est actif. Passez archived=true pour lister les actifs archivés seuls, ou archived=any pour lire les deux, sur les endpoints de liste et de recherche. archived_at sert au filtrage et au tri sur l’endpoint de recherche : une synchronisation récupère les actifs archivés depuis son exécution précédente.
Les relations suivent la même logique avec un indicateur archived et un nouveau updated_at. GET /relationships?archived=true liste les relations archivées seules, dont les deux actifs restent actifs ; archived=any renvoie toutes les relations quel que soit leur état, y compris celles archivées avec un de leurs actifs. L’archivage met à jour updated_at, que l’endpoint de recherche filtre et trie désormais.
Deux nouveaux endpoints restaurent les enregistrements archivés. POST /assets/{id}/restore réactive un actif et les relations qu’il peut, et renvoie leurs identifiants. POST /relationships/{id}/restore réactive une relation et la renvoie comme le ferait GET /relationships/{id}. Les deux nécessitent une clé Éditeur ou supérieure et fonctionnent aussi dans un scénario. Utilisez-les quand une ressource archivée par une synchronisation précédente réapparaît, au lieu de créer un doublon.
Cinq endpoints en masse traitent beaucoup d’enregistrements d’un coup : POST /bulk/assets/archive, /restore et /attest pour 500 actifs au plus, POST /bulk/relationships/archive et /restore pour 200 relations au plus. La réponse liste les identifiants écrits dans applied, et chaque identifiant laissé intact dans skipped avec une raison stable : not_found, forbidden, already_archived, already_active ou not_owner. Les enregistrements acceptés sont écrits en une transaction. Les autres validations et limites de l’offre restent applicables. Une restauration peut échouer sur un conflit d’unicité ou sur la limite d’actifs.
Propriétés de relations et relations parallèles
Les types de relations peuvent désormais porter leurs propres propriétés, et l’API les lit et les écrit. Les réponses de relations incluent un objet properties limité aux valeurs que vous pouvez voir. PATCH /relationships/{id} modifie les clés choisies et laisse les autres inchangées, et POST /relationships accepte properties à la création. Les endpoints du métamodèle listent les properties de chaque type de relation, sous la même forme que celles d’un type d’actif.
Quand un type a ses propriétés activées, plusieurs relations du même type peuvent relier les deux mêmes actifs. Passez allow_duplicate: true pour créer une nouvelle instance à côté des existantes, sur POST /relationships ou dans un élément de POST /bulk/relationships. La nouvelle instance doit différer des autres par au moins une valeur de propriété, sinon la requête échoue avec 409 identical_relationship_already_exists. Chaque instance a son propre identifiant : conservez-le pour modifier cette relation ensuite. Les réponses d’actifs avec include=relationships listent une entrée par instance, et supprimer une relation n’archive que cette instance.
Les types de relations acceptent aussi le type de propriété clé unique. Sa valeur est unique parmi les relations actives du type, et l’API adresse une relation par la clé composite {relationship_type_key}:{unique_property_key}:{value} sur GET, PATCH, DELETE et POST .../restore de /relationships/{id}, ainsi que dans relationship_id de PATCH /bulk/relationships. Une synchronisation qui stocke sa propre référence sur chaque relation n’a plus besoin de conserver les identifiants Boldo. Un identifiant qui n’est ni un UUID ni une clé composite échoue avec 400 invalid_identifier_format sur ces endpoints, comme c’était déjà le cas pour les actifs.
Le nouveau PATCH /bulk/relationships met à jour jusqu’à 10 000 relations en une requête. Comme les créations et mises à jour en masse, il est tout-ou-rien : chaque élément est vérifié d’abord, puis tous les changements sont écrits ensemble. La réponse liste chaque relation de la requête dans l’ordre, avec un indicateur changed qui précise si la modification a changé au moins une propriété.
Créer ou mettre à jour en un appel
Les quatre endpoints de création acceptent on_conflict. Quand les données envoyées correspondent à un enregistrement existant, update y fusionne les champs envoyés et le restaure d’abord s’il était archivé, ignore laisse le contenu de l’enregistrement inchangé, et error, la valeur par défaut, garde le 409 actuel. Un actif est reconnu par la valeur de clé unique dans ses properties ; une relation par une valeur de clé unique fournie, puis par le triplet type, source, cible si aucune clé ne correspond.
Chaque élément de la réponse porte désormais action : created, updated, restored ou unchanged, et le statut est 201 seulement quand tout a été créé. POST /bulk/assets et POST /bulk/relationships restent atomiques. Pour les actifs, update et ignore exigent une valeur de clé unique. Pour les relations, on_conflict: update ou ignore ne se combine pas avec allow_duplicate: true. Les endpoints d’actifs acceptent aussi attest: true, avec ou sans on_conflict : une synchronisation crée, met à jour et confirme ses enregistrements en un appel, puis repère ce qui a disparu de sa source avec un filtre last_attested_at. Le suivi qualité doit être actif et le titulaire actuel de la clé doit être propriétaire de chaque actif attesté. L’attestation n’est pas disponible dans un scénario.
Propriétaires, attestation et complétude
Les actifs portent désormais owned_by_ids, last_attested_at, last_attested_by_id et completion_score. Définissez les propriétaires à la création, à la modification et dans les requêtes en masse avec owned_by_ids ; les utilisateurs doivent être membres de l’organisation. Les propriétaires répondent de l’enregistrement, ils ne reçoivent aucun droit supplémentaire.
POST /assets/{id}/attest confirme qu’un actif est toujours exact sans toucher à son contenu ni à updated_at. Cet endpoint s’adresse aux systèmes de synchronisation qui vérifient un enregistrement contre sa source de vérité : l’attestation est attribuée au titulaire actuel de la clé, qui doit être l’un des propriétaires de l’actif. La qualité du référentiel doit être activée sur l’organisation.
Les réponses d’actifs indiquent aussi stale_marked_at, stale_marked_by_id et stale_mark_reason lorsqu’une nouvelle attestation a été demandée. Même un actif attesté récemment peut nécessiter une nouvelle vérification. La prochaine attestation efface cette demande.
Filtrez et triez sur ces nouveaux champs système. filter[owned_by_ids]=<user_id> renvoie les actifs dont un utilisateur est propriétaire. Les endpoints de recherche acceptent owned_by_ids, last_attested_at, last_attested_by_id, completion_score et access_domain_keys comme conditions, et last_attested_at et completion_score comme champs de tri.
Scénarios par l’API
GET /scenarios liste les scénarios visibles de l’utilisateur de la clé, paginés comme les autres listes, avec leur statut, leur état de préparation, leur scénario parent et leur nombre de changements. Ajoutez ?scenario={scenario_id} à une requête pour l’exécuter dans ce scénario. Les lectures sur les actifs, les relations et le métamodèle, y compris POST /search/* et POST /analytics/*, renvoient les données du scénario. Les écritures d’actifs et de relations sont enregistrées dans les changements du scénario, exactement comme les modifications faites dans l’application. Les endpoints d’administration refusent le paramètre avec 403 scenario_context_forbidden.
Le scénario doit être actif, prêt et visible de l’utilisateur de la clé, et les scénarios doivent être inclus dans le plan et activés pour l’organisation. Sans le paramètre, rien ne change : les requêtes continuent de lire et d’écrire les données réelles.
L’analyse d’impact par l’API
POST /analytics/assets/impact exécute le moteur des analyses d’impact de l’application sans rien sauvegarder : sources, relations à suivre avec leur direction, profondeur maximale, conditions d’arrêt et filtre d’affichage. Chaque actif atteint est renvoyé avec sa distance, les sources dont il provient, les types de relations qui l’ont atteint et un score de criticité structurel, le nombre d’autres actifs impactés perdus avec lui. Le résultat est paginé, fonctionne dans un scénario et renvoie les chemins détaillés sur demande. Un outil de gestion des changements peut désormais demander à Boldo ce qui dépend d’un serveur avant d’approuver un changement.
Pour un passage obligé, comme « les applications, puis leurs risques, puis les équipes responsables, puis tout ce que ces équipes impactent », envoyez plusieurs étapes (stages) : une analyse simple n’en a qu’une. Chaque étape suit ses propres relations depuis les actifs atteints par l’étape précédente, avec un handoff_filter optionnel sur ce qui passe à l’étape suivante. Chaque actif impacté et chaque segment du chemin indiquent leur étape, et le résumé indique pourquoi chaque étape s’est arrêtée.
Texte riche en Markdown
Les propriétés de type texte riche s’échangent désormais en Markdown, en lecture comme en écriture. Titres, emphase, liens, listes, citations et blocs de code font l’aller-retour ; le soulignement utilise la forme <u>texte</u>. Passez rich_text_format=plain, en paramètre de requête ou dans un corps de recherche, pour recevoir du texte brut. Les limites de longueur comptent le texte sans la mise en forme, et les filtres contains correspondent à ce qu’un lecteur voit.
Propriétés calculées et spécification typée
Les propriétés calculées sont en lecture seule par l’API. Les endpoints du métamodèle les signalent avec computed: true et la spécification typée les marque readOnly. Les propriétés masquées n’apparaissent plus dans la spécification typée. La spécification typée gagne aussi archived_at et le paramètre de scénario, pour que les clients générés puissent utiliser ces champs et paramètres. Elle type désormais les relations comme les actifs : chaque type de relation a ses propres schémas, avec ses propriétés et les types d’actifs de sa source et de sa cible, en lecture et à la création.
Régénérer une clé API
POST /api-keys/{id}/rotate remplace le secret d’une clé et renvoie le nouveau. La clé garde son identifiant, son nom, son type, ses rôles et son titulaire ; l’ancien secret cesse de fonctionner immédiatement, sans délai de grâce. Toute clé peut se régénérer elle-même, y compris une clé Lecteur : une intégration renouvelle ainsi son propre secret à intervalle régulier, et la réponse est la seule copie de la nouvelle valeur. Régénérer une autre clé demande une clé Éditeur ou Administrateur, et seulement pour une clé qu’elle pourrait créer. Une modification concurrente de la clé répond 409 api_key_changed.
Notes de compatibilité
La version de la spécification passe à 1.1.0. Trois changements cassent les intégrations qui lisent les champs concernés : vérifiez les champs de rôles, les relations des types d’actifs et la sortie du texte riche, puis les corrections ci-dessous. Les réponses de création gagnent un champ action.
rolesest retiré des utilisateurs et des clés API. Lisezrole_keys, un tableau de clés de rôles.relationshipsest retiré des types d’actifs, dansGET /metamodelet les endpoints/metamodel/asset-types: chaque type de relation y était répété sous sa source et sous sa cible. Lisezrelationship_typesdansGET /metamodel, où chaque type nomme une seule fois sa source et sa cible, ouGET /metamodel/relationship-types?filter[asset_type_key]={key}pour les types de relations d’un type d’actif.- Les valeurs de texte riche étaient renvoyées au format JSON de l’éditeur. Elles sont désormais en Markdown par défaut. Les intégrations qui lisaient ce JSON doivent lire du Markdown ou demander
rich_text_format=plain. properties.{key}dans une condition de recherche désigne toujours une propriété personnalisée, même quand la clé porte le nom d’un champ système commenameoucreated_at. Utilisez le nom de champ seul pour les champs système.- Supprimer une relation n’archive que cette relation. Les relations parallèles du même type entre les mêmes actifs ne sont pas touchées.
POST /analytics/assets/aggregaterenvoie des chiffres exacts pour les moyennes et les comptes de valeurs distinctes.meta.totalest désormais la mesure sur tous les actifs retenus : c’était la somme des groupes, qui additionnait les moyennes et comptait plusieurs fois un actif présent dans plusieurs groupes. Avecbreakdown_by, la valeur d’un groupe est calculée sur tout le groupe au lieu d’additionner sa ventilation.dataet chaquebreakdownsont triés par valeur décroissante.- Deux codes d’erreur nomment désormais leur objet, comme les autres. Un nom déjà porté par un actif du type répond
409 asset_name_already_existsau lieu dename_already_exists, et un type d’actif inconnu répond404 asset_type_not_foundau lieu demetamodel_not_found. - Une clé n’accorde désormais que son propre type et ses propres rôles, quel que soit son type, quand elle crée, modifie ou régénère une clé. Une clé Administrateur qui créait des clés avec des rôles qu’elle ne possède pas reçoit
403 insufficient_privileges_roles: donnez-lui les rôles qu’elle distribue. Renvoyer le type ou les rôles actuels d’une clé reste accepté, et une clé Administrateur peut toujours retirer des rôles qu’elle ne possède pas. - Aucun rôle compte comme le rôle Sans rôle : une clé qui a des rôles ne peut plus vider les
role_keysd’une clé, et surPOST /api-keysdesrole_keysvides ou absents donnent à la nouvelle clé les rôles de la clé appelante au lieu d’aucun.
Les réponses portent désormais exactement les champs que documente la spécification : quelques champs internes non documentés, comme sourceAssetId sur POST /relationships, ne sont plus renvoyés. Une réponse 429 donne l’attente dans retryAfterSeconds et dans l’en-tête Retry-After.
Les clés composites sont aussi plus strictes : quand plusieurs actifs partagent une valeur de clé unique, la requête échoue avec 409 ambiguous_asset_identifier au lieu d’en choisir un. Les réponses 403 documentent leurs nouveaux codes, dont scenario_context_forbidden, scenarios_disabled et repository_quality_disabled.
Consultez la lecture et la synchronisation, puis les écritures par l’API pour adapter votre intégration. La référence API détaille chaque capacité, et la spécification OpenAPI sur /api/v1/openapi/base.json décrit chaque endpoint.