# Delta `0.3.8-pre.005` — inspection PostgreSQL RawAccountState et dispatch Store ## Base requise Base directe attendue : ```text 0.3.8-pre.004-fix.001 workspace.package.version = 0.3.8-pre.4.fix.1 ``` Le gate opérateur de cette base est entièrement vert et le live proof RawTransaction a réellement passé sur PostgreSQL 17. La livraison est : ```text 0.3.8-pre.005 workspace.package.version = 0.3.8-pre.5 commit = v0.3.8-pre.005 tag = aucun ``` ## Objectif Compléter le second vertical slice physique de l'API d'inspection backend-neutral : ```text RawAccountStateInspectionRead ksp-store-postgres-lib -> ksp-store-lib::Store ``` Les deux familles RAW disposent alors de leur capability d'inspection random-access. Aucun branchement UI/DataTables, aucune migration et aucune capability destructive Account ne sont ajoutés. ## SQL d'inspection Account Deux statements privés existent, un par direction canonique. Chaque appel exécute une seule instruction SQL comprenant : ```text filtered_count conditional total_count LATERAL page ORDER BY slot, pubkey, state_hash LIMIT/OFFSET ``` `filtered_items` applique le filtre exact `pubkey` optionnel et le range slot inclusif. `total_items` reste le nombre exact de lignes `ksp_raw_account_states`. Lorsqu'aucun filtre n'est actif, le count filtré est réutilisé comme total. Counts et page proviennent donc du même snapshot de statement PostgreSQL. ## Aucun transfert de data bytes Le statement ne sélectionne jamais : ```text account_row.data ``` Il projette uniquement : ```text OCTET_LENGTH(account_row.data)::BIGINT AS data_length_bytes ``` Le summary reconstruit uniquement l'identité canonique, lamports, owner, executable, rent epoch et longueur des données. Aucun N+1 n'est introduit. ## Pagination et limites physiques Le chemin inspection convertit avant I/O : ```text limit -> i64 PostgreSQL offset -> i64 PostgreSQL ``` Un limit non représentable renvoie `PageLimitUnsupported`; un offset non représentable renvoie `QueryInvalid`. Les quatre statements Account historiques de pagination cursor/keyset restent OFFSET-free : ```text LIST_ACCOUNT_STATES_ASC_SQL LIST_ACCOUNT_STATES_DESC_SQL LIST_ACCOUNT_STATES_BY_PUBKEY_ASC_SQL LIST_ACCOUNT_STATES_BY_PUBKEY_DESC_SQL ``` L'OFFSET reste donc strictement local à l'inspection random-access. ## Façade Store et inventaire `PostgresBackend` et `Store` implémentent désormais `RawAccountStateInspectionRead`, avec guard network côté façade avant dispatch. L'inventaire RAW passe de 11 à 12 capabilities sur les deux couches : ```text 11 historiques incluant RawTransactionInspectionRead + RawAccountStateInspectionRead = 12 ``` Les inventaires Store/PostgreSQL restent exactement symétriques. ## Tests et live proof Le delta ajoute ou renforce les preuves suivantes : - conversion hostile limit/offset avant I/O ; - summary data-free avec domaine `u64` complet ; - rejet widths/décimaux/data length hostiles sans echo ; - séparation explicite keyset OFFSET-free / inspection avec OFFSET ; - SQL counted, single-statement, `OCTET_LENGTH(data)` et aucun data bytes ; - inventaires exacts 12/12 ; - live proof Account opt-in : filtre pubkey, counts, ordre asc/desc, offset, data length et page vide profonde. ## Fichiers ajoutés ```text deltas/0.3.8/pre.005.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-store-lib/src/lib.rs crates/ksp-store-lib/src/store.rs crates/ksp-store-lib/tests/dependency_boundary.rs crates/ksp-store-lib/tests/hardening_completeness.rs crates/ksp-store-lib/tests/public_api.rs 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/postgres_raw_account_live.rs crates/ksp-store-postgres-lib/tests/public_api.rs crates/ksp-store-postgres-lib/unit_tests/raw_account.rs docs/plans/029-V0_3_8_STORE_DESK_PLAN.md docs/validation/025-V0_3_8_STORE_DESK.md ``` ## Fichiers supprimés ```text aucun ``` ## Validations d'assemblage Contrôles exécutés avant emballage : ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) KSP workspace Rust rule audit: clean Markdown table audit: clean (314 table(s), 698 file(s)) pre.005 structural contract audit: clean workspace.package.version: 0.3.8-pre.5 Store RAW capability implementations: 12 PostgreSQL RAW capability implementations: 12 RawAccount keyset OFFSET occurrences: 0 RawAccount inspection OFFSET occurrences: 2 delta scope: 1 ajout / 16 modifications / 0 suppression ``` Le sandbox d'assemblage ne dispose pas de `cargo`/`rustfmt`; aucun gate Cargo de `pre.005` n'est donc revendiqué localement. ## Gate requis ```bash 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 cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-store-postgres-lib cargo test -p ksp-store-lib cargo check -p ksp-store-lib --no-default-features cargo test -p ksp-store-api ``` Live proof opt-in, uniquement sur base PostgreSQL dédiée vide : ```bash read -rsp 'Dedicated PostgreSQL URI: ' KSP_LIVE_PG_URI printf '\n' printf '%s\n' "$KSP_LIVE_PG_URI" | cargo test -p ksp-store-postgres-lib --test postgres_raw_account_live -- --ignored --nocapture unset KSP_LIVE_PG_URI ```