Mode CLI adapté à l’IA Server
À partir de Babel Licensing 11.8, la ligne de commande lic peut émettre un flux de sortie structuré et lisible par machine, adapté aux pipelines de CI, aux systèmes de commandes et aux agents IA, à l’image du mode que l’obfuscateur a reçu avec la version 11.7.
La sortie texte par défaut de lic est inchangée et reste entièrement rétrocompatible : les scripts existants ne nécessitent aucune modification.
Le mode adapté à l’IA s’active avec trois options globales :
--format=text|json|ndjsonsélectionne le format du canal de sortie--quiet(alias-q) supprime la bannière du logo et échoue immédiatement sur les invites interactives--strict-exitactive les codes de sortie sémantiques
Lorsque --format=json ou --format=ndjson est sélectionné, stdout transporte le flux structuré et les messages lisibles par une personne sont dirigés vers stderr, de sorte que les deux canaux ne s’entremêlent jamais.
--format est aussi l’option qui sélectionne le format de sortie de la licence (xml, serial, base32, ascii). Les deux ensembles de valeurs sont disjoints, si bien que les deux significations peuvent figurer sur une même ligne de commande : lic MyApp.dll --format base32 --format json.
Options
—format <format>
Sélectionne le format de sortie utilisé sur stdout. Valeurs autorisées :
| Valeur | Description |
|---|---|
text | Valeur par défaut. Sortie console historique, lisible par une personne. |
json | Document JSON unique, mis en tampon et écrit à la fin de l’exécution (ou avec --help / --version). À privilégier lorsque stdout est capturé dans un fichier ou redirigé vers un consommateur JSON. |
ndjson | JSON délimité par des sauts de ligne. Un événement par ligne, écrit dès qu’il est produit. À privilégier pour les consommateurs en flux continu, les collecteurs de journaux et les agents en direct. |
lic MyApp.dll --keyfile keys.pem --sign --expiredate 365 --format json > result.json
lic MyApp.dll --keyfile keys.pem --sign --format ndjson | jq -c 'select(.level=="error")'Avec json ou ndjson, la bannière du logo est supprimée quelle que soit la valeur de --logo, afin que le premier octet sur stdout soit du JSON valide.
—quiet (-q)
Supprime la bannière de copyright et toutes les invites interactives. La seule invite de lic est celle du mot de passe d’un fichier de clé PFX : avec --quiet, l’absence de --keypwd produit une erreur explicite au lieu de bloquer en attente d’une saisie, ce qui rend l’option sûre pour les exécutions sans intervention sur les exécuteurs de CI, dans les conteneurs et depuis des agents.
lic MyApp.dll --quiet --keyfile signing.pfx --keypwd "$KEY_PWD" --sign--quiet est indépendant de --format : il peut être combiné à la sortie text pour conserver des journaux lisibles par une personne, sans la bannière.
—strict-exit
Active les codes de sortie sémantiques pour le processus. Sans cette option, lic conserve le contrat historique, dans lequel 0 signifie la réussite et 1 tout échec.
| Code de sortie | Constante | Signification |
|---|---|---|
0 | success | La commande s’est terminée sans erreur. |
10 | invalidArguments | La ligne de commande n’a pas pu être analysée ou contenait une valeur non valide (par exemple une option inconnue). |
20 | inputNotFound | L’assembly, le fichier de licence ou un autre fichier d’entrée requis est introuvable. |
30 | processingFailure | Le traitement de la licence a échoué : génération, mise à jour ou signature dont la vérification a échoué. |
40 | licensingFailure | La licence Babel Licensing de l’outil lui-même est absente, non valide ou expirée. |
50 | keyOrSigningFailure | Un fichier ou un conteneur de clés n’a pas pu être chargé, ou une opération cryptographique a échoué. |
Les numéros sont les mêmes que dans le tableau --strict-exit de l’obfuscateur, de sorte qu’un même appelant peut piloter babel et lic à partir d’un seul tableau de codes de sortie ; la seule différence est que le code 30 désigne ici le traitement de la licence et, pour l’obfuscateur, l’obfuscation. La classification est aussi exposée sous le nom exitReason dans le résultat JSON, même lorsque --strict-exit n’est pas actif.
lic MyApp.licenses --verify --keyfile keys.pem --strict-exit --quiet
echo "exit=$?"Schéma : lic.cli.v1
Toutes les charges utiles structurées portent "schema": "lic.cli.v1" et un champ kind qui indique la nature du document : event, result, help ou version. Le schéma reprend celui de l’obfuscateur, babel.cli.v1, mais il est versionné séparément, car les deux outils exposent des ensembles d’options différents. Au sein d’une version majeure du schéma, les ajouts sont autorisés ; les changements incompatibles modifieront le nom du schéma.
Enregistrement d’événement
Chaque message émis pendant une exécution est converti en événement :
{
"schema": "lic.cli.v1",
"kind": "event",
"ts": "2026-09-03T06:31:54.1686900Z",
"level": "info",
"message": "License saved to 'MyApp.licenses'"
}| Champ | Type | Remarques |
|---|---|---|
ts | chaîne (ISO 8601, UTC) | Horodatage de la production de l’événement. |
level | debug | info | warning | error | Gravité. |
code | chaîne | Code de diagnostic, présent uniquement lorsque le message en a un. |
message | chaîne | Message lisible par une personne. |
data | objet | Charge utile structurée facultative, présente uniquement lorsqu’elle est jointe. |
Enveloppe de résultat
—format=json
Un seul objet JSON est écrit sur stdout à la fin de l’exécution. Il contient le résumé de l’exécution et tous les événements mis en tampon pendant celle-ci :
{
"schema": "lic.cli.v1",
"kind": "result",
"exitCode": 0,
"exitReason": "success",
"elapsedMs": 133,
"warnings": 0,
"errors": 0,
"events": [
{ "schema": "lic.cli.v1", "kind": "event", "ts": "2026-09-03T06:31:54.1686900Z", "level": "info", "message": "License saved to 'MyApp.licenses'" }
]
}Une exécution qui échoue indique la classe de l’échec dans exitReason et l’erreur parmi les événements. Ici, l’assembly d’entrée n’existait pas :
{
"schema": "lic.cli.v1",
"kind": "result",
"exitCode": 20,
"exitReason": "inputNotFound",
"elapsedMs": 34,
"warnings": 0,
"errors": 1,
"events": [
{ "schema": "lic.cli.v1", "kind": "event", "ts": "2026-09-03T06:30:27.4366510Z", "level": "error", "message": "Error: The specified file '/build/missing.dll' was not found." }
]
}—format=ndjson
Chaque événement est écrit dès qu’il est produit, sur sa propre ligne. Après le dernier événement, une ligne de résultat finale est ajoutée, sans tableau events puisque les événements ont déjà été transmis en continu :
{"schema":"lic.cli.v1","kind":"event","ts":"2026-09-03T06:31:54.3357790Z","level":"info","message":"License saved to 'MyApp.licenses'"}
{"schema":"lic.cli.v1","kind":"result","exitCode":0,"exitReason":"success","elapsedMs":141,"warnings":0,"errors":0}| Champ | Type | Remarques |
|---|---|---|
exitCode | entier | Code de sortie numérique réellement renvoyé par le processus (historique ou strict, selon --strict-exit). |
exitReason | chaîne | Jeton de classification stable. Reflète toujours la classe sémantique, même sans --strict-exit. |
elapsedMs | entier | Durée totale écoulée, en millisecondes. |
warnings | entier | Nombre d’événements de niveau warning. |
errors | entier | Nombre d’événements de niveau error. |
events | tableau | Présent en mode json ; omis en mode ndjson. |
—help lisible par machine
lic --help --format=json émet une description complète de chaque option publique, utile aux outils qui doivent inspecter la surface du CLI : complétion du shell, agents IA, générateurs de documentation.
{
"schema": "lic.cli.v1",
"kind": "help",
"version": "12.0.0.0",
"usage": "lic.exe <assembly|licensefile> [<other assemblies>...] [options]",
"options": [
{
"name": "trial",
"aliases": [],
"description": "Add or update trial license restriction",
"args": "<key=value>",
"argRequired": true,
"argOptional": false,
"negatable": false,
"incremental": false,
"container": "hash",
"type": "string",
"group": "- License Restrictions -",
"details": "Set trial restriction properties entering key-value pairs:\n\nid=<id> Restriction id\nexpire=<date> Set expiration date\ndays=<n> Set number of trial days\n..."
}
]
}| Champ | Signification |
|---|---|
name, aliases | Le nom de l’option et ses autres graphies, y compris les formes négatives et les alias d’une seule lettre. |
args | L’espace réservé de l’argument tel qu’il apparaît dans la syntaxe d’utilisation, ou vide pour une option sans argument. |
argRequired, argOptional | Indique si l’option prend un argument obligatoire ou facultatif. |
negatable | Indique si l’option accepte le préfixe no. |
container | scalar pour une valeur unique, array pour une option répétable, hash pour des paires key=value. |
type | string ou integer. |
group | La section de la sortie d’aide à laquelle appartient l’option. |
details | La description étendue, le même texte que celui qu’affiche lic --help <option>. |
Une forme ciblée est également prise en charge : lic --help trial --format=json émet la même enveloppe, qui ne contient que l’option trial. Les options masquées et internes ne sont jamais renvoyées.
—version lisible par machine
lic --version --format=json émet les informations sur le produit, la version, le runtime et la plateforme :
{
"schema": "lic.cli.v1",
"kind": "version",
"product": "Babel Licensing",
"version": "12.0.0.0",
"fileVersion": "12.0.0.1",
"runtime": ".NET 10.0.0",
"platform": "osx-arm64"
}Le champ platform utilise l’identificateur de runtime .NET (RID) sur .NET 5 et les versions ultérieures, et une chaîne synthétique <os>-<arch> sur les cibles plus anciennes.
Piloter lic depuis un agent
Un agent qui n’a jamais vu lic peut l’utiliser à partir de la seule aide JSON : lire le schéma des options, construire la ligne de commande à partir des indications args et container, exécuter avec --format json --quiet --strict-exit et décider de la suite selon exitReason. Une boucle type pour émettre une licence se présente ainsi :
lic --help --format json > lic-options.json
lic MyApp.dll --keyfile keys.pem --sign --licensee name="Contoso" --expiredate 365 --output MyApp.licenses --format json --quiet --strict-exit > result.json
jq -r '.exitReason' result.jsonLe même contrat, les mêmes codes de sortie et les mêmes noms d’options s’appliquent à la ligne de commande de l’obfuscateur, documentée dans Mode adapté à l’IA du manuel de l’obfuscateur, de sorte qu’une seule intégration couvre les deux outils.
Rétrocompatibilité
- La valeur par défaut de
--formatesttext; la sortie textuelle, les codes de sortie et le comportement historiques sont inchangés lorsqu’aucune nouvelle option n’est indiquée. - Sans
--strict-exit, le processus continue de renvoyer0en cas de réussite et1en cas d’échec, de sorte que les contrôles existants qui testent$?continuent de fonctionner. --quietest indépendant et peut être activé sans activer la sortie structurée.