v0.1.3-pre.015
This commit is contained in:
184
crates/ksp-config-lib/USAGE.md
Normal file
184
crates/ksp-config-lib/USAGE.md
Normal file
@@ -0,0 +1,184 @@
|
||||
<!-- file: crates/ksp-config-lib/USAGE.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Utilisation de ksp-config-lib
|
||||
|
||||
## 1. Bootstrap et moteur documentaire
|
||||
|
||||
Config doit interpréter ses propres arguments de bootstrap avant toute lecture de document :
|
||||
|
||||
```rust
|
||||
let args: std::vec::Vec<std::ffi::OsString> = std::env::args_os().collect();
|
||||
|
||||
let bootstrap = match ksp_config_lib::ConfigBootstrapOptions::from_args(args.as_slice()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let registry = match ksp_config_lib::ConfigFileRegistry::from_args(args.as_slice()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let engine = ksp_config_lib::ConfigDocumentEngine::new(bootstrap, registry);
|
||||
```
|
||||
|
||||
Les arguments compris par Config sont :
|
||||
|
||||
```text
|
||||
--cfgpath=/path/to/config
|
||||
--schemapath=/path/to/schemas
|
||||
--filemap=cfg.std.logging=my-logging.json
|
||||
```
|
||||
|
||||
`cfgpath` et `schemapath` ne sont jamais lus depuis JSON, `.env` ou une variable KSP : cette règle évite un bootstrap récursif.
|
||||
|
||||
## 2. Charger et valider un document connu
|
||||
|
||||
Les consumers utilisent un `file_id` logique :
|
||||
|
||||
```rust
|
||||
let file_id = match ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_STD_LOGGING) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let document = engine.load_validated_document(&file_id);
|
||||
```
|
||||
|
||||
Le moteur résout le path physique via le registre, charge le schema associé, valide le schema lui-même, valide l'instance puis applique les invariants sémantiques KSP.
|
||||
|
||||
## 3. Environnement effectif
|
||||
|
||||
`ConfigEnvironment::load()` capture les variables process KSP/KSPB et lit `./.env` :
|
||||
|
||||
```rust
|
||||
let environment = match ksp_config_lib::ConfigEnvironment::load() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
```
|
||||
|
||||
La priorité est :
|
||||
|
||||
```text
|
||||
process environment > .env > fallback > missing
|
||||
```
|
||||
|
||||
Une chaîne vide explicitement présente est une valeur définie ; elle ne provoque pas l'utilisation du fallback.
|
||||
|
||||
Exemples de placeholders :
|
||||
|
||||
```text
|
||||
${KSP_LOGS_DIRECTORY}
|
||||
${KSP_LOGS_DIRECTORY:-logs}
|
||||
```
|
||||
|
||||
Pour conserver la sensibilité et la provenance, préférer les variantes détaillées :
|
||||
|
||||
```rust
|
||||
let resolved = environment.resolve_text_detailed("${KSP_SECRET_EXAMPLE}");
|
||||
```
|
||||
|
||||
`ResolvedConfigText` / `ResolvedConfigJson` séparent valeur réelle et valeur sûre. Une représentation `Debug` ne doit pas révéler le réel d'un secret.
|
||||
|
||||
## 4. Construire Logging depuis Config
|
||||
|
||||
Le chemin normal consiste à charger le profil Logging, résoudre l'environnement puis construire directement le contrat Logging public :
|
||||
|
||||
```rust
|
||||
let resolved = match engine.load_resolved_logging_config(std::option::Option::None, &environment) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let settings = resolved.into_settings();
|
||||
let initialized = ksp_logging_lib::initialize(&settings);
|
||||
let mut logging_guard = match initialized {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
```
|
||||
|
||||
L'application/service possède `logging_guard`. Config ne conserve pas de singleton Logging.
|
||||
|
||||
Un `logs_directory` relatif est ancré sur le current working directory du processus. Un path absolu est conservé. Une valeur explicite invalide produit une erreur effective : elle ne retombe pas silencieusement sur le fallback du placeholder.
|
||||
|
||||
Les `files[].path` restent relatifs sous le root Logging, y compris après interpolation.
|
||||
|
||||
## 5. Profils et composites
|
||||
|
||||
Pour un document standard profilé :
|
||||
|
||||
```rust
|
||||
let profile = engine.load_resolved_profile(&file_id, std::option::Option::None);
|
||||
```
|
||||
|
||||
`None` utilise le `default_profile`; `Some("profile_id")` impose un profil explicite.
|
||||
|
||||
Un composite référence les documents par `file_id`, jamais par filename. `load_resolved_composite(...)` conserve chaque `ResolvedConfigProfile` composant et sa provenance plutôt que d'aplatir plusieurs domaines dans une map ambiguë.
|
||||
|
||||
## 6. Management de `std.logging.json`
|
||||
|
||||
Une application de management construit la façade à partir d'un moteur :
|
||||
|
||||
```rust
|
||||
let management = ksp_config_lib::ConfigManagement::new(engine);
|
||||
|
||||
let document = match management.load_logging_document() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
```
|
||||
|
||||
Le type `LoggingConfigDocument` et ses sous-structures exposent des setters/mutators typés. Après modification, la sauvegarde :
|
||||
|
||||
```rust
|
||||
let saved = management.save_logging_document(&document);
|
||||
```
|
||||
|
||||
valide le candidat complet avant toute substitution du fichier. Un candidat invalide ne remplace pas la source existante.
|
||||
|
||||
`read_source(file_id)` reste disponible pour une UI de réparation : il peut lire le texte brut d'un document enregistré même lorsque son JSON ou son schema est invalide. Il n'ouvre pas un path arbitraire.
|
||||
|
||||
## 7. Management de `.env`
|
||||
|
||||
Les rapports ordinaires sont sûrs :
|
||||
|
||||
```rust
|
||||
let report = management.environment_report();
|
||||
```
|
||||
|
||||
Ils distinguent notamment valeur souhaitée `.env`, valeur effective, source et shadowing process sans exposer un secret réel.
|
||||
|
||||
L'accès au réel est volontairement explicite :
|
||||
|
||||
```rust
|
||||
let effective = management.reveal_effective_environment_value("KSP_SECRET_EXAMPLE");
|
||||
let persisted = management.reveal_dotenv_value("KSP_SECRET_EXAMPLE");
|
||||
```
|
||||
|
||||
Une application doit contrôler l'autorisation de l'utilisateur avant ces appels et ne jamais journaliser les valeurs retournées.
|
||||
|
||||
Les mutations persistantes utilisent :
|
||||
|
||||
```rust
|
||||
let changed = management.set_dotenv_value("KSP_LOGS_DIRECTORY", "logs");
|
||||
let removed = management.remove_dotenv_value("KSP_LOGS_DIRECTORY");
|
||||
```
|
||||
|
||||
Elles n'altèrent jamais l'environnement hérité du processus. Une valeur process peut donc masquer une modification `.env`; `ConfigEnvironmentChangeReport` distingue `source_changed`, `effective_changed`, `shadowed_by_process_environment` et `reload_required`.
|
||||
|
||||
Sur Unix, un nouveau `.env` est créé avec des permissions privées `0600`; les permissions existantes sont préservées lors des remplacements atomiques.
|
||||
|
||||
## 8. `.env.example`
|
||||
|
||||
`/.env.example` est l'inventaire versionné. `/.env` reste local et ignoré.
|
||||
|
||||
Toute nouvelle variable runtime concrète `KSP_*` / `KSPB_*` introduite dans le code ou les documents Config doit être ajoutée à `.env.example` avec un commentaire expliquant son usage. Les audits `ksp-config-lib/tests/ownership.rs` font échouer `cargo test` lorsqu'une clé concrète est oubliée.
|
||||
|
||||
## 9. Frontière Tauri
|
||||
|
||||
Une application Tauri doit appeler les APIs ci-dessus via ses commandes/DTO applicatifs. Elle ne lit ni JSON ni `.env` directement et ne résout jamais elle-même les placeholders.
|
||||
|
||||
Les valeurs `Secret` ne doivent pas être incluses par défaut dans les DTO publics. Une action UI explicitement autorisée peut appeler une méthode `reveal_*` et transporter le résultat par un DTO spécifique, sans log ni diagnostic contenant la valeur réelle.
|
||||
Reference in New Issue
Block a user