v0.3.3-pre.001
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 347
|
||||
# version: 348
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.2"
|
||||
version = "0.3.3-pre.1"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
283
deltas/0.3.3/pre.001.md
Normal file
283
deltas/0.3.3/pre.001.md
Normal file
@@ -0,0 +1,283 @@
|
||||
<!-- file: deltas/0.3.3/pre.001.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.3.3-pre.001` — audit et physical design RawTransaction PostgreSQL
|
||||
|
||||
## 1. Objet
|
||||
|
||||
Ouverture de :
|
||||
|
||||
```text
|
||||
0.3.3 — Store/PostgreSQL RawTransaction vertical slice
|
||||
```
|
||||
|
||||
Cette tranche reste volontairement documentaire/conception : elle fixe l'audit, le threat model, le design physique V001 et le séquencement avant toute migration ou persistence métier.
|
||||
|
||||
## 2. Base
|
||||
|
||||
Base canonique :
|
||||
|
||||
```text
|
||||
v0.3.2
|
||||
```
|
||||
|
||||
Le gate opérateur fourni pour `0.3.2` est propre : audits Rust/Markdown, workspace check, Clippy, tests Store/API/PostgreSQL foundation/Config et `ksp-store-lib --no-default-features` passent ; les tests live restent opt-in/ignored conformément à la fondation.
|
||||
|
||||
## 3. Version
|
||||
|
||||
Version workspace après overlay :
|
||||
|
||||
```text
|
||||
0.3.3-pre.1
|
||||
```
|
||||
|
||||
Label de livraison :
|
||||
|
||||
```text
|
||||
0.3.3-pre.001
|
||||
```
|
||||
|
||||
## 4. Fichiers ajoutés
|
||||
|
||||
```text
|
||||
docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md
|
||||
docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md
|
||||
deltas/0.3.3/pre.001.md
|
||||
```
|
||||
|
||||
## 5. Fichier modifié
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
```
|
||||
|
||||
Modifications :
|
||||
|
||||
```text
|
||||
workspace.package.version : 0.3.2 -> 0.3.3-pre.1
|
||||
file header version : 347 -> 348
|
||||
```
|
||||
|
||||
## 6. Fichiers supprimés
|
||||
|
||||
Aucun.
|
||||
|
||||
## 7. Audit effectué
|
||||
|
||||
Ont été relus avant design :
|
||||
|
||||
- règles générales/KSP/Rust/dépendances/docs/file contracts/version workflow/prompt structure ;
|
||||
- architectures Layers/Dependencies/Store/API/Config concernées ;
|
||||
- plan/validation `0.3.1` ;
|
||||
- source/tests complets `ksp-store-api` ;
|
||||
- plan/validation `0.3.2` ;
|
||||
- source/tests complets `ksp-store-lib` et `ksp-store-postgres-lib` ;
|
||||
- surface Config `std.store` ;
|
||||
- archive historique kbot3 ciblée demandée par le prompt ;
|
||||
- documentation PostgreSQL/tokio-postgres nécessaire aux choix numériques et de concurrence.
|
||||
|
||||
## 8. Décisions majeures
|
||||
|
||||
### 8.1 `slot: u64`
|
||||
|
||||
`BIGINT` est rejeté pour `slot` car il narrowe le domaine API. V001 utilisera :
|
||||
|
||||
```text
|
||||
NUMERIC(20,0)
|
||||
```
|
||||
|
||||
avec conversion décimale fallible et tests jusqu'à `u64::MAX`.
|
||||
|
||||
### 8.2 Réseau physique
|
||||
|
||||
V001 introduira :
|
||||
|
||||
```text
|
||||
ksp_store_identity
|
||||
```
|
||||
|
||||
Une base V001 est mono-réseau. Le binding est créé/validé sous le bootstrap lock afin qu'une URI pointant vers un autre réseau échoue avant exposition d'un backend prêt.
|
||||
|
||||
### 8.3 Schéma RAW minimal
|
||||
|
||||
Tables décidées :
|
||||
|
||||
```text
|
||||
ksp_store_identity
|
||||
ksp_raw_transactions
|
||||
ksp_raw_transaction_observations
|
||||
ksp_raw_transaction_archive_payloads
|
||||
```
|
||||
|
||||
Index métier additionnel unique :
|
||||
|
||||
```text
|
||||
(slot, signature) WHERE retention_state <> 'purged'
|
||||
```
|
||||
|
||||
Aucun index provider/status/created_at/hash n'est ajouté sans requête correspondante.
|
||||
|
||||
### 8.4 Atomicité/idempotence
|
||||
|
||||
Le repository n'utilisera aucun `has_*` préalable. La stratégie est :
|
||||
|
||||
```text
|
||||
INSERT ... ON CONFLICT DO NOTHING RETURNING
|
||||
-> si conflit : SELECT ... FOR UPDATE
|
||||
-> comparaison exacte du contenu
|
||||
-> AlreadyPresent ou ERROR_CODE_RAW_CONFLICT
|
||||
```
|
||||
|
||||
Le canonique et son observation d'acquisition sont dans la même transaction PostgreSQL.
|
||||
|
||||
### 8.5 Pagination
|
||||
|
||||
Ordre total :
|
||||
|
||||
```text
|
||||
(slot, signature)
|
||||
```
|
||||
|
||||
Cursor backend-private V1 fixe 109 octets, lié par SHA-256 au réseau, à la direction, au slot range et à la dernière clé. Aucun cap métier arbitraire n'est ajouté.
|
||||
|
||||
### 8.6 Rétention
|
||||
|
||||
`Full`, `Archived` et `Purged` sont représentables honnêtement par le backend `0.3.3` avec une relation archive séparée du hot path.
|
||||
|
||||
`Compacted` n'est pas assimilé au TOAST PostgreSQL et n'est pas simulé. Le plan `0.3.1` le qualifiait déjà d'optionnel ; aucun changement `ksp-store-api` n'est donc justifié. Les transitions qui l'impliquent seront rejetées avant I/O par `store.postgres_retention_compaction_unsupported`.
|
||||
|
||||
## 9. Audit kbot3
|
||||
|
||||
Classification effectuée :
|
||||
|
||||
- **REPRENDRE** : unicités, FK, keyset/index slot conceptuels ;
|
||||
- **REDESSINER** : fixed bytes, payload opaque, u64 exact, atomicité, conflit réel, réseau, retention compare-and-transition ;
|
||||
- **REPORTER** : indexes provider/status/time, processing/replay, batches, apps, AccountState ;
|
||||
- **REJETER** : sqlx, `has_*`, JSONB canonique, narrowing i64/i32, FK `SET NULL`, error text SQL, caps 500/1000, processing_state RAW.
|
||||
|
||||
Aucun code historique n'est copié.
|
||||
|
||||
## 10. Threat model couvert
|
||||
|
||||
Le plan couvre explicitement :
|
||||
|
||||
- mauvaise URI/réseau ;
|
||||
- DB bytes malformés ;
|
||||
- overflow u64 ;
|
||||
- observation orpheline ;
|
||||
- inserts identiques/divergents concurrents ;
|
||||
- collision observation ;
|
||||
- cursor hostile/replay ;
|
||||
- ambiguïté pagination ;
|
||||
- retention race ;
|
||||
- purge/read/write race ;
|
||||
- ForceRehydrate race ;
|
||||
- fuite SQL/server text ;
|
||||
- cancellation/rollback ;
|
||||
- migration mismatch.
|
||||
|
||||
## 11. Séquencement recalibré
|
||||
|
||||
Le forecast initial est étendu à `pre.013` afin de séparer proprement :
|
||||
|
||||
1. généralisation du moteur de migration ;
|
||||
2. V001/binding réseau ;
|
||||
3. mapping/read ;
|
||||
4. write/observation atomiques ;
|
||||
5. pagination ;
|
||||
6. rétention ;
|
||||
7. façade ;
|
||||
8. live PostgreSQL ;
|
||||
9. hardening ;
|
||||
10. gate ;
|
||||
11. docs ;
|
||||
12. publication.
|
||||
|
||||
## 12. Hors scope conservé
|
||||
|
||||
Aucun changement fonctionnel n'est apporté à :
|
||||
|
||||
```text
|
||||
RawAccountState
|
||||
N2
|
||||
workers/jobs/backfills
|
||||
apps
|
||||
transport
|
||||
codecs wire
|
||||
event bus
|
||||
compression/archive worker global
|
||||
autres backends
|
||||
```
|
||||
|
||||
## 13. Validations exécutées
|
||||
|
||||
Audit statique de la base et de l'overlay :
|
||||
|
||||
```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.3
|
||||
Markdown table audit: clean (214 table(s), 131 file(s))
|
||||
|
||||
assertions structurelles locales
|
||||
workspace.package.version = 0.3.3-pre.1
|
||||
headers/version des trois nouveaux Markdown corrects
|
||||
aucune référence résiduelle au faux code API RAW_RETENTION_UNSUPPORTED
|
||||
```
|
||||
|
||||
L'audit de base couvre aussi manifests/features, modules/exports, V000 et checksum, Config `std.store`, plans/validations `0.3.1`/`0.3.2`, tests hardening/completeness et preuve live documentée.
|
||||
|
||||
## 14. Validations non exécutées
|
||||
|
||||
Le conteneur d'assemblage ne fournit pas l'exécutable `cargo`. Les commandes suivantes sont donc **NON EXÉCUTÉES**, jamais déclarées PASS :
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
Les tests PostgreSQL live ne sont pas exécutés non plus. `pre.001` ne modifie aucun SQL/runtime métier, la preuve foundation réelle `0.3.2` est déjà acquise et le futur test RawTransaction n'existe pas encore.
|
||||
|
||||
## 15. Questions ouvertes
|
||||
|
||||
Aucune question de design bloquante n'est laissée ouverte par `pre.001`.
|
||||
|
||||
Les valeurs runtime retenues sont déjà fixées :
|
||||
|
||||
```text
|
||||
store.postgres_retention_compaction_unsupported
|
||||
store.wrong_network
|
||||
store.raw_reference_not_found
|
||||
store.postgres_read_failed
|
||||
store.postgres_write_failed
|
||||
store.postgres_data_invalid
|
||||
store.postgres_page_limit_unsupported
|
||||
```
|
||||
|
||||
Le checksum V001 n'est pas une question de design : il sera calculé sur les bytes exacts lorsque `V001__raw_transaction.sql` sera créé en `pre.003`.
|
||||
|
||||
## 16. Gate demandé
|
||||
|
||||
```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/0.3.3
|
||||
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 PostgreSQL live n'est requis dans cette tranche documentaire.
|
||||
1161
docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md
Normal file
1161
docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md
Normal file
File diff suppressed because it is too large
Load Diff
594
docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md
Normal file
594
docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md
Normal file
@@ -0,0 +1,594 @@
|
||||
<!-- file: docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Validation `0.3.3` — Store/PostgreSQL RawTransaction vertical slice
|
||||
|
||||
## 1. Objet
|
||||
|
||||
Cette validation accompagne :
|
||||
|
||||
```text
|
||||
0.3.3 — Store/PostgreSQL RawTransaction vertical slice
|
||||
```
|
||||
|
||||
Elle démarre en `0.3.3-pre.001` comme matrice de preuve. Les lignes non encore implémentées restent explicitement `À FAIRE`; elles ne sont pas présentées comme acquises.
|
||||
|
||||
## 2. Baseline stable
|
||||
|
||||
| Preuve | Attendu `pre.001` | Statut |
|
||||
|-----------------------------------------|--------------------------------------------------------------------|--------|
|
||||
| Base de travail | archive/tag `v0.3.2` | PASS |
|
||||
| workspace package version avant overlay | `0.3.2` | PASS |
|
||||
| Gate opérateur `0.3.2` | audits/check/clippy/tests Store+Config/no-default-features propres | PASS |
|
||||
| PostgreSQL live métier `0.3.2` | absent ; seule fondation opt-in existe | PASS |
|
||||
| Prompt release | `prompts/022-V0_3_3_START_PROMPT.md` | PASS |
|
||||
| Archive historique kbot3 | audit ciblé uniquement | PASS |
|
||||
|
||||
## 2.1 Inventaire exact `0.3.2`
|
||||
|
||||
```text
|
||||
ksp-store-api modules=capability,error,model root pub use=60
|
||||
ksp-store-lib modules=constants,error,health,settings,store root pub use=84, default feature=postgres
|
||||
ksp-store-postgres-lib modules=constants,error,health,migration,runtime root pub use=7
|
||||
V000__bootstrap.sql SHA-256=d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450
|
||||
std.store format_version 1
|
||||
std.store profiles devnet/devnet, mainnet/mainnet-beta, testnet/testnet
|
||||
foundation live PASS PostgreSQL 17 en pre.008 et pre.010
|
||||
```
|
||||
|
||||
Le test live est `#[ignore]` dans les gates ordinaires mais sa preuve réelle antérieure est documentée dans `019-V0_3_2_STORE_POSTGRES_FOUNDATION.md`.
|
||||
|
||||
## 3. Scope exact des capacités
|
||||
|
||||
| Capacité | Backend PostgreSQL | Façade Store | Preuve finale |
|
||||
|----------------------------------|--------------------|--------------|---------------------------|
|
||||
| `RawTransactionRead` | À FAIRE | À FAIRE | unit + integration + live |
|
||||
| `RawTransactionWrite` | À FAIRE | À FAIRE | unit + concurrency live |
|
||||
| `RawTransactionObservationRead` | À FAIRE | À FAIRE | unit + live |
|
||||
| `RawTransactionObservationWrite` | À FAIRE | À FAIRE | unit + concurrency live |
|
||||
| `RawTransactionRetentionRead` | À FAIRE | À FAIRE | unit + live |
|
||||
| `RawTransactionRetentionWrite` | À FAIRE | À FAIRE | unit + race live |
|
||||
|
||||
Aucune capacité `RawAccountState`, structurale N2, job ou worker n'est admise dans cette matrice.
|
||||
|
||||
### 3.1 Matrice `RawTransactionRead`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|-------------------------------------------------------------|
|
||||
| input | reference pour get; query pour list |
|
||||
| invariants pré-I/O | network exact; cursor lié à query |
|
||||
| transaction SQL | aucune; statement cohérent |
|
||||
| rows touchées | transaction + archive pour get; index transaction pour list |
|
||||
| idempotence | N/A |
|
||||
| conflit | N/A; corruption != conflict métier |
|
||||
| absence/not-found | get None; list vide |
|
||||
| error mapping | query/wrong-network/data/query-failed sûrs |
|
||||
| concurrence | statement snapshot; aucun snapshot inter-pages |
|
||||
| test déterministe | full/archive/purged, u64 max, ranges, cursor hostile |
|
||||
| test PostgreSQL live | get exact + pages multi-slot/ties dans deux directions |
|
||||
|
||||
### 3.2 Matrice `RawTransactionWrite`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|-------------------------------------------------------------------|
|
||||
| input | transaction + observation + acquisition mode |
|
||||
| invariants pré-I/O | deux networks exacts; observation reference = canonical reference |
|
||||
| transaction SQL | une transaction atomique |
|
||||
| rows touchées | canonical + observation + archive si état existant Archived |
|
||||
| idempotence | contenu exact identique -> AlreadyPresent |
|
||||
| conflit | divergence même signature -> ERROR_CODE_RAW_CONFLICT |
|
||||
| absence/not-found | insert; Purged Normal compatible -> SkippedPurged/NotRecorded |
|
||||
| error mapping | API model/conflict; physical write/data sûrs |
|
||||
| concurrence | unique insert + FOR UPDATE du gagnant |
|
||||
| test déterministe | equality/conflict/tombstone/modes/redaction |
|
||||
| test PostgreSQL live | identical/divergent concurrent + rollback + force |
|
||||
|
||||
### 3.3 Matrice `RawTransactionObservationRead`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|-----------------------------------------------|
|
||||
| input | observation key |
|
||||
| invariants pré-I/O | key API valide; database network déjà bound |
|
||||
| transaction SQL | aucune |
|
||||
| rows touchées | observation |
|
||||
| idempotence | N/A |
|
||||
| conflit | N/A |
|
||||
| absence/not-found | None |
|
||||
| error mapping | stored-row invalid/query-failed sûrs |
|
||||
| concurrence | observation immuable, statement snapshot |
|
||||
| test déterministe | provenance complète/optionnelle + hostile row |
|
||||
| test PostgreSQL live | observation round-trip exact |
|
||||
|
||||
### 3.4 Matrice `RawTransactionObservationWrite`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|-----------------------------------------------------------|
|
||||
| input | observation |
|
||||
| invariants pré-I/O | observation transaction network exact |
|
||||
| transaction SQL | oui |
|
||||
| rows touchées | canonical verrouillé + observation |
|
||||
| idempotence | same key + fields identical -> AlreadyPresent |
|
||||
| conflit | same key + divergence -> ERROR_CODE_RAW_CONFLICT |
|
||||
| absence/not-found | canonical absent -> safe not-found; Purged -> NotRecorded |
|
||||
| error mapping | provenance/conflict API + not-found/write sûrs |
|
||||
| concurrence | canonical FOR UPDATE + unique observation key |
|
||||
| test déterministe | equality/missing/purged/error canaries |
|
||||
| test PostgreSQL live | identical/divergent observation races |
|
||||
|
||||
### 3.5 Matrice `RawTransactionRetentionRead`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|----------------------------------------------|
|
||||
| input | transaction reference |
|
||||
| invariants pré-I/O | network exact |
|
||||
| transaction SQL | aucune |
|
||||
| rows touchées | canonical metadata |
|
||||
| idempotence | N/A |
|
||||
| conflit | N/A |
|
||||
| absence/not-found | state unknown -> None; tombstone only Purged |
|
||||
| error mapping | wrong-network/stored-metadata invalid sûrs |
|
||||
| concurrence | état committé par statement |
|
||||
| test déterministe | Full/Archived/Purged + tombstone minimal |
|
||||
| test PostgreSQL live | reads après chaque transition |
|
||||
|
||||
### 3.6 Matrice `RawTransactionRetentionWrite`
|
||||
|
||||
| Axe | Preuve/attendu |
|
||||
|----------------------|---------------------------------------------------------|
|
||||
| input | retention transition |
|
||||
| invariants pré-I/O | network exact; Compacted non supporté rejeté avant pool |
|
||||
| transaction SQL | oui |
|
||||
| rows touchées | canonical + archive |
|
||||
| idempotence | current == target -> AlreadyAtTarget |
|
||||
| conflit | expected perdu -> ExpectedStateMismatch |
|
||||
| absence/not-found | unknown reference -> safe not-found |
|
||||
| error mapping | invalid transition API; unsupported/physical write sûrs |
|
||||
| concurrence | FOR UPDATE canonique |
|
||||
| test déterministe | transition matrix + Compacted unsupported |
|
||||
| test PostgreSQL live | transition/purge/write/force races |
|
||||
|
||||
## 4. Design physique V001
|
||||
|
||||
| Élément | Décision `pre.001` | Statut |
|
||||
|-------------------|----------------------------------------------------|-------------|
|
||||
| Migration | V001 embedded, après généralisation du moteur V000 | PASS design |
|
||||
| Database identity | singleton `ksp_store_identity` | PASS design |
|
||||
| Réseau | un réseau exact par base V001 | PASS design |
|
||||
| Transaction key | signature `BYTEA(64)` logique | PASS design |
|
||||
| Observation key | `BYTEA(32)` | PASS design |
|
||||
| Slot | `NUMERIC(20,0)` ; aucun narrowing `u64` | PASS design |
|
||||
| Format version | `BIGINT`, check domaine `u32` non nul | PASS design |
|
||||
| Timestamp | `BIGINT`, check borne `RawTimestamp` | PASS design |
|
||||
| Payload | `BYTEA`, 1..=16 MiB | PASS design |
|
||||
| Archive | relation dédiée hors index hot-path | PASS design |
|
||||
| Purge | tombstone minimal dans ligne canonique | PASS design |
|
||||
| Compacted | non simulé ; rejet stable tant qu'aucun codec réel | PASS design |
|
||||
| Navigation | index partiel `(slot, signature)` hors purged | PASS design |
|
||||
|
||||
## 5. Inventaire SQL minimal prévu
|
||||
|
||||
### 5.1 Tables
|
||||
|
||||
```text
|
||||
ksp_store_identity
|
||||
ksp_raw_transactions
|
||||
ksp_raw_transaction_observations
|
||||
ksp_raw_transaction_archive_payloads
|
||||
```
|
||||
|
||||
Statut `pre.001` : **design seulement**. Aucun de ces objets V001 n'est encore créé.
|
||||
|
||||
### 5.2 Indexes
|
||||
|
||||
```text
|
||||
PK ksp_raw_transactions(signature)
|
||||
PK ksp_raw_transaction_observations(observation_key)
|
||||
PK ksp_raw_transaction_archive_payloads(signature)
|
||||
ix_ksp_raw_transactions_slot_signature(slot, signature)
|
||||
WHERE retention_state <> 'purged'
|
||||
```
|
||||
|
||||
Tout index additionnel doit être justifié par une requête effectivement ajoutée à la release.
|
||||
|
||||
## 6. Mapping numérique sans narrowing
|
||||
|
||||
| Valeur API | Représentation SQL | Cas limites obligatoires |
|
||||
|-----------------------|----------------------------------------------------|-------------------------------------------|
|
||||
| `slot: u64` | `NUMERIC(20,0)` | 0, `i64::MAX`, `i64::MAX + 1`, `u64::MAX` |
|
||||
| `format_version: u32` | `BIGINT` | 1, `i32::MAX + 1`, `u32::MAX` |
|
||||
| `RawTimestamp` | `BIGINT` | 0, max documenté, max+1 DB hostile |
|
||||
| source payload size | `BIGINT` | 0, 64 MiB, >64 MiB DB hostile |
|
||||
| page limit | bind signé de `limit+1` seulement si représentable | `i64::MAX - 1`, valeur supérieure rejetée |
|
||||
|
||||
Critère : aucune branche ne doit utiliser `as i64`, `as i32`, clamp ou saturation pour faire tenir une valeur valide API.
|
||||
|
||||
## 7. Binding réseau
|
||||
|
||||
### 7.1 Bootstrap
|
||||
|
||||
| Cas | Résultat attendu |
|
||||
|-------------------------------------------|------------------------------------------------------------------------|
|
||||
| V001 appliquée pour la première fois | identity créée avec le réseau runtime dans la transaction de bootstrap |
|
||||
| réouverture même réseau | succès idempotent |
|
||||
| réouverture autre réseau | erreur terminale sûre |
|
||||
| V001 présente mais identity absente | mismatch/corruption, jamais rebind silencieuse |
|
||||
| identity malformée | erreur terminale sûre |
|
||||
| migration pending + auto_migrate disabled | backend non prêt, aucune persistence métier |
|
||||
|
||||
### 7.2 Pré-I/O capability
|
||||
|
||||
Pour tout input portant un `RawNetworkId`, un mismatch avec `Store.network` ou `PostgresBackend.network` doit être détecté avant acquisition d'un client du pool.
|
||||
|
||||
## 8. Idempotence canonique
|
||||
|
||||
| État existant | Input | Mode | Outcome attendu |
|
||||
|--------------------------------|-------------------------------|----------------|-------------------------------------------|
|
||||
| absent | canonique+observation valides | Normal | `Inserted / Inserted` |
|
||||
| Full identique | observation identique | Normal | `AlreadyPresent / AlreadyPresent` |
|
||||
| Full identique | observation nouvelle | Normal | `AlreadyPresent / Inserted` |
|
||||
| Full divergent | n'importe quelle observation | Normal | `ERROR_CODE_RAW_CONFLICT`, aucun write |
|
||||
| Archived identique | observation nouvelle | Normal | `AlreadyPresent / Inserted` |
|
||||
| Purged compatible | observation | Normal | `SkippedPurged / NotRecorded` |
|
||||
| Purged divergent sur tombstone | observation | Normal | `ERROR_CODE_RAW_CONFLICT` |
|
||||
| Purged compatible | observation | ForceRehydrate | `Rehydrated / Inserted ou AlreadyPresent` |
|
||||
| Purged divergent | observation | ForceRehydrate | `ERROR_CODE_RAW_CONFLICT` |
|
||||
|
||||
L'égalité canonique compare les octets réels lorsqu'ils sont encore retenus. Le content hash seul n'est jamais une preuve suffisante dans `Full` ou `Archived`.
|
||||
|
||||
## 9. Atomicité canonique + observation
|
||||
|
||||
### 9.1 Cas obligatoires
|
||||
|
||||
| Scénario | Preuve attendue |
|
||||
|--------------------------------------------------------------|----------------------------------|
|
||||
| nouvel insert, observation valide | les deux commit |
|
||||
| nouvel insert, observation divergente sur key déjà existante | rollback canonique + observation |
|
||||
| canonical conflict | aucune nouvelle observation |
|
||||
| cancellation avant commit | aucun succès partiel visible |
|
||||
| erreur SQL observation | rollback canonique |
|
||||
|
||||
### 9.2 FK
|
||||
|
||||
Le FK observation -> transaction est :
|
||||
|
||||
- non nullable ;
|
||||
- sans `ON DELETE SET NULL` ;
|
||||
- impossible à contourner dans le repository métier ;
|
||||
- cohérent avec le fait que purge conserve la ligne canonique/tombstone.
|
||||
|
||||
## 10. Concurrence
|
||||
|
||||
| Race | Attendu |
|
||||
|-----------------------------------------|-------------------------------------------------------------|
|
||||
| deux inserts identiques même signature | un `Inserted`, l'autre `AlreadyPresent`; données identiques |
|
||||
| deux inserts divergents même signature | un gagnant, l'autre `ERROR_CODE_RAW_CONFLICT` |
|
||||
| deux observations identiques même key | un `Inserted`, l'autre `AlreadyPresent` |
|
||||
| deux observations divergentes même key | un gagnant, l'autre conflit |
|
||||
| deux transitions vers même target | un transitionne, l'autre `AlreadyAtTarget` |
|
||||
| transitions avec expected incompatibles | gagnant déterministe + `ExpectedStateMismatch` |
|
||||
| purge vs acquisition | sérialisation sur ligne canonique |
|
||||
| purge vs ForceRehydrate | aucun état moitié purgé/moitié full |
|
||||
| deux ForceRehydrate | idempotence ou conflit selon contenu |
|
||||
|
||||
La preuve live doit utiliser de vraies tâches concurrentes, pas une simulation séquentielle renommée « concurrency ».
|
||||
|
||||
## 11. Observation write séparée
|
||||
|
||||
| Cas | Attendu |
|
||||
|-----------------------------------------|----------------------------------------|
|
||||
| canonique Full présent, key absente | `Inserted` |
|
||||
| canonique Archived présent, key absente | `Inserted` |
|
||||
| key identique | `AlreadyPresent` |
|
||||
| key divergente | `ERROR_CODE_RAW_CONFLICT` |
|
||||
| canonique absent | erreur sûre, aucune création implicite |
|
||||
| canonique Purged | `NotRecorded` |
|
||||
| mauvais réseau | rejet pré-I/O |
|
||||
|
||||
L'absence du canonical requis est classée `store.raw_reference_not_found`. Ce code runtime ne modifie pas les invariants de construction de `ksp-store-api`.
|
||||
|
||||
## 12. Lecture
|
||||
|
||||
### 12.1 RawTransaction
|
||||
|
||||
| État physique | `get_raw_transaction` |
|
||||
|-----------------------------------------|------------------------------------------------|
|
||||
| Full cohérent | `Some(RawTransaction)` depuis payload hot |
|
||||
| Archived cohérent | `Some(RawTransaction)` depuis archive relation |
|
||||
| Purged | `None` |
|
||||
| row inconnue | `None` |
|
||||
| état/bytes/taille/numérique incohérents | erreur sûre de donnée physique |
|
||||
|
||||
### 12.2 Observation
|
||||
|
||||
| Cas | Résultat |
|
||||
|----------------------------------|--------------------------------------------------------|
|
||||
| key connue | observation reconstruite avec network du backend bound |
|
||||
| key inconnue | `None` |
|
||||
| bytes/provenance invalides en DB | erreur sûre |
|
||||
|
||||
## 13. Pagination
|
||||
|
||||
### 13.1 Ordre
|
||||
|
||||
```text
|
||||
Ascending = (slot ASC, signature ASC)
|
||||
Descending = (slot DESC, signature DESC)
|
||||
```
|
||||
|
||||
### 13.2 Dataset obligatoire
|
||||
|
||||
Le test doit contenir au minimum :
|
||||
|
||||
- plusieurs slots ;
|
||||
- au moins trois signatures distinctes sur le même slot ;
|
||||
- suffisamment de rows pour trois pages ;
|
||||
- une row Purged exclue de la liste ;
|
||||
- bornes start/end présentes et absentes.
|
||||
|
||||
### 13.3 Cursor V1
|
||||
|
||||
| Test | Attendu |
|
||||
|----------------------------|---------------------------------|
|
||||
| round-trip | exact |
|
||||
| taille != 109 | rejet |
|
||||
| magic modifié | rejet |
|
||||
| version inconnue | rejet |
|
||||
| digest modifié | rejet |
|
||||
| direction différente | rejet |
|
||||
| range différente | rejet |
|
||||
| network différent | rejet |
|
||||
| last slot hors range | rejet |
|
||||
| random bytes <=4096 | rejet sans panic/echo |
|
||||
| cursor >4096 au niveau API | déjà rejeté par `RawPageCursor` |
|
||||
|
||||
### 13.4 Pas de cap métier
|
||||
|
||||
Aucun test ne doit imposer 100, 500 ou 1000 comme limite Store. La seule erreur de taille côté backend doit correspondre à la représentation physique nécessaire au `LIMIT + 1`.
|
||||
|
||||
## 14. Rétention
|
||||
|
||||
### 14.1 États supportés physiquement en `0.3.3`
|
||||
|
||||
```text
|
||||
Full
|
||||
Archived
|
||||
Purged
|
||||
```
|
||||
|
||||
`Compacted` reste un état logique API connu, explicitement optionnel depuis le plan `0.3.1`, mais non représenté mensongèrement par PostgreSQL `0.3.3`.
|
||||
|
||||
### 14.2 Matrice
|
||||
|
||||
| Current | Expected | Target | Attendu PostgreSQL 0.3.3 |
|
||||
|-------------------|-----------|-----------|------------------------------------------------------------|
|
||||
| Full | Full | Archived | `Transitioned` |
|
||||
| Archived | Full | Archived | `AlreadyAtTarget` |
|
||||
| Archived | Archived | Purged | `Transitioned` |
|
||||
| Purged | Archived | Purged | `AlreadyAtTarget` |
|
||||
| Full | Archived | Purged | input transition invalide au niveau API |
|
||||
| Full | Full | Compacted | `store.postgres_retention_compaction_unsupported`, pré-I/O |
|
||||
| Compacted attendu | Compacted | Archived | `store.postgres_retention_compaction_unsupported`, pré-I/O |
|
||||
| Full | Archived | Archived | `ExpectedStateMismatch` |
|
||||
|
||||
### 14.3 Tombstone
|
||||
|
||||
Après purge, la reconstruction autorisée contient exactement :
|
||||
|
||||
```text
|
||||
reference
|
||||
slot
|
||||
format_id
|
||||
format_version
|
||||
content_hash
|
||||
```
|
||||
|
||||
Le block time et les octets de payload ne restent pas dans la table hot ni dans la table archive.
|
||||
|
||||
## 15. ForceRehydrate
|
||||
|
||||
| Cas | Attendu |
|
||||
|--------------------------------------|------------------------------------------------|
|
||||
| Purged + tombstone compatible | restaure Full et payload, outcome `Rehydrated` |
|
||||
| Purged + slot divergent | conflict |
|
||||
| Purged + format id/version divergent | conflict |
|
||||
| Purged + content hash divergent | conflict |
|
||||
| Full/Archived identique + Force | idempotence normale, pas faux `Rehydrated` |
|
||||
| race avec purge | sérialisation ; état final cohérent |
|
||||
|
||||
## 16. Erreurs et redaction
|
||||
|
||||
### 16.1 Canary hostile
|
||||
|
||||
Les tests devront injecter des valeurs sentinelles dans :
|
||||
|
||||
```text
|
||||
URI
|
||||
server error text
|
||||
SQL text simulé
|
||||
signature
|
||||
observation key
|
||||
content hash
|
||||
payload
|
||||
provider/protocol/method
|
||||
cursor bytes
|
||||
row DB invalide
|
||||
```
|
||||
|
||||
Aucune sentinelle ne doit apparaître dans `Display`, `Debug` ou message sûr retourné.
|
||||
|
||||
### 16.2 Classification
|
||||
|
||||
| Classe | Interface attendue |
|
||||
|----------------------------------------|---------------------------------------------------------------|
|
||||
| input/model invalide | codes `ksp-store-api` acquis |
|
||||
| canonical/observation divergent | `ERROR_CODE_RAW_CONFLICT` |
|
||||
| retention representation non supportée | `store.postgres_retention_compaction_unsupported` |
|
||||
| réseau incohérent | code statique, pas de réseau hostile rendu |
|
||||
| DB row invalide | code statique de corruption/data invalid |
|
||||
| query/write PostgreSQL | code statique backend/runtime |
|
||||
| pool/cancel/migration | catégories runtime existantes ou extension statique justifiée |
|
||||
|
||||
SQLSTATE et texte PostgreSQL ne font pas partie du contrat public.
|
||||
|
||||
## 17. Migration engine
|
||||
|
||||
### 17.1 Multi-version
|
||||
|
||||
Preuves nécessaires avant V001 :
|
||||
|
||||
- V000 reste checksum-identique ;
|
||||
- registre embedded ordonné `[V000, V001]` ;
|
||||
- historique vide -> bootstrap correct ;
|
||||
- V000 seule + auto migrate -> V001 appliquée ;
|
||||
- V000 seule + auto migrate disabled -> pending/non-ready ;
|
||||
- V001 checksum divergent -> mismatch ;
|
||||
- version > V001 -> schema newer ;
|
||||
- ligne de migration manquante/divergente -> mismatch ;
|
||||
- deux open concurrents -> advisory lock, historique unique.
|
||||
|
||||
### 17.2 Binding réseau atomique
|
||||
|
||||
L'identité réseau doit être créée/validée avant commit du bootstrap V001. Un crash ne doit pas pouvoir laisser V001 « appliquée » avec une base prête mais sans identité exploitable.
|
||||
|
||||
## 18. Boundaries
|
||||
|
||||
Les scans/tests doivent garantir :
|
||||
|
||||
```text
|
||||
ksp-store-lib -X-> tokio-postgres/deadpool-postgres/rustls
|
||||
ksp-store-lib -X-> SQL literal
|
||||
ksp-store-lib -X-> std::env / dotenv / libpq files
|
||||
ksp-store-postgres-lib -X-> ksp-store-lib
|
||||
ksp-store-postgres-lib -X-> direct Config ownership
|
||||
ksp-store-api -X-> backend physical dependency
|
||||
```
|
||||
|
||||
La façade ne publie aucun `Client`, `Transaction`, pool, TLS type, SQL row ou type backend.
|
||||
|
||||
## 19. Feature matrix
|
||||
|
||||
| Build | Attendu |
|
||||
|---------------------------------------|----------------------------------------------------------------------------|
|
||||
| `ksp-store-lib` default | feature postgres active, six capacités dispatchables une fois implémentées |
|
||||
| `ksp-store-lib --no-default-features` | compile ; aucune dépendance backend tirée |
|
||||
| config backend postgres sans feature | erreur `backend_not_compiled` avant I/O |
|
||||
| malformed postgres URI avec feature | erreur safe pré-I/O comme `0.3.2` |
|
||||
|
||||
## 20. Audit historique — preuves de non-régression
|
||||
|
||||
Les tests/source scans devront empêcher le retour des patterns historiques rejetés :
|
||||
|
||||
```text
|
||||
has_raw_transaction_signature
|
||||
BIGSERIAL id comme identity publique
|
||||
slot BIGINT dans V001
|
||||
canonical_json JSONB
|
||||
processing_state
|
||||
ON DELETE SET NULL
|
||||
raw SQL error text dans Error
|
||||
cap 500/1000 dans Store pagination
|
||||
```
|
||||
|
||||
## 21. Planning de validation par tranche
|
||||
|
||||
### `pre.001`
|
||||
|
||||
- documents plan/validation ;
|
||||
- version `0.3.3-pre.1` ;
|
||||
- aucun SQL métier ;
|
||||
- gate workspace actuel.
|
||||
|
||||
### `pre.002`
|
||||
|
||||
- migration registry multi-version ;
|
||||
- tests V000 conservés ;
|
||||
- préparation binding.
|
||||
|
||||
### `pre.003`
|
||||
|
||||
- V001 + tables/constraints/indexes ;
|
||||
- binding réseau ;
|
||||
- checksum/inventory tests.
|
||||
|
||||
### `pre.004`
|
||||
|
||||
- row codecs et lectures ;
|
||||
- malformed DB matrix.
|
||||
|
||||
### `pre.005`
|
||||
|
||||
- atomic writes/idempotence/conflict ;
|
||||
- observation writes.
|
||||
|
||||
### `pre.006`
|
||||
|
||||
- list/cursor/order/ranges ;
|
||||
- hostile cursor matrix.
|
||||
|
||||
### `pre.007`
|
||||
|
||||
- archive/purge/tombstone/ForceRehydrate ;
|
||||
- Compacted unsupported stable.
|
||||
|
||||
### `pre.008`
|
||||
|
||||
- façade/feature dispatch ;
|
||||
- no physical leak ;
|
||||
- pre-I/O mismatch.
|
||||
|
||||
### `pre.009`
|
||||
|
||||
- PostgreSQL live opt-in complet.
|
||||
|
||||
### `pre.010`
|
||||
|
||||
- hardening/completeness.
|
||||
|
||||
### `pre.011`
|
||||
|
||||
- gate technique final.
|
||||
|
||||
### `pre.012`
|
||||
|
||||
- réconciliation documentaire.
|
||||
|
||||
### `pre.013`
|
||||
|
||||
- publication prep.
|
||||
|
||||
### `rel.001`
|
||||
|
||||
- publication stable.
|
||||
|
||||
## 22. Gate courant `pre.001`
|
||||
|
||||
```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/0.3.3
|
||||
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
|
||||
```
|
||||
|
||||
## 23. Critère de clôture de release
|
||||
|
||||
`0.3.3` ne pourra être déclarée stable que si :
|
||||
|
||||
- les six capacités sont réellement implémentées sur `PostgresBackend` et dispatchées par `Store` ;
|
||||
- aucune valeur valide API n'est narrowée ;
|
||||
- l'idempotence distingue strictement identité identique et contenu divergent ;
|
||||
- canonical+observation est atomique ;
|
||||
- pagination est déterministe et cursorisée ;
|
||||
- réseau physique incorrect est refusé ;
|
||||
- rétention supportée est honnête et atomique ;
|
||||
- `Compacted` n'est pas prétendu sans représentation réelle ;
|
||||
- tombstone et ForceRehydrate respectent les contrats acquis ;
|
||||
- les erreurs ne fuient aucun secret/SQL/server text ;
|
||||
- le live PostgreSQL opt-in couvre concurrence et rollback ;
|
||||
- tous les gates techniques/doc sont propres ;
|
||||
- aucun scope `RawAccountState`/worker/app/N2 n'a été ouvert.
|
||||
Reference in New Issue
Block a user