Files
khadhroony-solana-project/docs/plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md
2026-08-22 00:21:14 +02:00

71 KiB
Raw Blame History

Plan 0.1.4ksp-app-config-desk

1. Statut, base et objectif

Ce plan ouvre 0.1.4 avec 0.1.4-pre.001. Cette première tranche reste volontairement une tranche de brainstorming, audit et planification : elle ne crée pas encore la crate Tauri, n'ajoute aucune dépendance desktop et ne commence pas l'éditeur fonctionnel.

Base fournie et auditée :

khadhroony-solana-project-v0.1.3.zip
workspace.package.version = "0.1.3"
deltas/0.1.3/rel.001.md présent

L'archive khadhroony-solana-project-v0.1.3.zip est l'archive source générée automatiquement par Gitea à partir du tag stable v0.1.3, selon le mode de livraison normal du projet. L'absence de métadonnées .git à l'intérieur de cette archive est donc attendue et ne constitue pas une réserve sur la provenance de la base : l'archive Gitea nommée d'après le tag est prise comme export matériel de la release stable validée. Ce même principe s'applique aux futures bases KSP fournies sous forme d'archives de tag Gitea.

La mission de 0.1.4 est d'introduire la première application desktop spécialisée KSP :

ksp-app-config-desk

Elle doit valider réellement la surface stable de ksp-config-lib et le lifecycle de ksp-logging-lib, tout en restant une couche de composition/interface :

ksp-app-config-desk
    -> ksp-config-lib
    -> ksp-logging-lib
    -> ksp-core-lib via les contrats KSP nécessaires

L'application ne devient propriétaire ni du parsing Config, ni des schemas, ni des placeholders, ni de .env, ni de la classification des secrets, ni de la persistence Config, ni du runtime tracing.

2. Audit exact de la base stable 0.1.3

2.1 Workspace

Le workspace stable contient exactement les crates fonctionnelles suivantes :

crates/ksp-core-lib
crates/ksp-logging-lib
crates/ksp-config-lib

Les ressources requises par le prompt sont présentes :

config/std.logging.json
config/schemas/std.logging.schema.json
config/schemas/composite.schema.json
config/examples/std.logging.example.json
config/examples/composite.example.json
.env.example

Le Cargo.toml racine déclare Rust 2024 et les lints KSP attendus. Les dépendances externes communes sont centralisées sous [workspace.dependencies].

2.2 Surface Config réutilisable

L'audit confirme notamment :

  • ConfigBootstrapOptions pour --cfgpath / --schemapath ;
  • ConfigFileRegistry, ConfigFileId, ConfigFileDescriptor et --filemap ;
  • ConfigDocumentEngine ;
  • validation JSON, JSON Schema et sémantique ;
  • globals, profils, default_profile et provenance ;
  • composites génériques par file_id ;
  • ConfigEnvironment avec priorité process > .env > fallback ;
  • placeholders ${NAME} et ${NAME:-fallback} ;
  • sensibilité Public / Internal / Secret ;
  • représentations réelle/sûre et provenance ;
  • ResolvedLoggingConfig::into_settings() ;
  • ConfigManagement ;
  • ConfigManagement::read_source() pour lire le source d'un document Config enregistré même lorsqu'il est invalide ;
  • ConfigManagement::load_logging_document() / save_logging_document() ;
  • environment_report() ;
  • reveal_effective_environment_value() / reveal_dotenv_value() ;
  • set_dotenv_value() / remove_dotenv_value().

2.3 Lifecycle Logging déjà compatible avec le hot reload

ksp-logging-lib possède déjà le contrat essentiel de 0.1.4 :

initialize(&LoggingSettings) -> LoggingGuard
reinitialize(&mut LoggingGuard, &LoggingSettings) -> Result<()>

Le nouveau runtime est préparé avant le swap. Une erreur de validation/préparation ou de reload laisse donc le runtime valide précédent actif. 0.1.4 doit exploiter et démontrer cette propriété, pas la réimplémenter.

2.4 Deux lacunes publiques de Config révélées par l'usage desktop

L'audit fait apparaître deux besoins réels qui n'étaient pas nécessaires pour 0.1.3, mais deviennent bloquants pour un manager extensible.

A. Inventaire du registre

ConfigFileRegistry sait :

descriptor(file_id)
resolve_path(...)

mais n'expose pas aujourd'hui de vue publique permettant d'énumérer les descripteurs enregistrés.

Construire dans l'application une liste codée en dur de FILE_ID_* dupliquerait le registre et empêcherait l'extensibilité demandée. Une petite extension publique de ksp-config-lib devra donc fournir une vue en lecture seule/itérable des descripteurs, dans l'ordre déterministe du registre.

B. Réparation d'un document invalide

ConfigManagement::read_source() permet volontairement de lire un source invalide. En revanche :

load_logging_document()
    -> nécessite déjà un document valide

save_logging_document(&LoggingConfigDocument)
    -> sauve un candidat typé déjà reconstructible

Il n'existe pas encore de frontière publique permettant à une application de soumettre le texte corrigé d'un document enregistré qui était invalide, sans écrire directement le fichier physique.

La solution prévue est une API Config bornée, de forme conceptuelle :

save_source_candidate(file_id, source_text)

Le nom public final sera fixé dans la tranche d'implémentation, mais le contrat est décidé dès maintenant :

  1. file_id doit être connu et de kind Config ;
  2. le texte candidat est parsé par Config ;
  3. le document est validé contre le schema enregistré ;
  4. les invariants sémantiques Config sont exécutés ;
  5. rien n'est écrit si une étape échoue ;
  6. si tout est valide, Config sérialise/persiste atomiquement le document normalisé ;
  7. l'application ne reçoit aucun droit d'écrire un chemin arbitraire.

Cette API n'est pas un contournement permettant de persister un JSON invalide. Elle constitue précisément la frontière de réparation validée manquante.

Ces deux extensions appartiennent à ksp-config-lib, avec tests publics/unitaires appropriés ; elles ne doivent pas être simulées dans l'application Tauri.

3. Audit des règles Tauri et du gabarit bot3

Référence auditée :

khadhroony-bot3_v0.5.3-pre.005-fix010.zip
kb-app-demo-desktop

La référence est réutilisée par principes, pas copiée mécaniquement.

3.1 Éléments retenus

  • package Rust mixte lib + bin ;
  • binaire très mince ;
  • verrou single-instance avant l'entrée Tauri ;
  • tauri.rs centralisant run et les wrappers #[tauri::command] ;
  • logique métier/fenêtre hors des wrappers ;
  • fenêtre splash distincte de la fenêtre main ;
  • frontend Vanilla TypeScript + Vite ;
  • SCSS/SASS et Bootstrap ;
  • gabarit visuel initial de bot3 comme base à simplifier/affiner, sans recopier les écrans métier ;
  • même icône de base bot3 (favicon.png / favicon.ico) tant qu'aucune identité KSP plus spécifique n'est décidée ;
  • police locale du splash bot3 DOS_Amazigh.ttf (Dos Amazigh) reprise dans le répertoire frontend/fonts/ lors de la tranche bootstrap/splash ;
  • Font Awesome pour l'iconographie ;
  • SimpleBar pour le scrolling applicatif cohérent et visuellement plus confortable que les scrollbars WebKitGTK par défaut ;
  • resize-observer-polyfill comme dépendance du gabarit pour les composants/layouts qui doivent réagir proprement aux redimensionnements ;
  • organisation Vite explicite avec frontend sous frontend/ ;
  • génération TS-RS à la frontière applicative ;
  • LoggingGuard gardé durablement dans l'état backend.

3.2 Éléments à refondre ou ne pas reprendre

Le modèle bot3 contient encore :

SPLASH_MINIMUM_MS = 12100
SPLASH_FADE_MS = 12000
SPLASH_CLOSE_WAIT_MS = 12100

Ces timings codés en dur ne sont pas retenus. KSP introduira un réglage Config/.env résolu via ksp-config-lib au moment où le splash runtime sera implémenté.

Le frontend bot3 déclare @fltsci/tauri-plugin-tracing, package frontend compagnon de tauri-plugin-tracing. L'audit du projet officiel confirme que l'installation recommandée du plugin associe bien la crate Rust et ce package NPM. KSP conserve donc ce couple lorsqu'il introduit le plugin.

