# Validation `0.3.2` — Store/PostgreSQL runtime foundation ## 1. Objet Cette matrice est ouverte par `0.3.2-pre.001`. Elle fixe les critères de preuve de la fondation Store/PostgreSQL sans préjuger des résultats non encore exécutés. Statuts : ```text TODO preuve requise non encore exécutée PASS preuve réellement exécutée et verte FAIL preuve exécutée et en échec N/A non applicable avec justification ``` Aucun `TODO` n'est présenté comme validé. ## 2. Base et audit `pre.001` ### V32-BASE-001 — Base stable Critère : ```text workspace.package.version = 0.3.1 sur l'archive source deltas/0.3.1/rel.001.md présent prompt 021 présent ksp-store-api présent ksp-store-lib absent ksp-store-postgres-lib absent ``` Statut : `PASS` au gate documentaire `pre.001`. Note : metadata Git absente de l'archive ; le tag `v0.3.1` n'est pas interrogé localement. ### V32-AUDIT-001 — Sources internes Critère : règles, architecture, plan/validation `0.3.1`, source/tests `ksp-store-api`, CHANGELOG et ROADMAP relus avant design. Statut : `PASS` au gate documentaire `pre.001`. ### V32-AUDIT-002 — Archive kbot3 Critère : ancien Store/config/PostgreSQL/migrations/health/pool/erreurs relus et classés reprendre/redessiner/reporter/rejeter. Statut : `PASS` au gate documentaire `pre.001`. ### V32-AUDIT-003 — Audit externe actuel Critère : PostgreSQL, tokio-postgres, pool, TLS et helper migrations réaudités avec sources actuelles. Statut : `PASS` au gate documentaire `pre.001`. Référence du gate : ```text PostgreSQL 18.6 tokio-postgres 0.7.18 deadpool-postgres 0.14.2 tokio-postgres-rustls 0.14.0 sha2 0.11.0 refinery 0.9.2 audité/rejeté ``` Le gate opérateur après application de `pre.001`, fourni le 29 août 2026, est vert : audits Rust/Markdown, `cargo check --workspace` et `cargo clippy --workspace --all-targets` passent sur `0.3.2-pre.1`. Le gate opérateur de `pre.002`, fourni le 29 août 2026, confirme également les tests ciblés, `--no-default-features` et les `cargo tree`. `cargo check`/Clippy terminent avec succès mais signalent deux warnings par nouvelle crate (`TRACING_TARGET` importé mais inutilisé et constant `dead_code`) ; `pre.002-fix.001` traite cet écart par un canari compile-time privé, tout en conservant les invariants KSP-TRACE-102/103 et sans ajouter de logging runtime. Le gate opérateur de `pre.002-fix.001`, fourni le 29 août 2026, est entièrement vert et sans warning : audits Rust/Markdown, workspace check/Clippy, tests des deux crates et compilation `ksp-store-lib --no-default-features` passent. Cette base est l'entrée effective de `pre.003`. Le gate opérateur de `pre.003-fix.001`, fourni le 29 août 2026, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, tests `ksp-store-lib` avec et sans feature par défaut, tests backend et compilation `--no-default-features` passent. Cette base est l'entrée effective de `pre.004`. Le gate opérateur de `pre.004-fix.001`, après correction manuelle des commentaires `.env.example`, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, 126 tests `ksp-config-lib`, ownership, `ksp-store-lib` avec et sans feature PostgreSQL, compilation `--no-default-features` et 63 tests Config Desk passent. Cette base est l'entrée effective de `pre.005`. 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`. Le gate opérateur de `pre.009`, fourni le 29 août 2026, est entièrement vert : audits Rust/Markdown, workspace check/Clippy, `ksp-store-api`, backend PostgreSQL, façade avec et sans feature, Config, compilation `--no-default-features`, graphes/features/duplicates et `cargo test --workspace` passent. Les canaris hardening/completeness ajoutés par `pre.009` sont donc validés. Cette base est l'entrée effective de `pre.010`. ## 3. Frontières Cargo ### V32-DEP-001 — Façade -> API ```text ksp-store-lib -> ksp-store-api ``` Matérialisé par `0.3.2-pre.002` dans le manifest de `ksp-store-lib`. Statut : `PASS pre.002 opérateur` — test ciblé et `cargo tree` fournis. ### V32-DEP-002 — Backend -> API ```text ksp-store-postgres-lib -> ksp-store-api ``` Matérialisé par `0.3.2-pre.002` dans le manifest de `ksp-store-postgres-lib`. Statut : `PASS pre.002 opérateur` — test ciblé et `cargo tree` fournis. ### V32-DEP-003 — Pas de cycle backend ```text ksp-store-postgres-lib -X-> ksp-store-lib ``` 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 / PASS pre.009 opérateur`. ### V32-DEP-004 — Feature PostgreSQL Critères : ```text postgres est default feature de ksp-store-lib ksp-store-postgres-lib est optional dependency cargo check -p ksp-store-lib --no-default-features passe ``` Le manifest de `ksp-store-lib` matérialise `default = ["postgres"]` et l'optional dependency `ksp-store-postgres-lib`. La compilation sans default feature est une preuve opérateur obligatoire. Statut : `PASS pre.002 opérateur` — default feature, optional backend edge et compilation `--no-default-features` confirmés. ### V32-DEP-005 — Firewall domaines Interdictions : ```text Store/backend -> Config Store/backend -> Transport Store/backend -> Program Store/backend -> Materializer 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 / PASS pre.009 opérateur`. ### V32-DEP-006 — `ksp-store-api` non régressé Critères : ```text dépendance runtime exacte ksp-core-lib seulement exports/capabilities existants conservés aucun type backend ajouté pour PostgreSQL ``` Statut : `PASS pre.009 opérateur / TODO revalidation pre.010` — le canari backend externe de `ksp-store-api` est rejoué sans modification de la crate. ## 4. Public API et settings ### V32-API-001 — Settings Config-independent Critère : `StoreSettings` est constructible sans `ksp-config-lib`, sans env et sans serde requis par la façade. Matérialisé par `pre.003` : `StoreSettings`, `StoreBackendSettings`, `PostgresStoreSettings`, pool/bootstrap/TLS typés, sans dépendance Config/serde/env. Statut : `PASS pre.003-fix.001 opérateur`. ### V32-API-002 — Backend connu non compilé Critère : `Postgres` reste un backend connu sans feature et `Store::open` échoue avant I/O avec un code stable. 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 / PASS pre.009 opérateur`. ### V32-API-003 — Aucun type backend physique public Interdits dans crate-root `ksp-store-lib` : ```text tokio_postgres::* deadpool_postgres::* rustls::* PostgresBackend / Pool / Client / Row / Statement ``` Statut : `PASS pre.009 opérateur`. ### V32-API-004 — Réexports Store API Critère : un consumer de `ksp-store-lib` accède aux contrats Store API utiles sans dépendre directement de la crate backend. `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 / PASS pre.009 opérateur exact exports`. ### V32-API-005 — Lifecycle Critères : ```text Store::open async Store::close(self) async pas de pool/client échappé close borné Drop best-effort seulement ``` `pre.003` fixe les signatures `Store::open(settings).await` et `Store::close(self).await`. `pre.005` remplace le stop de staging PostgreSQL par l'ouverture physique : un succès exige `pool.get().await` après construction du pool, puis `close(self)` ferme et draine ce pool sous la deadline configurée. Aucun pool/client n'est exposé par la façade. Statut : `PASS pre.003-fix.001 opérateur` pour les signatures / `PASS pre.005-fix.001 opérateur` pour l'ouverture et le shutdown physiques / `PASS pre.007 opérateur` pour la composition health. ## 5. Config ownership ### V32-CONFIG-001 — Document/schema/example Critères : ```text std.store enregistré schema V1 valide example valide profiles/targets nommés typés un réseau explicite par target backend postgres explicite ``` Matérialisé par `pre.004` puis corrigé par `pre.004-fix.001` avec `cfg.std.store` / `schema.std.store`, trois targets committed `devnet`/`mainnet`/`testnet`, `default_profile = devnet`, un `network` explicite par target et des URI PostgreSQL séparées. Statut : `PASS pre.004-fix.001 opérateur`. ### V32-CONFIG-002 — Secrets/provenance Critères : ```text KSP_SECRET_STORE_{DEVNET,MAINNET,TESTNET}_POSTGRES_URI classés Secret safe projection redacted provenance sans valeur dotenv inventory à jour ``` Matérialisé par `pre.004-fix.001` : les trois URI réseau-spécifiques sont inventoriées, chaque fallback reste `Secret`, la safe projection est redacted et la provenance n'embarque aucune valeur. Statut : `PASS pre.004-fix.001 opérateur`. ### V32-CONFIG-002B — Target/réseau sans multiplexage Critères : ```text profile_id std.store = identifiant de target Store default_profile choisit exactement un target StoreSettings porte exactement un RawNetworkId résolution explicite mainnet/devnet/testnet retourne URI + network du target choisi ksp-store-lib ne possède aucun routeur multi-target/multi-réseau future RAW mismatch Store.network != entity/query.network rejeté avant I/O ``` Matérialisé contractuellement par `pre.004-fix.001`; l'enforcement sur opérations RAW sera exercé dans `0.3.3`/`0.3.4`. Statut : `PASS pre.004-fix.001 opérateur` pour la sélection target/réseau / `TODO 0.3.3-0.3.4` pour le mismatch RAW. ### V32-CONFIG-003 — No-env Store/backend Critère : production sources `ksp-store-lib` et `ksp-store-postgres-lib` ne lisent aucun : ```text std::env dotenv KSP_* KSPB_* PG* .pgpass ``` `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 / PASS pre.009 opérateur`. ### V32-CONFIG-004 — Adapter Config -> Store Critère : `ksp-config-lib` seul transforme un profil/target résolu en `StoreSettings` réseau-spécifique et ne transmet aucun secret dans diagnostics. Matérialisé par `pre.004` puis `pre.004-fix.001` : seul `ksp-config-lib` dépend de `ksp-store-lib` avec `default-features = false`; il mappe le `profile_id` sélectionné vers un target, construit son `RawNetworkId` et ses settings backend sans forcer la feature backend. Statut : `PASS pre.004-fix.001 opérateur`. ## 6. Pool et lifecycle PostgreSQL ### V32-POOL-001 — Pool borné Critères : ```text max_connections 1..64 wait/create/recycle timeouts bornés aucune taille zéro aucune valeur pathologique ``` Matérialisé par `pre.005` : `deadpool-postgres` possède un pool `max_size` explicite et applique les deadlines `wait/create/recycle`; `tokio-postgres::Config` reçoit aussi le `connect_timeout` typé après parsing de l'URI. Statut : `PASS pre.005-fix.001 opérateur`. ### V32-POOL-002 — Connection task ownership Critère : chaque connection future tokio-postgres est pilotée par le manager retenu et son task handle reste possédé jusqu'au drop/close. `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 / PASS pre.009 opérateur`. ### V32-POOL-003 — Open failure safe Critère : DNS/connect/auth/server errors ne copient ni URI ni texte remote arbitraire dans Display/Debug public. Matérialisé par `pre.005` : parsing/connexion/pool/TLS sont ramenés à une classification backend locale sans conserver le texte des erreurs externes ni l'URI. La façade mappe vers des codes `store.postgres_*` stables avec contexte statique sûr. Statut : `PASS pre.005-fix.001 opérateur`. ### V32-POOL-004 — Close Critères : ```text pool fermé nouvelles acquisitions refusées shutdown respecte timeout 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 / PASS live pre.008 PostgreSQL 17`. ## 7. TLS ### V32-TLS-001 — Modes exacts Surface initiale : ```text Disabled VerifyFull ``` Matérialisé par `pre.005` : la surface physique accepte exactement `Disabled` et `VerifyFull`; l'URI parsée est ensuite normalisée vers `SslMode::Disable` ou `SslMode::Require`, donc elle ne peut pas modifier la policy typée. Statut : `PASS pre.005-fix.001 opérateur`. ### V32-TLS-002 — VerifyFull Critères : ```text TLS requis root store système authenticité du certificat vérifiée nom serveur vérifié aucun fallback plaintext ``` Matérialisé par `pre.005` : `VerifyFull` construit un `rustls::RootCertStore` à partir des roots système, utilise explicitement le provider AWS-LC, requiert un host TCP pour l'identité serveur, rejette `hostaddr` seul et les sockets Unix, et ne permet aucun fallback plaintext. Les erreurs de roots/certificats sont réduites à des compteurs sûrs. Statut : `PASS pre.005-fix.001 opérateur`. ### V32-TLS-003 — Pas de fichier TLS implicite Critère : backend ne lit pas `sslrootcert`, `sslcert`, `sslkey`, `.postgresql/*` ou autre fichier implicite hors settings KSP. Statut : `PASS pre.009 opérateur`. ## 8. Migration/bootstrap ### V32-MIG-001 — Metadata privée uniquement Critère : `0.3.2` crée au plus la relation d'infrastructure : ```text ksp_store_schema_migrations ``` 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 / PASS live pre.008 PostgreSQL 17`. ### V32-MIG-002 — Version/checksum Critères : ```text version entière monotone nom immuable SHA-256 du SQL exact sentinel bootstrap version 0 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 / PASS live pre.008 PostgreSQL 17`. ### V32-MIG-003 — Concurrence Critère : deux runners concurrents sont sérialisés par advisory transaction lock avec attente bornée. `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 / PASS concurrence live pre.008 PostgreSQL 17`. ### V32-MIG-004 — Atomicité/recovery Critère : échec d'une migration du run courant rollback DDL + history de ce run ; un rerun depuis état précédent reste sûr. `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 / PASS rollback live pre.008 PostgreSQL 17`. ### V32-MIG-005 — Newer runtime guard Critère : migration appliquée inconnue/supérieure à la liste embarquée produit `STORE_POSTGRES_SCHEMA_NEWER`, sans down migration. `pre.006` connaît uniquement la version `0`; toute history `> 0` est classée `SchemaNewer` par le backend puis `store.postgres_schema_newer` par la façade. Aucun chemin de down migration n'existe. Statut : `PASS pre.006 opérateur`. ### V32-MIG-006 — SQL injection Critères : ```text SQL de migration statique embarqué values paramétrées 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 / PASS pre.009 opérateur hardening`. ### V32-MIG-007 — No business capability Critères : ```text 0 impl PostgreSQL de capability RawTransaction 0 impl PostgreSQL de capability RawAccountState 0 repository RAW métier ``` Statut : `PASS pre.009 opérateur / TODO revalidation pre.010`. ## 9. Health/readiness ### V32-HEALTH-001 — Projection portable Critère : façade expose uniquement état/backend/network/counts/migration safe, jamais URI/SQL/pool/client. `pre.007` matérialise `StoreRuntimeSnapshot`, `StoreHealthState::{Ready, NotReady}` et `StoreHealthSnapshot`. Les compteurs pool sont bornés en `u32`; la version migration est optionnelle si le probe ne peut pas la lire. Statut : `PASS pre.007 opérateur`. ### V32-HEALTH-002 — Readiness réelle Critère : `Store::open` ne retourne Ready qu'après connect + bootstrap/verify selon settings, et `Store::health()` sonde ensuite la disponibilité physique sous deadline. `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 / PASS live pre.008 PostgreSQL 17`. ### V32-HEALTH-003 — Error redaction Critère : un health failure n'expose pas server error string, query text ou credential. 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 / PASS pre.009 opérateur hardening`. ## 10. PostgreSQL integration réelle ### V32-LIVE-001 — Input opérateur explicite Critères : ```text #[ignore] URI lue depuis stdin aucun env requis 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 : `PASS live pre.008 PostgreSQL 17`. ### V32-LIVE-002 — Non destructif Critères : ```text refus si metadata table préexiste aucune base/schema drop aucune table métier créée 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 : `PASS live pre.008 PostgreSQL 17`. ### V32-LIVE-003 — Scénario foundation Preuves : ```text connect bootstrap initial bootstrap idempotent bootstrap concurrent checksum mismatch + restore/recovery failure rollback du V000 exact health ready close borné 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 : `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. Le gate opérateur réel a été exécuté avec succès sur PostgreSQL 17. Statut : `PASS live pre.008 PostgreSQL 17 / TODO revalidation pre.010`. ## 11. Security/adversarial ### V32-SEC-001 — URI hostile Cas : vide, surdimensionnée, malformed, paramètres conflictuels, password contenant contrôles/URL-like. Attendu : rejet borné sans echo. `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 : `PASS pre.009 opérateur`. ### V32-SEC-002 — Secret canary Injecter un canary dans URI/password et prouver son absence de : ```text Debug Display ErrorContext tracing snapshots health snapshots ``` `pre.009` injecte des canaris distincts dans la façade et le backend. Les settings Debug doivent afficher ``; 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 : `PASS pre.009 opérateur`. ### V32-SEC-003 — Timeouts hostiles 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 / `PASS pre.009 opérateur` hardening`. ### 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 / PASS pre.009 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`; `pre.009` ajoute un canari structurel prouvant que `PostgresBackendError` ne peut retenir que `kind + phase` statiques et que `PoolError::Backend(_)` abandonne le texte remote. `PASS pre.009 opérateur`. ## 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` : `PASS opérateur` — tests ciblés, canaris hardening, Config, graphes et `cargo test --workspace` verts. ## 13. Gate technique final `pre.010` `pre.010` ne contient aucun développement fonctionnel. Il doit revalider sur la version `0.3.2-pre.10` : ```text audits Rust/Markdown workspace check + Clippy Store API backend PostgreSQL façade default + no-default-features Config std.store cargo test --workspace graphes normal/features/duplicates PostgreSQL live foundation 3 builds Tauri avec resources std.store packagées ``` Statut global `pre.010` : `MATÉRIALISÉ / TODO gate opérateur`. ## 14. Gates Rust/workspace À chaque tranche applicable : ```bash cargo fmt --all python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.2 cargo check --workspace cargo clippy --workspace --all-targets ``` Après création des crates : ```bash cargo test -p ksp-store-api cargo test -p ksp-store-lib cargo test -p ksp-store-lib --no-default-features cargo test -p ksp-store-postgres-lib cargo test -p ksp-config-lib cargo check -p ksp-store-lib --no-default-features cargo tree -p ksp-store-lib --edges normal cargo tree -p ksp-store-lib -e features cargo tree -p ksp-store-postgres-lib --edges normal cargo tree --duplicates ``` Gate PostgreSQL réel `pre.010` après les gates déterministes : ```bash read -rsp "Dedicated PostgreSQL URI: " KSP_PG_TEST_URI; echo printf '%s\n' "$KSP_PG_TEST_URI" | cargo test -p ksp-store-postgres-lib --test postgres_foundation_live -- --ignored --nocapture --test-threads=1 unset KSP_PG_TEST_URI ``` `KSP_PG_TEST_URI` est ici une variable shell non exportée servant uniquement à masquer la saisie ; le test lit exclusivement stdin et ne lit aucun environnement. Gate technique final : ```bash cargo test --workspace (cd crates/ksp-app-config-desk && cargo tauri build) (cd crates/ksp-app-solprices-desk && cargo tauri build) (cd crates/ksp-app-wallet-desk && cargo tauri build) ``` Les trois builds Tauri sont requis au gate final parce que `pre.004` a réellement ajouté les resources `std.store` au packaging desktop. Statut global : `TODO gate opérateur pre.010`. ## 15. Critères de fermeture La matrice ne peut passer en finale que si tous les critères applicables sont `PASS` et que : ```text aucun RawTransaction PostgreSQL aucun RawAccountState PostgreSQL aucun SQL métier RAW aucune policy worker/job dans Store aucune fuite backend dans façade aucune lecture env par Store/backend PostgreSQL live vert workspace/clippy/tests verts ``` La réconciliation finale de cette matrice appartient à la prerelease documentaire précédant la lane de publication.