v0.3.4-pre.006
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md -->
|
||||
<!-- version: 9 -->
|
||||
<!-- version: 10 -->
|
||||
|
||||
# Plan `0.3.4` — Store/PostgreSQL `RawAccountState` + complétude RAW
|
||||
|
||||
@@ -625,19 +625,25 @@ Le correctif déplie les extractions physiques en `match` typés avec retour `Da
|
||||
|
||||
### `pre.005` — Acquisition atomique et idempotence
|
||||
|
||||
**Statut : réalisé ; gate opérateur complet à rejouer.**
|
||||
**Statut : réalisé ; gate opérateur complet PASS.**
|
||||
|
||||
Budget cible : **15-20 min**. L'acquisition account est désormais une transaction PostgreSQL unique : guard réseau et identité exacte avant I/O, `INSERT ... ON CONFLICT DO NOTHING` du state, verrouillage `FOR UPDATE` et comparaison exacte de `lamports/owner/executable/rent_epoch/data` en cas de collision, puis insertion idempotente de l'observation avec comparaison exacte de la référence, de toute la provenance et des metadata optionnelles. Une divergence retourne `Conflict` sans overwrite.
|
||||
|
||||
Si le state vient d'être inséré mais que l'observation collide avec un contenu divergent, le retour d'erreur abandonne la transaction et ne laisse donc aucun state orphelin durable. Le bridge étroit `PostgresBackend::persist_raw_account_acquisition` est ouvert sans implémenter `RawAccountStateWrite`; les quatre traits account restent fermés jusqu'à `pre.008`.
|
||||
|
||||
`record_raw_account_observation`, `list_raw_account_states`, le cursor `KSPA`, tout `UPDATE`/`DELETE` account et tout `ON CONFLICT DO UPDATE` restent absents. `pre.006` conserve la responsabilité de l'observation supplémentaire et des scénarios de concurrence/cancellation ciblés.
|
||||
À la clôture de `pre.005`, `record_raw_account_observation`, `list_raw_account_states`, le cursor `KSPA`, tout `UPDATE`/`DELETE` account et tout `ON CONFLICT DO UPDATE` restent absents. Le gate opérateur complet du 2026-08-30 est vert : audits Rust/Markdown, workspace check, Clippy all-targets, suites Store API/façade/PostgreSQL/Config et `--no-default-features` passent.
|
||||
|
||||
### `pre.006` — Observation supplémentaire et concurrence unitaire
|
||||
|
||||
**Statut : planifié.**
|
||||
**Statut : réalisé ; gate opérateur complet à rejouer.**
|
||||
|
||||
Budget cible : **15-20 min**. Ajouter l'observation supplémentaire et isoler les scénarios de race/cancellation unitaires sans élargir la surface de navigation.
|
||||
Budget cible : **15-20 min**. `PostgresBackend::record_raw_account_observation` ouvre le bridge étroit d'observation supplémentaire sans implémenter encore `RawAccountObservationWrite`. Le guard `observation.account.network == backend.network` est évalué avant `pool.get()`. La transaction verrouille ensuite la référence `(pubkey, slot, state_hash)` existante avec `SELECT 1 ... FOR KEY SHARE`; l'absence retourne `ReferenceNotFound` et aucun state n'est créé implicitement.
|
||||
|
||||
L'insertion réutilise exactement `persist_account_observation_row` de `pre.005` : `ON CONFLICT (observation_key) DO NOTHING`, puis `SELECT ... FOR UPDATE` et comparaison du `RawAccountObservation` complet sur collision. Une observation identique retourne `AlreadyPresent`; une collision divergente retourne `Conflict`, sans overwrite.
|
||||
|
||||
Les canaris unitaires figent l'ordre transactionnel `BEGIN -> FOR KEY SHARE -> insert/compare observation -> COMMIT`. Aucun `spawn`, `mem::forget` ou commit anticipé n'est admis dans ce chemin : si la future est annulée avant le commit, le `Transaction` local est droppé et PostgreSQL rollback la mutation non committée. Cette tranche prouve donc la structure de cancellation/race ; la preuve avec vraies tâches concurrentes et `JoinHandle::abort()` reste volontairement au live `pre.009`.
|
||||
|
||||
`list_raw_account_states`, le cursor `KSPA`, `OFFSET`, tout `UPDATE`/`DELETE` account, `ON CONFLICT DO UPDATE` et les quatre `impl RawAccount* for PostgresBackend` restent absents.
|
||||
|
||||
### `pre.007` — Liste account et cursor keyset V1
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Validation `0.3.4` — Store/PostgreSQL `RawAccountState` + complétude RAW
|
||||
|
||||
@@ -275,8 +275,8 @@ Le test live account devra être opt-in/ignored, URI stdin, sans environnement n
|
||||
| pre.002 | V002 registry + deux tables + PK/FK de base, sans repository | PASS |
|
||||
| pre.003 | contraintes complètes, index, schema compatibility, checksum V002 | PASS |
|
||||
| pre.004 | mapping privé state/observation + get reads + hostile rows | PASS |
|
||||
| pre.005 | acquisition atomique state+observation + idempotence/conflict | RECHECK |
|
||||
| pre.006 | observation supplémentaire + races/cancellation unitaires | PLANNED |
|
||||
| pre.005 | acquisition atomique state+observation + idempotence/conflict | PASS |
|
||||
| pre.006 | observation supplémentaire + races/cancellation unitaires | RECHECK |
|
||||
| pre.007 | list RawAccountStateQuery + keyset cursor V1 account | PLANNED |
|
||||
| pre.008 | 4 impl backend + 4 dispatch Store + conformance 10/10 | PLANNED |
|
||||
| pre.009 | preuve PostgreSQL live account + coexistence RawTransaction | PLANNED |
|
||||
@@ -451,7 +451,7 @@ Validations exécutées dans l'environnement d'assemblage du fix : audit Rust g
|
||||
|
||||
## 22. Verdict `pre.005`
|
||||
|
||||
Acquisition atomique account : **PASS statique ; gate opérateur complet à rejouer**.
|
||||
Acquisition atomique account : **PASS complet opérateur**.
|
||||
|
||||
Surface ajoutée :
|
||||
|
||||
@@ -474,5 +474,31 @@ La transaction commune garantit qu'une collision divergente sur l'observation ap
|
||||
|
||||
Canaries `pre.005` : guard réseau/référence, comparaison state complète, comparaison observation complète, encodage origin fermé, SQL `DO NOTHING + FOR UPDATE`, bridge backend-agnostic et absence des quatre implémentations `RawAccount*`.
|
||||
|
||||
Reste explicitement hors tranche : `record_raw_account_observation` (`pre.006`), concurrence/cancellation ciblées (`pre.006`), pagination/cursor (`pre.007`) et implémentations/dispatch 10/10 (`pre.008`). Les migrations V000/V001/V002 restent inchangées et le checksum V002 final demeure `ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e`.
|
||||
Le gate opérateur du 2026-08-30 est **PASS complet** : audits Rust/Markdown, `cargo check --workspace`, Clippy all-targets, Store API, Store façade, backend PostgreSQL (56 tests unitaires), Config et `ksp-store-lib --no-default-features` sont verts.
|
||||
|
||||
Reste après `pre.005` : observation supplémentaire/concurrence ciblée (`pre.006`), pagination/cursor (`pre.007`) et implémentations/dispatch 10/10 (`pre.008`). Les migrations V000/V001/V002 restent inchangées et le checksum V002 final demeure `ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e`.
|
||||
|
||||
## 23. Verdict `pre.006`
|
||||
|
||||
Observation supplémentaire account : **PASS statique ; gate opérateur complet à rejouer**.
|
||||
|
||||
Surface ajoutée :
|
||||
|
||||
```text
|
||||
PostgresBackend::record_raw_account_observation
|
||||
network guard avant pool.get()
|
||||
SELECT state reference FOR KEY SHARE
|
||||
state absent -> ReferenceNotFound
|
||||
INSERT observation ON CONFLICT DO NOTHING
|
||||
collision -> SELECT observation FOR UPDATE + comparaison exacte
|
||||
COMMIT unique
|
||||
```
|
||||
|
||||
Le state référencé doit être déjà durable : `record_raw_account_observation` ne crée jamais de `RawAccountState` et ne retransmet pas ses bytes. Le lock `FOR KEY SHARE` protège la référence pendant l'insertion observation/FK sans prendre un lock de contenu plus fort que nécessaire.
|
||||
|
||||
L'idempotence et le conflit réutilisent le chemin `persist_account_observation_row` déjà validé en `pre.005`. Une même clé avec observation identique produit `AlreadyPresent`; une même clé avec contenu/provenance/metadata divergents produit `Conflict`. Le réseau de l'observation est rejeté avant toute acquisition de connexion lorsqu'il diffère du backend.
|
||||
|
||||
La preuve de race/cancellation de cette tranche est volontairement unitaire/structurelle : les canaris imposent l'ordre `transaction -> FOR KEY SHARE -> persist/compare -> commit`, l'absence de commit anticipé et l'absence de tâche détachée ou de fuite volontaire du handle transactionnel. Une cancellation avant commit droppe donc le `Transaction` local et laisse le rollback à PostgreSQL. Les scénarios de vraies tâches concurrentes et `JoinHandle::abort()` restent au test live `pre.009`.
|
||||
|
||||
Restent fermés : `list_raw_account_states`, cursor `KSPA`, `OFFSET`, `UPDATE`/`DELETE`, `ON CONFLICT DO UPDATE`, les quatre implémentations `RawAccount*` sur `PostgresBackend` et tout dispatch account dans `Store`. Les migrations V000/V001/V002 sont inchangées ; le checksum V002 final reste `ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user