Bot3 n'utilise toutefois pas directement les helpers JS du package pour son routing applicatif : son frontend_log.ts appelle une commande Tauri dédiée avec un niveau, un target frontend explicite et le message. Ce principe est retenu et refondu dans KSP afin de conserver des targets KSP contrôlés et de faire passer l'émission finale par ksp-logging-lib. Le package officiel reste disponible pour les capacités réellement utiles du plugin, notamment l'intégration console lorsque celle-ci est compatible avec l'ownership Logging KSP.

Les dépendances propres aux nombreuses démos bot3 ne sont pas toutes reprises par défaut. Sont écartées tant qu'un besoin immédiat n'est pas démontré :

  • ECharts ;
  • @andypf/json-viewer ;
  • markdown-it en l'absence de vue de présentation.

SimpleBar et resize-observer-polyfill restent au contraire dans le gabarit frontend KSP : ils participent au confort et à la robustesse visuelle du shell, notamment pour éviter de dépendre uniquement du scrolling natif WebKitGTK et pour conserver des composants correctement redimensionnés.

DataTables n'est pas imposé au tout premier squelette vide, mais il fait partie des composants attendus dès qu'un tableau HTML devient réellement interactif. Dès qu'un panneau requiert tri, filtrage, pagination locale, sélection, cases à cocher ou autres interactions tabulaires structurées, la tranche qui introduit ce besoin doit ajouter/configurer DataTables plutôt que réimplémenter ces fonctions à la main. Le couple bot3 datatables.net-bs5 + datatables.net-select-bs5 constitue la référence à réauditer au moment de son introduction.

init_rustls n'est pas copié par réflexe. Aucun besoin TLS direct de Config Desk n'est identifié. Le helper ne sera introduit que si une dépendance réellement utilisée l'exige. Le helper bot3 d'ouverture/focus de fenêtre est réduit à une primitive commune adaptée au shell (show/focus de main après splash) ; aucun helper multi-fenêtres générique n'est ajouté sans deuxième usage.

3.3 Décision frontend

Le frontend de référence pour 0.1.4 sera :

Vanilla TypeScript
Vite
SCSS via sass-embedded
Bootstrap
Font Awesome Free
SimpleBar
resize-observer-polyfill
DataTables lorsque le premier tableau interactif le justifie

Aucun framework React/Vue/Svelte n'est nécessaire pour ce manager spécialisé. Cette décision réduit la surface et reste cohérente avec le modèle bot3 ainsi qu'avec le template Vanilla TypeScript officiellement supporté par Tauri 2.

Le premier éditeur raw utilisera un contrôle texte natif correctement stylé ; aucun éditeur de code lourd n'est ajouté tant qu'un besoin fonctionnel ne l'impose pas.

3.4 Conventions frontend, artefacts et ports des applications desk

Le layout frontend reprend la convention éprouvée de bot3 : les sources web sont contenues dans frontend/, les modules TypeScript dans frontend/ts/, les styles SCSS dans frontend/sass/ et les bindings TS-RS générés sous frontend/ts/bindings/. Les DTO Rust restent propriétaires de leur contrat ; les fichiers TypeScript générés ne sont jamais édités manuellement et bindings/ reste ignoré par Git.

Les artefacts frontend construits doivent être séparés des sources. Pour ksp-app-config-desk, la destination contractuelle est fixée à :

../../../builds/khadhroony-solana-project/ksp-app-config-desk/dist

Cette valeur est utilisée par build.frontendDist dans tauri.conf.json. vite.config.ts utilise la même destination comme build.outDir depuis son introduction en pre.005. Elle remplace le ../dist/../../dist historique du gabarit bot3.

