199 lines
6.7 KiB
Markdown
199 lines
6.7 KiB
Markdown
<!-- file: deltas/0.3.8/pre.004.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.3.8-pre.004` — inspection PostgreSQL RawTransaction et dispatch Store
|
|
|
|
## Base requise
|
|
|
|
Base directe attendue :
|
|
|
|
```text
|
|
0.3.8-pre.003-fix.001
|
|
workspace.package.version = 0.3.8-pre.3.fix.1
|
|
```
|
|
|
|
Le gate opérateur fourni sur cette base est entièrement vert : audits Rust/Markdown, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, `ksp-store-api`, `ksp-store-lib`, `ksp-store-lib --no-default-features` et `ksp-app-store-desk`.
|
|
|
|
La livraison est :
|
|
|
|
```text
|
|
0.3.8-pre.004
|
|
workspace.package.version = 0.3.8-pre.4
|
|
commit = v0.3.8-pre.004
|
|
tag = aucun
|
|
```
|
|
|
|
## Objectif
|
|
|
|
Implémenter le premier vertical slice physique de la primitive backend-neutral créée en `pre.003` :
|
|
|
|
```text
|
|
RawTransactionInspectionRead
|
|
ksp-store-postgres-lib
|
|
-> ksp-store-lib::Store
|
|
```
|
|
|
|
`RawAccountStateInspectionRead` reste volontairement non implémenté jusqu'à `pre.005`. Aucun SQL de migration, aucune UI Store Desk et aucun branchement DataTables `serverSide` ne sont introduits.
|
|
|
|
## SQL d'inspection
|
|
|
|
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, signature
|
|
LIMIT/OFFSET
|
|
```
|
|
|
|
Cette forme garantit que counts et page sont issus du même snapshot de statement PostgreSQL.
|
|
|
|
Lorsque le range slot est absent, `filtered_count` est réutilisé comme `total_count`; aucun second `COUNT(*)` n'est exécuté. Avec un filtre slot, `total_items` reste le total exact de la famille transaction dans le Store/network et `filtered_items` représente le sous-ensemble filtré.
|
|
|
|
Les tombstones `Purged` sont inclus dans l'inspection afin que l'outil opérateur puisse voir l'état de rétention durable. Le listage cursor/keyset historique reste inchangé et continue d'exclure `Purged`.
|
|
|
|
## Pas de transfert payload / pas de N+1
|
|
|
|
Le statement de page ne sélectionne jamais :
|
|
|
|
```text
|
|
transaction_row.payload
|
|
archive_row.payload
|
|
```
|
|
|
|
Il projette seulement :
|
|
|
|
```text
|
|
OCTET_LENGTH(transaction_row.payload)
|
|
OCTET_LENGTH(archive_row.payload)
|
|
hot_payload_present
|
|
archive_payload_present
|
|
```
|
|
|
|
Le summary final est donc construit en une seule requête, sans chargement individuel par ligne et sans gros bytes IPC/runtime. Les marqueurs de présence permettent en outre de rejeter une forme PostgreSQL incohérente (`Full` avec archive résiduelle, `Archived` avec hot payload, `Purged` avec payload ou block time résiduel).
|
|
|
|
## Limites physiques et offset
|
|
|
|
`RawPageLimit` reste sans plafond politique côté API. Le backend 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`. Ces validations sont effectuées avant `pool.get()`.
|
|
|
|
Une page vide causée par un offset supérieur à `filtered_items` reste valide et retourne les counts exacts avec `items = []`.
|
|
|
|
## Façade Store
|
|
|
|
`PostgresBackend` et `Store` implémentent désormais `RawTransactionInspectionRead`. Le dispatch Store applique d'abord le même guard network que les autres opérations network-scoped.
|
|
|
|
L'inventaire physique/facade passe donc temporairement de 10 à 11 capabilities RAW implémentées :
|
|
|
|
```text
|
|
10 historiques
|
|
+ RawTransactionInspectionRead
|
|
= 11
|
|
```
|
|
|
|
Les deux inventaires restent strictement symétriques et `RawAccountStateInspectionRead` est explicitement absent jusqu'à `pre.005`.
|
|
|
|
## Cursor/keyset préservé
|
|
|
|
Les statements historiques `LIST_TRANSACTIONS_ASC_SQL` / `LIST_TRANSACTIONS_DESC_SQL` restent contrôlés séparément :
|
|
|
|
```text
|
|
keyset (slot, signature)
|
|
LIMIT + continuation probe
|
|
aucun OFFSET
|
|
retention_state <> 'purged'
|
|
```
|
|
|
|
L'exception `OFFSET` est donc locale au chemin inspection random-access et ne modifie pas le contrat machine/replay/backfill.
|
|
|
|
## Tests et canaris
|
|
|
|
Le delta ajoute/actualise les preuves suivantes :
|
|
|
|
- conversion limit/offset hostile avant I/O ;
|
|
- décodage summary `Full` / `Archived` / `Purged` sans bytes ;
|
|
- rejet des résidus physiques incompatibles avec l'état de rétention ;
|
|
- canari SQL séparant explicitement keyset sans OFFSET et inspection avec OFFSET ;
|
|
- preuve que l'inspection utilise counts, LATERAL page et `OCTET_LENGTH` sans sélectionner les payloads ;
|
|
- inventaires exacts 11/11 côté backend et façade ;
|
|
- live proof PostgreSQL opt-in : filtre slot, counts, asc/desc, offset et page vide profonde.
|
|
|
|
## Fichiers ajoutés
|
|
|
|
```text
|
|
deltas/0.3.8/pre.004.md
|
|
```
|
|
|
|
## Fichiers modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
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/error.rs
|
|
crates/ksp-store-postgres-lib/src/lib.rs
|
|
crates/ksp-store-postgres-lib/src/raw_transaction.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_transaction_live.rs
|
|
crates/ksp-store-postgres-lib/tests/public_api.rs
|
|
crates/ksp-store-postgres-lib/unit_tests/raw_transaction.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), 696 file(s))
|
|
pre.004 structural contract audit: clean
|
|
workspace.package.version: 0.3.8-pre.4
|
|
Store Raw capability implementations: 11
|
|
PostgreSQL Raw capability implementations: 11
|
|
RawAccountStateInspectionRead implementations: 0
|
|
RawTransaction keyset OFFSET occurrences: 0
|
|
RawTransaction 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.004` n'est donc revendiqué localement. Le gate opérateur requis est :
|
|
|
|
```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
|
|
```
|
|
|
|
Le live proof reste opt-in et doit être exécuté uniquement sur une base PostgreSQL dédiée vide si une preuve réelle est souhaitée :
|
|
|
|
```bash
|
|
cargo test -p ksp-store-postgres-lib --test postgres_raw_transaction_live -- --ignored --nocapture
|
|
```
|