Files
khadhroony-solana-project/deltas/0.3.4/pre.004.md
2026-08-30 21:57:23 +02:00

10 KiB

Delta 0.3.4-pre.004 — mapping PostgreSQL privé et lectures RawAccountState

1. Base requise

0.3.4-pre.3.fix.1

Le gate opérateur fourni le 2026-08-30 pour pre.003-fix.001 est entièrement vert :

cargo fmt --all                                         PASS
audit Rust général / exports / workspace                PASS
audit Markdown                                           PASS — 239 tables / 139 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 — 45 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

V002 finale et son checksum sont donc considérés acquis avant l'ouverture du mapping account.

2. Objectif

Implémenter la tranche de lecture de la vertical slice PostgreSQL RawAccountState sans ouvrir les writes, la pagination ni les implémentations de traits :

mapping SQL privé state
mapping SQL privé observation
get_raw_account_state
get_raw_account_observation
hostile-row guards

Les méthodes du backend retournent uniquement des modèles ksp-store-api. Aucun tokio_postgres::Row, SQL, bind, SQLSTATE ou type physique ne traverse le bridge public.

3. Version

Le workspace passe à :

0.3.4-pre.4

Aucune crate ne redéfinit localement la version héritée.

4. Module physique privé

Nouveau module :

crates/ksp-store-postgres-lib/src/raw_account.rs

Il possède les deux SELECT et les codecs physiques de cette tranche. runtime.rs ne contient aucun SQL métier et délègue les lectures au module privé.

La tranche est strictement read-only :

INSERT INTO          absent
UPDATE               absent
DELETE FROM          absent
ON CONFLICT          absent
FOR UPDATE           absent
list/cursor account  absent

Les écritures state+observation restent pre.005, l'observation supplémentaire pre.006, la pagination/cursor pre.007 et les quatre impl RawAccount* pre.008.

5. get_raw_account_state

Le SELECT adresse exactement la clé physique :

(pubkey, slot, state_hash)

Le mapping reconstruit :

network       <- backend mono-réseau
pubkey        <- BYTEA exactement 32 bytes
slot          <- NUMERIC(20,0)::text -> u64
state_hash    <- BYTEA exactement 32 bytes
lamports      <- NUMERIC(20,0)::text -> u64
owner         <- BYTEA exactement 32 bytes
executable    <- BOOLEAN
rent_epoch    <- NUMERIC(20,0)::text -> u64
data          <- BYTEA exact -> RawAccountState::try_new

Le chemin décimal couvre tout le domaine u64, y compris les valeurs supérieures à i64::MAX et u64::MAX lui-même. Aucun narrowing via BIGINT n'est introduit.

RawAccountState::try_new revalide la borne backend-agnostic des bytes account : data vide est valide ; une ligne hostile dépassant 16 MiB devient DataInvalid.

Après décodage, la référence reconstruite doit rester exactement égale à la référence demandée. Une cardinalité autre que 0/1 est également DataInvalid.

6. Garde réseau pré-I/O

get_raw_account_state vérifie avant pool.get() :

reference.network == backend.network -> continuer
sinon                                -> WrongNetwork

Le mauvais réseau ne consomme donc aucune connexion PostgreSQL et n'expose aucune valeur fournie.

7. get_raw_account_observation

RawObservationKey ne porte pas de réseau. Le réseau de la RawAccountStateReference reconstruite provient donc exclusivement du backend mono-réseau déjà lié par ksp_store_identity.

Le mapping couvre :

observation_key
account.pubkey
account.slot
account.state_hash
provider
protocol
acquisition_method
origin
received_at
capture_session_id optionnel
commitment optionnel
endpoint_id optionnel
filter_id optionnel
observed_at optionnel
source_payload_hash optionnel
source_payload_size_bytes optionnel
is_startup optionnel
transaction_signature optionnelle
write_version optionnel

Spécificités physiques :

account.slot / write_version -> NUMERIC(20,0)::text -> u64
transaction_signature        -> NULL ou exactement 64 bytes
hash/key/pubkey               -> exactement 32 bytes
received/observed             -> BIGINT -> u64 -> RawTimestamp
source payload size           -> BIGINT -> u64 + borne API 64 MiB
provenance codes              -> constructeurs API fallibles
origin                        -> cinq variantes API uniquement