La gestion npm distingue le runtime frontend du tooling. Les bibliothèques consommées par le bundle appartiennent à dependencies; les outils de compilation/développement (@tauri-apps/cli, Vite, TypeScript, Sass) et les paquets @types/* appartiennent à devDependencies. npm est utilisé directement uniquement pour installer ou mettre à jour ces dépendances. Pour la première installation, l'opérateur se place dans crates/ksp-app-config-desk et exécute npm i -D. Le cycle normal de développement et de build reste ensuite crate-local : (cd crates/ksp-app-config-desk && cargo tauri dev) et (cd crates/ksp-app-config-desk && cargo tauri build). -c/--config n'est pas utilisé pour sélectionner l'application car Tauri le traite comme un overlay de configuration. Tauri déclenche lui-même npm run dev / npm run build au travers des hooks configurés. Aucun lockfile npm n'est versionné.

Chaque application Tauri desk KSP reçoit un couple de ports Vite/HMR propre. La première application réserve :

Application Port Vite HTTP Port HMR
ksp-app-config-desk 1430 1431

Les applications suivantes incrémentent le couple de deux ports (1432/1433, puis 1434/1435, etc.). Vite doit utiliser un port strict afin qu'une collision soit signalée au lieu de provoquer un basculement silencieux vers un autre port. Cette allocation permet de faire fonctionner simultanément plusieurs applications desk en mode développement.

4. Audit des dépendances actuelles au 2026-08-16

Aucune dépendance n'est ajoutée par pre.001. Les versions suivantes ont été revérifiées depuis les registres/documentations officiels afin de fixer la génération candidate à réévaluer au moment exact de l'ajout :

Dépendance Version actuelle auditée Usage envisagé
tauri 2.11.5 runtime desktop
tauri-build 2.6.3 build Tauri
tauri-plugin-tracing 0.3.4 intégration tracing à la frontière Tauri
ts-rs 12.0.1 bindings DTO applicatifs
fs2 0.4.3 verrou single-instance
@fltsci/tauri-plugin-tracing 0.3.4 package frontend compagnon du plugin tracing
@tauri-apps/api 2.11.1 frontend Tauri
@tauri-apps/cli 2.11.4 dev/build desktop
@types/bootstrap 5.2.11 typings Bootstrap
vite 8.2.1 build frontend
typescript 7.0.2 frontend TypeScript
sass-embedded 1.102.0 compilation SCSS
bootstrap 5.3.8 composants/layout
@fortawesome/fontawesome-free 7.3.1 iconographie

Sources d'audit :

Vite 8 reste compatible avec la direction choisie, mais demande une version Node moderne. Le poste de build devra donc être vérifié contre le prérequis Vite au moment de la création du frontend.

4.1 Décision explicite tauri-plugin-tracing

La version auditée 0.3.4 convient à l'ownership KSP sur un point essentiel : elle n'installe pas de subscriber global par défaut. Config Desk devra enregistrer le plugin avec un builder qui n'appelle jamais :

with_default_subscriber()

Le subscriber global reste exclusivement installé par ksp-logging-lib::initialize().

Un autre point a été vérifié dans le source 0.3.4 : la commande JS -> Rust log émet actuellement des événements tracing avec :

target: ""

Or ksp-logging-lib impose aux target filters configurables un prefix ksp- et son takeover runtime est centré sur ksp-.

Décision 0.1.4 :

  • intégrer le plugin Rust à la frontière Tauri sans subscriber propre ;
  • intégrer son package frontend compagnon @fltsci/tauri-plugin-tracing dans le gabarit desktop au même moment ;
  • ne pas utiliser with_default_subscriber() ;
  • ne pas installer une seconde pile tracing-subscriber dans l'application ;
  • ne pas détendre la politique ksp-* de ksp-logging-lib uniquement pour faire passer le target vide de la commande JS standard du plugin ;
  • reprendre/refondre le pont frontend_logging de bot3 : helpers TypeScript -> commande Tauri dédiée -> service Rust -> façade ksp-logging-lib ;
  • normaliser/whitelister les targets frontend et de test côté Rust afin qu'un texte arbitraire reçu depuis la webview ne devienne jamais un target de callsite arbitraire ;
  • utiliser le package officiel pour les fonctions réellement utiles du plugin (attachConsole ou autre) uniquement lorsque leur comportement reste compatible avec le runtime KSP ;
  • le bridge KSP actuel couvre WebView -> Rust et conserve les appels JavaScript dans la console WebKit, mais ne couvre pas encore Rust -> WebKit ; avec le subscriber custom de KSP, attachConsole() requiert une tauri_plugin_tracing::WebviewLayer intégrée au subscriber possédé par ksp-logging-lib ; cette capacité sera ajoutée seulement via un adapter qui préserve cet ownership ;
  • ne pas utiliser directement interceptConsole() / takeoverConsole() comme unique pont JS -> Rust si cela produit des événements impossibles à router selon les targets KSP ou une boucle/double émission avec le bridge KSP ;
  • pour les événements de test Logging de 0.1.4, utiliser la façade/macros de ksp-logging-lib avec un target KSP contrôlé et un domain structuré optionnel ;
  • revérifier ce point lors de l'introduction réelle des dépendances, car une nouvelle version du plugin pourrait étendre son contrat frontend.

tauri-plugin-log est explicitement exclu.

5. Layout interne cible de crates/ksp-app-config-desk

La crate sera ajoutée directement sous :

crates/ksp-app-config-desk

Layout cible :

crates/ksp-app-config-desk/
├── Cargo.toml
├── README.md
├── USAGE.md
├── build.rs
├── package.json
├── tsconfig.json
├── vite.config.ts
├── tauri.conf.json
├── capabilities/
├── icons/
├── frontend/
│   ├── main.html
│   ├── splash.html
│   ├── ts/
│   │   ├── main.ts
│   │   ├── splash.ts
│   │   ├── invoke.ts
│   │   ├── frontend_log.ts
│   │   ├── state.ts
│   │   └── bindings/             # généré, ignoré
│   └── sass/
│       ├── main.scss
│       ├── splash.scss
│       └── _shared.scss
├── src/
│   ├── main.rs
│   ├── lib.rs
│   ├── tauri.rs
│   ├── app_state.rs
│   ├── bootstrap.rs
│   ├── errors.rs
│   ├── config_service.rs
│   ├── environment_service.rs
│   ├── logging_service.rs
│   ├── secret_service.rs
│   ├── splash.rs
│   ├── tw_main.rs
│   ├── tw_splash.rs
│   ├── dto_common.rs
│   ├── dto_documents.rs
│   ├── dto_environment.rs
│   ├── dto_logging.rs
│   └── dto_secret.rs
├── unit_tests/
│   └── ... miroir des modules Rust testés
└── tests/
    └── ... API publique / intégration bornée

Le layout pourra être ajusté lors de la création réelle si Tauri 2 impose un fichier généré spécifique, mais les responsabilités ci-dessous sont fixées.

5.1 Contrat lib + bin

Le package est mixte :

package : ksp-app-config-desk
lib     : ksp_app_config_desk_lib
bin     : ksp-app-config-desk

main.rs reste minimal :

  1. construire/acquérir le verrou single-instance ;
  2. collecter les arguments de processus nécessaires au bootstrap ;
  3. appeler l'entrée run(...) de la bibliothèque ;
  4. convertir explicitement le résultat en ExitCode.

main.rs ne lit pas KSP_* / KSPB_* et ne parse pas lui-même Config.

lib.rs est limité aux déclarations de modules et réexports réellement nécessaires.

tauri.rs possède :

  • run ;
  • le tauri::Builder ;
  • l'enregistrement du plugin tracing ;
  • l'enregistrement du state ;
  • toutes les annotations #[tauri::command] ;
  • les wrappers très minces qui délèguent aux services/modules ;
  • les helpers Tauri réellement transverses de démarrage/fenêtres.

La construction du runtime Tauri doit rester lisible et facilement désactivable par étape. run ne doit donc pas accumuler une longue chaîne de .plugin(...).manage(...).setup(...).invoke_handler(...). La convention cible est une variable builder construite/réassignée progressivement, éventuellement via des helpers courts :

let mut builder = tauri::Builder::default();
builder = configure_tracing(builder, ...);
builder = configure_state(builder, ...);
builder = configure_plugins(builder, ...);
builder = configure_setup(builder, ...);
builder = configure_commands(builder, ...);

Le code Rust final respectera évidemment les signatures réelles de Tauri et les règles KSP de retours explicites. L'objectif architectural est qu'un plugin, un bloc de setup ou un groupe de commandes puisse être commenté/désactivé temporairement sans devoir démanteler ou reformater une chaîne de builder monolithique.

Aucune annotation #[tauri::command] n'est dispersée dans config_service.rs, logging_service.rs, tw_*, etc.

5.2 Convention tw_*

tw_* est retenu pour les modules liés à une fenêtre Tauri :

tw_main.rs
tw_splash.rs

Les opérations métier ne sont pas placées dans ces modules. Le shell fonctionnel reste essentiellement monofenêtre ; tw_main orchestre la fenêtre, pas la logique Config.

6. Modèle d'état applicatif et ownership de LoggingGuard

L'état backend cible est conceptuellement :

AppState
├── ConfigManagement
└── Mutex<LoggingRuntimeState>
    ├── LoggingGuard
    ├── active_profile_id
    └── generation/revision runtime

Principes :

  • ConfigManagement reste la façade de management ;
  • son ConfigDocumentEngine porte bootstrap + registry ;
  • ConfigEnvironment::load() produit un snapshot frais lorsqu'une résolution runtime doit refléter le process/.env courant ;
  • LoggingGuard vit aussi longtemps que l'application ;
  • guard + métadonnées du profil actif sont protégés ensemble pour éviter un état incohérent après reload ;
  • l'identifiant de profil actif n'est modifié qu'après succès de reinitialize() ;
  • un échec conserve guard, profil actif et génération précédents.

6.1 Bootstrap Logging initial

Ordre cible :

argv
-> ConfigBootstrapOptions / ConfigFileRegistry via ksp-config-lib
-> ConfigDocumentEngine
-> ConfigEnvironment::load()
-> load_resolved_logging_config(None, env)
-> ResolvedLoggingConfig::into_settings()
-> ksp_logging_lib::initialize(...)
-> LoggingGuard
-> AppState
-> tauri::Builder

None utilise le default_profile du document Logging. Une sélection explicite ultérieure est faite depuis l'UI.

Si le document Logging est invalide au démarrage, l'application doit quand même pouvoir devenir un outil de réparation. Il faudra donc prévoir un fallback de bootstrap applicatif sûr qui ne duplique pas la configuration Logging : par exemple démarrer avec un settings KSP minimal construit par l'application uniquement pour rendre le manager utilisable, tout en affichant clairement le diagnostic Config. Le contrat exact de ce fallback sera implémenté/testé dans la tranche bootstrap ; il ne doit jamais remplacer silencieusement la configuration utilisateur ni être persisté automatiquement.

Ce fallback est un point de vigilance : sans lui, l'exigence « afficher le source brut invalide afin de permettre sa réparation » serait impossible lorsque std.logging.json lui-même empêche le démarrage.

7. Shell et écrans/panneaux minimums

Décision : une fenêtre principale de management, plus le splash de démarrage. Les fonctions sont des panneaux/routes internes, pas une collection de fenêtres séparées.

Navigation minimum :

Vue d'ensemble
Documents
Profils
Environnement / .env
Logging

7.1 Vue d'ensemble

Affiche uniquement des informations sûres :

  • racines bootstrap Config ;
  • nombre de documents Config enregistrés ;
  • état valide/invalide des documents inspectés ;
  • profil Logging runtime actif ;
  • génération/revision de reload ;
  • présence de shadowing environnement ;
  • dernier résultat de mutation/test .env ;
  • dernier résultat de test Logging interactif.

7.2 Documents

Fonctions :

  • lister les documents de kind Config issus du registre Config ;
  • afficher file_id, filename mappé, schema associé et path résolu ;
  • charger/valider un document via Config ;
  • classifier l'erreur ;
  • en cas d'invalidité, afficher le source brut fourni par ConfigManagement::read_source() ;
  • permettre l'édition du texte puis soumettre le candidat à l'API Config de réparation validée ;
  • recharger le document après succès.

L'UI n'utilise ni JSON.parse comme validateur de vérité, ni un schema frontend dupliqué pour décider si la sauvegarde est valide. Un parsing frontend éventuel ne sert qu'à l'ergonomie ; l'autorité est le résultat backend Config.

7.3 Profils

Le premier document spécialisé est Logging.

L'UI doit montrer :

  • default_profile ;
  • profils disponibles ;
  • profil explicitement sélectionné pour inspection ;
  • source de sélection (default_profile ou explicite) ;
  • globals ;
  • contenu du profil ;
  • effective après résolution environnement ;
  • provenance utile sans valeur Secret réelle.

L'inspection générique par file_id reste prévue dans le shell, mais 0.1.4 ne crée pas d'éditeur générique de tout schema inconnu.

7.4 Environnement / .env

Ce panneau est une surface fonctionnelle de validation de ksp-config-lib, pas un simple écran de diagnostic. Il doit permettre de vérifier le comportement réel de ConfigEnvironment et ConfigManagement sans lecture/écriture directe de .env depuis l'application.

Il comporte deux zones complémentaires.

7.4.1 Rapport desired/effective

La table est alimentée uniquement par ConfigManagement::environment_report() et expose les variables KSP/KSPB présentes dans le process ou .env :

  • nom ;
  • namespace KSP/KSPB ;
  • sensibilité Public / Internal / Secret ;
  • desired_safe_value persistée dans .env ;
  • effective_safe_value ;
  • source effective process / .env ;
  • indicateur shadowed_by_process_environment ;
  • actions management adaptées à la ligne ;
  • action privilégiée « Révéler » séparée pour les valeurs réelles.

Aucune valeur réelle Secret n'est nécessaire pour construire cette table.

7.4.2 Management/test .env

Une zone d'édition dédiée permet de tester réellement les frontières déjà fournies par Config :

Variable : variable existante | nouveau nom KSP_*/KSPB_*
Valeur   : champ d'édition, masqué lorsqu'il s'agit d'un Secret
Actions  : Créer/Modifier | Supprimer | Recharger le rapport
Résultat : source_changed | effective_changed | shadowed | reload_required

