41 KiB
Validation 0.3.3 — Store/PostgreSQL RawTransaction vertical slice
1. Objet
Cette validation accompagne :
0.3.3 — Store/PostgreSQL RawTransaction vertical slice
Elle démarre en 0.3.3-pre.001 comme matrice de preuve. Les gates opérateur de pre.001 et pre.002 sont verts. pre.003 a été commité avant son gate opérateur ; pre.003-fix.001 corrige donc sa matérialisation physique par-dessus ce commit. Son premier gate opérateur a ensuite révélé un défaut de binding ToSql dans l’introspection catalogue et un faux positif ownership dû à des constantes internes KSP_*; pre.003-fix.002 corrige uniquement ces deux défauts sans modifier le contrat physique ni les checksums de migration. Son gate opérateur compile désormais le backend mais révèle trois reliquats locaux : un binding inutilisé, cinq usages de ? interdits par la policy Clippy KSP et un include_str! du test live resté sur l’ancien chemin V000 ; pre.003-fix.003 corrige uniquement ces reliquats sans toucher aux ressources SQL ni aux checksums. Les lignes non encore implémentées restent explicitement À FAIRE; elles ne sont pas présentées comme acquises.
2. Baseline stable
| Preuve | Attendu pre.001 |
Statut |
|---|---|---|
| Base de travail | archive/tag v0.3.2 |
PASS |
| workspace package version avant overlay | 0.3.2 |
PASS |
Gate opérateur 0.3.2 |
audits/check/clippy/tests Store+Config/no-default-features propres | PASS |
PostgreSQL live métier 0.3.2 |
absent ; seule fondation opt-in existe | PASS |
| Prompt release | prompts/022-V0_3_3_START_PROMPT.md |
PASS |
| Archive historique kbot3 | audit ciblé uniquement | PASS |
2.1 Inventaire exact 0.3.2
ksp-store-api modules=capability,error,model root pub use=60
ksp-store-lib modules=constants,error,health,settings,store root pub use=84, default feature=postgres
ksp-store-postgres-lib modules=constants,error,health,migration,runtime root pub use=7
V000__bootstrap.sql SHA-256=d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
std.store format_version 1
std.store profiles devnet/devnet, mainnet/mainnet-beta, testnet/testnet
foundation live PASS PostgreSQL 17 en pre.008 et pre.010
Le test live est #[ignore] dans les gates ordinaires mais sa preuve réelle antérieure est documentée dans 019-V0_3_2_STORE_POSTGRES_FOUNDATION.md.
3. Scope exact des capacités
| Capacité | Backend PostgreSQL | Façade Store | Preuve finale |
|---|---|---|---|
RawTransactionRead |
À FAIRE | À FAIRE | unit + integration + live |
RawTransactionWrite |
À FAIRE | À FAIRE | unit + concurrency live |
RawTransactionObservationRead |
À FAIRE | À FAIRE | unit + live |
RawTransactionObservationWrite |
À FAIRE | À FAIRE | unit + concurrency live |
RawTransactionRetentionRead |
À FAIRE | À FAIRE | unit + live |
RawTransactionRetentionWrite |
À FAIRE | À FAIRE | unit + race live |
Aucune capacité RawAccountState, structurale N2, job ou worker n'est admise dans cette matrice.
3.1 Matrice RawTransactionRead
| Axe | Preuve/attendu |
|---|---|
| input | reference pour get; query pour list |
| invariants pré-I/O | network exact; cursor lié à query |
| transaction SQL | aucune; statement cohérent |
| rows touchées | transaction + archive pour get; index transaction pour list |
| idempotence | N/A |
| conflit | N/A; corruption != conflict métier |
| absence/not-found | get None; list vide |
| error mapping | query/wrong-network/data/query-failed sûrs |
| concurrence | statement snapshot; aucun snapshot inter-pages |
| test déterministe | full/archive/purged, u64 max, ranges, cursor hostile |
| test PostgreSQL live | get exact + pages multi-slot/ties dans deux directions |
3.2 Matrice RawTransactionWrite
| Axe | Preuve/attendu |
|---|---|
| input | transaction + observation + acquisition mode |
| invariants pré-I/O | deux networks exacts; observation reference = canonical reference |
| transaction SQL | une transaction atomique |
| rows touchées | canonical + observation + archive si état existant Archived |
| idempotence | contenu exact identique -> AlreadyPresent |
| conflit | divergence même signature -> ERROR_CODE_RAW_CONFLICT |
| absence/not-found | insert; Purged Normal compatible -> SkippedPurged/NotRecorded |
| error mapping | API model/conflict; physical write/data sûrs |
| concurrence | unique insert + FOR UPDATE du gagnant |
| test déterministe | equality/conflict/tombstone/modes/redaction |
| test PostgreSQL live | identical/divergent concurrent + rollback + force |
3.3 Matrice RawTransactionObservationRead
| Axe | Preuve/attendu |
|---|---|
| input | observation key |
| invariants pré-I/O | key API valide; database network déjà bound |
| transaction SQL | aucune |
| rows touchées | observation |
| idempotence | N/A |
| conflit | N/A |
| absence/not-found | None |
| error mapping | stored-row invalid/query-failed sûrs |
| concurrence | observation immuable, statement snapshot |
| test déterministe | provenance complète/optionnelle + hostile row |
| test PostgreSQL live | observation round-trip exact |
3.4 Matrice RawTransactionObservationWrite
| Axe | Preuve/attendu |
|---|---|
| input | observation |
| invariants pré-I/O | observation transaction network exact |
| transaction SQL | oui |
| rows touchées | canonical verrouillé + observation |
| idempotence | same key + fields identical -> AlreadyPresent |
| conflit | same key + divergence -> ERROR_CODE_RAW_CONFLICT |
| absence/not-found | canonical absent -> safe not-found; Purged -> NotRecorded |
| error mapping | provenance/conflict API + not-found/write sûrs |
| concurrence | canonical FOR UPDATE + unique observation key |
| test déterministe | equality/missing/purged/error canaries |
| test PostgreSQL live | identical/divergent observation races |
3.5 Matrice RawTransactionRetentionRead
| Axe | Preuve/attendu |
|---|---|
| input | transaction reference |
| invariants pré-I/O | network exact |
| transaction SQL | aucune |
| rows touchées | canonical metadata |
| idempotence | N/A |
| conflit | N/A |
| absence/not-found | state unknown -> None; tombstone only Purged |
| error mapping | wrong-network/stored-metadata invalid sûrs |
| concurrence | état committé par statement |
| test déterministe | Full/Archived/Purged + tombstone minimal |
| test PostgreSQL live | reads après chaque transition |
3.6 Matrice RawTransactionRetentionWrite
| Axe | Preuve/attendu |
|---|---|
| input | retention transition |
| invariants pré-I/O | network exact; Compacted non supporté rejeté avant pool |
| transaction SQL | oui |
| rows touchées | canonical + archive |
| idempotence | current == target -> AlreadyAtTarget |
| conflit | expected perdu -> ExpectedStateMismatch |
| absence/not-found | unknown reference -> safe not-found |
| error mapping | invalid transition API; unsupported/physical write sûrs |
| concurrence | FOR UPDATE canonique |
| test déterministe | transition matrix + Compacted unsupported |
| test PostgreSQL live | transition/purge/write/force races |
4. Design physique V001
| Élément | Décision pre.001 |
Statut |
|---|---|---|
| Migration | V001 embedded, après généralisation du moteur V000 | PASS design |
| Database identity | singleton ksp_store_identity |
PASS design |
| Réseau | un réseau exact par base V001 | PASS design |
| Transaction key | signature BYTEA(64) logique |
PASS design |
| Observation key | BYTEA(32) |
PASS design |
| Slot | NUMERIC(20,0) ; aucun narrowing u64 |
PASS design |
| Format version | BIGINT, check domaine u32 non nul |
PASS design |
| Timestamp | BIGINT, check borne RawTimestamp |
PASS design |
| Payload | BYTEA, 1..=16 MiB |
PASS design |
| Archive | relation dédiée hors index hot-path | PASS design |
| Purge | tombstone minimal dans ligne canonique | PASS design |
| Compacted | non simulé ; rejet stable tant qu'aucun codec réel | PASS design |
| Navigation | index partiel (slot, signature) hors purged |
PASS design |
5. Inventaire SQL minimal prévu
5.1 Tables
ksp_store_identity
ksp_raw_transactions
ksp_raw_transaction_observations
ksp_raw_transaction_archive_payloads
Statut après pre.003-fix.001 : matérialisé dans V001. Les quatre tables sont des ressources embedded distinctes sous migrations/v001_raw_transaction/tables/; contraintes et index sont séparés dans leurs propres sous-répertoires. V001 reste une migration logique unique et aucune capability/repository ne les consomme encore.
5.2 Indexes
PK ksp_raw_transactions(signature)
PK ksp_raw_transaction_observations(observation_key)
PK ksp_raw_transaction_archive_payloads(signature)
ix_ksp_raw_transactions_slot_signature(slot, signature)
WHERE retention_state <> 'purged'
Tout index additionnel doit être justifié par une requête effectivement ajoutée à la release.
6. Mapping numérique sans narrowing
| Valeur API | Représentation SQL | Cas limites obligatoires |
|---|---|---|
slot: u64 |
NUMERIC(20,0) |
0, i64::MAX, i64::MAX + 1, u64::MAX |
format_version: u32 |
BIGINT |
1, i32::MAX + 1, u32::MAX |
RawTimestamp |
BIGINT |
0, max documenté, max+1 DB hostile |
| source payload size | BIGINT |
0, 64 MiB, >64 MiB DB hostile |
| page limit | bind signé de limit+1 seulement si représentable |
i64::MAX - 1, valeur supérieure rejetée |
Critère : aucune branche ne doit utiliser as i64, as i32, clamp ou saturation pour faire tenir une valeur valide API.
7. Binding réseau
7.1 Bootstrap
| Cas | Résultat attendu |
|---|---|
| V001 appliquée pour la première fois | identity créée avec le réseau runtime dans la transaction de bootstrap |
| réouverture même réseau | succès idempotent |
| réouverture autre réseau | erreur terminale sûre |
| V001 présente mais identity absente | mismatch/corruption, jamais rebind silencieuse |
| identity malformée | erreur terminale sûre |
migration pending + schema_autoupdate=false |
backend non prêt, aucune persistence métier |
7.2 Pré-I/O capability
Pour tout input portant un RawNetworkId, un mismatch avec Store.network ou PostgresBackend.network doit être détecté avant acquisition d'un client du pool.
8. Idempotence canonique
| État existant | Input | Mode | Outcome attendu |
|---|---|---|---|
| absent | canonique+observation valides | Normal | Inserted / Inserted |
| Full identique | observation identique | Normal | AlreadyPresent / AlreadyPresent |
| Full identique | observation nouvelle | Normal | AlreadyPresent / Inserted |
| Full divergent | n'importe quelle observation | Normal | ERROR_CODE_RAW_CONFLICT, aucun write |
| Archived identique | observation nouvelle | Normal | AlreadyPresent / Inserted |
| Purged compatible | observation | Normal | SkippedPurged / NotRecorded |
| Purged divergent sur tombstone | observation | Normal | ERROR_CODE_RAW_CONFLICT |
| Purged compatible | observation | ForceRehydrate | Rehydrated / Inserted ou AlreadyPresent |
| Purged divergent | observation | ForceRehydrate | ERROR_CODE_RAW_CONFLICT |
L'égalité canonique compare les octets réels lorsqu'ils sont encore retenus. Le content hash seul n'est jamais une preuve suffisante dans Full ou Archived.
9. Atomicité canonique + observation
9.1 Cas obligatoires
| Scénario | Preuve attendue |
|---|---|
| nouvel insert, observation valide | les deux commit |
| nouvel insert, observation divergente sur key déjà existante | rollback canonique + observation |
| canonical conflict | aucune nouvelle observation |
| cancellation avant commit | aucun succès partiel visible |
| erreur SQL observation | rollback canonique |
9.2 FK
Le FK observation -> transaction est :
- non nullable ;
- sans
ON DELETE SET NULL; - impossible à contourner dans le repository métier ;
- cohérent avec le fait que purge conserve la ligne canonique/tombstone.
10. Concurrence
| Race | Attendu |
|---|---|
| deux inserts identiques même signature | un Inserted, l'autre AlreadyPresent; données identiques |
| deux inserts divergents même signature | un gagnant, l'autre ERROR_CODE_RAW_CONFLICT |
| deux observations identiques même key | un Inserted, l'autre AlreadyPresent |
| deux observations divergentes même key | un gagnant, l'autre conflit |
| deux transitions vers même target | un transitionne, l'autre AlreadyAtTarget |
| transitions avec expected incompatibles | gagnant déterministe + ExpectedStateMismatch |
| purge vs acquisition | sérialisation sur ligne canonique |
| purge vs ForceRehydrate | aucun état moitié purgé/moitié full |
| deux ForceRehydrate | idempotence ou conflit selon contenu |
La preuve live doit utiliser de vraies tâches concurrentes, pas une simulation séquentielle renommée « concurrency ».
11. Observation write séparée
| Cas | Attendu |
|---|---|
| canonique Full présent, key absente | Inserted |
| canonique Archived présent, key absente | Inserted |
| key identique | AlreadyPresent |
| key divergente | ERROR_CODE_RAW_CONFLICT |
| canonique absent | erreur sûre, aucune création implicite |
| canonique Purged | NotRecorded |
| mauvais réseau | rejet pré-I/O |
L'absence du canonical requis est classée store.raw_reference_not_found. Ce code runtime ne modifie pas les invariants de construction de ksp-store-api.
12. Lecture
12.1 RawTransaction
| État physique | get_raw_transaction |
|---|---|
| Full cohérent | Some(RawTransaction) depuis payload hot |
| Archived cohérent | Some(RawTransaction) depuis archive relation |
| Purged | None |
| row inconnue | None |
| état/bytes/taille/numérique incohérents | erreur sûre de donnée physique |
12.2 Observation
| Cas | Résultat |
|---|---|
| key connue | observation reconstruite avec network du backend bound |
| key inconnue | None |
| bytes/provenance invalides en DB | erreur sûre |
13. Pagination
13.1 Ordre
Ascending = (slot ASC, signature ASC)
Descending = (slot DESC, signature DESC)
13.2 Dataset obligatoire
Le test doit contenir au minimum :
- plusieurs slots ;
- au moins trois signatures distinctes sur le même slot ;
- suffisamment de rows pour trois pages ;
- une row Purged exclue de la liste ;
- bornes start/end présentes et absentes.
13.3 Cursor V1
| Test | Attendu |
|---|---|
| round-trip | exact |
| taille != 109 | rejet |
| magic modifié | rejet |
| version inconnue | rejet |
| digest modifié | rejet |
| direction différente | rejet |
| range différente | rejet |
| network différent | rejet |
| last slot hors range | rejet |
| random bytes <=4096 | rejet sans panic/echo |
| cursor >4096 au niveau API | déjà rejeté par RawPageCursor |
13.4 Pas de cap métier
Aucun test ne doit imposer 100, 500 ou 1000 comme limite Store. La seule erreur de taille côté backend doit correspondre à la représentation physique nécessaire au LIMIT + 1.
14. Rétention
14.1 États supportés physiquement en 0.3.3
Full
Archived
Purged
Compacted reste un état logique API connu, explicitement optionnel depuis le plan 0.3.1, mais non représenté mensongèrement par PostgreSQL 0.3.3. Le code store.postgres_retention_compaction_unsupported est matérialisé dès pre.003 dans ksp-store-postgres-lib et ksp-store-lib avec la même valeur KSP ; son usage opérationnel par les transitions sera branché en pre.007.
14.2 Matrice
| Current | Expected | Target | Attendu PostgreSQL 0.3.3 |
|---|---|---|---|
| Full | Full | Archived | Transitioned |
| Archived | Full | Archived | AlreadyAtTarget |
| Archived | Archived | Purged | Transitioned |
| Purged | Archived | Purged | AlreadyAtTarget |
| Full | Archived | Purged | input transition invalide au niveau API |
| Full | Full | Compacted | store.postgres_retention_compaction_unsupported, pré-I/O |
| Compacted attendu | Compacted | Archived | store.postgres_retention_compaction_unsupported, pré-I/O |
| Full | Archived | Archived | ExpectedStateMismatch |
14.3 Tombstone
Après purge, la reconstruction autorisée contient exactement :
reference
slot
format_id
format_version
content_hash
Le block time et les octets de payload ne restent pas dans la table hot ni dans la table archive.
15. ForceRehydrate
| Cas | Attendu |
|---|---|
| Purged + tombstone compatible | restaure Full et payload, outcome Rehydrated |
| Purged + slot divergent | conflict |
| Purged + format id/version divergent | conflict |
| Purged + content hash divergent | conflict |
| Full/Archived identique + Force | idempotence normale, pas faux Rehydrated |
| race avec purge | sérialisation ; état final cohérent |
16. Erreurs et redaction
16.1 Canary hostile
Les tests devront injecter des valeurs sentinelles dans :
URI
server error text
SQL text simulé
signature
observation key
content hash
payload
provider/protocol/method
cursor bytes
row DB invalide
Aucune sentinelle ne doit apparaître dans Display, Debug ou message sûr retourné.
16.2 Classification
| Classe | Interface attendue |
|---|---|
| input/model invalide | codes ksp-store-api acquis |
| canonical/observation divergent | ERROR_CODE_RAW_CONFLICT |
| retention representation non supportée | store.postgres_retention_compaction_unsupported |
| réseau incohérent | code statique, pas de réseau hostile rendu |
| DB row invalide | code statique de corruption/data invalid |
| query/write PostgreSQL | code statique backend/runtime |
| pool/cancel/migration | catégories runtime existantes ou extension statique justifiée |
SQLSTATE et texte PostgreSQL ne font pas partie du contrat public.
17. Migration engine
17.1 Multi-version
Preuves acquises en pre.002 avant création réelle de V001 :
- V000 reste byte-identique et conserve le checksum
d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450; - le registre embedded privé est ordonné et commence à V000 ;
- le moteur valide un historique comme préfixe exact du registre ;
- un registre synthétique
[V000, V001]prouve qu'un historique V000 seul retourne l'index pending V001 sans être classé mismatch ; - nom/checksum divergent, historique vide avec metadata existante ou trou de préfixe -> mismatch ;
- version supérieure au registre connu -> schema newer, sans down migration ;
auto_migrate = falserefuse un registre incomplet parmigration_pending;- les migrations pending sont appliquées dans l'ordre sous la transaction et l'advisory lock déjà acquis ;
- chaque migration vérifie encore la forme de la metadata avant d'insérer sa ligne d'historique.
Le commit pre.003 a matérialisé la vraie V001 et son binding réseau, mais son fichier SQL monolithique et le seul contrôle de l'historique ne suffisaient pas à prouver la compatibilité structurelle de la base. Son checksum V001 historique de prerelease était 6fe57ed0313d2ed295280dd6e49f6d86695d4e4effee2724a25e36db1ea17761.
Preuves statiques ajoutées par pre.003-fix.001 :
- V000 déplacée byte-identique, checksum toujours
d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450; - V001 logique unique composée de 40 ressources ordonnées : 4 tables, 35 contraintes et 1 index ;
- checksum V001 multi-ressources
31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51; - anciens fichiers monolithiques absents après application du delta ;
CREATE ... IF NOT EXISTS/guards servent uniquement à la création additive, jamais à déclarer un objet compatible ;- inspection catalogue indépendante de l'historique avec états
Compatible,Missing,Incompatible; - contraintes attendues comparées exactement à une définition canonique issue de la ressource SQL correspondante ;
- colonne externe nullable sans default/identity/generated acceptée comme extension non bloquante ;
- index externe non unique accepté ;
- mauvais type/nullabilité sur colonne obligatoire, extra colonne write-blocking, contrainte externe non équivalente, unique index autonome, trigger actif, rule ou RLS bloquent
Ready; - ressource obligatoire manquante réparable seulement lorsque la politique le permet et que la réparation est additive/sûre ;
- identité V001 manquante sur un historique déjà appliqué reste terminale et n'est jamais auto-recréée ;
std.storeV2 sépareschema_autocreateetschema_autoupdate, avec lecture V1 conservée et mapping deauto_migratevers les deux valeurs.
L'application V000 -> V001, les réparations réelles, le rollback du hook, la réouverture même/autre réseau et la matrice de drift sur PostgreSQL réel restent à prouver dans le gate live dédié pre.009; elles ne sont pas déclarées PASS par le correctif statique. Une base ayant déjà enregistré l'ancien checksum V001 de pre.003 doit être réinitialisée ou réconciliée manuellement ; le moteur ne réécrit pas son historique silencieusement.
17.2 Binding réseau atomique
pre.002 prépare la frontière sans créer l'identité : RawNetworkId est transmis au moteur et chaque migration possède un hook privé exécuté sous la même transaction/advisory lock. Deux contextes sont distingués : AppliedNow pour une migration qui vient d'être exécutée et Existing pour une migration déjà présente dans l'historique lors d'une réouverture. V000 déclare explicitement le hook neutre.
pre.003 branche le hook V001 réel : en contexte AppliedNow, il insère la singleton puis relit/valide ksp_store_identity avant insertion de l'historique V001 ; en contexte Existing, il relit/valide strictement l'identité sans jamais la recréer. Une absence, un nombre de lignes inattendu, une forme invalide ou un réseau différent sont classés MigrationMismatch avec phase statique et sans rendre le réseau stocké. L'atomicité PostgreSQL réelle de ce chemin sera prouvée dans pre.009.
18. Boundaries
Les scans/tests doivent garantir :
ksp-store-lib -X-> tokio-postgres/deadpool-postgres/rustls
ksp-store-lib -X-> SQL literal
ksp-store-lib -X-> std::env / dotenv / libpq files
ksp-store-postgres-lib -X-> ksp-store-lib
ksp-store-postgres-lib -X-> direct Config ownership
ksp-store-api -X-> backend physical dependency
La façade ne publie aucun Client, Transaction, pool, TLS type, SQL row ou type backend.
19. Feature matrix
| Build | Attendu |
|---|---|
ksp-store-lib default |
feature postgres active, six capacités dispatchables une fois implémentées |
ksp-store-lib --no-default-features |
compile ; aucune dépendance backend tirée |
| config backend postgres sans feature | erreur backend_not_compiled avant I/O |
| malformed postgres URI avec feature | erreur safe pré-I/O comme 0.3.2 |
20. Audit historique — preuves de non-régression
Les tests/source scans devront empêcher le retour des patterns historiques rejetés :
has_raw_transaction_signature
BIGSERIAL id comme identity publique
slot BIGINT dans V001
canonical_json JSONB
processing_state
ON DELETE SET NULL
raw SQL error text dans Error
cap 500/1000 dans Store pagination
21. Planning de validation par tranche
pre.001
- documents plan/validation ;
- version
0.3.3-pre.1; - aucun SQL métier ;
- gate workspace actuel.
pre.002
- migration registry multi-version : PASS statique ;
- V000/checksum conservés : PASS ;
- validation préfixe/mismatch/newer : PASS unit design + canaris source ;
- préparation hook binding réseau transactionnel : PASS ;
- aucune V001 métier créée : PASS.
pre.003
- V001 + tables/constraints/indexes : matérialisé puis corrigé par
pre.003-fix.001; - binding réseau hook
AppliedNow/Existing: PASS statique ; - code
postgres_retention_compaction_unsupportedbackend + façade : PASS ; - gate opérateur
pre.003: NON FOURNI avant le correctif.
pre.003-fix.001
- arborescence versionnée et 40 ressources V001 : PASS statique ;
- V000 byte-identique/checksum historique : PASS statique ;
- checksum/inventory/order V001 multi-ressources : PASS statique ;
- contrat catalogue
Compatible/Missing/Incompatible: PASS statique ; - politiques
schema_autocreate/schema_autoupdate+ compatibilité Config V1 : PASS statique ; - extensions externes non bloquantes tolérées, extensions write-blocking refusées : PASS statique ;
- preuve PostgreSQL réelle V001/drift/réparation : différée à
pre.009; - gate Cargo opérateur : FAIL sur
schema.rs(&str/ToSql) puis sur les canaris ownership Config (KSP_*interne interprété comme variable runtime).
pre.003-fix.002
- binding des paramètres catalogue
&strversToSqlcorrigé avec&&str: PASS statique ; - constantes de contrat renommées sans préfixe
KSP_réservé au namespace d’environnement Config : PASS statique ; - aucune ressource SQL, aucun ordre de migration et aucun checksum V000/V001 modifié ;
- gate opérateur : FAIL Clippy (
question_mark_used+ warning) et ancieninclude_str!V000 du test live.
pre.003-fix.003
- warning
unused variable, opérateurs?et canari test Clippy corrigés : PASS ; postgres_foundation_liverelocalisé vers V000 versionnée : PASS ;- README/USAGE backend réconciliés avec l'arborescence split : PASS ;
- gate opérateur complet du 2026-08-30 : PASS (
check, Clippy, Store/API/PostgreSQL/Config, no-default-features).
pre.004
- quatre lectures RAW backend-specific sans fuite de row/SQL : PASS ;
- conversion
NUMERIC(20,0) -> u64jusqu'àu64::MAXet conversions entières/timestamps fallibles : PASS ; Full/Archived/Purged, observation complète, rétention/tombstone : PASS ;- mauvais réseau avant pool I/O : PASS ;
- malformed DB ->
DataInvalid, SELECT ->ReadFailed, aucune valeur hostile retenue : PASS ; - SQL strictement read-only dans cette tranche : PASS ;
- gate opérateur complet du 2026-08-30 : PASS (
check, Clippy, Store/API/PostgreSQL/Config, no-default-features ; 25 tests unit backend).
pre.005
- acquisition transaction + observation atomique sous transaction SQL : PASS statique/design ;
- insert unique sans
has_*, puis verrouillageFOR UPDATEet comparaison réelle : PASS statique/unit design ; - même contenu ->
AlreadyPresent, divergence ->Conflict: PASS unit design ; - tombstone compatible
Normal->SkippedPurged/NotRecorded: PASS statique/design ; - tombstone compatible
ForceRehydrate->Rehydrated+ observation atomique : PASS statique/design ; - observation write séparée, key identique/divergente, absent/purged : PASS statique/unit design ;
Conflict/ReferenceNotFound/WriteFailedsans texte serveur : PASS statique ;- preuve PostgreSQL concurrente/rollback réelle : différée à
pre.009; - gate opérateur complet du 2026-08-30 : PASS (
check, Clippy, Store/API/PostgreSQL/Config, no-default-features ; 30 tests unit backend).
pre.006
list_raw_transactionsbackend-specific et mauvais réseau pré-I/O : PASS statique/unit design ;- ordre total ASC/DESC
(slot, signature)et keyset stricte sans OFFSET : PASS statique ; - bornes inclusives et exclusion
Purged: PASS statique ; - cursor V1 fixe 109 octets, magic/version/last key/digest : PASS unit design ;
- binding digest network/direction/range + replay hostile rejeté : PASS unit design ;
- taille/magic/version/digest/random bytes hostiles : PASS unit design ;
last_slothors range rejeté : PASS unit design ;LIMIT requested + 1, limitei64::MAX - 1, aucun cap worker : PASS unit/statique ;- index V001
(slot, signature)partiel réutilisé, migration inchangée : PASS statique ; - snapshot inter-pages explicitement non garanti : PASS doc ;
- gate Cargo opérateur : À EXÉCUTER.
pre.007
- archive/purge/tombstone/ForceRehydrate ;
- Compacted unsupported stable.
pre.008
- façade/feature dispatch ;
- no physical leak ;
- pre-I/O mismatch.
pre.009
- PostgreSQL live opt-in complet.
pre.010
- hardening/completeness.
pre.011
- gate technique final.
pre.012
- réconciliation documentaire.
pre.013
- publication prep.
rel.001
- publication stable.
22. Gate courant pre.006
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.3
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-store-api
cargo test -p ksp-store-lib
cargo test -p ksp-store-postgres-lib
cargo test -p ksp-config-lib
cargo check -p ksp-store-lib --no-default-features
23. Critère de clôture de release
0.3.3 ne pourra être déclarée stable que si :
- les six capacités sont réellement implémentées sur
PostgresBackendet dispatchées parStore; - aucune valeur valide API n'est narrowée ;
- l'idempotence distingue strictement identité identique et contenu divergent ;
- canonical+observation est atomique ;
- pagination est déterministe et cursorisée ;
- réseau physique incorrect est refusé ;
- rétention supportée est honnête et atomique ;
Compactedn'est pas prétendu sans représentation réelle ;- tombstone et ForceRehydrate respectent les contrats acquis ;
- les erreurs ne fuient aucun secret/SQL/server text ;
- le live PostgreSQL opt-in couvre concurrence et rollback ;
- tous les gates techniques/doc sont propres ;
- aucun scope
RawAccountState/worker/app/N2 n'a été ouvert.
pre.003-fix.003
- [PASS] correction du binding local inutilisé dans l’inventaire des indexes uniques ;
- [PASS] extraction de définition de contrainte sans opérateur
?, conformément àclippy::question_mark_used = deny; - [PASS] canari unitaire sans assertion constante ;
- [PASS] test live V000 relocalisé vers
migrations/v000_bootstrap/tables/001_ksp_store_schema_migrations.sql; - [PASS] aucune ressource SQL V000/V001 modifiée ; checksums inchangés ;
- [PASS] gate opérateur complet de
fix.003fourni le 2026-08-30.
pre.004 — état de la tranche
- [PASS] module privé
raw_transactionavec SELECT uniquement ; - [PASS]
get_raw_transactionFull/Archived/Purged ; - [PASS]
get_raw_transaction_observationet provenance complète ; - [PASS] lectures rétention/tombstone ;
- [PASS] conversions fallibles
NUMERIC(20,0)/BIGINT/BYTEA/TEXTsans narrowing ; - [PASS] wrong-network gardé avant pool I/O ;
- [PASS]
ReadFailed/DataInvalid/WrongNetworksans texte externe ; - [PASS] tests déterministes de row mapping et hostile data ajoutés ;
- [PASS] gate Cargo opérateur complet de
pre.004fourni le 2026-08-30.
pre.005 — état de la tranche
- [PASS] écritures backend-specific canonique + observation ajoutées sans implémenter encore les traits incomplets ;
- [PASS] validation réseau et cohérence transaction/observation avant
pool.get(); - [PASS] idempotence par insert unique + comparaison réelle sous
FOR UPDATE, sanshas_*; - [PASS] payload comparé byte-for-byte lorsque disponible ;
- [PASS]
Purgednormal skip etForceRehydrateatomique selon tombstone ; - [PASS] observation write séparée :
Inserted/AlreadyPresent/NotRecorded/ conflit ; - [PASS] référence canonique absente classée
ReferenceNotFound; - [PASS] erreurs physiques d'écriture classées
WriteFailedsans conserver le texte PostgreSQL ; - [PASS] aucune migration SQL modifiée et aucun scope pagination/rétention mutante ouvert ;
- [PASS] gate Cargo opérateur complet de
pre.005fourni le 2026-08-30.
pre.006 — état de la tranche
- [PASS] bridge
list_raw_transactionsajouté sans type PostgreSQL public ; - [PASS] keyset stricte ASC/DESC sur
(slot, signature), sansOFFSET; - [PASS] bornes de slots inclusives et tombstones
Purgedexclus ; - [PASS] cursor V1 fixe 109 octets et digest lié à la query ;
- [PASS] replay network/direction/range et cursor hostile classés
QueryInvalid; - [PASS] limite physique
requested <= i64::MAX - 1, au-delàPageLimitUnsupportedsans clamp ; - [PASS] aucune migration SQL modifiée, aucun scope rétention mutante/façade ouvert ;
- [À FAIRE] gate Cargo opérateur complet de
pre.006.