299 lines
10 KiB
Markdown
299 lines
10 KiB
Markdown
<!-- file: deltas/0.3.4/pre.004.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.3.4-pre.004` — mapping PostgreSQL privé et lectures `RawAccountState`
|
|
|
|
## 1. Base requise
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 à :
|
|
|
|
```text
|
|
0.3.4-pre.4
|
|
```
|
|
|
|
Aucune crate ne redéfinit localement la version héritée.
|
|
|
|
## 4. Module physique privé
|
|
|
|
Nouveau module :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
(pubkey, slot, state_hash)
|
|
```
|
|
|
|
Le mapping reconstruit :
|
|
|
|
```text
|
|
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()` :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```text
|
|
V000 = d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
|
|
V001 = 31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51
|
|
V002 = ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e
|
|
```
|
|
|
|
Le bridge du checksum provisoire `pre.002` reste inchangé.
|
|
|
|
## 12. Fichiers ajoutés
|
|
|
|
```text
|
|
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
|
|
|
|
```text
|
|
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
|
|
|
|
```text
|
|
aucun
|
|
```
|
|
|
|
## 15. Validations exécutées
|
|
|
|
Dans l'environnement d'assemblage :
|
|
|
|
```text
|
|
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 :
|
|
|
|
```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
|
|
```
|
|
|
|
## 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
|
|
|
|
```text
|
|
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`.
|