Règles :

  • création/modification uniquement via ConfigManagement::set_dotenv_value() ;
  • suppression uniquement via ConfigManagement::remove_dotenv_value() ;
  • le backend Config reste seul responsable de la validation du nom, de l'encodage .env, de la persistence atomique et du rechargement de ses snapshots ;
  • l'application ne lit pas le fichier .env brut et ne reconstruit pas son format ;
  • après chaque mutation, le rapport est rechargé depuis Config afin de montrer l'état réellement persisté/effectif ;
  • le résultat ConfigEnvironmentChangeReport est présenté explicitement à l'opérateur ;
  • une valeur process héritée n'est jamais modifiée par l'application.

Après une mutation .env, l'UI doit donc pouvoir afficher sans ambiguïté :

source_changed      = true|false
effective_changed   = true|false
shadowed_by_process = true|false
reload_required     = true|false

Le scénario de shadowing est un test fonctionnel obligatoire. Si par exemple le process fournit une variable et .env contient une autre valeur pour le même nom, une modification de .env doit changer la valeur desired mais laisser la valeur effective issue du process inchangée. L'UI doit expliquer que la priorité reste :

process > .env > fallback de placeholder

et qu'un processus enfant ne peut pas modifier l'environnement déjà hérité de son parent. Le scénario reproductible de validation pourra lancer l'application avec KSP_LOGS_DIRECTORY=<valeur-process> dans l'environnement du process, puis modifier la même variable dans .env depuis le panneau et vérifier que la valeur effective reste celle du process.

Le panneau sert aussi à valider le lien entre .env et la résolution des documents Config. La base stable fournit déjà un cas reproductible :

config/std.logging.json
logs_directory = "${KSP_LOGS_DIRECTORY:-logs}"

Une modification de KSP_LOGS_DIRECTORY via le panneau doit pouvoir être suivie d'une nouvelle résolution Config/Logging et rendre observable la nouvelle valeur effective/provenance, sans que le frontend résolve lui-même le placeholder. Si une variable process masque KSP_LOGS_DIRECTORY, le test doit au contraire démontrer que la modification .env n'affecte pas la résolution effective tant que le process reste prioritaire.

Pour une variable Secret, l'ancienne valeur réelle n'est pas préchargée automatiquement dans le formulaire. Une nouvelle valeur peut être saisie explicitement pour remplacement ; la consultation de l'ancienne valeur passe exclusivement par le flux reveal privilégié décrit plus loin.

7.5 Logging

Éditeur spécialisé et typé couvrant au minimum :

  • default_profile ;
  • création d'un profil ;
  • duplication d'un profil ;
  • renommage ;
  • suppression avec garde sur default_profile ;
  • filtre par défaut ;
  • span events ;
  • console enabled/output/ANSI/format/filter ;
  • plusieurs fichiers ;
  • output_id ;
  • path ;
  • rotation ;
  • format ;
  • filtres level/targets/domains ;
  • target filters ;
  • sauvegarde ;
  • sélection d'un profil à appliquer ;
  • hot reload ;
  • émission d'événements de test contrôlés depuis l'UI.

Les opérations frontend produisent des DTO applicatifs ; le service Rust reconstruit/utilise les types publics LoggingConfigDocument et sous-contrats de ksp-config-lib. Le frontend ne fabrique pas directement le JSON persistant comme source d'autorité.

7.6 Test Logging interactif

Le panneau Logging comporte une zone de test manuelle destinée à prouver le routing réel du runtime actif après sauvegarde/reload.

Contrôles minimums :

Message : texte libre explicitement destiné au log de test
Niveau  : trace | debug | info | warn | error | tous
Target  : select de targets KSP contrôlés
Domain  : aucun | domaine connu | personnalisé
Bouton  : Log

Le message n'est jamais prérempli depuis Config, un diagnostic, un reveal Secret ou un état contenant une valeur réelle. L'UI indique explicitement que le contenu sera journalisé et ne doit contenir aucune donnée sensible.

Le mode tous émet le même message de test aux cinq niveaux avec un identifiant de test commun afin de visualiser immédiatement les seuils de filtrage.

Le target n'est pas un texte Rust arbitraire. Le frontend transmet un target_id appartenant à une liste exposée par l'application, par exemple :

config_desk
frontend
logging_test
config_test
tauri

Le service Rust mappe ces identifiants vers des callsites/targets KSP fixes tels que :

ksp-app-config-desk
ksp-app-config-desk.frontend
ksp-app-config-desk.test.logging
ksp-app-config-desk.test.config
ksp-app-config-desk.tauri

Le domain, au contraire, reste un champ structuré distinct du target. Le select peut proposer les domaines utilisés par la configuration Logging chargée, des domaines de test prédéfinis et une option personnalisée. Une valeur personnalisée reste un champ d'événement et ne modifie pas le target propriétaire.

Le bouton Log appelle une commande Tauri dédiée. L'émission backend utilise uniquement ksp-logging-lib; aucune commande applicative n'appelle directement tracing pour posséder le routing. Le résultat retourné à l'UI contient au minimum l'identifiant du test, les niveaux émis, le target sélectionné, le domaine sélectionné et la génération du runtime actif, mais ne recopie pas inutilement le message.

En parallèle, le frontend_log.ts commun reprend/refond le mécanisme bot3 pour les logs techniques du frontend et le bridge console. Il passe par une commande emit_frontend_log séparée et des targets frontend whitelistés. Les deux chemins peuvent partager le même service d'émission Rust sans confondre leurs DTO et leurs responsabilités.

Le shell applique également une instrumentation frontend systématique : clics et transitions détat significatives en debug; rendu, remplacement de sections, événements fréquents et étapes techniques en trace. Les wrappers IPC journalisent le début et la fin des chargements sans recopier les arguments ou payloads susceptibles de devenir sensibles. Cette convention devient le modèle des futures applications desk KSP.

8. Matrice commandes Tauri / services / APIs KSP

Les noms ci-dessous sont les noms fonctionnels cibles ; ils pourront être normalisés avant implémentation, mais leurs responsabilités sont fixées.

