21 KiB
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 :
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 :
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 :
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.
3. Frontières Cargo
V32-DEP-001 — Façade -> API
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
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
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 :
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 :
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 / TODO pre.009.
V32-DEP-006 — ksp-store-api non régressé
Critères :
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 :
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 :
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 / TODO pre.007 pour la composition health.
5. Config ownership
V32-CONFIG-001 — Document/schema/example
Critères :
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 :
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 :
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 :
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 :
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 / 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 : PASS pre.005-fix.001 opérateur.
V32-POOL-004 — Close
Critères :
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 / TODO pre.007/pre.008.
7. TLS
V32-TLS-001 — Modes exacts
Surface initiale :
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 :
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 : 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 :
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 : TODO gate opérateur pre.006 / TODO pre.008 live.
V32-MIG-002 — Version/checksum
Critères :
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 : TODO gate opérateur pre.006 / TODO pre.008 live.
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 : TODO gate opérateur pre.006 / TODO pre.008 concurrence réelle.
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 : TODO gate opérateur pre.006 / TODO pre.008 rollback réel.
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 : TODO gate opérateur pre.006.
V32-MIG-006 — SQL injection
Critères :
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 : TODO gate opérateur pre.006 / TODO pre.009 hardening.
V32-MIG-007 — No business capability
Critères :
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 :
#[ignore]
URI lue depuis stdin
aucun env requis
URI jamais imprimée
Statut : TODO pre.008.
V32-LIVE-002 — Non destructif
Critères :
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 :
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 :
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. 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 / TODO gate opérateur pre.006 pour migration / TODO pre.009 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 / 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 : bridge de sanitization matérialisé en pre.005; TODO pre.009 pour le canary serveur hostile.
12. Gates Rust/workspace
À chaque tranche applicable :
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 :
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 :
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 :
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.