Files
khadhroony-solana-project/docs/plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md
2026-08-16 08:52:09 +02:00

45 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 ne contient pas de métadonnées .git. Le tag Git v0.1.3 ne peut donc pas être revérifié matériellement depuis cette archive seule ; la livraison stable fournie est prise comme base de session, conformément au prérequis utilisateur de publication/tag validés.

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 ;
  • Font Awesome pour l'iconographie ;
  • 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 aussi @fltsci/tauri-plugin-tracing sans l'importer. KSP ne reprend pas une dépendance frontend inutilisée par simple symétrie.

Les dépendances propres aux nombreuses démos bot3 ne sont pas retenues pour Config Desk :

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

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

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.

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
@tauri-apps/api 2.11.1 frontend Tauri
@tauri-apps/cli 2.11.4 dev/build desktop
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 ;
  • 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 du plugin ;
  • ne pas ajouter le package JS @fltsci/tauri-plugin-tracing tant qu'un adapter réellement fonctionnel et conforme aux targets KSP n'est pas défini ;
  • 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é ;
  • enregistrer cette incompatibilité comme point à revérifier si une nouvelle version du plugin permet un target frontend namespacé ou si KSP introduit plus tard une extension explicitement conçue de Logging.

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
│   │   ├── state.ts
│   │   └── bindings/             # généré, ignoré
│   └── scss/
│       ├── 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.

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
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 probe Logging.

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

Table sûre pour les variables présentes dans les rapports Config :

  • nom ;
  • namespace KSP/KSPB ;
  • sensibilité ;
  • safe_value desired .env ;
  • safe_value effective ;
  • source effective process/.env ;
  • indicateur shadowed ;
  • actions créer/modifier/supprimer .env ;
  • action privilégiée « Révéler » séparée.

Après une mutation .env, l'UI affiche explicitement :

source modifiée ?
valeur effective modifiée ?
shadowed par process ?

Elle ne prétend jamais modifier l'environnement du parent/process déjà hérité.

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'un probe contrôlé.

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é.

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 entrée potentiellement Secret, jamais loggée
remove_dotenv_value environment_service ConfigManagement::remove_dotenv_value 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
run_logging_probe logging_service macros/façade ksp-logging-lib non, payload fixé
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
EnvironmentMutationResultDto
LoggingDocumentDto
LoggingProfileDto
LoggingConsoleDto
LoggingFileDto
LoggingFilterDto
LoggingRuntimeDto
LoggingProbeResultDto

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/probe ne reçoit 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 Probe contrôlé

run_logging_probe ne reçoit pas un message de log libre contenant potentiellement un secret. Il émet une petite séquence contrôlée, avec un identifiant unique non sensible retourné à l'UI, par exemple :

INFO  target=ksp-app-config-desk.probe domain=config-desk
DEBUG target=ksp-app-config-desk.probe domain=config-desk
WARN  target=ksp-app-config-desk.probe domain=config-desk

L'UI affiche l'identifiant du probe et rappelle les sinks attendus. La démonstration manuelle peut ainsi vérifier qu'après reload :

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

11.3 Profil invalide

Test obligatoire :

runtime A valide actif
-> tentative apply B invalide
-> erreur
-> probe 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 probe avant/après changement de routing/format/sink observable sans redémarrage
L8 appliquer config invalide erreur visible, runtime précédent reste fonctionnel
L9 redémarrer l'app profil/default persisté retrouvé selon le document sauvegardé
L10 modifier default profile nouveau default_profile validé/persisté par Config

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

La ou les clés Config/.env exactes ne sont pas figées dans pre.001, conformément à la règle qui demande de les nommer lors de leur première utilisation concrète. Elles devront :

  • utiliser KSP_* ou KSP_PUBLIC_* selon exposition ;
  • être lues uniquement via Config ;
  • être ajoutées à .env.example avec commentaire dans le même delta ;
  • posséder fallback et bornes de validation ;
  • être transmises au frontend uniquement si celui-ci a réellement besoin de la valeur.

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.

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 ;
  • AppState : metadata runtime ne change qu'après reload réussi ;
  • policy reveal ;
  • probe : payload fixe ;
  • 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 ;
  • tests de fonctions pures TypeScript uniquement si une logique non triviale apparaît ;
  • 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 ;
  • 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 tranche vise environ 1520 minutes de travail effectif. Cette prévision est un ordre de travail, pas un plafond contractuel.

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