Commande Tauri Service interne API KSP principale Secret réel ?
get_app_snapshot config_service + logging_service registry/management + runtime state non
list_config_documents config_service future vue publique du ConfigFileRegistry non
inspect_config_document config_service load_validated_document + read_source si erreur non
save_config_source_candidate config_service future API Config de réparation validée non
inspect_profile config_service load_resolved_profile + résolution détaillée non
get_environment_report environment_service ConfigManagement::environment_report non
set_dotenv_value environment_service ConfigManagement::set_dotenv_value + rapport frais entrée potentiellement Secret, jamais loggée
remove_dotenv_value environment_service ConfigManagement::remove_dotenv_value + rapport frais non
reveal_environment_value secret_service reveal_effective_environment_value ou reveal_dotenv_value oui
get_logging_editor logging_service load_logging_document non
save_logging_document logging_service save_logging_document non par design Logging
apply_logging_profile logging_service ConfigEnvironment::load + load_resolved_logging_config + reinitialize valeurs resolved possibles, jamais DTO/log
emit_frontend_log frontend_logging_service façade ksp-logging-lib non, message technique frontend seulement
emit_logging_test logging_service façade/macros ksp-logging-lib non, message explicitement saisi pour test
splash_frontend_ready splash lifecycle Tauri + settings splash déjà résolus non

Tous les wrappers dans tauri.rs :

  • retournent explicitement Ok/Err ;
  • n'utilisent ni ?, ni unwrap, ni expect, ni panic ;
  • ne contiennent pas la logique métier ;
  • convertissent les erreurs vers un DTO sûr sans sérialiser aveuglément Error::context().

9. Matrice DTO ordinaires / DTO secrets

9.1 DTO ordinaires

Familles prévues :

AppSnapshotDto
ConfigDocumentDescriptorDto
ConfigDocumentInspectionDto
ConfigDiagnosticDto
ProfileInspectionDto
EnvironmentVariableReportDto
DotenvMutationRequestDto
EnvironmentMutationResultDto
LoggingDocumentDto
LoggingProfileDto
LoggingConsoleDto
LoggingFileDto
LoggingFilterDto
LoggingRuntimeDto
FrontendLogPayloadDto
LoggingTargetOptionDto
LoggingTestRequestDto
LoggingTestResultDto

Règles :

  • valeurs environnement = safe/redacted uniquement ;
  • aucun champ « real_value » générique ;
  • aucune copie brute d'un contexte d'erreur pouvant contenir une donnée sensible ;
  • ConfigDiagnosticDto contient au minimum domaine/code/message/catégorie + métadonnées sûres connues de la requête (file_id, éventuellement path Config), jamais une source externe arbitraire ;
  • bindings TS-RS dans la crate applicative.

9.2 Classification des diagnostics

L'application classe par ErrorCode stable, pas par parsing du texte :

Json
Schema
Semantic
Effective
Environment
BootstrapOrMapping
PersistenceOrManagement
RuntimeLogging
Tauri

Exemples :

  • json_syntax_invalid -> Json ;
  • schema_invalid / schema_validation_failed -> Schema ;
  • document_semantic_invalid -> Semantic ;
  • effective_config_invalid -> Effective ;
  • erreurs de placeholder/variable -> Environment.

9.3 DTO secret privilégié

Le reveal utilise une commande et des DTO séparés :

SecretRevealRequestDto
SecretRevealResponseDto

Le response DTO :

  • est sérialisable vers Tauri ;
  • n'est pas incorporé dans un snapshot global ;
  • n'est pas mis en cache dans AppState ;
  • n'est pas cloné/Debug par convenance ;
  • n'est jamais inclus dans un diagnostic/log.

Le frontend :

  • n'appelle reveal qu'après action explicite sur une variable nommée ;
  • affiche un modal de confirmation mentionnant la variable et la source demandée ;
  • affiche le secret dans un contrôle transitoire masqué par défaut ;
  • retire la valeur du state frontend à la fermeture/changement de panneau ;
  • n'utilise ni localStorage, ni sessionStorage, ni persistance automatique pour cette valeur.

10. Modèle d'autorisation pour les secrets en 0.1.4

Le threat model de la première version est la prévention de divulgation accidentelle dans les DTO généraux, logs, diagnostics, snapshots et état UI persistant.

L'application est locale et hérite de l'authentification de la session desktop qui l'exécute. 0.1.4 n'introduit pas de mot de passe KSP maison, de biométrie, de keychain ni de secrets manager distant.

L'autorisation applicative retenue est donc :

  1. le reveal n'existe que dans une commande Tauri distincte ;
  2. la requête porte exactement le nom de variable et la source (effective ou .env) ;
  3. le frontend impose une confirmation utilisateur explicite juste avant l'appel ;
  4. le backend revérifie que le nom appartient bien aux namespaces KSP/KSPB et applique sa policy de reveal ;
  5. seule la méthode reveal_* Config est appelée ;
  6. la réponse n'est jamais conservée dans l'état backend ;
  7. aucun log, bridge frontend ou test Logging ne reçoit automatiquement la valeur.

Cette barrière n'est pas présentée comme une ré-authentification forte contre une webview déjà compromise. Une auth OS forte éventuelle est hors scope de 0.1.4 et devra être conçue séparément si le threat model futur l'exige.

11. Hot reload Logging : flux et preuve observable

11.1 Sauvegarde et application restent deux opérations

Flux :

éditer
-> sauver document via Config
-> choisir profil à appliquer
-> construire ConfigEnvironment frais
-> load_resolved_logging_config(Some(profile), env)
-> into_settings()
-> reinitialize(guard, settings)
-> succès : mise à jour metadata runtime
-> échec : runtime précédent inchangé

La sauvegarde ne doit pas déclencher implicitement un reload. Cela permet d'éditer plusieurs profils sans changer le runtime et rend les erreurs/rollback compréhensibles.

11.2 Événement de test interactif et séquence multi-niveaux

emit_logging_test reçoit uniquement les valeurs explicitement saisies/sélectionnées dans le panneau de test :

message
action level = trace | debug | info | warn | error | all
target_id
domain optionnel

Le backend valide target_id, choisit un callsite KSP fixe, puis émet via ksp-logging-lib. Le domain est ajouté comme champ structuré lorsqu'il est présent.

Chaque action reçoit un identifiant unique non sensible. En mode all, le backend émet la même intention de test aux cinq niveaux afin de tester le seuil de chacun des sinks.

Exemple de campagne manuelle :

message = "routing-test-42"
target  = ksp-app-config-desk.test.logging
domain  = logging.hot-reload
level   = all

La démonstration peut ainsi vérifier qu'après reload :

  • un sink apparaît/disparaît ;
  • un format change ;
  • un niveau/routing change ;
  • un target est accepté/refusé par un output ;
  • un domain est accepté/refusé par un output ;
  • la console reçoit ou non l'événement ;
  • un fichier distinct reçoit l'événement correspondant.

Le bridge technique frontend_log.ts est testé séparément avec au moins un événement frontend identifiable afin de prouver que les logs de la webview rejoignent le même runtime KSP sans seconde pile de logging.

11.3 Profil invalide

Test obligatoire :

runtime A valide actif
-> tentative apply B invalide
-> erreur
-> événement de test suivant toujours routé selon A

La réussite de ce scénario ferme le critère « une erreur de nouvelle configuration ne détruit pas le runtime Logging déjà valide ».

12. Matrice fonctionnelle de clôture Logging

La release ne peut pas être clôturée sans preuve des cas suivants :

Cas Action UI Résultat attendu
L1 créer un second profil profil ajouté via types Config et sauvegardable
L2 modifier le profil existant mutation persistée via save_logging_document()
L3 profil mono-fichier console optionnelle + exactement un sink fichier valide
L4 profil multi-fichiers au moins deux sinks fichier distincts + sortie logiciel/console
L5 sauvegarder sans appliquer source change, runtime reste inchangé
L6 sélectionner/appliquer profil load_resolved_logging_config + reinitialize réussissent
L7 message + niveau avant/après changement de routing/format/sink observable sans redémarrage
L8 changer target de test routing target observable selon la configuration active
L9 changer domain de test routing domain observable selon la configuration active
L10 mode tous seuils trace/debug/info/warn/error vérifiables en une campagne
L11 log frontend via bridge événement frontend identifiable rejoint le runtime KSP
L12 appliquer config invalide erreur visible, runtime précédent reste fonctionnel et le bouton Log le prouve
L13 redémarrer l'app profil/default persisté retrouvé selon le document sauvegardé
L14 modifier default profile nouveau default_profile validé/persisté par Config
L15 redémarrer plusieurs fois chaque lancement écrit dans un fichier applicatif distinct horodaté
L16 clôturer la release target applicatif ramené à info ou warn dans le profil de référence

La démonstration de clôture conservera deux profils de test reproductibles, sans dépendre de données secrètes.

