docs(kogus): align Deployment.md with LeCoffre nested secrets and SUPERADMIN_IDNOTS

This commit is contained in:
4NK 2026-04-15 17:33:59 +02:00 committed by Nicolas Cantu
parent 73bea86a4d
commit 69427fc263

View File

@ -2,19 +2,46 @@
**Auteur** : Équipe 4NK
## Source de vérité multisite (dépôt LeCoffre)
La documentation **canonique** multisite (architecture, secrets imbriqués **`.secrets/<site>/<env>/`**, **`.secrets/kogus/<env>/`**, manifeste, runbooks, politique données LeCoffre ↔ **ia_dev**) est versionnée dans le dépôt applicatif dont `conf.json` expose **`deploy.repository_root`** (clone **LeCoffre** / **kogus** sur Gitea).
- Politique données : **`docs/features/multisite-data-policy-lecoffre-vs-ia-dev.md`** sur la branche suivie (ex. **test**).
- Checklist opérateur : **`docs/features/multisite-operator-master-checklist.md`**.
- Snippet wiki à publier : **`docs/features/wiki-deployment-multisite-snippet.md`**.
- Fichier aligné sur ce miroir : **`docs/Deployment.md`** (racine du clone LeCoffre).
URL type (adapter branche) : `https://git.4nkweb.com/4nk/kogus/src/branch/test/docs/features/multisite-data-policy-lecoffre-vs-ia-dev.md`.
Les sections suivantes reprennent le contenu de **`docs/Deployment.md`** du clone LeCoffre. Les chemins **`.md`** et répertoires **`.secrets/...`** ci-dessous sont relatifs à **la racine Git du dépôt LeCoffre** (`repository_root`), pas à la racine du dépôt **ia_dev**.
En cas de divergence entre ce fichier et le dépôt LeCoffre, **priorité au dépôt LeCoffre**.
---
## Vérification site_texts (seeds, env, boot)
Objectif : aligner les clés site_texts entre seeds, env et boot (test, pprod, prod).
### 1. Seeds ↔ env (SITE_TEXTS_KEYS_INDEX)
Les clés de `.secrets/<env>/seed-site-texts-<env>.ts` (champ `textKey`) doivent être exactement celles listées dans `SITE_TEXTS_KEYS_INDEX` du fichier `.secrets/<env>/env-full-<env>-for-bdd-injection.txt`.
Les clés du seed `seed-site-texts-<env>.ts` (champ `textKey`) doivent être exactement celles listées dans `SITE_TEXTS_KEYS_INDEX` du fichier `env-full-<env>-for-bdd-injection.txt` du **même environnement**.
Chemins :
- **Multi-site (préféré)** : `.secrets/<site_dir>/<env>/…` (ligne notaire : **`.secrets/lecoffreio/test/`** avec **`SITE_CODE=lecoffreio`** côté processus / BDD ; voir **`docs/features/secrets-multisite-kogus-and-sites.md`**).
- **Legacy** (checkout non migré) : `.secrets/<env>/…` (ex. `.secrets/test/`).
**Commandes** :
```bash
grep -oP 'textKey: "\K[^"]+' .secrets/test/seed-site-texts-test.ts | sort -u > /tmp/seed-keys.txt
grep '^SITE_TEXTS_KEYS_INDEX=' .secrets/test/env-full-test-for-bdd-injection.txt | sed 's/SITE_TEXTS_KEYS_INDEX=//' | tr ',' '\n' | sort -u > /tmp/env-keys.txt
SITE_CODE=lecoffreio
ENV=test
# Ligne notaire : répertoire disque lecoffreio/ (SITE_CODE processus = lecoffreio)
SECRETS_DIR=".secrets/lecoffreio/${ENV}" # ou ".secrets/${ENV}" (legacy plat)
grep -oP 'textKey: "\K[^"]+' "${SECRETS_DIR}/seed-site-texts-${ENV}.ts" | sort -u > /tmp/seed-keys.txt
grep '^SITE_TEXTS_KEYS_INDEX=' "${SECRETS_DIR}/env-full-${ENV}-for-bdd-injection.txt" | sed 's/SITE_TEXTS_KEYS_INDEX=//' | tr ',' '\n' | sort -u > /tmp/env-keys.txt
diff /tmp/seed-keys.txt /tmp/env-keys.txt # doit être vide
```
@ -24,13 +51,13 @@ Mêmes clés site_texts sur les trois environnements ; seuls les contenus peuven
### 3. Boot : SITE_TEXTS_BOOT_SCOPES
`SITE_TEXTS_BOOT_SCOPES` (dans `lecoffre-front-main/src/front/Stores/siteTextsBootConfig.ts`) doit couvrir tous les scopes chargés au boot. Valeur type : `["login", "my-account", "components", "folder", "forms", "documentTypes", "office", "thirdParty"]`. Aucun scope des seeds ne doit être absent du boot.
`SITE_TEXTS_BOOT_SCOPES` (dans `front-common/src/front/Stores/siteTextsBootConfig.ts`) doit couvrir tous les scopes chargés au boot. Valeur type : `["login", "my-account", "components", "folder", "forms", "documentTypes", "office", "thirdParty"]`. Aucun scope des seeds ne doit être absent du boot.
### 3.1 Scope des textes « tiers » (`thirdParty.roleLabel.*`)
- **Cible** : pour les clés dont le `textKey` commence par `thirdParty.` (ex. `thirdParty.roleLabel.courtier`), le champ **`scope`** en base et dans `seed-site-texts-<env>.ts` doit être exactement **`thirdParty`** (camelCase), comme dans `defaultSiteTextFallbacks.ts`. Le préfixe API publique utilise ce même identifiant : `GET .../site-texts?scope=thirdParty,...`.
- **À ne pas confondre** : les clés **`forms.thirdParty.*`** (formulaire édition tiers) restent en scope **`forms`**. La variante UI `THIRD_PARTY_UI_VARIANT = "third-party"` (tiret) concerne le parcours / laffichage membre, **pas** le scope `site_texts`.
- **Vérification en lecture seule** (sur la base V2 de lenvironnement) : le script **ne se connecte pas à une base locale** ; il copie le SQL et un runner sur le **serveur de déploiement** (SSH, même mécanisme que `scripts/e2e-verify-db-env.sh`), puis exécute `psql` **sur la cible** en utilisant `.secrets/<env>/.env.<env>.connectDB` **présent sur ce serveur** (`DATABASE_HOST=db``127.0.0.1` côté cible).
- **Vérification en lecture seule** (sur la base V2 de lenvironnement) : le script **ne se connecte pas à une base locale** ; il copie le SQL et un runner sur le **serveur de déploiement** (SSH, même mécanisme que `scripts/e2e-verify-db-env.sh`), puis exécute `psql` **sur la cible** en utilisant le fichier connectDB résolu sur la cible (canonique imbriqué `.secrets/<site_code>/<env>/.env.<env>.connectDB`, orchestrateur **`.secrets/kogus/<env>/.env.<env>.connectDB`**, ou legacy `deploy/.env.<env>.connectDB`, comme `resolve_connect_db_path_on_target` / `import-v1.sh`) **présent sur ce serveur** (`DATABASE_HOST=db``127.0.0.1` côté cible).
```bash
./scripts/verify-site-texts-thirdparty-scope-readonly.sh <test|pprod|prod>
@ -65,17 +92,20 @@ Liste des fichiers contenant les textes affichés à lutilisateur (libellés,
- **COMMON_UI_I18N** : commonUiI18nPart1.ts, commonUiI18nPart2.ts (modales, formulaires, dossiers, documents, rôles, types dactes, souscription, Corbeille, erreurs métier, confrères, admin site texts, collaborateurs, etc.).
- **Upload / validation** : fileUploadUiI18n.ts, fileValidationI18n.ts.
- **Erreurs / login** : Utils/errorMessages/* (getUserFriendlyError, httpStatusMessages, humanizeError), loginErrorCodes.ts.
- **Site texts** : `.secrets/<env>/seed-site-texts-<env>.ts` ; clés dans env-full-*-for-bdd-injection.txt (SITE_TEXTS_KEYS_INDEX).
- **Site texts** : `.secrets/<site_code>/<env>/seed-site-texts-<env>.ts` (ou legacy `.secrets/<env>/…`) ; clés dans `env-full-*-for-bdd-injection.txt` (SITE_TEXTS_KEYS_INDEX).
---
## Déploiement applicatif
- **Multi-site (`SITE_CODE`, secrets imbriqués)** : les scripts applicatifs (`deploy/scripts_v2`, `connect-db-paths.sh`) attendent **`.secrets/<site>/<env>/`** avec **`site ∈ { notary, enso, genealogie }`**. **`SITE_CODE`** (ou **`LECOFFRE_SITE_CODE`** / **`DEPLOY_SITE_CODE`**) doit être **exporté explicitement** avant ces scripts ; lorchestrateur **ia_dev** ne le déduit pas depuis le `conf.json`. Sous **`projects/kogus/conf.json`**, **`deploy.secrets_path`** pointe souvent vers un arbre **plat** **`<secrets_path>/<env>/`** uniquement : **`orchestrator.sh`** et **`deploy/deploy-by-script-to.sh`** peuvent alors créer pour chaque site **notary**, **enso**, **genealogie** un lien **`<secrets_path>/<site>/<env>``../<env>`** si lemplacement imbriqué nexiste pas encore et que **`<secrets_path>/<env>/`** est un répertoire. Un répertoire **réel** (non lien) existant nest pas écrasé ; pour des secrets **distincts** par site, remplacer le lien par un vrai répertoire.
- **Orchestration ia_dev** : depuis la racine du dépôt ia_dev, `./deploy/deploy.sh <project_id> <env> [options]` exporte `IA_PROJECT_ID` puis exécute `orchestrator.sh`. Celui-ci enchaîne les scripts listés dans `deploy.hooks.phases` du `conf.json` du projet (chemins relatifs à `repository_root`), ou exécute `deploy.deploy_script_path` si `phases` est vide. `run-project-hooks.sh` délègue à `orchestrator.sh` (compatibilité). Cadrage : `deploy/DEPLOY_ORCHESTRATION_IA_DEV.md`.
- **Multi-site (runbook)** : ordre **test** → préparation **pprod/prod**, migrations Prisma, smoke `site-config`**`docs/features/multi-site-deploy-runbook.md`** ; snippet wiki **`docs/features/wiki-deployment-multisite-snippet.md`**.
- **Admin local (exports / imports secrets par site, sans déploiement)** : **`docs/features/secrets-devai-kogus-sites-and-imports.md`** — couches dev_ai / kogus / site, API `back-admin`, UI `front-admin`, fichiers matrice et catalogues actes.
- **Orchestration ia_dev** : depuis la racine du dépôt ia_dev, `./deploy/deploy.sh <project_id> <env> [options]` exporte `IA_PROJECT_ID` puis exécute `orchestrator.sh`. Celui-ci enchaîne les scripts listés dans `deploy.hooks.phases` du `conf.json` du projet (chemins relatifs à `repository_root`), ou exécute `deploy.deploy_script_path` si `phases` est vide. `run-project-hooks.sh` délègue à `orchestrator.sh` (compatibilité). Cadrage : `deploy/DEPLOY_ORCHESTRATION_IA_DEV.md` (fichier dans le dépôt **ia_dev**).
- **Scripts** : `deploy/scripts_v2/` ; chemin projet dans ia_dev `projects/kogus/conf.json` (project_path, build_dirs, deploy.deploy_script_path, deploy.secrets_path).
- **Clé SSH déploiement (`DEPLOY_SSH_KEY`)** : définie dans `.secrets/<env>/.env.<env>`. Utiliser un chemin **portable** : par ex. `DEPLOY_SSH_KEY='$HOME/.ssh/id_ed25519_4nk'` (lexpansion de `$HOME`, `${HOME}` et un préfixe `~/` est appliquée par `lecoffre_deploy_resolve_deploy_ssh_key` après `load_dotenv_file_strict`, qui ne fait pas d`eval`). Ne pas figer un autre compte système (`/home/desk/...`). Ordre de repli si la clé indiquée est absente : `$HOME/.ssh/id_ed25519_4nk`, puis `$HOME/.ssh/id_ed25519`. Avant toute connexion SSH, la clé retenue est validée avec `ssh-keygen -y`. Vérification réseau : `bash deploy/scripts_v2/run-verify-ssh.sh <env>` ou les trois dun coup : `bash deploy/scripts_v2/run-verify-ssh-all-envs.sh`.
- **Modifications locales** : en **test**, le script `deploy.sh` met en stash les changements non commités avant pull/require_clean et les remet en place (stash pop) en fin de déploiement réussi. En **pprod** et **prod**, les changements locaux sont mis en stash sans remise en place (pas de développement local à conserver).
- **Clé SSH déploiement (`DEPLOY_SSH_KEY`)** : définie dans `.secrets/<site_code>/<env>/.env.<env>` (layout imbriqué obligatoire pour le multisite ; migration depuis lancien plat : `deploy/scripts_v2/sites/notary/migrate-secrets-legacy-to-nested-notary.sh`). Utiliser un chemin **portable** : par ex. `DEPLOY_SSH_KEY='$HOME/.ssh/id_ed25519_4nk'` (lexpansion de `$HOME`, `${HOME}` et un préfixe `~/` est appliquée par `lecoffre_deploy_resolve_deploy_ssh_key` après `load_dotenv_file_strict`, qui ne fait pas d`eval`). Ne pas figer un autre compte système (`/home/desk/...`). Ordre de repli si la clé indiquée est absente : `$HOME/.ssh/id_ed25519_4nk`, puis `$HOME/.ssh/id_ed25519`. Avant toute connexion SSH, la clé retenue est validée avec `ssh-keygen -y`. Vérification réseau : `bash deploy/scripts_v2/run-verify-ssh.sh <env>` ou les trois dun coup : `bash deploy/scripts_v2/run-verify-ssh-all-envs.sh`.
- **Modifications locales** : **`deploy.sh`** (LeCoffre) ne modifie pas la branche locale **`test`** (pas de **`git pull`** ni **`git stash`** sur **`test`** avec **`--sync-origin`**). Les fichiers déployés depuis lorchestrateur (scripts, **`import-v1`**) proviennent dun **worktree** détaché au ref **`kogus/<branche denv>`** ; le working tree du clone principal peut donc contenir du WIP non poussé sans être écrasé — seul le tip **`kogus/test`** (ou branche alignée pour **pprod**/**prod**) part sur la cible après **`git push`**. Pour **pprod**/**prod**, lindex du clone principal doit rester propre (**`local_git_require_clean_index_strict`**).
- **Versions** : version.package_json_paths (backend, frontend) ; splash_app_name pour la notice.
- **Secrets** : `.secrets/<env>/env-full-<env>-for-bdd-injection.txt` pour linjection en BDD ; NOTARY_AI_AGENT_URL, NOTARY_AI_AGENT_TOKEN pour lagent IA notaire (voir API.md).
- **Dépendances npm (fiabilité avant phases distantes)** : `deploy.sh` exécute `hooks/verify-npm-lockfiles.sh` sur la racine du **worktree** de déploiement (ref **`kogus/<branche>`**), après préparation de ce worktree et après le hook de concurrence. Pour chaque `build_dir` (ressources-common, back-common, front-common) : présence de `package-lock.json`, JSON valide, `npm install --package-lock-only --dry-run` (cohérence `package.json` ↔ lockfile), puis `npm audit --audit-level=high`. Sur la cible, `deploy/scripts_v2/remote/deploy-app.sh` exécute `npm_ci_strict` (suppression de `node_modules` puis `npm ci` sans repli `npm install`) pour les trois mêmes répertoires. Contournements documentés : `DEPLOY_SKIP_NPM_LOCKFILE_VERIFY=1`, `DEPLOY_SKIP_NPM_AUDIT=1`.
- **Secrets / injection BDD** : `.secrets/<site_code>/<env>/env-full-<env>-for-bdd-injection.txt` pour linjection en BDD (répertoire imbriqué ; ancien plat `.secrets/<env>/` uniquement le temps dune migration). Super-admins systématiques après déploiement : clé **`SUPERADMIN_IDNOTS`** (liste `users.idNot`, virgules) — succède à **`SUPERADMIN_EMAILS`** ; voir `deploy/scripts_v2/remote/sql/list-lecoffreio-users-by-office-name-pattern-readonly.sql` et `deploy/scripts_v2/remote/promote-super-admins.sh`. NOTARY_AI_AGENT_URL, NOTARY_AI_AGENT_TOKEN pour lagent IA notaire (voir API.md).
- **Cartographie des checks de déploiement** : référence unique dans la doc projet (ex. projects/kogus/docs ou doc dédiée) ; ne pas dupliquer ici.
- **ShellCheck** : `npm run lint:shell` exécute `scripts/run-shellcheck.sh` sur `deploy/**/*.sh`, `scripts/*.sh` et `back-common/scripts/**/*.sh` (options : `--external-sources`, `--source-path=SCRIPTDIR`, `--severity=warning`). Helpers déploiement : `_lib/deploy-export-ssh-from-infos-json.sh` (chargement `infos.json`), `_lib/ssh-run-app-script.sh` (`lecoffre_ssh_run_remote_deploy_script`, `lecoffre_ssh_run_remote_mkdir_p`, etc.). Détail : `deploy/scripts_v2/hooks/README.md`.