71 KiB
Plan 0.1.4 — ksp-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 :
ConfigBootstrapOptionspour--cfgpath/--schemapath;ConfigFileRegistry,ConfigFileId,ConfigFileDescriptoret--filemap;ConfigDocumentEngine;- validation JSON, JSON Schema et sémantique ;
- globals, profils,
default_profileet provenance ; - composites génériques par
file_id; ConfigEnvironmentavec 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 :
file_iddoit être connu et de kindConfig;- le texte candidat est parsé par Config ;
- le document est validé contre le schema enregistré ;
- les invariants sémantiques Config sont exécutés ;
- rien n'est écrit si une étape échoue ;
- si tout est valide, Config sérialise/persiste atomiquement le document normalisé ;
- 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.rscentralisantrunet les wrappers#[tauri::command];- logique métier/fenêtre hors des wrappers ;
- fenêtre
splashdistincte de la fenêtremain; - 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épertoirefrontend/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-polyfillcomme 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 ;
LoggingGuardgardé 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-iten 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 :
- https://crates.io/crates/tauri
- https://crates.io/crates/tauri-build
- https://crates.io/crates/tauri-plugin-tracing
- https://crates.io/crates/ts-rs
- https://crates.io/crates/fs2
- https://github.com/fltsci/tauri-plugin-tracing
- https://github.com/fltsci/tauri-plugin-tracing/blob/main/package.json
- https://www.npmjs.com/package/@tauri-apps/api
- https://www.npmjs.com/package/@tauri-apps/cli
- https://www.npmjs.com/package/@types/bootstrap
- https://www.npmjs.com/package/vite
- https://www.npmjs.com/package/typescript
- https://www.npmjs.com/package/sass-embedded
- https://www.npmjs.com/package/bootstrap
- https://www.npmjs.com/package/@fortawesome/fontawesome-free
- https://docs.rs/tauri-plugin-tracing/0.3.4/tauri_plugin_tracing/
- https://github.com/fltsci/tauri-plugin-tracing/blob/tracing-v0.3.4/src/commands.rs
- https://v2.tauri.app/start/create-project/
- https://vite.dev/guide/
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-tracingdans le gabarit desktop au même moment ; - ne pas utiliser
with_default_subscriber(); - ne pas installer une seconde pile
tracing-subscriberdans l'application ; - ne pas détendre la politique
ksp-*deksp-logging-libuniquement pour faire passer le target vide de la commande JS standard du plugin ; - reprendre/refondre le pont
frontend_loggingde bot3 : helpers TypeScript -> commande Tauri dédiée -> service Rust -> façadeksp-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 (
attachConsoleou 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 unetauri_plugin_tracing::WebviewLayerintégrée au subscriber possédé parksp-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 deksp-logging-libavec un target KSP contrôlé et undomainstructuré 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 :
- construire/acquérir le verrou single-instance ;
- collecter les arguments de processus nécessaires au bootstrap ;
- appeler l'entrée
run(...)de la bibliothèque ; - 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 :
ConfigManagementreste la façade de management ;- son
ConfigDocumentEngineporte bootstrap + registry ; ConfigEnvironment::load()produit un snapshot frais lorsqu'une résolution runtime doit refléter le process/.envcourant ;LoggingGuardvit 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
Configissus 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_profileou 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_valuepersisté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
.envbrut 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
ConfigEnvironmentChangeReportest 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
?, niunwrap, niexpect, nipanic; - 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 ;
ConfigDiagnosticDtocontient 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 :
- le reveal n'existe que dans une commande Tauri distincte ;
- la requête porte exactement le nom de variable et la source (
effectiveou.env) ; - le frontend impose une confirmation utilisateur explicite juste avant l'appel ;
- le backend revérifie que le nom appartient bien aux namespaces KSP/KSPB et applique sa policy de reveal ;
- seule la méthode
reveal_*Config est appelée ; - la réponse n'est jamais conservée dans l'état backend ;
- 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 : l’application conserve les timings de fallback en mémoire et journalise seulement domaine/code de l’erreur.
Le frontend reçoit uniquement les durées d’animation 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à l’identité 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 l’activation 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 n’exé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
.envvia 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 :
tscstrict ;- build Vite uniquement via le
beforeBuildCommandde la validation finalecargo 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
.envobservables 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.envnon 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 15–20 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 l’application é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 d’ouverture de 0.2.0-pre.001, release intermédiaire consacrée à l’audit 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.rsmince,lib.rsdéclaratif ; runconfigure letauri::Builderpar é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-tracingintégré avec le gabarit ; - bridge
frontend_log.tsKSP présent, targets frontend contrôlés, aucune seconde pilelog; - 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_profileet profils inspectables ;- source/global/profile/effective montrés lorsque pertinent.
Environnement / .env / secrets
- panneau
.envfonctionnel, pas seulement un affichage de diagnostics ; - rapports desired/effective/source/shadow issus de Config ;
- création et modification
.envviaset_dotenv_value(); - suppression
.envviaremove_dotenv_value(); - résultat de mutation
source_changed/effective_changed/shadowed/reload_requiredrendu observable ; - rapport rechargé depuis Config après mutation ;
- priorité process >
.envdé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.envnon 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 + Logfonctionnel ; - 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_idne 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 :
- nom public exact des deux petites extensions Config (
descriptors/inventaire et sauvegarde de source candidate) ; - nom exact et nombre minimal de variables splash Config/.env ;
- features Cargo minimales de Tauri/Tokio nécessaires au shell/splash ;
- détails du fallback Logging minimal utilisé uniquement lorsque la Config Logging ne peut pas être résolue au démarrage ;
- retour Rust -> console WebKit : étudié à la clôture
pre.019puis reporté hors0.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 deksp-logging-lib, sans second subscriber, double émission ni boucle avec le bridgeconsole.*.
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.