13. Splashscreen commun

13.1 Décision de 0.1.4

0.1.4 établit la référence canonique du lifecycle splash KSP, mais ne crée pas prématurément une nouvelle crate ksp-tauri-lib avec un seul consumer.

Le splash sera isolé proprement :

backend : splash.rs + tw_splash.rs
frontend: splash.ts + splash.scss + splash.html

Les helpers ne sont pas recopiés entre fenêtres.

Lorsque la deuxième application Tauri KSP sera introduite, elle devra réutiliser/extracter cette capacité commune au lieu de copier le code. Si un deuxième consumer apparaît avant la clôture de 0.1.4, l'extraction en crate/module partagé pourra être avancée par delta explicite.

13.2 Configuration

Aucune durée sensible à l'environnement n'est codée en dur par application.

Le besoin runtime devra au minimum distinguer ce qui est réellement nécessaire, par exemple :

minimum display duration
fade duration
close delay si techniquement distinct

0.2.6-pre.014 aligne les deux Desks sur trois clés communes, en reprenant la séparation fonctionnelle du splash kbot3 :

KSP_DESK_SPLASH_FADE_IN_MS=300
KSP_DESK_SPLASH_MINIMUM_MS=1200
KSP_DESK_SPLASH_FADE_OUT_MS=300

Elles sont résolues uniquement via ConfigEnvironment avec priorité process > .env > fallback. KSP_DESK_SPLASH_MINIMUM_MS est bornée à 60 000 ms et chaque fade à 10 000 ms. Une valeur invalide ne rend pas Config Desk inutilisable : lapplication conserve les timings de fallback en mémoire et journalise seulement domaine/code de lerreur.

Le frontend reçoit uniquement les durées danimation nécessaires dans les ordres du splash; la durée minimale reste backend. Après readiness frontend, Rust émet fade_in, attend fade_in, maintient la splash pleinement visible pendant minimum, émet fade_out, attend fade_out, puis affiche/focalise main et détruit splash. Avec fade_in=3000, minimum=12000 et fade_out=3000, le lifecycle backend attendu est proche de 18000 ms. Le splash possède en outre le flux de messages généraux en bas et le flux diagnostic debug en haut repris du comportement kbot3.

13.3 Racine runtime en développement

Avec le workflow crate-local (cd crates/ksp-app-config-desk && cargo tauri dev), Tauri lance le projet applicatif attendu et le binaire Rust démarre avec la crate applicative comme current working directory. Les defaults Config config/, config/schemas/ et .env sont cependant des chemins de projet enracinés à la racine du workspace. En build debug, le launcher replace donc le CWD sur env!("CARGO_MANIFEST_DIR")/../.. avant le bootstrap Config. Il ne lit aucune ressource KSP lui-même ; ksp-config-lib continue à gérer paths, .env, precedence et validation. Un runtime distribué ne doit pas dépendre de cette racine source et sera cadré séparément.

13.4 Header et navigation

Le logo de Config Desk porte déjà lidentité graphique KSP. Le header ne répète donc pas KSP en texte : il suit Config Desk — <vue active>. Les cinq commandes principales utilisent désormais des pills verticales dans une sidebar du contenu principal, alignées avec Wallet Desk ; le header conserve uniquement l'identité fonctionnelle et le titre de la vue active. Les clics/changements de tabs sont tracés (trace pour le clic/état technique, debug pour lactivation utilisateur significative).

14. Présentation et Markdown

Décision explicite : aucune vue de présentation dans 0.1.4.

L'application est un manager monofenêtre avec navigation fonctionnelle. En conséquence :

PRESENTATION.md : absent
markdown-it     : absent

README.md reste la documentation du package et n'est jamais chargé dans une webview.

Si une future version ajoute réellement une vue de présentation, elle ouvrira alors le besoin PRESENTATION.md + markdown-it et appliquera la règle d'absence de liens navigables dans le contenu affiché.

15. Extensibilité des futurs file_id / schemas / éditeurs

L'extensibilité est structurée en trois niveaux.

15.1 Shell générique

Le shell sait :

  • demander à Config quels documents sont enregistrés ;
  • afficher leurs descripteurs ;
  • demander validation/diagnostic/source ;
  • afficher les diagnostics sans connaître le schema métier.

Il ne code pas la liste cfg.std.logging comme unique vérité du système.

15.2 Adapter d'éditeur spécialisé

Logging est le premier adapter spécialisé :

file_id = cfg.std.logging
editor = LoggingEditor

Le frontend possède une table/registry applicative simple d'éditeurs disponibles, basée sur file_id. Un futur document pourra ajouter :

file_id -> panel/editor spécialisé

sans modifier le moteur générique de liste/diagnostic/source.

15.3 Config reste propriétaire

Même avec un éditeur spécialisé :

DTO UI
-> service app
-> type public ksp-config-lib
-> validation/persistence ksp-config-lib

Aucun nouvel éditeur ne reçoit une API de filesystem directe ni ne transporte son propre validateur autoritatif.

15.4 Implémentation pre.018

Le shell applicatif matérialise désormais cette architecture dans frontend/ts/shell_registry.ts : les vues sont décrites dans un registre unique et les adapters spécialisés sont déclarés séparément par file_id. Le panneau Documents interroge ce registre pour afficher ou non Ouvrir l'éditeur spécialisé ; il ne contient aucune branche métier Logging. Le premier mapping est cfg.std.logging -> logging.

Le bootstrap Logging sépare également la résolution du plan de démarrage de l'installation du subscriber. Une source invalide peut ainsi être testée comme plan fallback sans initialiser le subscriber global du binaire de tests.

La convention desktop actuelle nexécute plus de script npm de contrôle/dev/build directement côté opérateur. Tauri possède le cycle applicatif et déclenche npm run dev / npm run build via ses hooks crate-local. Le build Tauri reste réservé à la dernière validation, après fmt/check/clippy, les tests et le parcours fonctionnel cargo tauri dev.

16. Stratégie de tests

16.1 ksp-config-lib

Pour les deux extensions révélées par l'audit :

  • unit tests hors src, structure miroir ;
  • tests de registre : ordre, kind, schema, override conservé ;
  • tests de réparation : JSON invalide refusé, schema invalide refusé, sémantique invalide refusée, source valide atomiquement persistée, path arbitraire impossible ;
  • test public d'usage depuis tests/ si le contrat public le justifie.

16.2 Rust applicatif

Tests ciblés :

  • conversion sûre ksp_core_lib::Error -> diagnostic DTO ;
  • aucune valeur de contexte sensible recopiée ;
  • mapping DTO Logging -> contrats Config ;
  • mapping rapports Environment -> DTO safe ;
  • mutations .env via services uniquement, sans accès filesystem applicatif ;
  • propagation de source_changed / effective_changed / shadowed / reload_required ;
  • AppState : metadata runtime ne change qu'après reload réussi ;
  • policy reveal ;
  • test Logging : validation niveau/target_id/domain, mapping vers callsites KSP fixes et mode multi-niveaux ;
  • frontend logging : normalisation des targets whitelistés et dispatch par niveau ;
  • splash settings : bornes et lifecycle ;
  • single-instance helper lorsque testable sans flakiness.

Pendant le développement :

cargo test -p ksp-config-lib
cargo test -p ksp-app-config-desk

selon la tranche.

16.3 Frontend

Le frontend reste suffisamment mince pour ne pas nécessiter dès le départ un framework de test lourd. Les validations minimum prévues :

  • tsc strict ;
  • build Vite uniquement via le beforeBuildCommand de la validation finale cargo tauri build ;
  • tests de fonctions pures TypeScript uniquement si une logique non triviale apparaît ;
  • parcours manuel reproductible du panneau .env (create/update/delete/reload/shadowing) ;
  • parcours manuel reproductible des panneaux et de la matrice Logging.

Si des fonctions UI critiques deviennent suffisamment complexes, un runner de tests sera ajouté seulement au moment du besoin réel.

16.4 Tauri / intégration

