Files
khadhroony-solana-project/deltas/0.1.3/pre.013.md
2026-08-16 06:04:06 +02:00

349 lines
9.7 KiB
Markdown

<!-- file: deltas/0.1.3/pre.013.md -->
<!-- version: 1 -->
# Delta 0.1.3-pre.013
## Base requise
Livraison précédente validée :
```text
0.1.3-pre.012
```
Version technique de cette base :
```text
workspace.package.version = "0.1.3-pre.12"
Cargo.toml header version = 56
```
Validations utilisateur exécutées le 2026-08-16 :
```text
cargo fmt --all OK
cargo check --workspace OK
cargo clippy --workspace --all-targets OK
cargo test --workspace OK
cargo tree -p ksp-config-lib OK
cargo tree -p ksp-config-lib -d OK, doublon transitif syn 2/3 déjà connu
cargo tree -p ksp-config-lib -e features OK
cargo tree -p ksp-logging-lib -d OK, aucun doublon
```
`cargo test --workspace` confirme notamment 70 tests unitaires + 10 tests publics pour `ksp-config-lib` et 34 tests unitaires Logging avec toutes ses intégrations vertes.
## Objet de pre.013
Fermer la première surface de management/persistence Config sans introduire Tauri ni permettre aux applications de contourner `ksp-config-lib` :
```text
registered file_id
-> management source read
-> typed std.logging mutation
-> candidate validation
-> atomic persistence
process env (read-only) + .env (read/write)
-> desired/effective/shadow report
-> explicit reveal when UI management intentionally needs the real value
```
## `ConfigManagement`
Nouveau contrat public :
```text
ConfigManagement
```
Il possède un `ConfigDocumentEngine` et utilise par défaut le `.env` conventionnel :
```text
./.env
```
Il n'ajoute aucun path runtime Config supplémentaire et ne modifie jamais l'environnement hérité du processus.
L'authentification/autorisation de l'utilisateur final reste une responsabilité de la future application `ksp-app-config-desk`. Config fournit une frontière explicite qui évite l'exposition accidentelle mais ne prétend pas être un système d'authentification intra-processus.
## Lecture management
`ConfigManagement::read_source(file_id)` lit le texte brut d'un document **Config enregistré** par son `file_id`.
Cette lecture :
- ne prend jamais un path arbitraire fourni par le caller ;
- refuse un `file_id` de kind Schema ;
- reste possible lorsque le document est syntaxiquement/schema/sémantiquement invalide, afin qu'une UI de management puisse afficher et corriger sa source ;
- retourne `ConfigManagedSource`, dont `Debug` n'expose pas le contenu brut.
Aucune primitive publique générique « save raw JSON to path » n'est ajoutée.
## Mutation typée de `std.logging.json`
Nouveaux contrats source publics :
```text
LoggingConfigDocument
LoggingProfileConfig
LoggingConsoleConfig
LoggingFileConfig
LoggingOutputFilterConfig
LoggingTargetFilterConfig
```
Ils représentent la forme source de `cfg.std.logging` et permettent une mutation structurée en mémoire.
La persistance suit obligatoirement :
```text
LoggingConfigDocument
-> serde_json candidate
-> registered std.logging schema
-> KSP profile/logging semantic invariants
-> pretty JSON + newline final
-> atomic commit
```
Un candidate invalide retourne l'erreur de validation existante et ne touche pas au fichier destination.
`ConfigDocumentEngine` reçoit uniquement un helper interne `validate_candidate(...)`; la validation reste possédée par Config et n'est pas dupliquée dans la couche management.
## Persistence atomique
Nouveau module privé :
```text
src/persistence.rs
```
Stratégie :
1. créer un fichier temporaire avec `create_new` dans le même répertoire que la destination ;
2. appliquer les permissions requises ;
3. écrire tout le contenu ;
4. `sync_all` le fichier temporaire ;
5. fermer le handle ;
6. remplacer la destination par `rename` ;
7. nettoyer le temporaire si une étape pré-commit échoue.
La destination reste donc l'ancien fichier complet jusqu'au commit final.
Les permissions du fichier existant sont conservées. Sur Unix, un nouveau `.env` créé par Config reçoit explicitement :
```text
0600
```
Les documents JSON ne reçoivent pas artificiellement ce mode privé ; un fichier existant conserve son mode.
Nouveau code d'erreur :
```text
config.persistence_write_failed
```
## Management du `.env`
Nouvelles opérations :
```text
set_dotenv_value(name, value)
remove_dotenv_value(name)
reveal_dotenv_value(name)
reveal_effective_environment_value(name)
environment_report()
```
Mutation autorisée uniquement pour les namespaces déjà possédés par Config :
```text
KSP_*
KSPB_*
```
Une mutation ne touche jamais `std::env::set_var/remove_var` et ne prétend donc jamais modifier le shell parent, systemd, Docker/Kubernetes ou l'environnement déjà hérité du processus.
Avant mutation, le `.env` existant doit être interprétable par la grammaire Config actuelle. Un `.env` invalide est refusé sans altération.
L'éditeur ciblé :
- conserve les lignes/commentaires non concernés ;
- remplace uniquement l'assignment ciblé ;
- encode les valeurs nécessitant espaces, `#`, quotes, backslash ou contrôles avec la forme double-quoted déjà comprise par Config ;
- normalise un fichier modifié avec newline final ;
- ne réécrit pas un assignment si la valeur persistée est déjà identique ;
- ne crée pas le fichier lors d'un remove d'une clé absente.
## Desired / effective / shadow
`ConfigEnvironmentReport` n'embarque aucune valeur réelle secrète.
Il expose :
```text
variable_name
sensitivity
desired_safe_value # valeur .env persistée
effective_safe_value # process sinon .env
effective_source
shadowed_by_process_environment
```
Une entrée `.env` est `desired`; la valeur héritée du process reste prioritaire et peut donc la shadow.
`ConfigEnvironmentChangeReport` expose après create/update/remove :
```text
source_changed
effective_changed
shadowed_by_process_environment
reload_required
```
Si le process shadow une modification `.env`, `source_changed = true` mais `effective_changed = false` et `reload_required = false` pour le processus courant.
## Reveal explicite et secrets
Les rapports management ordinaires utilisent la représentation sûre :
```text
KSP_SECRET_* / KSPB_SECRET_* -> ********
```
La valeur réelle n'est accessible qu'en appelant explicitement :
```text
reveal_dotenv_value(...)
reveal_effective_environment_value(...)
```
Ces méthodes sont destinées à une surface UI management légitimement autorisée. Elles ne changent pas les règles suivantes :
- jamais de secret réel dans `Debug` ;
- jamais de secret réel dans les logs ;
- jamais de secret réel dans les diagnostics génériques ;
- l'application reste propriétaire de l'autorisation utilisateur.
## Règles durables
Ajout de :
```text
KSP-CONFIG-014
KSP-CONFIG-015
KSP-CONFIG-016
```
pour figer respectivement :
- la persistence validée/atomique bornée aux ressources Config connues ;
- la distinction process read-only / `.env` read-write et le reporting shadow ;
- la séparation report sûr / reveal explicite des valeurs sensibles.
`FILE_CONTRACTS.md` documente également la stratégie de persistence, le newline JSON, la preservation des permissions et le mode `0600` d'un nouveau `.env` sur Unix.
## `.env.example`
Aucune nouvelle variable runtime n'est introduite par cette tranche.
`.env.example` reste donc inchangé :
```text
KSP_LOGS_DIRECTORY=logs
```
Les variables utilisées uniquement comme canaries/tests ne font pas partie de l'inventaire runtime.
## Dépendances
Aucune nouvelle dépendance Cargo.
La direction reste :
```text
ksp-config-lib -> ksp-core-lib
ksp-config-lib -> ksp-logging-lib
ksp-logging-lib -X-> ksp-config-lib
```
## Tests ajoutés
Le nouveau module `unit_tests/management.rs` ajoute 10 tests couvrant notamment :
- lecture raw d'un source schema-invalide ;
- mutation typée + persistance + reload de `std.logging.json` ;
- candidate Logging invalide sans altération du fichier ;
- save identique sans reload ;
- create/update/remove `.env` ;
- quoting et preservation de commentaires/lignes externes ;
- `.env` invalide non modifié ;
- namespace externe refusé sans création de `.env` ;
- report secret redacted + reveal explicite du canary ;
- process shadowing desired `.env` sans faux changement effectif ;
- mode `0600` du nouveau `.env` sur Unix.
La surface publique ajoute un test d'adressabilité des contrats management.
Après ajout, `ksp-config-lib` doit compter :
```text
80 tests unitaires
11 tests publics
```
à exécuter chez l'utilisateur.
## Fichiers ajoutés
```text
crates/ksp-config-lib/src/management.rs
crates/ksp-config-lib/src/persistence.rs
crates/ksp-config-lib/unit_tests/management.rs
deltas/0.1.3/pre.013.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-config-lib/src/document.rs
crates/ksp-config-lib/src/environment.rs
crates/ksp-config-lib/src/error.rs
crates/ksp-config-lib/src/lib.rs
crates/ksp-config-lib/tests/public_api.rs
docs/rules/RULES_KSP.md
docs/rules/FILE_CONTRACTS.md
docs/plans/000-README.md
docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md
```
## Hors scope
Toujours hors `pre.013` :
- application desktop Config/Tauri ;
- watcher automatique de fichiers ;
- rechargement automatique du runtime après save ;
- mutation générique de documents arbitraires ;
- management d'un environnement parent/systemd/container ;
- autres documents standard Store/Wallet/Transport ;
- audit global empêchant tous les futurs contournements Config hors crate, prévu en `pre.014`.
## Validation demandée
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
cargo tree -p ksp-config-lib
cargo tree -p ksp-config-lib -d
cargo tree -p ksp-config-lib -e features
cargo tree -p ksp-logging-lib -d
```
Aucune validation Cargo locale n'est revendiquée dans l'environnement de génération de ce delta.