# Commandes de gestion de projet et de build (v0.7.194)

Source : https://docs.berkios.online/reference/commandes-projet-build/ · Section : Référence · Documentation officielle BERKIOS (https://docs.berkios.online)


22 commandes système du Bridge, déclarées dans le registre commun (domaines `projet` et `build`, 4 langues).
Elles suivent les règles des autres commandes système : **aucun shell, aucun processus, aucun script de projet n'est exécuté**,
tout chemin reste dans le workspace autorisé, et chaque commande exige une **permission accordée explicitement** par l'appelant.

Code : `bridge/project-build-commands.mjs` · Tests : `bridge/tests/project-build-commands.test.mjs`.

## Vue d'ensemble

| Commande | Arguments (`?` = facultatif) | Permission | Rôle |
|---|---|---|---|
| `version-actuelle` | `source?` | `project.read` | Lit la version (`project.json`→`appVersion`, `package.json`, `VERSION.txt`) et signale les incohérences |
| `version-incrementer` | `part`, `tag?` | `project.write` | `majeur` / `mineur` / `correctif` / `prerelease` ; met à jour **tous** les fichiers de version |
| `build-configurer` | `profile`, `options?` | `project.write` | Configure et active un profil `dev` / `staging` / `prod` (`.berkios/build.json`) |
| `variable-environnement-lire` | `name`, `file?` | `project.env.read` | Lit une variable de `.env` (sensibles masquées) |
| `variable-environnement-lister` | `file?` | `project.env.read` | Liste les variables (sensibles masquées) |
| `variable-environnement-ajouter` | `name`, `value`, `file?` | `project.env.write` | Ajoute ; **refuse** si elle existe |
| `variable-environnement-modifier` | `name`, `value`, `file?` | `project.env.write` | Modifie ; **refuse** si elle n'existe pas |
| `variable-environnement-editer` | `name`, `value`, `file?` | `project.env.write` | Ajoute **ou** modifie (upsert) |
| `variable-environnement-supprimer` | `name`, `file?` | `project.env.write` | Supprime la variable |
| `feature-flag-verifier` | `name` | `project.read` | `value: true/false` (flag inconnu = `false`, `existe: false`) |
| `feature-flag-activer` | `name`, `description?` | `project.write` | Active (crée le flag si besoin) |
| `feature-flag-desactiver` | `name` | `project.write` | Désactive |
| `feature-flag-lister` | — | `project.read` | Liste les flags |
| `asset-charger` | `path`, `type?` | `project.read` | Charge une image / police / icône en Base64 (5 Mio max) |
| `arbre-dependance` | `options?` | `project.read` | Arbre des dépendances (npm + verrou, ou `pubspec.yaml`) |
| `dependance-verifier` | `name?` | `project.read` | Cohérence manifeste ↔ verrou ↔ `node_modules` |
| `paquet-installer` | `name`, `version?`, `options?` | `package.install` | Déclare le paquet dans `package.json`, puis installe via l'adaptateur de l'hôte |
| `paquet-mettre-a-jour` | `name`, `version?`, `options?` | `package.install` | Met à jour la version déclarée, puis applique via l'adaptateur |
| `signer-application` | `path`, `privateKey`, `options?` | `app.sign` | Signe un fichier ou un dossier → `<chemin>.sig.json` |
| `publier-application` | `path`, `target`, `options?` | `app.publish` | Vérifie la signature puis publie en boutique (**simulation par défaut**) |
| `changelog-generer` | `version?`, `items?`, `options?` | `project.write` | Insère une section dans `CHANGELOG.md` |
| `migration-schema` | `action`, `argument?`, `options?` | `sql.migrate` | `creer`, `statut`, `appliquer`, `annuler` |

Les arguments objets (`options`) peuvent être passés comme objet ou comme **chaîne JSON** (les scripts BERKIOS transmettent du texte).
Les booléens acceptent `true/false`, `oui/non`, `vrai/faux`, `1/0`.

## Variables d'environnement (`.env`)

Ajouter, modifier, éditer, supprimer, lire et lister fonctionnent sur `.env` ou `.env.<profil>` (ex. `.env.production`) **à la racine du projet** uniquement.

- Les commentaires, l'ordre des lignes, le préfixe `export` et les fins de ligne (LF / CRLF) sont conservés.
- Les valeurs avec espaces, `#`, guillemets ou retours à la ligne sont écrites entre guillemets et relues sans perte.
- Les noms contenant `TOKEN`, `SECRET`, `PASSWORD`, `PASSWD`, `KEY`, `CREDENTIAL` ou `PRIVATE` sont **sensibles** : `lire` et `lister` renvoient `********` ; les commandes d'écriture ne renvoient jamais la valeur. L'hôte peut lever le masquage avec `options.revealSensitiveEnv = true`.
- Ces commandes éditent le **fichier** ; elles ne modifient jamais les variables du processus du Bridge. La lecture des variables du processus reste `systeme-variable-lire`.
- Écritures atomiques et sérialisées : des modifications concurrentes ne se perdent pas.

