Files
khadhroony-solana-project/deltas/0.1.4/pre.003.md
2026-08-16 10:21:15 +02:00

241 lines
9.5 KiB
Markdown

<!-- file: deltas/0.1.4/pre.003.md -->
<!-- version: 1 -->
# Delta 0.1.4-pre.003 — réparation validée d'un source Config
## Base requise
```text
0.1.4-pre.002
workspace.package.version = "0.1.4-pre.2"
```
`pre.002` est considéré comme validé et commité après exécution locale de `cargo fmt`, `cargo check`, Clippy, des tests ciblés `ksp-config-lib` et de `cargo tree -p ksp-config-lib`.
## Objectif
Fermer la seconde lacune `ksp-config-lib` identifiée pendant `pre.001` avant la construction de `ksp-app-config-desk` : permettre à une application de management de corriger le texte brut d'un document Config invalide sans obtenir d'accès filesystem direct ni reproduire le parsing, la validation JSON Schema ou les invariants sémantiques de Config.
Cette tranche reste bornée à la persistence d'un **document de kind Config déjà enregistré dans `ConfigFileRegistry`**. Les schemas restent read-only depuis cette surface et aucun path arbitraire n'est accepté.
## Version Cargo
Conformément à `VER-ID-009`, `workspace.package.version` passe de :
```text
0.1.4-pre.2
```
à :
```text
0.1.4-pre.3
```
L'identifiant de livraison est :
```text
0.1.4-pre.003
```
## 1. API publique de réparation
`ConfigManagement` expose désormais :
```rust
pub fn save_source_candidate(
&self,
file_id: &ConfigFileId,
source: &str,
) -> ksp_core_lib::Result<ConfigDocumentChangeReport>
```
Le workflow est :
```text
file_id enregistré de kind Config
-> résolution du path par ConfigFileRegistry
-> parsing JSON du texte candidat
-> validation du schema enregistré
-> validation des invariants sémantiques KSP
-> comparaison aux octets existants
-> persistence atomique uniquement si le candidat est valide et différent
```
L'appelant ne fournit jamais de path physique.
Un `file_id` inconnu est rejeté par le registre. Un `file_id` de kind `Schema` est rejeté par la façade de management. Cette surface ne constitue donc pas une primitive de write générique.
## 2. Conservation du source brut
Contrairement à `save_logging_document()`, qui sérialise volontairement son contrat typé en JSON pretty-printé, `save_source_candidate()` persiste le **texte brut validé exactement tel qu'il a été soumis**.
Cette différence est intentionnelle : le workflow Documents de Config Desk doit pouvoir afficher un fichier invalide, laisser l'opérateur corriger son source, puis le sauvegarder sans reformattage implicite supplémentaire.
Le candidat reste néanmoins interprété et validé par `ksp-config-lib`; la conservation du formatting ne déplace aucune autorité de validation vers l'UI.
## 3. Validation du candidat dans le moteur documentaire
`ConfigDocumentEngine` possède maintenant une petite primitive interne `validate_source_candidate()` qui :
- résout le path logique nécessaire aux diagnostics ;
- parse le texte via `serde_json` ;
- produit le même `ERROR_CODE_JSON_SYNTAX_INVALID` que la lecture documentaire normale ;
- délègue ensuite à la validation candidate existante pour le schema et les invariants sémantiques.
Cette fonction reste `pub(crate)` : la surface publique de mutation est `ConfigManagement`, pas le moteur brut.
## 4. Persistence partagée
La comparaison du source existant et l'appel à `persistence::atomic_write()` sont regroupés dans un helper privé de management commun à :
- `save_source_candidate()` ;
- `save_logging_document()`.
Le contrat existant de la sauvegarde Logging ne change pas : elle continue de pretty-printer et d'ajouter un newline final avant d'utiliser la même étape de persistence.
`ConfigDocumentChangeReport` conserve sa sémantique :
- source identique -> `source_changed = false`, `reload_required = false` ;
- source validé et remplacé -> `source_changed = true`, `reload_required = true`.
## 5. No-write-on-error
Les tests couvrent séparément les échecs avant persistence :
- JSON syntaxiquement invalide -> `ERROR_CODE_JSON_SYNTAX_INVALID` ;
- document ne satisfaisant pas le schema -> `ERROR_CODE_SCHEMA_VALIDATION_FAILED` ;
- document schema-valid mais sémantiquement invalide -> `ERROR_CODE_DOCUMENT_SEMANTIC_INVALID`.
Dans les trois cas, les octets du fichier existant sont comparés avant/après et doivent rester strictement identiques.
Un test de réparation part d'un fichier physiquement corrompu puis soumet un candidat valide. La sauvegarde doit réussir, conserver exactement le texte candidat et rendre le document de nouveau chargeable via `load_logging_document()`.
## 6. Bornage par registre
Les tests vérifient également :
- refus d'un `schema.std.logging` par `ERROR_CODE_MANAGEMENT_OPERATION_INVALID` ;
- refus d'un `cfg.not.registered` par `ERROR_CODE_FILE_ID_UNKNOWN` ;
- absence de création d'un fichier dérivé du texte du `file_id` inconnu.
La signature publique ne contient aucun `Path`/`PathBuf`, ce qui maintient l'ownership du mapping physique dans `ConfigFileRegistry`.
## 7. Surface publique
`tests/public_api.rs` compile la signature de `ConfigManagement::save_source_candidate()` depuis la racine de crate avec :
- `ConfigManagement` ;
- `ConfigFileId` ;
- `ConfigDocumentChangeReport`.
Aucun nouveau DTO ou type public n'est nécessaire.
## 8. Documentation Config
`README.md` documente maintenant la paire :
```text
read_source()
-> inspection brute même si invalide
save_source_candidate()
-> parse + schema + sémantique + persistence atomique
```
`USAGE.md` ajoute le workflow version-neutral de réparation et précise la différence entre source brut et sauvegarde Logging typée.
`TODO.md` marque les deux extensions Config préalables au desktop comme traitées :
- inventaire du registre par `pre.002` ;
- réparation validée du source par `pre.003`.
## Hors scope confirmé
Cette tranche n'ajoute pas :
- `ksp-app-config-desk` ;
- Tauri ou dépendance frontend ;
- DTO TS-RS ;
- édition de schemas ;
- JSON Patch générique ;
- path physique fourni par l'appelant ;
- nouveau document Config/schema ;
- variable `.env` ;
- watcher filesystem ;
- reload runtime Logging.
## Fichiers ajoutés
```text
deltas/0.1.4/pre.003.md
```
## Fichiers modifiés
| Fichier | Version précédente | Nouvelle version |
| ---------------------------------------------- | ------------------: | ---------------: |
| `Cargo.toml` | 63 | 64 |
| `crates/ksp-config-lib/src/document.rs` | 4 | 5 |
| `crates/ksp-config-lib/src/management.rs` | 1 | 2 |
| `crates/ksp-config-lib/unit_tests/management.rs` | 1 | 2 |
| `crates/ksp-config-lib/tests/public_api.rs` | 11 | 12 |
| `crates/ksp-config-lib/README.md` | 2 | 3 |
| `crates/ksp-config-lib/USAGE.md` | 3 | 4 |
| `crates/ksp-config-lib/TODO.md` | 2 | 3 |
## Fichiers supprimés
Aucun.
## Validations exécutées dans l'environnement de préparation
- contrôle statique du diff et du périmètre `pre.003` ;
- vérification de `workspace.package.version = "0.1.4-pre.3"` ;
- vérification des headers `file:` / `version:` des fichiers modifiés ;
- vérification de la limite KSP de 160 colonnes sur les fichiers Rust modifiés ;
- vérification de l'absence d'ajout de dépendance ;
- vérification que l'API publique n'accepte aucun path physique ;
- vérification des cas de tests JSON/schema/sémantique/no-write, réparation valide et bornage `file_id` ;
- vérification syntaxique TOML avec le parseur disponible ;
- contrôle des fences Markdown et des espaces de fin de ligne des fichiers livrés.
## Validations à exécuter localement
Le sandbox de préparation ne fournit pas les binaires Rust/Cargo. Avant validation/commit de `pre.003`, exécuter :
```text
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-config-lib
cargo tree -p ksp-config-lib
```
`cargo test --workspace` n'est pas requis pour cette tranche ciblée ; il reste réservé aux frontières globales prévues par le plan de `0.1.4`.
## Résultat attendu des nouveaux tests
Par rapport à `pre.002`, cette tranche ajoute cinq tests unitaires de management :
1. réparation/persistence exacte d'un candidat valide ;
2. rejet syntaxique sans write ;
3. rejet schema sans write ;
4. rejet sémantique sans write ;
5. refus des `file_id` schema/inconnus comme cible de persistence Config.
Le nombre exact affiché par `cargo test` doit être relevé lors de la validation locale plutôt que codé comme invariant documentaire.
## Décisions prises
- le nom public retenu est `ConfigManagement::save_source_candidate()` ;
- la mutation est générique par `file_id`, mais uniquement pour les documents de kind `Config` déjà enregistrés ;
- le source brut validé est conservé tel quel ;
- les sauvegardes typées spécialisées, comme Logging, peuvent conserver leur propre normalisation ;
- schema et invariants sémantiques restent entièrement propriétaires de `ksp-config-lib` ;
- aucune surface de write de schema ou de filesystem arbitraire n'est introduite.
## Suite
Après validation et commit de `pre.003`, les deux prérequis Config révélés par `pre.001` sont fermés. La tranche suivante prévue par le plan est `0.1.4-pre.004` : **squelette Rust Tauri de `ksp-app-config-desk`**, package mixte `lib` + `bin`, frontière `tauri.rs`, single-instance et builder construit par étapes courtes.