Les metadata Yellowstone restent strictement observation-only. Une colonne NULL reste None; aucune valeur false, zéro, signature ou write version n'est inventée.

8. Hostile-row guards

Les tests unitaires couvrent notamment :

state slot/lamports/rent_epoch = u64::MAX
write_version = u64::MAX
account data vide
account data > 16 MiB -> DataInvalid
pubkey de 31 bytes -> DataInvalid
signature transaction de 63 bytes -> DataInvalid
décimal négatif ou > u64::MAX -> DataInvalid
origin hostile -> DataInvalid
observed_at > received_at -> DataInvalid
metadata optionnelles absentes -> None
wrong network state reference -> WrongNetwork pré-I/O

Les erreurs ne retiennent que PostgresBackendErrorKind + phase &'static str; les chaînes hostiles ne sont jamais interpolées dans l'erreur.

9. Surface backend

PostgresBackend expose désormais le bridge étroit :

get_raw_account_state
get_raw_account_observation

Ces méthodes ne constituent pas encore les implémentations de RawAccountStateRead et RawAccountObservationRead : le premier trait exige aussi list_raw_account_states, réservé à pre.007. Les quatre traits account seront ouverts ensemble en pre.008 afin de passer directement de 6/10 à 10/10 capabilities physiques.

10. Canaries transformés

Les canaris historiques qui interdisaient tout module account sont ajustés sans perdre leur rôle :

  • dependency_boundary.rs exige un module raw_account privé, read-only, sans pagination ni trait impl ;
  • hardening_completeness.rs inclut le nouveau module dans l'inventaire exact et dans les scans anti-secret/anti-reverse-edge ;
  • les interdictions des quatre impl RawAccount* for PostgresBackend restent actives ;
  • public_api.rs prouve que les deux méthodes du bridge n'utilisent que les modèles backend-agnostic.

Les canaris V000/health business-free restent inchangés.

11. Migrations

Aucune ressource sous migrations/ n'est modifiée.

Checksums conservés :

V000 = d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
V001 = 31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51
V002 = ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e

Le bridge du checksum provisoire pre.002 reste inchangé.

12. Fichiers ajoutés

crates/ksp-store-postgres-lib/src/raw_account.rs
crates/ksp-store-postgres-lib/unit_tests/raw_account.rs
deltas/0.3.4/pre.004.md

13. Fichiers modifiés

Cargo.toml
crates/ksp-store-postgres-lib/src/lib.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
docs/plans/025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md
docs/validation/021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md

14. Fichiers supprimés

aucun

15. Validations exécutées

Dans l'environnement d'assemblage :

python3 scripts/audit_rust_workspace_rules.py
    General Rust rule audit: clean
    Rust export completeness audit: 0 candidate(s)
    KSP workspace Rust rule audit: clean

python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.4
    PASS après alignement RustRover des tableaux touchés

Le contrôle différentiel doit également confirmer qu'aucune ressource V000/V001/V002 n'a changé.

16. Validations non exécutées dans l'environnement d'assemblage

cargo, rustc et rustfmt ne sont pas disponibles dans cet environnement. Ne sont donc pas revendiqués PASS ici :

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

17. Décisions prises

  • Réutiliser la frontière éprouvée de 0.3.3-pre.004 : SQL/mapping privé, méthodes backend étroites, traits plus tard.
  • Garder les conversions NUMERIC(20,0) via ::text -> u64 afin de ne pas ajouter de dépendance décimale ni de narrowing.
  • Revalider les invariants API au read même si V002 possède déjà des CHECK SQL ; la DB peut être externe, héritée ou hostile.
  • Ne pas factoriser prématurément les codecs transaction/account dans un nouveau module commun : les familles ont des formes différentes et pre.004 doit rester bornée.
  • Ne pas ouvrir RawAccountStateRead avant que list_raw_account_states existe ; l'inventaire de capabilities reste volontairement 6/10 jusqu'à pre.008.

18. Questions ouvertes

Aucune question bloquante nouvelle. Les détails des writes, races et cursor restent ceux figés par le plan pre.001 et appartiennent respectivement à pre.005, pre.006 et pre.007.

19. Gate opérateur attendu

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.4
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

Aucun test live PostgreSQL account n'est demandé dans cette tranche ; la preuve live complète reste pre.009.