v0.3.4-pre.007

This commit is contained in:
2026-08-30 22:47:33 +02:00
parent fccb7d876c
commit 902b5fba99
12 changed files with 904 additions and 16 deletions

248
deltas/0.3.4/pre.007.md Normal file
View File

@@ -0,0 +1,248 @@
<!-- file: deltas/0.3.4/pre.007.md -->
<!-- version: 1 -->
# Delta `0.3.4-pre.007` — pagination account keyset + cursor `KSPA`
## 1. Base requise
```text
0.3.4-pre.6
```
Le gate opérateur fourni le 2026-08-30 pour `pre.006` est entièrement vert :
```text
cargo fmt --all PASS
audit Rust général / exports / workspace PASS
audit Markdown PASS — 239 tables / 143 files
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS
cargo test -p ksp-store-api PASS
cargo test -p ksp-store-lib PASS
cargo test -p ksp-store-postgres-lib PASS — 58 unit tests + canaris, live ignored
cargo test -p ksp-config-lib PASS — 128 unit tests + ownership/public API
cargo check -p ksp-store-lib --no-default-features PASS
```
L'observation supplémentaire account et son contrat transactionnel/cancellation sont donc considérés acquis.
## 2. Objectif
Implémenter uniquement la navigation `RawAccountStateQuery` :
```text
ordre total (slot, pubkey, state_hash)
ASC / DESC complètement inversés
filtre pubkey optionnel
bornes de slot inclusives
keyset pagination uniquement
cursor account KSPA V1
LIMIT + 1 sans policy KSP
```
Les quatre capabilities account et leur dispatch `Store` restent hors tranche jusqu'à `pre.008`.
## 3. Version
Le workspace passe à :
```text
0.3.4-pre.7
```
## 4. Requêtes physiques
`raw_account.rs` ajoute quatre SELECT privés :
```text
sans pubkey : ASC / DESC
avec pubkey : ASC / DESC
```
L'ordre total est :
```text
ASC (slot ASC, pubkey ASC, state_hash ASC)
DESC (slot DESC, pubkey DESC, state_hash DESC)
```
Les continuations utilisent exclusivement :
```text
(slot, pubkey, state_hash) > (last_slot, last_pubkey, last_state_hash)
(slot, pubkey, state_hash) < (last_slot, last_pubkey, last_state_hash)
```
Sans filtre, l'index V002 `(slot, pubkey, state_hash)` porte la navigation. Avec filtre pubkey, la PK `(pubkey, slot, state_hash)` porte le préfixe account et le même ordre déterministe.
## 5. Cursor account V1
Nouveau module privé :
```text
crates/ksp-store-postgres-lib/src/raw_account/cursor.rs
```
Format fixe :
```text
0..4 magic KSPA
4 version 1
5..13 last_slot u64 big-endian
13..45 last_pubkey 32 bytes
45..77 last_state_hash 32 bytes
77..109 SHA-256 binding digest
```
Domaine :
```text
KSP/raw-account-state-cursor/v1
```
Le digest lie :
```text
network
pubkey filter presence/value
direction
slot.start_inclusive
slot.end_inclusive
last_slot
last_pubkey
last_state_hash
```
Un cursor transaction `KSPT` ne peut donc pas être rejoué comme cursor account et échoue dès le magic.
## 6. Limite physique de page
Comme la verticale transaction, le backend applique `LIMIT + 1` uniquement pour détecter une page suivante. Aucun maximum fonctionnel KSP n'est ajouté.
La limite physique exacte reste :
```text
9_223_372_036_854_775_806
```
car `requested + 1` doit être représentable par un `i64` PostgreSQL.
## 7. Mapping de liste
Chaque row de liste revalide :
```text
pubkey exact 32 bytes
slot NUMERIC(20,0)::text -> u64 exact
state_hash exact 32 bytes
```
Le résultat public du bridge est exclusivement :
```text
RawPage<RawAccountStateReference>
```
Aucun row PostgreSQL, SQL ou cursor décodé ne traverse la frontière backend.
## 8. Bridge backend
`PostgresBackend` expose :
```text
list_raw_account_states(
&RawAccountStateQuery,
) -> RawPage<RawAccountStateReference>
```
Ce bridge reste une méthode étroite. `RawAccountStateRead`, `RawAccountStateWrite`, `RawAccountObservationRead` et `RawAccountObservationWrite` ne sont toujours pas implémentés sur `PostgresBackend`.
## 9. Scope négatif
Restent absents :
```text
OFFSET
batch max 500/1000
priority / worker policy
clamp/min artificiel
UPDATE / DELETE account
ON CONFLICT DO UPDATE
impl RawAccountStateRead for PostgresBackend
impl RawAccountStateWrite for PostgresBackend
impl RawAccountObservationRead for PostgresBackend
impl RawAccountObservationWrite for PostgresBackend
Store dispatch account
```
Toutes les migrations V000/V001/V002 restent byte-inchangées. Le checksum V002 final reste :
```text
ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e
```
## 10. Fichiers ajoutés
```text
crates/ksp-store-postgres-lib/src/raw_account/cursor.rs
deltas/0.3.4/pre.007.md
```
## 11. Fichiers modifiés
```text
Cargo.toml
crates/ksp-store-postgres-lib/src/lib.rs
crates/ksp-store-postgres-lib/src/raw_account.rs
crates/ksp-store-postgres-lib/src/runtime.rs
crates/ksp-store-postgres-lib/tests/dependency_boundary.rs
crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
crates/ksp-store-postgres-lib/tests/public_api.rs
crates/ksp-store-postgres-lib/unit_tests/raw_account.rs
docs/plans/025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md
docs/validation/021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md
```
## 12. Fichiers supprimés
```text
aucun
```
## 13. Validations exécutées à l'assemblage
```text
python3 scripts/audit_rust_workspace_rules.py PASS
python3 scripts/audit_markdown_tables.py ... deltas/0.3.4 PASS
migrations V000/V001/V002 byte-identiques à pre.006 PASS
scope pre.008 absent PASS
```
Le gate Cargo/Clippy/tests de `pre.007` doit être rejoué par l'opérateur.
## 14. Validations non exécutées
```text
cargo fmt --all
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
```
`cargo` n'est pas disponible dans l'environnement d'assemblage.
## 15. Décisions prises
- le cursor account reste distinct de `KSPT` par magic et domaine SHA-256 ;
- le filtre pubkey fait partie du binding du cursor ;
- les deux chemins SQL avec/sans pubkey sont séparés pour conserver une surface physique compatible avec les indexes possédés ;
- aucune policy d'exécution n'est ajoutée à la pagination Store ;
- les quatre capabilities account restent groupées pour `pre.008`.
## 16. Questions ouvertes
Aucune question bloquante pour `pre.008`.