# Prompt de démarrage `0.3.4` — Store/PostgreSQL `RawAccountState` + complétude RAW ## 1. Identité de la release et base exacte requise La release à ouvrir est : ```text 0.3.4 — Store/PostgreSQL RawAccountState + complétude/conformance RAW ``` La base autoritaire attendue est exclusivement la release stable : ```text v0.3.3 workspace.package.version = 0.3.3 ``` L'archive/repository `v0.3.3` fournie par l'opérateur prévaut sur toute mémoire, snippet, ancien artefact ou hypothèse de cette session. La première tranche est : ```text 0.3.4-pre.001 ``` Elle reste obligatoirement une tranche de **lecture + audit + brainstorming + threat model + design physique + sizing + planification**. Ne pas créer V002, les tables account ni les repositories SQL lourds avant la sortie cohérente de ce gate. --- ## 2. Mission et résultat attendu `0.3.4` termine la couche RAW physique PostgreSQL ouverte par les trois releases précédentes : ```text 0.3.1 contrats backend-agnostic ksp-store-api 0.3.2 façade/runtime + backend PostgreSQL foundation 0.3.3 vertical slice RawTransaction complète 0.3.4 vertical slice RawAccountState + conformance RAW cross-family finale ``` La release étend le couple existant : ```text ksp-store-lib ksp-store-postgres-lib ``` avec les quatre capabilities account déjà stables dans `ksp-store-api` : ```text RawAccountStateRead RawAccountStateWrite RawAccountObservationRead RawAccountObservationWrite ``` Le résultat attendu à la clôture est que : ```text PostgresBackend implémente les quatre capabilities RawAccount* Store implémente/dispatch les quatre capabilities RawAccount* les six capabilities RawTransaction acquises en 0.3.3 restent intactes PostgresBackend et Store satisfont donc les dix capabilities RAW de ksp-store-api RawAccountState est persisté sans perte de bytes ni narrowing entier RawAccountState + observation initiale sont atomiques une référence account déjà présente avec contenu identique est idempotente une même référence avec contenu divergent retourne ERROR_CODE_RAW_CONFLICT plusieurs états distincts d'un même pubkey dans un même slot restent représentables lorsque state_hash diffère une observation supplémentaire est idempotente et ne crée jamais implicitement son state get/list respectent RawAccountStateQuery et un ordre total déterministe le cursor account est opaque, borné et impossible à rejouer comme cursor transaction ou contre une autre query les optional Yellowstone metadata restent observation-only V000/V001 restent immuables et la nouvelle persistence est additive aucun index owner/provider/time n'est ajouté sans query réellement exposée aucun SQL/type PostgreSQL ne fuit par ksp-store-lib le tout est prouvé sur PostgreSQL réel avec coexistence RawTransaction + RawAccountState ``` Cette release ferme la **complétude RAW Store/PostgreSQL**, mais elle n'ouvre ni STRUCTURAL, ni Interface events, ni jobs/workers/backfill. La release suivante reste : ```text 0.3.5 — ksp-interface-lib : modèles passifs/events réellement partagés par les premiers consumers d'acquisition ``` --- ## 3. Sources de vérité internes obligatoires — ordre de lecture ### 3.1 Règles globales Lire d'abord : ```text RULES.md docs/000-README.md docs/rules/RULES_GENERAL.md docs/rules/RULES_KSP.md docs/rules/RULES_RUST.md docs/rules/RULES_DEPENDENCIES.md docs/rules/RULES_DOCUMENTATION.md docs/rules/FILE_CONTRACTS.md docs/rules/VERSION_WORKFLOW.md docs/rules/PROMPT_STRUCTURE.md ``` Relire particulièrement les règles applicables aux frontières : ```text KSP-API-* KSP-CONFIG-* KSP-STORE-* KSP-NOTIFY-* KSP-PROC-* KSP-REL-* DEP-KSP-* DEP-CARGO-* DEP-LOG-* DEP-STORE-* DEP-WORKER-* DEP-JOB-* ``` Rappels structurants : ```text ksp-store-lib -> ksp-store-api ksp-store-lib[postgres] -> ksp-store-postgres-lib ksp-store-postgres-lib -> ksp-store-api ksp-store-postgres-lib -X-> ksp-store-lib Config -> Store autorisé Store/backend -X-> Config Transport -X-> Store Program/Materializer -X-> Store consumer ordinaire -> ksp-store-lib consumer ordinaire -X-> ksp-store-postgres-lib ``` Un fix strictement documentaire ne modifie pas `workspace.package.version`. Une prerelease non-fix, y compris une tranche de publication, synchronise en revanche la version Cargo conformément à `VER-ID-009`. ### 3.2 Architecture durable Lire ensuite : ```text docs/architecture/000-README.md docs/architecture/001-PROJECT_OBJECTIVES.md docs/architecture/002-LAYERS_AND_DEPENDENCIES.md docs/architecture/003-COMPONENT_CONTRACTS.md docs/architecture/004-COMPONENT_INVENTORY.md docs/architecture/005-DEPENDENCY_GRAPH.md docs/architecture/007-EXECUTION_AND_POLICY.md docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md ``` Préserver notamment : ```text RAW -> STRUCTURAL -> DECODED -> DOMAIN Store persiste et sert ; il ne possède pas la policy de travail pagination/cursorisation Store != batch-size/priorité/backlog worker/job 1 Store instance = 1 RawNetworkId + 1 backend physique pas de multiplexage automatique de réseaux/bases dans Store Config possède targets/URI/.env/secrets backend PostgreSQL possède driver/pool/TLS/SQL/migrations aucun type backend physique ne traverse la façade commune ``` ### 3.3 Contrats RAW stables `0.3.1` Lire intégralement : ```text docs/plans/022-V0_3_1_STORE_RAW_PLAN.md docs/validation/018-V0_3_1_STORE_RAW.md crates/ksp-store-api/Cargo.toml crates/ksp-store-api/src/** crates/ksp-store-api/tests/** ``` Relire particulièrement : ```text RawAccountStateReference RawAccountState RawAccountObservation RawAccountStateQuery RawPage / RawPageRequest / RawPageCursor / RawPageLimit RawSlotRange / RawSortDirection RawAcquisitionWriteOutcome RawEntityWriteOutcome RawObservationWriteOutcome RawAcquisitionProvenance RawObservationKey RawContentHash RawTransactionSignature MAX_RAW_ACCOUNT_DATA_BYTES les quatre capabilities RawAccount* les six capabilities RawTransaction* ``` Ne pas redessiner `ksp-store-api` pour simplifier PostgreSQL. Une modification de l'API n'est recevable que si `pre.001` démontre un gap **backend-agnostic réel, bloquant et cross-backend**. ### 3.4 Fondation runtime/backend `0.3.2` Lire : ```text docs/plans/023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md docs/validation/019-V0_3_2_STORE_POSTGRES_FOUNDATION.md crates/ksp-store-lib/Cargo.toml crates/ksp-store-lib/src/** crates/ksp-store-lib/tests/** crates/ksp-store-postgres-lib/Cargo.toml crates/ksp-store-postgres-lib/src/** crates/ksp-store-postgres-lib/tests/** crates/ksp-config-lib/README.md crates/ksp-config-lib/USAGE.md config/std.store.json config/schemas/std.store.schema.json config/examples/std.store.example.json ``` ### 3.5 Vertical slice `RawTransaction` stable `0.3.3` Lire ensuite intégralement : ```text docs/plans/024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md docs/validation/020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md crates/ksp-store-lib/README.md crates/ksp-store-lib/USAGE.md crates/ksp-store-postgres-lib/README.md crates/ksp-store-postgres-lib/USAGE.md crates/ksp-store-lib/src/** crates/ksp-store-lib/tests/** crates/ksp-store-postgres-lib/src/** crates/ksp-store-postgres-lib/unit_tests/** crates/ksp-store-postgres-lib/tests/** crates/ksp-store-postgres-lib/migrations/** ``` Les patterns acquis de `0.3.3` sont des **précédents à réutiliser lorsque la sémantique account est réellement équivalente**, pas une invitation à copier chaque détail transaction. Préserver notamment : ```text V000/V001 checksummés et immuables migration logique découpée en ressources typées backend-private schema introspection Compatible/Missing/Incompatible network binding via ksp_store_identity u64 exact en NUMERIC(20,0) lorsque nécessaire BYTEA fixed-width validé pour signatures/hashes/keys transactions SQL atomiques INSERT ... ON CONFLICT DO NOTHING puis comparaison exacte sous lock keyset pagination sans OFFSET cursor opaque lié à la query PostgresBackendError = kind + phase statique/sûre façade Store sans SQL/type physique ``` Lire enfin : ```text CHANGELOG.md ROADMAP.md ``` Créer en `pre.001` : ```text docs/plans/025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md docs/validation/021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md ``` --- ## 4. Audit historique kbot3 obligatoire et ciblé L'archive historique requise est : ```text khadhroony-bot3_v0.5.3-pre.005-fix010.zip ``` Elle doit être disponible au `pre.001` parce que `0.3.4` ouvre la seconde famille métier PostgreSQL et doit comparer l'ancienne persistence account/observation avant de figer V002. Réauditer uniquement les surfaces historiques pertinentes : ```text ks-store/Cargo.toml ks-store/README.md ks-store/USAGE.md ks-store/src/contracts/dto/raw.rs ks-store/src/contracts/entity/raw.rs ks-store/src/contracts/repository.rs ks-store/src/contracts/dto/account_state.rs ks-store/src/contracts/dto/core.rs ks-store/src/contracts/entity/core.rs ks-store/src/postgres/query/account_state_queries.rs ks-store/src/postgres/repository/account_state_repository.rs ks-store/migrations/postgres/schema/tables/create_table_if_not_exists_k_sol_obs_account_observations.sql ks-store/migrations/postgres/schema/tables/create_table_if_not_exists_k_sol_core_account_states.sql ks-store/migrations/postgres/schema/constraints/*account_observations* ks-store/migrations/postgres/schema/constraints/*account_states* ks-store/migrations/postgres/schema/indexes/*account_observations* ks-store/migrations/postgres/schema/indexes/*account_states* docs/guides/POSTGRES_STORAGE.md docs/plans/V0_5_3_KS_STORE_NORMALIZATION_PLAN.md ``` Classer explicitement chaque idée sous : ```text REPRENDRE REDESSINER REPORTER REJETER ``` Points de comparaison obligatoires : ```text identité account physique pubkey/slot/hash data bytes vs base64/text lamports/rent_epoch exacts owner/executable observation identity/provenance write_version Yellowstone transaction_signature Yellowstone is_startup Yellowstone atomicité state + observation idempotence observation ordre/list/indexes schema constraints processing/normalization coupling error mapping ``` Attention particulière : l'ancien `k_sol_core_account_states` appartient à une ancienne logique **CORE/normalization**, alors que le `RawAccountState` KSP actuel est un modèle **D1 RAW complet**. Ne pas traiter l'ancienne table CORE comme schéma de référence de V002. Ne pas reprendre automatiquement : ```text SQLx ancien monolithe Store processing ledger/stage dans la persistence RAW MAX_ACCOUNT_STATE_SELECTION_ROWS ou autre batch-size worker/job base64 comme représentation physique obligatoire des bytes RAW BIGINT signé pour u64 ON CONFLICT DO UPDATE silencieux status/error_message de processing dans les observations RAW indexes owner/provider/method/time sans query KSP correspondante maintenance destructive publique IDs BIGSERIAL comme identité publique ``` Si l'archive historique n'est pas disponible : ```text ne pas inventer son contenu depuis la mémoire ne pas déclarer l'audit héritage terminé ne pas figer V002/indexes account définitifs ``` --- ## 5. Sources externes à réauditer lorsque nécessaire `0.3.4` n'est pas une release de mise à jour de dépendances. Avant tout changement de version/feature, vérifier la version stable réellement courante et la documentation primaire des dépendances déjà utilisées : ```text tokio-postgres deadpool-postgres tokio-postgres-rustls rustls sha2 PostgreSQL ``` Réauditer les sources PostgreSQL/tokio-postgres seulement lorsque le design l'exige, notamment pour : ```text NUMERIC(20,0) et conversion exacte u64 BYTEA / length constraints transactions et row locking INSERT ... ON CONFLICT FK/UNIQUE/CHECK keyset pagination composite NULL et optional metadata catalog introspection / pg_get_constraintdef cancellation/rollback statement/parameter size pour account data jusqu'à la borne KSP ``` Ne pas ajouter ORM, query builder, codec wire ou SDK externe par habitude. `RawAccountState::data()` fournit déjà des bytes canoniques. Aucun `bincode` n'est autorisé et aucun codec wire n'est requis pour cette persistence. --- ## 6. État validé `0.3.3` à préserver ### 6.1 `ksp-store-api` La base stable possède **10 capabilities RAW** : ```text 6 RawTransaction* 4 RawAccount* ``` Les quatre capabilities account existent déjà et sont object-safe ; `0.3.4` doit les implémenter, pas les réinventer. ### 6.2 Façade `ksp-store-lib` La base stable possède notamment : ```text feature default = postgres Store::open / runtime_snapshot / health / close 1 Store = 1 RawNetworkId + 1 backend six capabilities RawTransaction dispatchées validation réseau pré-I/O mapping d'erreurs backend vers codes Store/API stables compilation --no-default-features aucun type PostgreSQL public ``` ### 6.3 Backend `ksp-store-postgres-lib` La base stable possède notamment : ```text tokio-postgres + Deadpool + Rustls moteur migration privé V000 bootstrap V001 RawTransaction ksp_store_identity mono-network schema resource compatibility + safe additive repair PostgresBackendError kind + phase sûre RawTransaction read/write/observation/retention complets cursor transaction V1 opaque live PostgreSQL 17 vert ``` Checksums immuables acquis : ```text V000 d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450 V001 31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51 ``` `0.3.4` ne modifie jamais les bytes de V000/V001 pour ajouter les comptes. Toute nouvelle structure physique est additive, normalement sous une nouvelle migration logique **V002** si le gate `pre.001` confirme ce design. --- ## 7. Contrat `RawAccountState` à respecter exactement ### 7.1 Référence canonique L'identité backend-agnostic est : ```text RawAccountStateReference network pubkey slot state_hash ``` Le commentaire API est structurant : plusieurs écritures d'un même compte peuvent exister dans le **même slot** lorsque les transports communs n'exposent pas `write_version`. Par conséquent : ```text même pubkey + même slot + state_hash différent != conflit automatique ``` Ce sont potentiellement deux états canoniques distincts. En revanche : ```text même RawAccountStateReference + contenu complet divergent => ERROR_CODE_RAW_CONFLICT ``` Le hash ne dispense jamais de comparer exactement les champs canoniques en cas de collision. ### 7.2 Contenu canonique `RawAccountState` contient exactement : ```text reference lamports: u64 owner: Pubkey executable: bool rent_epoch: u64 data: complete bytes ``` Les bytes doivent rester complets, non `jsonParsed`, non sliced et non convertis en base64 comme contrat physique obligatoire. Borne KSP : ```text MAX_RAW_ACCOUNT_DATA_BYTES = 16 MiB ``` Cette borne est une admission Store, pas une affirmation de limite protocolaire Solana. ### 7.3 Observation `RawAccountObservation` contient : ```text observation_key account reference provenance is_startup: Option transaction_signature: Option write_version: Option ``` Les trois champs optionnels sont **observation metadata**. Ils ne modifient jamais l'identité canonique account. Ne pas inventer de valeur lorsque HTTP/WS ne l'expose pas. ### 7.4 Query `RawAccountStateQuery` expose : ```text network optional pubkey inclusive slot range direction page/cursor ``` Ne pas ajouter un index ou une query `owner`, provider, commitment, timestamp ou write_version si aucun contrat public ne le demande réellement. --- ## 8. Décisions déjà acquises et questions réellement ouvertes ### 8.1 Acquis ```text PostgreSQL est le backend de référence V000/V001 sont immuables schema additions passent par le moteur de migrations existant Store reste mono-network u64 ne doit jamais être narrow vers BIGINT signé pubkey/hash/observation key/signature ont des tailles exactes connues canonical + observation initiale doivent être atomiques idempotence identical / conflit divergent sont obligatoires pagination Store reste policy-free backend/facade ne lisent pas l'environnement aucune erreur SQL/server brute ne traverse l'API ``` ### 8.2 À décider en `pre.001` Décider explicitement : ```text forme et nom exacts de V002 ressources physiques exactes account state / observation clé primaire/unique minimale ordre total de RawAccountStateQuery format/version du cursor account liaison anti-replay cross-family transaction <-> account indexes strictement nécessaires aux queries publiques représentation PostgreSQL exacte de pubkey/hash/data/u64/optional u64 FK observation -> canonical account state algorithme de collision canonical algorithme d'idempotence observation comportement concurrent identical/divergent mapping d'erreurs account stratégie live cross-family ``` Ne pas décider arbitrairement une rétention account : **aucune capability `RawAccountRetention*` n'existe dans `ksp-store-api`**. Ne pas réutiliser `RawTransactionRetention*` pour les accounts. --- ## 9. Design physique attendu — contraintes de conception, pas schéma imposé `pre.001` doit proposer puis figer un schéma minimal capable de représenter sans perte : ```text RawAccountState RawAccountObservation ``` Le design doit au minimum étudier : ### 9.1 Canonical account state Candidats de représentation à auditer : ```text pubkey BYTEA exact 32 bytes slot NUMERIC(20,0) state_hash BYTEA exact 32 bytes lamports NUMERIC(20,0) owner BYTEA exact 32 bytes executable BOOLEAN rent_epoch NUMERIC(20,0) data BYTEA ``` Ce ne sont pas des noms de colonnes imposés ; le gate doit en revanche justifier toute représentation différente. ### 9.2 Observation Candidats à auditer : ```text observation_key BYTEA exact 32 bytes account reference FK/colonnes exactes vers canonical provenance mêmes codes/timestamps sûrs que RawTransactionObservation is_startup BOOLEAN NULL transaction_signature BYTEA exact 64 bytes NULL write_version NUMERIC(20,0) NULL ``` ### 9.3 Uniqueness et idempotence Le design doit préserver : ```text RawAccountStateReference unique RawObservationKey unique globalement dans la famille account au minimum observation référence exactement un canonical existant pas de silent overwrite ``` Auditer si l'unicité `RawObservationKey` doit rester séparée par famille physique ou si un invariant cross-family est nécessaire. Ne pas changer `ksp-store-api` sans raison backend-agnostic. ### 9.4 Indexes Partir des queries réelles : ```text get by full reference list optional pubkey + slot range + direction + cursor get observation by observation_key ``` Le nombre d'indexes doit rester minimal et justifié par ces surfaces. Les indexes kbot3 suivants ne sont **pas** automatiquement justifiés : ```text owner provider/method received_at status ``` --- ## 10. Atomicité, idempotence et concurrence ### 10.1 Acquisition state + observation `persist_raw_account_acquisition(state, observation)` est une opération logique atomique : ```text canonical state durable + observation durable ou aucun des deux ``` Valider avant I/O : ```text network du state == network du backend observation.account == state.reference ``` ### 10.2 Collision canonical La stratégie doit reprendre le principe validé en transaction lorsque compatible : ```text INSERT ... ON CONFLICT DO NOTHING RETURNING si insert absent -> lock/read canonical existant comparaison exacte de tous les champs identique -> AlreadyPresent divergent -> Conflict ``` Le `state_hash` n'est pas une preuve suffisante d'égalité des bytes et champs en cas de collision. ### 10.3 Observation Pour une observation supplémentaire : ```text canonical absent -> ReferenceNotFound observation key nouvelle -> Inserted observation key existante + contenu complet identique -> AlreadyPresent observation key existante + contenu divergent -> Conflict ``` Ne pas créer le canonical par effet de bord. ### 10.4 Concurrence Prouver au minimum : ```text deux acquisitions identiques concurrentes même référence + contenu divergent concurrent collision observation key entre deux acquisitions annulation après insert canonical mais avant observation observation supplémentaire concurrente ``` Les outcomes exacts doivent être déterministes ou, lorsque deux winners sont possibles, l'ensemble d'outcomes attendu doit être explicitement borné. --- ## 11. Pagination et cursor account Le list account doit définir un ordre **total**, stable et compatible avec : ```text optional pubkey filter slot range Ascending Descending continuation sans duplicate/skip ``` Le cursor reste backend-private et transporté uniquement via `RawPageCursor`. Il doit être lié au minimum à : ```text family = account network pubkey filter présent/absent + valeur slot range direction last total-order key cursor format/version ``` Un cursor transaction ne doit jamais être accepté comme cursor account, et inversement. Ne pas utiliser : ```text OFFSET cursor JSON public codec wire de ksp-interface-lib bincode batch-size worker caché ``` La limite demandée par `RawPageLimit` n'est pas une policy de worker. Seule une vraie borne physique PostgreSQL peut être refusée explicitement. --- ## 12. Complétude/conformance RAW cross-family La release ne se limite pas à « ajouter deux tables ». Elle doit fermer la surface PostgreSQL RAW complète. À la fin : ```text PostgresBackend implémente exactement les 10 capabilities ksp-store-api Store implémente exactement les mêmes 10 capabilities RawTransaction reste non régressé RawAccountState est complet feature postgres default reste correcte --no-default-features reste compilable/testable aucun backend physique ne fuite error mapping couvre toutes les classes nécessaires aux deux familles migrations V000/V001/V002 sont cohérentes et vérifiables schema compatibility/hardening couvre toutes les ressources gérées ``` Auditer les canaris de `pre.009/pre.010` de `0.3.3` : certains interdisent volontairement `RawAccount*` et devront être **mis à jour au moment exact où le scope devient légitime**, jamais supprimés globalement sans remplacement. --- ## 13. Threat model obligatoire Couvrir au minimum : ```text wrong-network input avant I/O wrong-network database URI pubkey/hash/observation key/signature malformés dans DB u64 overflow/narrowing slot/lamports/rent_epoch/write_version account data > MAX_RAW_ACCOUNT_DATA_BYTES row data corrompue observation orphan canonical orphan après rollback même pubkey+slot avec hashes distincts légitimes même full reference avec contenu divergent identical concurrent insert divergent concurrent insert observation-key collision cursor hostile cursor replay avec autre network cursor replay avec autre pubkey filter/range/direction cursor transaction rejoué sur account pagination duplicate/skip sous ordre ambigu optional Yellowstone metadata NULL/non-NULL mal mappées SQL/server error leak pool cancellation pendant transaction V002 checksum/history mismatch schema resource missing/incompatible V000/V001 mutation accidentelle index excessif/non justifié ``` --- ## 14. Première mission `pre.001` ### 14.1 Lecture et inventaire Avant toute modification fonctionnelle : 1. vérifier que la base est bien `v0.3.3` stable ; 2. lire toutes les sources internes listées ci-dessus ; 3. inventorier V000/V001 et recalculer leurs checksums ; 4. inventorier les 10 capabilities et confirmer que 6/10 sont déjà implémentées physiquement ; 5. inventorier tous les canaris qui interdisent encore `RawAccount*` ; 6. inspecter `RawAccountState`, `RawAccountObservation` et `RawAccountStateQuery` champ par champ ; 7. auditer l'archive kbot3 ciblée ; 8. vérifier les dépendances actuelles seulement si le design en dépend. ### 14.2 Matrice des quatre capabilities Produire une matrice explicite : ```text capability input output network guard SQL/transaction requis idempotence conflit absence/reference behavior pagination/cursor éventuel error mapping live proof ``` ### 14.3 Matrice modèle -> physique Pour chaque champ account : ```text champ API type Rust cardinalité/optionality représentation PostgreSQL borne/constraint mapping read mapping write risque de narrowing/perte ``` ### 14.4 Audit historique Classer l'héritage kbot3 sous : ```text REPRENDRE REDESSINER REPORTER REJETER ``` Documenter explicitement pourquoi l'ancien `CoreAccountState` n'est pas le nouveau `RawAccountState`. ### 14.5 Design V002 Proposer : ```text migration logical version/name resource tree tables/constraints/indexes identité canonical observation FK/unicity u64 representation byte fixed-width checks account data representation indexes minimaux schema compatibility contract ``` Ne pas écrire les ressources SQL avant validation cohérente du design. ### 14.6 Cursor/order Décider l'ordre total account et un format cursor backend-private avec anti-replay cross-family. ### 14.7 Concurrence Écrire les algorithmes d'acquisition/observation et leurs états de course avant le code SQL. ### 14.8 Threat model Produire la matrice décrite en section 13. ### 14.9 Sizing Chaque tranche prévue au-delà d'environ **15 à 20 minutes de travail effectif** doit être scindée. Si `RawAccountState + conformance RAW` n'est plus clôturable dans cette session, redécouper avant V002 lourd. Ne jamais aspirer `0.3.5` dans `0.3.4`. ### 14.10 Documents de gate Créer : ```text docs/plans/025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md docs/validation/021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md ``` ### 14.11 Critères de sortie de `pre.001` `pre.001` est terminé seulement si : ```text base v0.3.3 vérifiée V000/V001 immuables vérifiés quatre capabilities account auditées 10-capability cross-family inventory établi kbot3 account audit classé Core historique != RawAccount actuel explicitement documenté V002 proposé mapping exact de tous les champs décidé u64/bytes/optionality décidés identity/unicity/FK décidés atomicité/idempotence/conflit décidés ordre total/cursor anti-replay décidé indexes minimaux justifiés par query error taxonomy décidée threat model complet stratégie live cross-family définie plan 025 créé validation 021 créée prévision souple recalibrée aucune persistence account lourde créée prématurément ``` --- ## 15. Prévision souple initiale des prereleases Cette prévision peut être scindée/recalibrée par `pre.001`. ### `pre.001` — Audit contrats, kbot3, V002, cursor, concurrence et sizing Lectures, inventaire 10 capabilities, audit account historique, design physique, threat model, plan/validation. ### `pre.002` — V002 + schéma/indexes account Ajouter uniquement les ressources physiques account réellement nécessaires via le moteur de migrations existant. V000/V001 restent byte-identiques. Tests registry/checksum/schema compatibility. ### `pre.003` — Mapping physique + lectures account Mappings rows/API privés, `get_raw_account_state`, `get_raw_account_observation`, hostile rows, wrong-network pré-I/O. ### `pre.004` — Persistence account atomique + observations `persist_raw_account_acquisition` et `record_raw_account_observation`, idempotence/conflit, exact compare, rollback et concurrence unitaire/intégration sans live externe. ### `pre.005` — List/query + cursor account `RawAccountStateQuery`, ordre total, optional pubkey, ranges, directions, cursor opaque/versionné et anti-replay cross-family. ### `pre.006` — Façade + conformance des quatre capabilities account Implémenter/dispatcher les quatre traits sur `PostgresBackend` et `Store`, network guard, error mapping, feature mismatch. Verrouiller la surface totale à 10 capabilities. ### `pre.007` — PostgreSQL integration réelle `RawAccountState` Gate opt-in sur database dédiée : V000+V001+V002, state+observation atomic, idempotence, conflit, observations, concurrence, pagination, cancellation/rollback et petite preuve de coexistence transaction/account. ### `pre.008` — Hardening/completeness RAW cross-family Exact modules/exports/capabilities, hostile rows/cursors, no-secret/no-SQL-leak, migration resource completeness, canaris transaction non régressés, aucun scope STRUCTURAL/Interface/job. ### `pre.009` — Gate technique/live final Workspace complet, `--no-default-features`, `cargo test --workspace`, graphes/features/duplicates, replay des preuves PostgreSQL nécessaires et vérification finale des migrations V000/V001/V002. ### `pre.010` — Réconciliation documentaire finale README/USAGE Store/backend, plan `025`, validation `021`, indexes docs et autres références durables réellement impactées. `USAGE.md` reste un guide d'utilisation durable avec exemples ; aucune preuve de gate/chronologie de prerelease n'y est ajoutée. Ne pas toucher `CHANGELOG.md`, `ROADMAP.md` ni au prompt suivant. ### `pre.011` — Préparation de publication minimale Uniquement : ```text Cargo.toml CHANGELOG.md ROADMAP.md prompts/024-V0_3_5_START_PROMPT.md deltas/0.3.4/pre.011.md ``` ### `rel.001` — Publication stable Version finale + delta uniquement. --- ## 16. Versionnement, deltas, commits et tags Respecter `docs/rules/VERSION_WORKFLOW.md`. Rappels : ```text workspace.package.version prerelease : 0.3.4-pre.N livraison : 0.3.4-pre.NNN fix code/runtime/config : Cargo 0.3.4-pre.N.fix.M fix strictement documentaire : Cargo inchangé prerelease non-fix documentaire/publication : Cargo synchronisé chaque delta commité tag stable final : v0.3.4 ``` Chaque delta contient au minimum : ```text base requise objectif fichiers ajoutés fichiers modifiés fichiers supprimés validations exécutées validations non exécutées décisions questions ouvertes ``` Une commande non exécutée n'est jamais déclarée PASS. --- ## 17. Procédure d'application et validation opérateur Après chaque overlay : ```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.4 cargo check --workspace cargo clippy --workspace --all-targets ``` Tests ciblés typiques : ```bash 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 ``` Lorsque la façade/account conformance change : ```bash cargo test -p ksp-store-lib --no-default-features ``` Lorsque le graphe/features change ou au gate final : ```bash cargo tree -p ksp-store-lib --edges normal cargo tree -p ksp-store-lib -e features cargo tree -p ksp-store-postgres-lib --edges normal cargo tree --duplicates ``` Le gate technique final inclut : ```bash cargo test --workspace ``` Ne pas refaire des builds Tauri sans changement de resources/config/packaging desktop démontré. --- ## 18. Validation PostgreSQL réelle spécifique La release doit disposer d'une preuve account opt-in sur une database PostgreSQL dédiée. Le test doit refuser de démarrer si le jeu d'objets KSP qu'il pourrait détruire existe déjà. Il ne doit jamais afficher l'URI. Couvrir au minimum : ```text PostgreSQL >= 15 bootstrap V000 + V001 + V002 health Ready wrong network rejeté persist state + observation read state exact, bytes inclus read observation exacte re-persist identique -> AlreadyPresent même full reference + contenu divergent -> Conflict même pubkey + même slot + state_hash différent -> deux states distincts admis observation supplémentaire observation idempotente observation-key collision divergente optional is_startup/transaction_signature/write_version round-trip concurrence identical/divergent list avec/sans pubkey filter Ascending/Descending slot range plusieurs pages cursor hostile/cross-query rejeté cursor transaction -> account rejeté annulation/rollback sans canonical orphelin petit canari RawTransaction après V002 close borné cleanup uniquement des tables KSP dont l'absence initiale a été prouvée ``` Le test ne doit pas : ```text lire l'environnement depuis Store/backend afficher URI/credentials DROP database/schema non créé par lui exiger endpoint Solana HTTP/WS/gRPC introduire worker/job/processing ledger ``` --- ## 19. Critères de clôture de `0.3.4` La release stable est prête seulement si : ```text V000/V001 restent byte-identiques V002 account est versionnée/checksummée et additive schema physique représente RawAccountState sans perte/narrowing PostgresBackend satisfait les 4 capabilities RawAccount Store satisfait/dispatch les 4 capabilities RawAccount PostgresBackend + Store satisfont les 10 capabilities RAW RawTransaction reste intégralement vert wrong-network est rejeté avant I/O state+observation est atomique identical est idempotent divergent même full reference -> ERROR_CODE_RAW_CONFLICT states distincts même pubkey+slot avec hash différent restent possibles observations supplémentaires sont idempotentes optional Yellowstone metadata round-trip exactement get state/observation fonctionnent list account est total/déterministe/cursorisé cursor account est lié à sa family/query aucun batch/backlog/policy n'est introduit aucun index sans query réelle n'est ajouté aucun SQL/type physique ne fuit aucun secret/data/SQL distant ne fuite dans erreurs/logs ksp-store-api reste backend-agnostic aucune rétention account inventée PostgreSQL live account/cross-family est vert workspace/Clippy/tests/graphes sont verts README/USAGE/plan/validation sont réconciliés selon leur rôle documentaire prompt 0.3.5 est prêt ``` --- ## 20. Hors périmètre explicite Ne pas ouvrir dans `0.3.4` : ```text nouvelles familles RAW RawAccount retention/tombstone non contracté STRUCTURAL persistence Program decode/materialization ksp-interface-lib events de 0.3.5 ksp-job-api/backfill de 0.3.6 application backfill/inspection de 0.3.7 worker RAW live notification bus dédié nouveau backend SQL/NoSQL Store Desk wire codec policy de batch/priorité/retry ``` --- ## 21. Release suivante et instruction d'ouverture La release suivante envisagée est : ```text 0.3.5 — Interface events/acquisitions partagés si consumer réel ``` ### Instruction d'ouverture À réception de la base stable `v0.3.3` **et de l'archive kbot3 requise** : 1. vérifier la base exacte et recalculer V000/V001 ; 2. lire règles, architecture, plans/validations `0.3.1` à `0.3.3` ; 3. inventorier les 10 capabilities et confirmer que seules les quatre `RawAccount*` restent sans implémentation physique ; 4. auditer `RawAccountState`, `RawAccountObservation` et `RawAccountStateQuery` champ par champ ; 5. réauditer kbot3 uniquement sur account observation/state/indexes et séparer RAW actuel de l'ancien CORE ; 6. figer V002, identity/unicity/FK, u64/bytes, atomicité, cursor/order, error mapping et indexes ; 7. produire threat model, sizing, plan `025` et validation `021` ; 8. **ne pas écrire V002 ni le repository account lourd avant validation cohérente de `pre.001`** ; 9. **ne pas ouvrir STRUCTURAL, Interface events, jobs/workers/backfill ou application dans `0.3.4`**.