```text
variable-environnement-ajouter  "API_URL" "https://api.exemple.cd"
variable-environnement-editer   "API_URL" "https://api.exemple.cd/v2" ".env.production"
variable-environnement-supprimer "DEBUG"
```

## Version, build, flags

- `version-incrementer "mineur" "beta"` → `1.3.0-beta.1` ; `prerelease` incrémente le compteur (`beta.1` → `beta.2`). Refuse si les fichiers de version ne sont pas alignés (`version_mismatch`).
- `build-configurer "prod" {apiUrl, target, debug, minify, sourceMaps, obfuscate, envFile, outputDir}` : alias acceptés (`production`, `developpement`, `preproduction`, `recette`). Garde-fous : `prod` refuse `debug:true` et une `apiUrl` non https ; les options inconnues sont refusées.
- Flags : fichier `.berkios/feature-flags.json` ; noms en minuscules (`a-z 0-9 . _ -`, 64 max) ; 500 flags max.

## Assets

`asset-charger "assets/logo.png"` → `{ value: <base64>, type, mime, octets, sha256, chemin }`.
Le type est déduit de l'extension (`image`, `police`, `icone`) ou imposé par le 2ᵉ argument. La **signature binaire** est contrôlée (un `.png` qui n'en est pas un est refusé : `asset_corrupt`). Un SVG contenant `<script>`, un gestionnaire `on…=`, `javascript:` ou `<foreignObject>` est refusé (`unsafe_svg`).

## Dépendances et paquets

