280 lines
17 KiB
Markdown
280 lines
17 KiB
Markdown
<!-- file: crates/ksp-app-config-desk/USAGE.md -->
|
||
<!-- version: 20 -->
|
||
|
||
# Utilisation de `ksp-app-config-desk`
|
||
|
||
## État actuel
|
||
|
||
Le gabarit Rust/Tauri et le frontend Vite/TypeScript/SCSS sont présents. Le backend initialise Config, le runtime Logging et `AppState`. Les panneaux Documents, Profils et Environnement/`.env` sont fonctionnels, y compris les mutations `.env` create/update/remove et les reveals Secrets privilégiés. Logging expose maintenant un brouillon typé éditable, une persistence atomique, un hot reload sans redémarrage, un profil runtime sélectionnable indépendamment du `default_profile`, une identité de lancement observable pour isoler les fichiers persistants et un panneau de test du routing backend/frontend.
|
||
|
||
La fenêtre `splash` est visible au démarrage. Après readiness du frontend et temporisation résolue par Config, l'application effectue le fade-out, affiche/focalise `main` puis détruit `splash`. La fenêtre principale expose immédiatement la navigation monofenêtre de référence.
|
||
|
||
## Première installation des dépendances frontend
|
||
|
||
Depuis :
|
||
|
||
```text
|
||
crates/ksp-app-config-desk
|
||
```
|
||
|
||
installer les dépendances déclarées avec la commande de gestion prévue par le projet :
|
||
|
||
```bash
|
||
npm i -D
|
||
cd ../../
|
||
```
|
||
|
||
`npm i -D` sans nom de package installe les dépendances déclarées du package ; la classification `dependencies` / `devDependencies` reste celle de `package.json`. Les lockfiles frontend restent ignorés et ne sont pas versionnés. Après cette installation, les commandes Cargo/Tauri sont exécutées depuis la racine du workspace.
|
||
|
||
## Développement normal
|
||
|
||
Le frontend n'est pas lancé directement avec npm. KSP est un workspace Rust multi-app : depuis la racine du workspace, la configuration Tauri de l'application doit être sélectionnée explicitement :
|
||
|
||
```bash
|
||
cargo tauri dev -c crates/ksp-app-config-desk/tauri.conf.json
|
||
```
|
||
|
||
Tauri exécute alors le hook :
|
||
|
||
```text
|
||
npm run dev
|
||
```
|
||
|
||
Vite écoute strictement sur :
|
||
|
||
```text
|
||
HTTP : 1430
|
||
WS : 1431
|
||
```
|
||
|
||
Si le port HTTP est déjà occupé, le démarrage doit échouer au lieu de sélectionner silencieusement un autre port.
|
||
|
||
## Build frontend
|
||
|
||
Le build de l'application passe également par Tauri. Depuis la racine du workspace :
|
||
|
||
```bash
|
||
cargo tauri build -c crates/ksp-app-config-desk/tauri.conf.json
|
||
```
|
||
|
||
`beforeBuildCommand` déclenche :
|
||
|
||
```text
|
||
npm run build
|
||
```
|
||
|
||
Vite construit les pages `main.html` et `splash.html` vers :
|
||
|
||
```text
|
||
../../builds/khadhroony-solana-project/ksp-app-config-desk/dist
|
||
```
|
||
|
||
Cette destination est résolue depuis la racine de la crate dans `vite.config.ts` et correspond au `frontendDist` de `tauri.conf.json`.
|
||
|
||
## Tracing desktop
|
||
|
||
`tauri-plugin-tracing` est enregistré côté Rust et la capability contient `tracing:default`. Le package frontend associé reste disponible comme adaptateur Tauri, sans installer de subscriber concurrent.
|
||
|
||
Les logs techniques du frontend passent maintenant par `frontend/ts/frontend_log.ts` puis la commande Tauri `emit_frontend_log`. Les identifiants de target autorisés sont :
|
||
|
||
```text
|
||
frontend
|
||
main
|
||
splash
|
||
```
|
||
|
||
Ils sont convertis côté Rust vers des targets KSP statiques `ksp-app-config-desk.frontend*` et émis uniquement via `ksp-logging-lib`. Un niveau différent de `trace`, `debug`, `info`, `warn` ou `error`, ou un `targetId` non whitelisté, est rejeté avec un `CommandErrorDto` sûr.
|
||
|
||
`main.ts` et `splash.ts` installent aussi le bridge `console.*`; l'échec éventuel d'un `invoke` est écrit uniquement sur la console WebView originale afin d'éviter une boucle de logging. Ce bridge conserve donc les messages JavaScript dans la console WebKit et les transmet vers Rust, mais il ne reflète pas encore les événements Rust généraux dans cette console. `attachConsole()` du package officiel nécessite que le subscriber Rust publie vers une `WebviewLayer`; cette couche devra être raccordée plus tard à l'ownership de `ksp-logging-lib` plutôt que d'installer un subscriber Tauri parallèle.
|
||
|
||
## Bindings TS-RS
|
||
|
||
Le layout cible est :
|
||
|
||
```text
|
||
frontend/ts/bindings/ksp_app_config_desk/...
|
||
```
|
||
|
||
Les bindings sont générés au premier DTO Tauri réel ; aucune structure factice n'est ajoutée uniquement pour créer le répertoire.
|
||
|
||
|
||
## Bootstrap backend
|
||
|
||
Les arguments `--cfgpath`, `--schemapath` et `--filemap=...` sont transmis tels quels à `ksp-config-lib`. En build debug, le launcher replace le current working directory Rust à la racine du workspace avant ce bootstrap afin que les defaults relatifs `config/`, `config/schemas/` et `.env` désignent les ressources racine même lorsque Tauri lance `cargo run` depuis la crate de l'application. Le launcher ne lit pas ces ressources lui-même. Le profil Logging initial est le `default_profile` de `std.logging.json`.
|
||
|
||
Si cette configuration ne peut pas être utilisée, l'application doit rester démarrable pour permettre sa réparation : elle utilise alors un fallback Logging console/stderr en mémoire. Le fallback n'écrit aucun fichier de configuration et n'écrase aucune valeur utilisateur.
|
||
|
||
La commande Tauri `get_app_snapshot` expose un état sûr du bootstrap. Ses types TypeScript sont générés par `cargo test -p ksp-app-config-desk` sous `frontend/ts/bindings/`.
|
||
|
||
## Lifecycle et timings du splash
|
||
|
||
Les variables communes sont :
|
||
|
||
```text
|
||
KSP_DESK_SPLASH_MINIMUM_MS=1200
|
||
KSP_DESK_SPLASH_FADE_MS=300
|
||
```
|
||
|
||
La priorité est celle de Config : process > `.env` > fallback. Les valeurs sont lues uniquement via `ksp-config-lib`. Une valeur non numérique ou hors borne déclenche un fallback runtime en mémoire plutôt qu'un refus de démarrer Config Desk.
|
||
|
||
Le frontend `splash.ts` installe son listener puis appelle `splash_frontend_ready`. Le backend vérifie que l'appel provient réellement de la WebView `splash`; une readiness dupliquée (par exemple après reload Vite) est ignorée. La durée minimale commence à cette readiness : Rust émet le fade-in, attend `minimum`, émet le fade-out, attend `fade`, puis active `main`. Ainsi `KSP_DESK_SPLASH_MINIMUM_MS=12000` et `KSP_DESK_SPLASH_FADE_MS=3000` donnent environ `15000 ms` de lifecycle backend. Des logs `debug` indiquent source des deux valeurs, attentes configurées/réelles et durée totale afin de vérifier ce contrat.
|
||
|
||
## Navigation principale
|
||
|
||
La barre principale contient :
|
||
|
||
```text
|
||
Vue d'ensemble
|
||
Documents
|
||
Profils
|
||
Environnement / .env
|
||
Logging
|
||
```
|
||
|
||
Les cinq vues sont fonctionnelles. Logging charge le contrat typé `std.logging.json`, permet de modifier son brouillon, de le persister via Config puis de l'appliquer immédiatement au runtime KSP sans redémarrage. Le header affiche `Config Desk — <vue active>` : le logo fournit déjà l'identité KSP. Les commandes principales peu nombreuses utilisent des pills/tabs alignées à droite ; une application plus chargée devra préférer un dropdown. Chaque clic de tab est tracé en `trace`, l'activation utilisateur significative reste tracée en `debug`, et chaque remplacement/rendu de section en `trace`. Les appels Tauri partagés utilisent `frontend/ts/invoke.ts`, qui journalise le début et la fin d'une commande sans journaliser ses arguments.
|
||
|
||
## Asset font du splash
|
||
|
||
La police bot3 de référence est `DOS_Amazigh.ttf`. Vérifier l'asset local contre l'empreinte documentée dans `frontend/fonts/README.md` ; `frontend/sass/splash.scss` l'applique au titre du splash.
|
||
|
||
## Panneau Documents
|
||
|
||
La vue **Documents** liste les documents de kind `Config` depuis le registre `ksp-config-lib`; les schemas ne sont pas codés en dur dans le frontend. DataTables fournit tri, recherche, pagination et sélection simple.
|
||
|
||
Pour chaque document, le backend expose :
|
||
|
||
- `file_id` ;
|
||
- filename mappé ;
|
||
- schema associé ;
|
||
- path résolu par Config ;
|
||
- état valide/invalide ;
|
||
- étape de diagnostic `read`, `json`, `schema`, `semantic`, `effective` ou `other`.
|
||
|
||
La sélection charge le source brut via `ConfigManagement::read_source()`, y compris lorsque le document est invalide mais lisible. Le bouton **Valider et sauvegarder** envoie le texte à `ConfigManagement::save_source_candidate()` : aucune écriture frontend directe du fichier n’est effectuée. Un candidat invalide est refusé avant persistence et le diagnostic backend reste l’autorité de validation.
|
||
|
||
Les clics, sélections, chargements, remplacements DOM et sauvegardes sont tracés via le bridge frontend KSP sans journaliser le contenu du source.
|
||
|
||
|
||
## Panneau Profils
|
||
|
||
La vue **Profils** charge l'inventaire des documents Config validés qui possèdent `default_profile` et `profiles`. Pour le document sélectionné :
|
||
|
||
- **Profil par défaut** appelle le backend sans `profile_id` et doit afficher `source de sélection = default_profile` ;
|
||
- changer **Profil inspecté** effectue une sélection explicite et doit afficher `source de sélection = sélection explicite` ;
|
||
- **Globals source** et **Profil source** affichent les objets validés correspondants ;
|
||
- **Effective sûre** affiche le résultat de résolution environnementale redacted par Config ;
|
||
- **Provenance top-level** indique si chaque clé effective vient des globals ou du profil ;
|
||
- **Provenance environnement** indique JSON Pointer, variable, source et sensibilité sans valeur réelle.
|
||
|
||
Avec le `std.logging.json` actuel et `KSP_LOGS_DIRECTORY` défini dans `.env`, la provenance attendue pour `/logs_directory` est `KSP_LOGS_DIRECTORY`, source `dotenv`, sensibilité `Internal`. Le contenu des vues JSON n'est pas recopié dans les logs ; seuls les identifiants de document/profil et métadonnées de résolution sont tracés.
|
||
|
||
|
||
## Panneau Environnement / `.env`
|
||
|
||
La vue **Environnement / `.env`** charge `get_environment_report`, qui projette exclusivement `ConfigManagement::environment_report()`. La table affiche :
|
||
|
||
- nom de variable ;
|
||
- namespace KSP/KSPB ;
|
||
- sensibilité ;
|
||
- valeur persisted `.env` sûre (`desired`) ;
|
||
- valeur effective process-ou-`.env` sûre ;
|
||
- source effective ;
|
||
- indicateur `shadowed` lorsqu'une valeur `.env` existe mais que le process hérité gagne.
|
||
|
||
Une valeur Secret doit apparaître redacted (`********`) dans les colonnes desired/effective. Le bouton **Rafraîchir** relit le rapport Config.
|
||
|
||
La zone **Management / test .env** accepte une variable existante ou un nouveau nom `KSP_*` / `KSPB_*`. **Créer / Modifier** appelle `ConfigManagement::set_dotenv_value()` et **Supprimer** appelle `ConfigManagement::remove_dotenv_value()` ; aucune écriture `.env` n'est implémentée dans le frontend ou dans la couche Tauri. Après chaque mutation, le rapport est rechargé et les quatre indicateurs Config sont affichés :
|
||
|
||
```text
|
||
source_changed
|
||
effective_changed
|
||
shadowed_by_process_environment
|
||
reload_required
|
||
```
|
||
|
||
Cliquer une ligne du rapport remplit uniquement le nom de variable. L'ancienne valeur n'est jamais préchargée dans le formulaire. Une saisie `KSP_SECRET_*` / `KSPB_SECRET_*` est masquée. Pour une variable Secret sélectionnée, **Révéler effective** et **Révéler .env** deviennent disponibles. Ils ouvrent un modal Bootstrap de confirmation avant toute commande Tauri privilégiée.
|
||
|
||
Le reveal utilise un DTO et une commande séparés des rapports ordinaires. Après confirmation, la valeur réelle est affichée dans un champ transitoire `password`, masqué par défaut ; **Afficher/Masquer** ne modifie que le contrôle local. Fermer le modal ou quitter la vue Environnement efface immédiatement la valeur du DOM. Le backend refuse le reveal des namespaces Public/Internal et ne journalise que le nom, la source demandée et la présence/absence d'une valeur.
|
||
|
||
Le bouton **Supprimer** ouvre un modal Bootstrap indiquant la variable ciblée. **Annuler**, la fermeture du modal ou `Esc` abandonnent l'opération ; **Supprimer** confirme ensuite l'appel à `ConfigManagement::remove_dotenv_value()`. Aucun `window.confirm()` natif n'est utilisé.
|
||
|
||
Pour valider le shadowing, lancer ponctuellement l'application avec `KSP_LOGS_DIRECTORY` fourni par le process puis modifier la même variable dans `.env` depuis le panneau. Le résultat attendu est `source_changed=true`, `effective_changed=false`, `shadowed_by_process_environment=true`, `reload_required=false`. Le process hérité reste prioritaire et n'est jamais modifié par Config Desk.
|
||
|
||
## Panneau Logging — édition typée
|
||
|
||
La vue **Logging** appelle `get_logging_document`. Le backend charge le document avec `ConfigManagement::load_logging_document()` et expose :
|
||
|
||
- `file_id`, path résolu, `format_version`, `logs_directory`, `default_profile` ;
|
||
- chaque profil avec `default_filter` et `span_events` ;
|
||
- la console (`enabled`, output, ANSI, format, level, targets, domains) ;
|
||
- tous les fichiers (`output_id`, path, rotation, format, ANSI et filtre) ;
|
||
- tous les `target_filters` globaux.
|
||
|
||
Le sélecteur **Profil édité** travaille sur un brouillon local. `logs_directory`, `default_profile`, profils, console, file sinks, filtres et target overrides sont modifiables. **Créer**, **Cloner**, **Renommer** et **Supprimer** agissent d'abord sur le brouillon ; la suppression de profil est confirmée par modal Bootstrap. **Sauvegarder et appliquer** envoie un candidat typé à `save_logging_document`, qui reconstruit les contrats Config, persiste atomiquement après validation, recharge un `ConfigEnvironment` frais, résout le `default_profile` et hot-reload le `LoggingGuard`. Si le runtime ne peut pas être préparé/rechargé, l'ancien runtime reste actif et la source précédente est restaurée. **Recharger le document** resynchronise uniquement le brouillon depuis la source persistée et demande confirmation si des changements non sauvegardés existent. Les messages Cargo/Tauri/Vite affichés par `cargo tauri dev` sont externes au runtime Logging KSP et ne dépendent pas de `console.enabled`.
|
||
|
||
|
||
|
||
## Test Logging — routing backend et bridge frontend
|
||
|
||
La section **Test Logging — routing contrôlé** utilise un message explicitement destiné aux logs. Ne jamais y copier une valeur `KSP_SECRET_*` / `KSPB_SECRET_*`.
|
||
|
||
Pour le backend :
|
||
|
||
1. choisir `trace`, `debug`, `info`, `warn`, `error` ou `tous` ;
|
||
2. choisir `ksp-app-config-desk` ou `ksp-app-config-desk.logging-test` ;
|
||
3. choisir un domain `absent`, `connu` (`config.logging_test`, `config.logging_runtime`, `frontend`) ou `personnalisé` ;
|
||
4. cliquer **Log backend**.
|
||
|
||
La commande `emit_logging_test` renvoie le nombre d'événements émis et la génération runtime active, mais ne duplique pas le message dans son DTO de résultat. Le test `tous` émet exactement cinq événements, un par niveau.
|
||
|
||
**Log via bridge frontend** réutilise le même message et le même niveau, mais garde le contrat du bridge : `target=ksp-app-config-desk.frontend.main`, `domain=frontend`. En mode `tous`, cinq événements sont envoyés. Cette voie permet de vérifier que les changements de console/file sinks/target/domain appliqués par hot reload affectent aussi les événements issus de la WebView.
|
||
|
||
Scénario conseillé : émettre `tous`, modifier les filtres du profil actif, **Sauvegarder et appliquer**, réémettre exactement le même test et comparer les sinks réellement alimentés sans redémarrer l'application.
|
||
|
||
## Runtime Logging — profil actif, génération et fichiers par lancement
|
||
|
||
La section **Runtime actif** du panneau Logging ne décrit pas le brouillon : elle interroge l'état réellement installé dans `ksp-logging-lib`.
|
||
|
||
Elle expose :
|
||
|
||
- `active_profile` ;
|
||
- `selection_source` : `default_profile`, `explicit` ou `fallback` ;
|
||
- `generation` ;
|
||
- console active/inactive ;
|
||
- compteurs cumulés de lignes abandonnées ;
|
||
- `application_id` ;
|
||
- `launch_timestamp` ;
|
||
- chaque file sink actif avec son directory, son prefix effectif et sa rotation.
|
||
|
||
Au démarrage de Config Desk, l'identité de lancement est construite une seule fois avec un token de la forme :
|
||
|
||
```text
|
||
20260816-182519.123Z-p4242
|
||
```
|
||
|
||
Pour un fichier source configuré comme `debug/ksp-debug.log`, le runtime peut donc exposer un prefix comme :
|
||
|
||
```text
|
||
ksp-app-config-desk.20260816-182519.123Z-p4242.ksp-debug.log
|
||
```
|
||
|
||
Le même `launch_timestamp` doit rester affiché après chaque hot reload du processus courant. Après fermeture puis nouveau lancement de l'application, il doit changer. La rotation `daily` ou `hourly` peut ajouter sa composante de rotation, mais deux lancements ne doivent plus partager le même prefix applicatif.
|
||
|
||
### Sélection explicite du profil runtime
|
||
|
||
`default_profile` reste une propriété persistée de `std.logging.json`. Le sélecteur **Profil runtime à appliquer** travaille uniquement avec les profils déjà persistés et ne modifie pas ce champ.
|
||
|
||
Scénario attendu avec deux profils persistés `local_dev` et `local_test` :
|
||
|
||
1. garder `default_profile=local_dev` ;
|
||
2. sélectionner `local_test` dans **Profil runtime à appliquer** ;
|
||
3. cliquer **Appliquer le profil** ;
|
||
4. vérifier `active_profile=local_test`, `selection_source=explicit` et `generation + 1` ;
|
||
5. cliquer **Recharger le document** : `default_profile` doit toujours être `local_dev` ;
|
||
6. sélectionner/appliquer `local_dev` explicitement si souhaité ;
|
||
7. **Sauvegarder et appliquer** un document valide : le runtime revient au `default_profile` du document et `selection_source=default_profile`.
|
||
|
||
Le bouton d'application explicite est désactivé lorsque le brouillon est sale afin qu'un profil affiché mais non persisté ne soit jamais confondu avec un profil réellement chargeable par Config.
|
||
|
||
Si la résolution ou la préparation du profil explicite échoue, `ksp_logging_lib::reinitialize()` ne remplace pas les layers actifs et la génération ne doit pas avancer. Une sauvegarde de document qui échoue pendant l'application runtime conserve également l'ancien runtime et restaure la source précédente lorsqu'elle avait été modifiée.
|