Les commandes sont testées principalement via leurs services Rust sans lancer une webview. Les points nécessitant Tauri réel sont validés par :

  • build Tauri ;
  • lancement tauri dev ;
  • splash -> main ;
  • single-instance ;
  • commandes invoke ;
  • mutations .env observables via rapport frais, sans accès fichier direct ;
  • démonstration du shadowing process > .env ;
  • démonstration d'une nouvelle résolution de ${KSP_LOGS_DIRECTORY:-logs} après mutation .env non shadowée ;
  • hot reload Logging observable ;
  • absence de crash après échec de reload.

16.5 Frontières globales

Après toute modification Rust :

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets

Les tests ciblés par package sont privilégiés pendant les tranches.

cargo test --workspace est obligatoire :

  • à l'ouverture globale si nécessaire pour confirmer la base ;
  • à la fermeture finale de 0.1.4 ;
  • lors d'une tranche transversale qui le justifie explicitement.

Les cargo tree pertinents seront exécutés après ajout/modification des dépendances Tauri/Config/Logging et à la clôture.

Côté frontend, les commandes de build/test retenues seront ajoutées au package.json et exécutées dans les tranches concernées.

17. Hors scope confirmé

0.1.4 n'ouvre pas :

  • Wallet ;
  • Store/PostgreSQL ;
  • RPC/WS/provider ;
  • Program/decoder/executor ;
  • workers/jobs/pipelines ;
  • trading/ML ;
  • nouveaux documents Config pour composants inexistants ;
  • watcher filesystem générique ;
  • service distribué de configuration ;
  • secrets manager distant ;
  • chiffrement maison de .env ;
  • auth biométrique/keychain ;
  • application de contrôle globale KSP ;
  • système générique de plugins UI dynamiques chargés à runtime ;
  • éditeur de JSON Schema ;
  • viewer de logs complet dans l'UI ;
  • nouvelle crate partagée Tauri sans deuxième consumer concret.

18. Prévision souple des prereleases

Chaque prerelease vise environ 1520 minutes de travail effectif. Cette prévision est volontairement souple : une tranche peut être scindée si elle dépasse nettement ce budget, fusionnée avec la suivante si elle se révèle triviale, ou réordonnée si une dépendance technique est découverte. Le numéro exact de la dernière prerelease n'est donc pas contractuel.

Découpage candidat :

pre.001  audit + brainstorming + plan détaillé

pre.002  Config — inventaire public du registre
         - API read-only des descripteurs
         - ordre déterministe
         - tests unitaires/publics
         - README/USAGE/TODO Config si nécessaire

pre.003  Config — réparation source candidate
         - API bornée par file_id
         - parse/schema/sémantique avant persistence
         - atomicité/no-write-on-error
         - tests + docs ciblés

pre.004  squelette Rust Tauri
         - membre workspace
         - Cargo lib+bin/build.rs
         - main.rs/lib.rs/tauri.rs minimaux
         - builder Tauri configuré par étapes courtes/réassignées, sans chaîne monolithique
         - tauri.conf/capabilities/icône
         - frontendDist externe contractuel
         - réservation 1430/1431 et convention des couples de ports desk
         - layout frontend/ts/bindings + frontend/sass fixé sans dépendances npm prématurées
         - single-instance

pre.005  squelette frontend/gabarit
         - package.json + Vite/TypeScript
         - npm utilisé pour la gestion des dépendances, cycle dev/build lancé par Tauri
         - build.outDir identique au frontendDist externe
         - port Vite 1430 strict + HMR 1431
         - SCSS/Bootstrap/Font Awesome
         - SimpleBar + resize-observer-polyfill comme socle du gabarit
         - @fltsci/tauri-plugin-tracing avec plugin Rust
         - main/splash HTML+TS minimaux
         - build frontend de base

pre.006  bootstrap backend + AppState
         - argv -> Config bootstrap/registry/management
         - initialisation Logging
         - fallback sûr si std.logging invalide
         - LoggingGuard durable
         - erreurs/DTO communs + premier get_app_snapshot TS-RS
         - inventaire/provenance de la police DOS_Amazigh du splash bot3

pre.007  frontend logging commun
         - frontend_log.ts repris/refondu depuis bot3
         - emit_frontend_log centralisé dans tauri.rs
         - targets frontend whitelistés
         - émission via ksp-logging-lib
         - intégration console plugin compatible seulement

pre.008  shell main + splash de référence
         - tw_splash + tw_main
         - lifecycle splash configurable
         - KSP_DESK_SPLASH_FADE_IN_MS / KSP_DESK_SPLASH_MINIMUM_MS / KSP_DESK_SPLASH_FADE_OUT_MS + .env.example
         - normalisation du CWD debug vers la racine workspace avant bootstrap Config
         - navigation monofenêtre + header `Config Desk — <vue>`
         - helpers show/focus/destroy
         - instrumentation debug/trace des interactions, tabs et timings splash

pre.009  Documents + diagnostics [réalisé]
         - inventaire générique par registre
         - catégories JSON/schema/sémantique/effective
         - source brut invalide
         - réparation via Config
         - DataTables 3 + Select 4 pour tri/filtre/pagination/sélection

pre.010  Profils + provenance [réalisé]
         - default_profile
         - sélection explicite
         - global/profile/effective
         - provenance sûre

pre.011  Environnement — rapports [réalisé]
         - desired/effective/source/shadow
         - sensibilité + safe values
         - table issue uniquement de Config
         - DataTables si tri/filtre/sélection/checkboxes sont requis à ce stade
         - refresh/reload du rapport

pre.012  Environnement — management/test .env [réalisé]
         - create/update via set_dotenv_value
         - remove via remove_dotenv_value
         - confirmation destructive via modal Bootstrap, sans dialogue natif window.confirm
         - résultats source/effective/shadow/reload
         - démonstration process > .env
         - démonstration placeholder KSP_LOGS_DIRECTORY

pre.013  Secrets privilégiés [réalisé]
         - DTO séparés
         - confirmation explicite
         - reveal transitoire
         - édition Secret sans préchargement réel
         - audits non-divulgation

pre.014  Logging editor — lecture/DTO [réalisé]
         - document/profils/console/files/filters
         - targets/domains
         - mapping types Config -> DTO

pre.015  Logging editor — mutations/persistence [réalisé]
         - create/clone/rename/delete profils
         - default_profile
         - mono-fichier/multi-fichiers
         - save_logging_document
         - Sauvegarder et appliquer = persistence + hot reload immédiat du profil default
         - Recharger le document = resynchronisation du brouillon uniquement
         - rollback source + ancien runtime conservé si lapplication échoue

pre.016  Logging runtime — compléments [réalisé]
         - fichiers applicatifs uniques par lancement avec timestamp de démarrage
         - sélection explicite du profil à appliquer indépendamment du default_profile
         - observabilité metadata/génération du runtime
         - consolidation des scénarios de rollback/runtime

pre.017  panneau Test Logging [réalisé]
         - champ message
         - niveau trace/debug/info/warn/error/tous
         - select target KSP contrôlé
         - domain absent/connu/personnalisé
         - bouton Log -> commande Tauri
         - preuve routing avant/après hot reload
         - preuve bridge frontend

pre.018  robustesse/extensibilité/tests desktop [réalisé]
         - invalid source au démarrage
         - audits secrets/Config ownership/tracing
         - tests frontend/Tauri/build
         - ajout futur file_id/editor sans refonte shell

pre.019  clôture [réalisé]
         - fmt/check/clippy
         - tests ciblés + cargo test --workspace
         - cargo tree pertinents
         - build frontend/Tauri
         - matrice fonctionnelle complète
         - README.md + USAGE.md finalisés
         - aucun PRESENTATION.md
         - TODO fermés/reportés
         - documentation/changelog/prompt suivant
         - préparation rel.001

Ce découpage est une prévision, pas une obligation de produire exactement dix-neuf prereleases. Lorsqu'une tranche atteint son objectif en moins de temps, elle peut absorber le début logique de la suivante ; lorsqu'elle dépasse 20 minutes de façon significative, elle doit préférentiellement être scindée plutôt que compressée. Un défaut déjà livré est corrigé par un fix conformément au workflow KSP.

18.1 État de clôture pre.019

La tranche finale remet la configuration Logging canonique à une baseline de release info/warn, retire le profil de test de la source de référence, ferme les TODO bloquants 0.1.4, crée une matrice de validation durable sous docs/validation/, et prépare le prompt douverture de 0.2.0-pre.001, release intermédiaire consacrée à laudit de khadhroony-bot3 et au découpage du reste de 0.2.x.