- `arbre-dependance {depth: 1–6, inclureDev}` résout l'arbre depuis `package-lock.json` (y compris les versions imbriquées de npm). Sans verrou : arbre déclaré uniquement, `statut: verrou-absent`. Sans `package.json` : lit `pubspec.yaml` (Flutter/Dart), sans résolution.
- `dependance-verifier` détecte : `verrou-absent`, `absent-du-verrou`, `verrou-obsolete`, `version-incompatible`, `node_modules-desynchronise`, `non-installee`, `non-verifiable`. `value` vaut `true` s'il n'y a aucun problème bloquant. La vérification de plage couvre `^ ~ >= > <= < =` et les plages `x` ; les plages composées ou les sources git/fichier sont signalées `non-verifiable` plutôt que supposées valides.
- `paquet-installer` / `paquet-mettre-a-jour` : le nom doit être un nom npm valide ; la version doit être `X.Y.Z`, `^X.Y.Z`, `~X.Y.Z` ou `>=X.Y.Z` — **tags, URL, chemins et dépôts git sont refusés** (chaîne d'approvisionnement). Rétrogradation refusée sauf `options.retrograder`. Si l'installation échoue, le manifeste est **restauré**.

**Adaptateur `options.packageManager`** (fourni par l'hôte, optionnel) :

```js
{ resolveLatest(name) → "2.1.0",            // sans version explicite
  install(cwd, { name, spec, dev }),
  update(cwd, { name, spec }) }
```

Sans adaptateur, seul le manifeste est mis à jour et la réponse indique `installation: "non-executee"` : le Bridge ne lance jamais `npm` lui-même.

## Signature et publication

- `signer-application "dist/app.aab" <clé PEM privée>` : clé **ECDSA P-256** ou **RSA ≥ 2048 bits** (générable avec `cle-signature-generer`). L'empreinte SHA-256 d'un fichier, ou d'un dossier (liste triée des fichiers ; liens symboliques refusés ; 5000 fichiers / 512 Mio max), est signée avec le nom, la taille et la version du projet. Résultat : `dist/app.aab.sig.json` (clé publique, empreinte de clé, signature). La clé privée n'est jamais écrite ni renvoyée. Re-signer exige `options.replace`.
- `publier-application "dist/app.aab" "google-play" {track, dryRun, empreinteCle, confirmerProduction}` :
  - cibles : `google-play` (`.aab`/`.apk`), `app-store` (`.ipa`), `microsoft-store` (`.msix`, `.msixbundle`, `.appx`, `.appxbundle`), `web` (dossier ou `.zip`) ; alias `android`, `ios`, `windows`…
  - contrôles : artefact signé **et inchangé**, version connue, correspondance format/cible ; pistes `internal` (défaut), `beta`, `production`.
  - **`dryRun` vaut `true` par défaut** : la commande renvoie le plan et les avertissements sans rien publier.
  - publication réelle (`dryRun:false`) : exige une entrée de `CHANGELOG.md` pour la version, un adaptateur `options.publisher`, et `confirmerProduction:true` pour la piste `production`. Chaque publication réussie est journalisée dans `.berkios/publications.json`.
  - `options.empreinteCle` épingle la clé du signataire. **Sans épinglage, la signature prouve l'intégrité mais pas l'identité** (un avertissement le signale).

**Adaptateur `options.publisher`** : `publish({ cible, piste, fichier, version, notes, signature }) → { id, url? }`. Les identifiants et les API de boutique restent côté hôte.

## Changelog

`changelog-generer "1.4.0" ["feat(api): webhooks", "fix: calcul TVA"]` insère `## v1.4.0 — AAAA-MM-JJ` **en tête** du fichier (le fichier est créé s'il n'existe pas) et refuse de dupliquer une version existante.
Les messages « conventional commits » sont classés : `feat` → Ajouts, `fix` → Corrections, `perf`, `refactor`, `docs`, `security`, `chore/build/ci/test/style` → Maintenance, le reste → Autres ; `!` ou `BREAKING CHANGE` → **Changements incompatibles** (en premier). Les doublons sont supprimés.
Sans `items`, la commande utilise `options.git.log()` si l'hôte le fournit, sinon refuse (`entries_required`). `options.ecrire = false` renvoie le texte sans écrire ; `options.date` impose la date.

## Migrations de schéma

Fichiers `migrations/AAAAMMJJHHMMSS_nom.sql`, avec deux sections : `-- up` et `-- down`.

| Action | Effet |
|---|---|
| `creer "nom"` | Crée le fichier modèle ; refuse un nom déjà utilisé ou un ordre non croissant |
| `statut` | État de chaque migration : `appliquee`, `en-attente`, `modifiee`, `orpheline` (ou `inconnu` sans base) |
| `appliquer [cible?]` | Applique les migrations en attente (jusqu'à `cible` incluse), **une transaction par migration** |
| `annuler [n?]` + `{confirmer:true}` | Annule les `n` dernières (1–10) via leur section `-- down` |

L'historique est la table `_berkios_migrations` (id, nom, **checksum**, date). Si un fichier déjà appliqué a été modifié, ou si la base contient une migration sans fichier, `appliquer` et `annuler` s'arrêtent (`migration_drift`). Une migration sans section `-- down` bloque l'annulation.

L'adaptateur `options.db` doit fournir `exec(sql)` et `prepare(sql).run/all` (contrat de `sql-executer` ; `node:sqlite` et `better-sqlite3` conviennent). Le SQL des fichiers est exécuté tel quel : la permission **`sql.migrate` équivaut au droit d'exécuter du SQL libre** et ne doit être accordée qu'à du code de confiance.

## Codes d'erreur principaux

`version_not_found`, `version_mismatch`, `invalid_version`, `unsafe_profile`, `env_exists`, `env_not_found`, `env_file_not_found`, `invalid_env_name`, `flag_not_found`, `invalid_flag_name`, `asset_corrupt`, `asset_unsupported`, `asset_type_mismatch`, `unsafe_svg`, `manifest_not_found`, `package_exists`, `package_not_found`, `invalid_package_name`, `invalid_package_version`, `version_required`, `downgrade_refused`, `package_manager_failed`, `invalid_key`, `file_exists`, `signature_check_failed`, `artifact_target_mismatch`, `artifact_not_found`, `changelog_missing`, `changelog_exists`, `confirmation_required`, `publisher_unavailable`, `publish_failed`, `entries_required`, `migration_exists`, `migration_order`, `migration_drift`, `migration_failed`, `migration_no_down`, `migration_empty`, `db_unavailable`.

## Limites assumées

- `version-incrementer` gère `project.json`, `package.json` et `VERSION.txt` ; la version de `pubspec.yaml` (`x.y.z+build`) n'est pas modifiée.
- `signer-application` produit une signature **BERKIOS** (intégrité / provenance). Elle **ne remplace pas** la signature de code Authenticode, Apple (notarisation) ou Android (keystore) exigée par les boutiques : ces étapes relèvent de l'outillage de la plateforme, côté hôte.
- Aucune publication réelle ni installation réelle n'a été exercée contre un vrai registre ou une vraie boutique : ces deux chemins sont testés avec des adaptateurs simulés. Les migrations sont testées sur une vraie base SQLite (`node:sqlite`) ; le comportement transactionnel des DDL dépend du moteur (SQLite : oui ; MySQL : non).
- Le contrôle de plages semver est un sous-ensemble ; `arbre-dependance` / `dependance-verifier` ne lisent que npm (et `pubspec.yaml` pour l'arbre).
