v0.3.2-pre.009

This commit is contained in:
2026-08-29 22:00:20 +02:00
parent 80eea82398
commit 9ec4f26874
6 changed files with 753 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md -->
<!-- version: 10 -->
<!-- version: 11 -->
# Validation `0.3.2` — Store/PostgreSQL runtime foundation
@@ -78,6 +78,12 @@ Le gate opérateur de `pre.004-fix.001`, après correction manuelle des commenta
Le gate opérateur de `pre.005-fix.001`, fourni le 29 août 2026, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, 5 tests runtime backend, canaris de dépendances/API, façade avec et sans feature PostgreSQL et compilation `--no-default-features` passent. Cette base est l'entrée effective de `pre.006`.
Le gate opérateur de `pre.006`, fourni le 29 août 2026, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, 9 tests backend incluant la migration V000, façade avec et sans feature PostgreSQL, compilation `--no-default-features` et graphes Cargo passent.
Le gate opérateur de `pre.007`, fourni le 29 août 2026, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, 12 tests backend incluant health/readiness, façade avec et sans feature PostgreSQL, compilation `--no-default-features` et graphes Cargo passent.
Le gate `pre.008` du 29 août 2026 est doublement vert : le gate déterministe passe intégralement puis `postgres_foundation_live` passe sur **PostgreSQL 17**. La preuve réelle couvre bootstrap initial/idempotent/concurrent, mismatch/recovery checksum, rollback transactionnel, health `Ready`, fermeture bornée et cleanup de la metadata possédée par le test. Cette base est l'entrée effective de `pre.009`.
## 3. Frontières Cargo
### V32-DEP-001 — Façade -> API
@@ -110,7 +116,7 @@ Preuves : manifest scanner + cargo tree.
Le canari source de `pre.002` interdit explicitement la dépendance inverse ; le `cargo tree` opérateur confirme l'absence de cycle. La frontière sera durcie à nouveau en `pre.009`.
Statut : `PASS pre.002 opérateur / TODO pre.009 final`.
Statut : `PASS pre.002 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-DEP-004 — Feature PostgreSQL
@@ -140,7 +146,7 @@ consumer ordinaire -> ksp-store-postgres-lib
Matérialisé par `pre.005` : les types physiques nécessaires sont publics uniquement dans la crate backend pour la frontière inter-crates et ne sont jamais réexportés par `ksp-store-lib`; `Pool/Client/Row/Statement` restent absents de sa crate-root.
Statut : `PASS pre.005-fix.001 opérateur / TODO pre.009`.
Statut : `PASS pre.005-fix.001 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-DEP-006 — `ksp-store-api` non régressé
@@ -152,7 +158,7 @@ exports/capabilities existants conservés
aucun type backend ajouté pour PostgreSQL
```
Statut : `TODO gate final`, baseline `v0.3.1` déjà verte.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur puis gate final` — le canari backend externe de `ksp-store-api` est rejoué sans modification de la crate.
## 4. Public API et settings
@@ -170,7 +176,7 @@ Critère : `Postgres` reste un backend connu sans feature et `Store::open` écho
Matérialisé par `pre.003` : le test `feature_mismatch` appelle réellement `Store::open` sous `--no-default-features` et exige `store.backend_not_compiled`.
Statut : `PASS pre.003-fix.001 opérateur / TODO pre.009 final`.
Statut : `PASS pre.003-fix.001 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-API-003 — Aucun type backend physique public
@@ -183,7 +189,7 @@ rustls::*
PostgresBackend / Pool / Client / Row / Statement
```
Statut : `TODO pre.009`.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-API-004 — Réexports Store API
@@ -191,7 +197,7 @@ Critère : un consumer de `ksp-store-lib` accède aux contrats Store API utiles
`pre.003` réexporte explicitement les 60 symboles crate-root acquis de `ksp-store-api` depuis `ksp-store-lib`, sans glob et sans réexport backend.
Statut : `PASS pre.003-fix.001 opérateur / TODO pre.009 exact exports`.
Statut : `PASS pre.003-fix.001 opérateur / MATÉRIALISÉ pre.009 exact exports / TODO gate opérateur`.
### V32-API-005 — Lifecycle
@@ -275,7 +281,7 @@ PG*
`pre.004` renforce aussi le canari d'ownership avec les nouveaux filenames Store ; `pre.004-fix.001` conserve cette frontière tout en ajoutant le réseau au contrat `StoreSettings`. Store/backend restent sans dépendance Config et sans lecture KSP/KSPB.
Statut : `PASS pre.004-fix.001 opérateur / TODO pre.009`.
Statut : `PASS pre.004-fix.001 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-CONFIG-004 — Adapter Config -> Store
@@ -308,7 +314,7 @@ Critère : chaque connection future tokio-postgres est pilotée par le manager r
`pre.005` délègue la création/recycle des connexions au `Manager` Deadpool retenu ; aucun `tokio::spawn` KSP n'est introduit dans Store. La preuve de non-régression détaillée reste au hardening.
Statut : `PASS pre.005-fix.001 opérateur / TODO pre.009`.
Statut : `PASS pre.005-fix.001 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-POOL-003 — Open failure safe
@@ -331,7 +337,7 @@ aucune tâche volontairement laissée orpheline
`pre.005` matérialise déjà `Pool::close()` et un drain borné par `shutdown_timeout`; `Drop` ne fait qu'un `close()` best-effort. La preuve end-to-end avec backend réel reste réservée à `pre.007/pre.008`.
Statut : `PASS pre.005-fix.001 opérateur / PASS pre.007 opérateur / TODO exécution live pre.008`.
Statut : `PASS pre.005-fix.001 opérateur / PASS pre.007 opérateur / PASS live pre.008 PostgreSQL 17`.
## 7. TLS
@@ -368,7 +374,7 @@ Statut : `PASS pre.005-fix.001 opérateur`.
Critère : backend ne lit pas `sslrootcert`, `sslcert`, `sslkey`, `.postgresql/*` ou autre fichier implicite hors settings KSP.
Statut : `TODO pre.009`.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur`.
## 8. Migration/bootstrap
@@ -384,7 +390,7 @@ et aucune table métier RAW/CORE/DECODE/SPECIALIZED.
`pre.006` embarque exactement `migrations/V000__bootstrap.sql`, dont le seul DDL de production crée `ksp_store_schema_migrations`. Le canari source interdit les identifiants métier RAW/CORE/DECODE/SPECIALIZED dans le moteur et la ressource SQL.
Statut : `PASS pre.006 opérateur / MATÉRIALISÉ pre.008 / TODO exécution live opérateur`.
Statut : `PASS pre.006 opérateur / PASS live pre.008 PostgreSQL 17`.
### V32-MIG-002 — Version/checksum
@@ -400,7 +406,7 @@ mismatch historique terminal
`pre.006` calcule explicitement SHA-256 sur les octets exacts du SQL embarqué puis encode les 32 octets en 64 caractères hex minuscules. Le sentinel `(0, bootstrap, checksum)` est inséré dans la même transaction que la création metadata. Les tests unitaires figent le checksum du SQL committed et couvrent sentinel valide, missing, nom/checksum divergents et historique plus récent.
Statut : `PASS pre.006 opérateur / MATÉRIALISÉ pre.008 / TODO exécution live opérateur`.
Statut : `PASS pre.006 opérateur / PASS live pre.008 PostgreSQL 17`.
### V32-MIG-003 — Concurrence
@@ -408,7 +414,7 @@ Critère : deux runners concurrents sont sérialisés par advisory transaction l
`pre.006` utilise une clé KSP fixe et `pg_try_advisory_xact_lock($1)` dans une boucle bornée par `migration_lock_timeout`, avec polling de 25 ms maximum. Aucun lock bloquant illimité n'est utilisé.
Statut : `PASS pre.006 opérateur / MATÉRIALISÉ pre.008 / TODO concurrence live opérateur`.
Statut : `PASS pre.006 opérateur / PASS concurrence live pre.008 PostgreSQL 17`.
### V32-MIG-004 — Atomicité/recovery
@@ -416,7 +422,7 @@ Critère : échec d'une migration du run courant rollback DDL + history de ce ru
`pre.006` place lock, metadata DDL, sentinel et validation dans une transaction unique ; toute sortie d'erreur avant `commit()` droppe la transaction et PostgreSQL rollback le run courant. Un timeout externe borne également l'ensemble du bootstrap. L'injection d'échec et la preuve physique du rollback restent au smoke réel.
Statut : `PASS pre.006 opérateur / MATÉRIALISÉ pre.008 / TODO rollback live opérateur`.
Statut : `PASS pre.006 opérateur / PASS rollback live pre.008 PostgreSQL 17`.
### V32-MIG-005 — Newer runtime guard
@@ -438,7 +444,7 @@ aucun identifier physique user-configurable en 0.3.2
`pre.006` garde le DDL versionné sous `include_str!` et toutes les values variables des requêtes de contrôle (`lock key`, `statement_timeout`, history values) passent par paramètres. Les noms physiques sont des constantes KSP, jamais des settings.
Statut : `PASS pre.006 opérateur / TODO pre.009 hardening`.
Statut : `PASS pre.006 opérateur / MATÉRIALISÉ pre.009 hardening / TODO gate opérateur`.
### V32-MIG-007 — No business capability
@@ -450,7 +456,7 @@ Critères :
0 repository RAW métier
```
Statut : `TODO pre.009/gate final`.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur puis gate final`.
## 9. Health/readiness
@@ -468,7 +474,7 @@ Critère : `Store::open` ne retourne Ready qu'après connect + bootstrap/verify
`pre.007` conserve l'ouverture stricte acquise en `pre.006` et ajoute un probe borné par le `wait_timeout` du pool : acquisition, `SELECT 1`, lecture de version migration. Le smoke réel reste nécessaire pour prouver ce chemin contre PostgreSQL.
Statut : `PASS pre.007 opérateur / TODO exécution live pre.008`.
Statut : `PASS pre.007 opérateur / PASS live pre.008 PostgreSQL 17`.
### V32-HEALTH-003 — Error redaction
@@ -476,7 +482,7 @@ Critère : un health failure n'expose pas server error string, query text ou cre
Le backend ne conserve que `PostgresBackendErrorKind`; la façade mappe vers un `ErrorCode` KSP optionnel. Le snapshot public ne contient aucune string serveur, URI, SQL, host, user, database ou handle.
Statut : `PASS pre.007 opérateur / TODO pre.009 hardening`.
Statut : `PASS pre.007 opérateur / MATÉRIALISÉ pre.009 hardening / TODO gate opérateur`.
## 10. PostgreSQL integration réelle
@@ -493,7 +499,7 @@ URI jamais imprimée par le test
`pre.008` ajoute `tests/postgres_foundation_live.rs`. Le test borne l'entrée à 4096 octets, ne conserve dans ses erreurs que des phases statiques et ne rend jamais l'erreur PostgreSQL brute. L'opérateur peut masquer la saisie côté shell puis piper une seule ligne sur stdin ; aucune variable d'environnement n'est lue par le test.
Statut : `MATÉRIALISÉ pre.008 / TODO exécution live opérateur`.
Statut : `PASS live pre.008 PostgreSQL 17`.
### V32-LIVE-002 — Non destructif
@@ -508,7 +514,7 @@ cleanup seulement de metadata créée par le test
Le test interroge `information_schema.tables` avant toute mutation. Il ne prend ownership du cleanup qu'après avoir prouvé que le bootstrap initial a créé la metadata alors que la précondition était absente. Les seuls `DROP` exécutés ciblent `ksp_store_schema_migrations` pendant les resets contrôlés et le cleanup final.
Statut : `MATÉRIALISÉ pre.008 / TODO exécution live opérateur`.
Statut : `PASS live pre.008 PostgreSQL 17`.
### V32-LIVE-003 — Scénario foundation
@@ -528,15 +534,15 @@ cleanup metadata
La preuve rollback évite tout hook public de test : une transaction `tokio-postgres` de test exécute le V000 exact par `include_str!`, insère un sentinel transitoire, provoque ensuite une erreur SQL puis est droppée. Le test vérifie que la metadata n'existe pas après le rollback implicite et que le bootstrap KSP normal peut repartir proprement.
Statut : `MATÉRIALISÉ pre.008 / TODO exécution live opérateur puis revalidation pre.010`.
Statut : `PASS live pre.008 PostgreSQL 17 / TODO revalidation pre.010`.
### V32-LIVE-004 — PostgreSQL support
Critère : test refuse major < 15 et enregistre seulement le major safe réellement testé.
Cible release : PostgreSQL 18.6. `pre.008` interroge uniquement `SHOW server_version_num`, dérive le major et n'imprime aucune identité de serveur.
Cible release : PostgreSQL 18.6. `pre.008` interroge uniquement `SHOW server_version_num`, dérive le major et n'imprime aucune identité de serveur. Le gate opérateur réel a été exécuté avec succès sur PostgreSQL 17.
Statut : `MATÉRIALISÉ pre.008 / TODO exécution live opérateur puis revalidation pre.010`.
Statut : `PASS live pre.008 PostgreSQL 17 / TODO revalidation pre.010`.
## 11. Security/adversarial
@@ -546,7 +552,9 @@ Cas : vide, surdimensionnée, malformed, paramètres conflictuels, password cont
Attendu : rejet borné sans echo.
Statut : `TODO pre.009`.
`pre.009` ajoute un test d'intégration backend qui force avant I/O : URI malformed, URI > 4096 octets, `hostaddr` sans identité sous `VerifyFull` et `options=` libpq. Chaque cas contient un canary secret et exige une erreur `ConfigInvalid` avec phase statique seulement.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-SEC-002 — Secret canary
@@ -560,7 +568,9 @@ tracing snapshots
health snapshots
```
Statut : `TODO pre.009`.
`pre.009` injecte des canaris distincts dans la façade et le backend. Les settings Debug doivent afficher `<redacted>`; les erreurs pré-I/O publiques/backend ne doivent contenir aucun canary. Les snapshots health restent couverts par les canaris déterministes de `pre.007`.
Statut : `MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-SEC-003 — Timeouts hostiles
@@ -568,21 +578,46 @@ Cas : zéro, inversion, dépassement bornes pour pool/connect/migration/close.
Les bornes backend-neutral décidées en `pre.001` sont matérialisées et couvertes par tests unitaires en `pre.003`. `pre.005` applique physiquement `connect/wait/create/recycle/shutdown`; `pre.006` applique physiquement `migration_timeout` et `migration_lock_timeout`.
Statut : `PASS pre.003-fix.001 opérateur` pour les bornes backend-neutral / `PASS pre.005-fix.001 opérateur` pour pool/connect/shutdown / `PASS pre.006 opérateur` pour migration / `TODO pre.009` hardening.
Statut : `PASS pre.003-fix.001 opérateur` pour les bornes backend-neutral / `PASS pre.005-fix.001 opérateur` pour pool/connect/shutdown / `PASS pre.006 opérateur` pour migration / `MATÉRIALISÉ pre.009` hardening / `TODO gate opérateur`.
### V32-SEC-004 — Feature mismatch avant I/O
`pre.003` matérialise un canari d'intégration compilé avec et sans `postgres`. Sans feature, `Store::open` retourne le code stable `store.backend_not_compiled` avant tout chemin backend physique.
Statut : `PASS pre.003-fix.001 opérateur / TODO pre.009`.
Statut : `PASS pre.003-fix.001 opérateur / MATÉRIALISÉ pre.009 / TODO gate opérateur`.
### V32-SEC-005 — Server error sanitization
Un serveur/test double qui renvoie un message contenant un canary ne doit pas le faire traverser l'erreur publique.
Statut : bridge de sanitization matérialisé en `pre.005`; `TODO pre.009` pour le canary serveur hostile.
Statut : bridge de sanitization matérialisé en `pre.005`; `pre.009` ajoute un canari structurel prouvant que `PostgresBackendError` ne peut retenir que `kind + phase` statiques et que `PoolError::Backend(_)` abandonne le texte remote. `TODO gate opérateur`.
## 12. Gates Rust/workspace
## 12. Hardening/completeness `pre.009`
Deux nouveaux canaris d'intégration figent sans modifier la production :
```text
crates/ksp-store-lib/tests/hardening_completeness.rs
crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
```
Ils couvrent :
```text
84 exports façade exacts / 5 modules privés exacts
7 exports backend exacts / 5 modules privés exacts
manifests et feature postgres exacts
URI hostiles et canaris secrets avant I/O
sanitization structurelle des erreurs serveur/pool
no-env / no-.pgpass / no-libpq-TLS-files
aucune capability PostgreSQL RawTransaction/RawAccount
V000 metadata-only
compatibilité backend externe ksp-store-api rejouée au gate
```
Statut global `pre.009` : `MATÉRIALISÉ / TODO gate opérateur`.
## 13. Gates Rust/workspace
À chaque tranche applicable :
@@ -629,7 +664,7 @@ Les builds Tauri ne sont requis que si `pre.004` modifie réellement les resourc
Statut global : `TODO` jusqu'aux preuves de chaque tranche.
## 13. Critères de fermeture
## 14. Critères de fermeture
La matrice ne peut passer en finale que si tous les critères applicables sont `PASS` et que :