La validation finale a suivi KSP-APP-034 : tous les contrôles Rust et frontend, puis le parcours tauri dev, puis cargo tauri build en toute dernière opération. La matrice est validée et 0.1.4-rel.001 publie désormais la release stable.

18.2 Clôture stable rel.001

0.1.4 est clôturée et publiée comme release stable. ksp-app-config-desk valide les frontières Config/Logging/Tauri prévues par ce plan, la baseline Logging canonique est revenue à info/warn, les TODO non bloquants sont reportés explicitement, et le prochain point de reprise est 0.2.0-pre.001 via prompts/005-V0_2_0_START_PROMPT.md.

19. Dépendances et ordre d'introduction

Aucune dépendance n'est ajoutée par pre.001.

Ordre candidat :

Rust desktop

tauri
 tauri-build
tauri-plugin-tracing
fs2
ts-rs

serde / serde_json existent déjà dans le workspace et seront réutilisés si nécessaires aux DTO. Les dépendances Rust desktop destinées à être réutilisables par les futures applications (tauri, tauri-build, tauri-plugin-tracing, fs2, ts-rs) seront versionnées au Cargo.toml racine sous [workspace.dependencies] puis consommées avec .workspace = true ; aucune version externe partagée ne sera dupliquée dans la crate applicative.

tokio n'est pas automatiquement promu à full. Les features nécessaires au splash seront choisies au besoin réel. Aucun rustls direct n'est ajouté par symétrie avec bot3.

Frontend

dependencies :

@fltsci/tauri-plugin-tracing
@fortawesome/fontawesome-free
@tauri-apps/api
bootstrap
simplebar
resize-observer-polyfill

devDependencies :

@tauri-apps/cli
@types/bootstrap
@types/node
sass-embedded
typescript
vite

DataTables est ajouté à la première tranche qui introduit un tableau nécessitant tri/filtrage/sélection/checkboxes, avec le couple bot3 datatables.net-bs5 + datatables.net-select-bs5 comme référence à réauditer avant ajout. Il n'est pas ajouté au squelette vide uniquement par symétrie.

@types/node est requis par la configuration Vite TypeScript actuelle. Les autres paquets @types/* sont ajoutés uniquement lorsqu'une dépendance réellement utilisée en a besoin. ECharts, @andypf/json-viewer et les autres packages métier/démo bot3 restent exclus tant qu'une tranche n'en démontre pas l'usage immédiat.

La politique KSP sans lockfile versionné reste inchangée.

20. Critères de validation de la release

0.1.4 peut être considérée fonctionnellement complète seulement si tous les critères suivants sont vrais :

Architecture

  • la crate est directement sous crates/ ;
  • lib+bin séparés, main.rs mince, lib.rs déclaratif ;
  • run configure le tauri::Builder par étapes courtes/réassignées ou helpers ciblés, sans longue chaîne monolithique ;
  • toutes les commandes Tauri sont dans tauri.rs ;
  • services/modules métier hors wrappers ;
  • aucune lecture/écriture directe des fichiers Config/.env ;
  • aucune lecture std::env::var* pour KSP/KSPB hors Config ;
  • aucun tauri-plugin-log ;
  • aucun subscriber tracing parallèle ;
  • plugin tracing intégré sans with_default_subscriber() ;
  • package frontend compagnon @fltsci/tauri-plugin-tracing intégré avec le gabarit ;
  • bridge frontend_log.ts KSP présent, targets frontend contrôlés, aucune seconde pile log ;
  • Logging runtime possédé par ksp-logging-lib.

Documents/profils

  • documents enregistrés listés depuis Config ;
  • source invalide inspectable et réparable sans filesystem direct ;
  • erreurs JSON/schema/sémantiques/effective distinguées ;
  • default_profile et profils inspectables ;
  • source/global/profile/effective montrés lorsque pertinent.

Environnement / .env / secrets

  • panneau .env fonctionnel, pas seulement un affichage de diagnostics ;
  • rapports desired/effective/source/shadow issus de Config ;
  • création et modification .env via set_dotenv_value() ;
  • suppression .env via remove_dotenv_value() ;
  • résultat de mutation source_changed / effective_changed / shadowed / reload_required rendu observable ;
  • rapport rechargé depuis Config après mutation ;
  • priorité process > .env démontrée avec un cas de shadowing ;
  • impossibilité de modifier le process parent expliquée ;
  • résolution ${KSP_LOGS_DIRECTORY:-logs} redémontrée après une mutation .env non shadowée, sans résolution frontend ;
  • safe values par défaut ;
  • reveal séparé et explicite ;
  • une valeur Secret existante n'est pas préchargée automatiquement dans l'éditeur ;
  • aucune valeur Secret réelle dans logs/diagnostics/snapshot/state persistant.

Logging

  • plusieurs profils créables/modifiables ;
  • profil mono-fichier démontré ;
  • profil multi-fichiers + console démontré ;
  • sauvegarde fonctionnelle ;
  • profil sélectionnable/appliquable ;
  • hot reload observable sans redémarrage ;
  • panneau de test message + niveau + target + domain + Log fonctionnel ;
  • mode multi-niveaux permettant de tester les seuils ;
  • bridge frontend réellement observable dans le runtime KSP ;
  • échec reload laisse ancien runtime actif et le panneau de test le démontre.

Extensibilité

  • shell Documents non codé uniquement autour de Logging ;
  • registre Config reste source de vérité des file_id ;
  • Logging est un éditeur spécialisé branché sur un shell générique ;
  • ajout futur d'un file_id ne demande pas de réécrire bootstrap/diagnostics/persistence.

21. Documentation finale attendue

À la clôture :

crates/ksp-app-config-desk/README.md
crates/ksp-app-config-desk/USAGE.md

README.md décrit le rôle, l'architecture, les dépendances et les frontières de sécurité.

USAGE.md décrit :

  • lancement/arguments bootstrap ;
  • splash ;
  • fenêtre principale ;
  • panneau Documents ;
  • panneau Profils ;
  • panneau Environnement / .env ;
  • création/modification/suppression .env, reload et shadowing ;
  • reveal secrets ;
  • panneau Logging ;
  • sauvegarde/application ;
  • test Logging interactif/hot reload ;
  • bridge frontend Logging ;
  • diagnostics usuels.

Il n'y aura pas de PRESENTATION.md dans 0.1.4 tant qu'aucune vue de présentation n'existe.

22. Questions ouvertes volontairement reportées à leur tranche

Aucune question n'empêche d'ouvrir le développement après validation du présent plan. Les choix suivants seront figés au moment où l'implémentation fournit les contraintes réelles :

  1. nom public exact des deux petites extensions Config (descriptors/inventaire et sauvegarde de source candidate) ;
  2. nom exact et nombre minimal de variables splash Config/.env ;
  3. features Cargo minimales de Tauri/Tokio nécessaires au shell/splash ;
  4. détails du fallback Logging minimal utilisé uniquement lorsque la Config Logging ne peut pas être résolue au démarrage ;
  5. retour Rust -> console WebKit : étudié à la clôture pre.019 puis reporté hors 0.1.4. Le bridge WebView -> Rust -> KSP et le panneau Test Logging couvrent le besoin fonctionnel de cette release. Une future réflexion Rust -> WebKit devra rester sous ownership de ksp-logging-lib, sans second subscriber, double émission ni boucle avec le bridge console.*.

Ces points doivent être résolus par code/tests dans les prereleases prévues, pas par contournement applicatif.

Harmonisation desktop 0.2.6-pre.014

Le polish partagé avec Wallet Desk déplace les pills de navigation Config dans une sidebar verticale du contenu principal, tout en conservant la palette claire historique de Config Desk. Les quatre fichiers HTML des deux Desks utilisent les en-têtes normalisés file/version. Le splash reprend les flux kbot3 (messages généraux en bas, diagnostics debug en haut) avec trois timings Config-owned distincts KSP_DESK_SPLASH_FADE_IN_MS, KSP_DESK_SPLASH_MINIMUM_MS et KSP_DESK_SPLASH_FADE_OUT_MS.

Le même chantier corrige le lancement Tauri multi-app : chaque app est lancée depuis sa crate, car -c/--config est un overlay et non un sélecteur de backend.