45 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 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 :
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 ; - Font Awesome pour l'iconographie ;
- 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 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-iten 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 :
- 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://www.npmjs.com/package/@tauri-apps/api
- https://www.npmjs.com/package/@tauri-apps/cli
- 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 ;
- 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 du plugin ; - ne pas ajouter le package JS
@fltsci/tauri-plugin-tracingtant 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 deksp-logging-libavec 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 :
- 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.
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
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
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
Table sûre pour les variables présentes dans les rapports Config :
- nom ;
- namespace KSP/KSPB ;
- sensibilité ;
safe_valuedesired.env;safe_valueeffective ;- 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
?, 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
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 ;
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/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_*ouKSP_PUBLIC_*selon exposition ; - être lues uniquement via Config ;
- être ajoutées à
.env.exampleavec 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 :
tscstrict ;- 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 15–20 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.rsmince,lib.rsdé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_profileet profils inspectables ;- source/global/profile/effective montrés lorsque pertinent.
Environnement/secrets
- rapports desired/effective/source/shadow fonctionnels ;
- set/remove
.envvia 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_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 ;
- 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 :
- 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 ;
- possibilité d'exploiter une évolution future de
tauri-plugin-tracingpermettant 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.