Files
2026-08-16 06:04:06 +02:00

9.7 KiB

Delta 0.1.3-pre.013

Base requise

Livraison précédente validée :

0.1.3-pre.012

Version technique de cette base :

workspace.package.version = "0.1.3-pre.12"
Cargo.toml header version = 56

Validations utilisateur exécutées le 2026-08-16 :

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 :

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 :

ConfigManagement

Il possède un ConfigDocumentEngine et utilise par défaut le .env conventionnel :

./.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 :

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 :

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

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 :

0600

Les documents JSON ne reçoivent pas artificiellement ce mode privé ; un fichier existant conserve son mode.

Nouveau code d'erreur :

config.persistence_write_failed

Management du .env

Nouvelles opérations :

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 :

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 :

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 :

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 :

KSP_SECRET_* / KSPB_SECRET_* -> ********

La valeur réelle n'est accessible qu'en appelant explicitement :

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 :

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

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 :

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 :

80 tests unitaires
11 tests publics

à exécuter chez l'utilisateur.

Fichiers ajoutés

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

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

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.