pre.002  compléter ksp-config-lib pour Config Desk
         - vue publique du registre
         - réparation source validée/atomique par file_id
         - tests + docs Config ciblés

pre.003  créer ksp-app-config-desk
         - membre workspace
         - Cargo lib+bin/build.rs
         - package frontend/Vite/TS/SCSS minimal
         - tauri.conf/capabilities/icône de base
         - single-instance
         - plugin tracing Rust sans subscriber propre

pre.004  bootstrap backend + AppState
         - argv -> bootstrap/registry/engine/management
         - initialisation Logging
         - fallback sûr si Logging source invalide
         - LoggingGuard durable
         - erreurs/DTO communs

pre.005  shell main + splash de référence
         - lifecycle splash
         - timing via Config/.env
         - .env.example dans le même delta
         - navigation monofenêtre
         - gabarit SCSS/Bootstrap/Font Awesome

pre.006  Documents + diagnostics
         - inventaire générique
         - catégories d'erreurs
         - source brut invalide
         - réparation via Config

pre.007  Profils + provenance
         - default_profile
         - sélection explicite
         - global/profile/effective/provenance sûre

pre.008  Environnement
         - rapports desired/effective/shadow
         - set/remove .env
         - messages process shadowing

pre.009  Secrets privilégiés
         - DTO séparés
         - UX confirmation/reveal transitoire
         - audits non-divulgation

pre.010  Logging editor — contrats
         - DTO typés
         - profils/console/files/filters
         - mapping vers types management Config

pre.011  Logging editor — opérations/persistence
         - create/clone/rename/delete profils
         - default_profile
         - mono-fichier/multi-fichiers
         - save_logging_document

pre.012  Logging runtime
         - sélection profil à appliquer
         - ConfigEnvironment frais
         - reinitialize
         - metadata runtime transactionnelle
         - probe contrôlé

pre.013  matrice fonctionnelle Logging
         - cas mono-fichier
         - cas multi-fichiers + console
         - save sans apply
         - hot reload observable
         - reload invalide -> ancien runtime conservé

pre.014  robustesse desktop/extensibilité
         - diagnostics invalid source au démarrage
         - audits secrets/Config ownership/tracing
         - tests frontend/Tauri/build
         - vérification ajout futur file_id/editor

pre.015  clôture
         - fmt/check/clippy
         - tests package + cargo test --workspace
         - cargo tree pertinents
         - build frontend/Tauri
         - README.md + USAGE.md finalisés
         - aucun PRESENTATION.md
         - TODO fermés/reportés
         - documentation/changelog/prompt suivant
         - préparation rel.001

Une tranche qui dépasse clairement le budget sera scindée plutôt que comprimée. Un défaut livré est corrigé par un fix conformément au workflow KSP.

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

@tauri-apps/api
@tauri-apps/cli
vite
typescript
sass-embedded
bootstrap
@fortawesome/fontawesome-free

@types/node ne sera ajouté que si la configuration Vite TypeScript en a réellement besoin. Les autres packages bot3 sont 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 ;
  • 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() ;
  • 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/secrets

  • rapports desired/effective/source/shadow fonctionnels ;
  • set/remove .env via Config ;
  • shadow process expliqué ;
  • safe values par défaut ;
  • reveal séparé et explicite ;
  • 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 ;
  • probe contrôlé ;
  • échec reload laisse ancien runtime actif.

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 ;
  • reveal secrets ;
  • panneau Logging ;
  • sauvegarde/application ;
  • probe/hot reload ;
  • 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. possibilité d'exploiter une évolution future de tauri-plugin-tracing permettant un target JS namespacé ksp-* sans affaiblir Logging.

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