6.3 KiB
Delta 0.3.4-pre.007 — pagination account keyset + cursor KSPA
1. Base requise
0.3.4-pre.6
Le gate opérateur fourni le 2026-08-30 pour pre.006 est entièrement vert :
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 :
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 à :
0.3.4-pre.7
4. Requêtes physiques
raw_account.rs ajoute quatre SELECT privés :
sans pubkey : ASC / DESC
avec pubkey : ASC / DESC
L'ordre total est :
ASC (slot ASC, pubkey ASC, state_hash ASC)
DESC (slot DESC, pubkey DESC, state_hash DESC)
Les continuations utilisent exclusivement :
(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é :
crates/ksp-store-postgres-lib/src/raw_account/cursor.rs
Format fixe :
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 :
KSP/raw-account-state-cursor/v1
Le digest lie :
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 :
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 :
pubkey exact 32 bytes
slot NUMERIC(20,0)::text -> u64 exact
state_hash exact 32 bytes
Le résultat public du bridge est exclusivement :
RawPage<RawAccountStateReference>
Aucun row PostgreSQL, SQL ou cursor décodé ne traverse la frontière backend.
8. Bridge backend
PostgresBackend expose :
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 :
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 :
ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e
10. Fichiers ajoutés
crates/ksp-store-postgres-lib/src/raw_account/cursor.rs
deltas/0.3.4/pre.007.md
11. Fichiers modifiés
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
aucun
13. Validations exécutées à l'assemblage
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
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
KSPTpar 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.