# 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.1 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`. ## 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 / TODO pre.009 final`. ### 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 : `TODO gate opérateur pre.005 / TODO pre.009`. ### 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 : `TODO gate final`, baseline `v0.3.1` déjà verte. ## 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 / TODO pre.009 final`. ### 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 : `TODO pre.009`. ### 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 / TODO pre.009 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 / `TODO gate opérateur pre.005` pour l'ouverture et le shutdown physiques / `TODO pre.007` 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 / TODO pre.009`. ### 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 : `TODO gate opérateur pre.005`. ### 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 : `TODO gate opérateur pre.005 / TODO pre.009`. ### 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 : `TODO gate opérateur pre.005`. ### 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 : `TODO gate opérateur pre.005 / TODO pre.007/pre.008`. ## 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 : `TODO gate opérateur pre.005`. ### 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 : `TODO gate opérateur pre.005`. ### 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 : `TODO pre.009`. ## 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. Statut : `TODO pre.006`. ### 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 ``` Statut : `TODO pre.006`. ### V32-MIG-003 — Concurrence Critère : deux runners concurrents sont sérialisés par advisory transaction lock avec attente bornée. Statut : `TODO pre.006/pre.008`. ### 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. Statut : `TODO pre.006/pre.008`. ### 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. Statut : `TODO pre.006`. ### 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 ``` Statut : `TODO pre.006/pre.009`. ### 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 : `TODO pre.009/gate final`. ## 9. Health/readiness ### V32-HEALTH-001 — Projection portable Critère : façade expose uniquement état/backend/counts/migration safe, jamais URI/SQL/pool/client. Statut : `TODO pre.007`. ### V32-HEALTH-002 — Readiness réelle Critère : `Store::open` ne retourne Ready qu'après connect + bootstrap/verify selon settings. Statut : `TODO pre.007/pre.008`. ### V32-HEALTH-003 — Error redaction Critère : un health failure n'expose pas server error string, query text ou credential. Statut : `TODO pre.007/pre.009`. ## 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 ``` Statut : `TODO pre.008`. ### 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 ``` Statut : `TODO pre.008`. ### V32-LIVE-003 — Scénario foundation Preuves : ```text connect bootstrap initial bootstrap idempotent bootstrap concurrent checksum mismatch failure rollback health ready close borné ``` Statut : `TODO pre.008/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. Statut : `TODO pre.008/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. Statut : `TODO pre.009`. ### V32-SEC-002 — Secret canary Injecter un canary dans URI/password et prouver son absence de : ```text Debug Display ErrorContext tracing snapshots health snapshots ``` Statut : `TODO pre.009`. ### 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`. Le parsing PostgreSQL et les timeouts physiques restent à `pre.005`. Statut : `PASS pre.003-fix.001 opérateur` pour les bornes backend-neutral / `TODO pre.005 / TODO pre.009` pour les timeouts physiques. ### 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`. ### 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 : `TODO pre.005/pre.009`. ## 12. 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 technique final : ```bash cargo test --workspace ``` Les builds Tauri ne sont requis que si `pre.004` modifie réellement les resources/packaging desktop de manière justifiant cette preuve, puis au gate final si la matrice de packaging l'exige. Statut global : `TODO` jusqu'aux preuves de chaque tranche. ## 13. 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.