# Base de données PostgreSQL est le backend principal prévu pour `khadhroony-bot2`. `0.2.0` fixe uniquement les conventions de stockage : les migrations complètes, repositories SQL et diagnostics applicatifs sont reportés aux jalons suivants. ## Décision PostgreSQL Le projet ne crée pas de schémas PostgreSQL applicatifs explicites. Le store utilise le schéma courant du profil PostgreSQL, généralement `public`. Le choix du schéma reste donc une responsabilité de configuration ou d'administration PostgreSQL, pas une responsabilité des migrations applicatives. Interdits, écrits avec `DOT` pour que les audits textuels simples ne confondent pas documentation et usage réel : ```text raw DOT kb_sol_rpc_transactions core DOT kb_sol_transactions obs DOT kb_sol_program_observations decode DOT kb_sol_decoded_events mat DOT kb_sol_trade_events catalog DOT kb_sol_tokens ops DOT kb_sol_processing_ledger ``` Autorisés : ```text kb_sol_raw_transactions kb_sol_core_transactions kb_sol_obs_program_observations kb_sol_decode_decoded_events kb_sol_mat_trade_events kb_sol_catalog_tokens kb_sol_ops_processing_ledger ``` ## Format canonique des tables Solana Toutes les tables Solana applicatives suivent ce format : ```text kb_sol__ ``` Domaines autorisés au départ : | Domaine | Rôle logique | Exemple de table | |-----------|-------------------------------------------------------------------------------------|---------------------------------------| | `raw` | transactions Solana canoniques, source-indépendantes et rejouables | `kb_sol_raw_transactions` | | `core` | extraction Solana générique normalisée | `kb_sol_core_instructions` | | `obs` | observations techniques de source, programmes, instructions, logs et discriminators | `kb_sol_obs_transaction_observations` | | `decode` | événements décodés par les décodeurs | `kb_sol_decode_decoded_events` | | `mat` | projections métier matérialisées | `kb_sol_mat_trade_events` | | `catalog` | tokens, pools, paires et références stables | `kb_sol_catalog_pairs` | | `agg` | agrégations temporelles ou analytiques | `kb_sol_agg_pair_candles` | | `ops` | ledger de traitement, migrations applicatives et diagnostics | `kb_sol_ops_processing_ledger` | | `wallet` | métadonnées wallet non sensibles | `kb_sol_wallet_accounts` | Le domaine reste un préfixe de nom de table, jamais un schéma PostgreSQL. ## Décision de phasage à partir de `0.3.x` `0.3.x` corrige le modèle d’acquisition avant les décodeurs : transaction canonique source-indépendante, observations de source légères, backfill HTTP sur comptes gratuits et extraction vers `core`. Les flux payants Helius `transactionSubscribe` et Yellowstone gRPC sont reportés à `0.10.x`, après les décodeurs Core, Pump, Meteora, Raydium, Orca et Jupiter. Ils devront alimenter exactement le même contrat canonique que `getTransaction`. ## Tables candidates initiales Ces tables sont candidates, pas toutes implémentées en `0.2.0`. | Table | Jalons pressentis | Rôle | |---------------------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------| | `kb_sol_raw_rpc_transactions` | `0.2.3` historique | Ancienne table validée puis remplacée pendant `0.3.1`; absente de la baseline SQL active. | | `kb_sol_raw_transactions` | `0.3.1` | Stocker une transaction Solana canonique unique par signature, indépendante de la source. | | `kb_sol_raw_ws_notifications` | `0.2.3` historique | Ancienne table supprimée pendant `0.3.1` après conversion des métadonnées utiles; absente de la baseline active. | | `kb_sol_obs_transaction_observations` | `0.3.1` | Stocker source, protocole, méthode, timestamps, taille, latences et statuts sans dupliquer le payload transactionnel. | | `kb_sol_core_transactions` | `0.2.4` | Ligne transaction normalisée liée à une signature. | | `kb_sol_core_account_keys` | `0.2.4` | Comptes résolus, y compris loaded addresses. | | `kb_sol_core_instructions` | `0.2.4` | Instructions top-level normalisées. | | `kb_sol_core_inner_instructions` | `0.2.4` | Instructions internes normalisées. | | `kb_sol_core_logs` | `0.2.4` | Logs de transaction et ordre d'apparition. | | `kb_sol_core_balance_changes` | `0.2.4` | Deltas SOL/SPL dérivés du metadata RPC. | | `kb_sol_obs_program_observations` | `0.3.4+` | Observations par programme invoqué, après stabilisation de l'ingestion et de l'extraction. | | `kb_sol_obs_instruction_observations` | `0.3.4+` | Observations par instruction, discriminator et surface candidate, après stabilisation de l'ingestion et de l'extraction. | | `kb_sol_decode_decoded_events` | `0.4.x+` | Événements décodés par surface et version de décodeur. | | `kb_sol_mat_trade_events` | `0.5.x+` | Trades matérialisés. | | `kb_sol_catalog_tokens` | `0.5.x+` | Catalogue de tokens observés. | | `kb_sol_catalog_pools` | `0.5.x+` | Catalogue de pools observés. | | `kb_sol_catalog_pairs` | `0.5.x+` | Catalogue de paires tradables. | | `kb_sol_ops_processing_ledger` | `0.3.4+` | Ledger de traitements par module, version, input et statut, après stabilisation de l'ingestion. | ## Règles SQL générales - `id` est la clé primaire technique, sauf exception explicitement documentée. - `created_at` est le timestamp d'insertion. - `updated_at` existe seulement si la table est mutable. - `slot` est un `BIGINT` côté SQL ; les conversions Rust doivent être explicites. - `signature` est un texte non vide quand applicable. - `program_id` est un texte non vide quand applicable. - `canonical_json` est un `JSONB` réservé à la représentation canonique source-indépendante de la transaction. - `payload_json` est un `JSONB` réservé au payload décodé, enrichi ou matérialisé. - Les index minimaux sont ajoutés selon l'usage : `signature`, `slot`, `program_id`, `created_at`. - Les noms d'index utilisent un préfixe fonctionnel : `ux_` pour les index uniques et `ix_` pour les index non uniques, par exemple `ux_kb_sol_raw_transactions_signature` ou `ix_kb_sol_obs_transaction_observations_signature`. - Les contraintes de clés nommées utilisent un préfixe fonctionnel : `pk_` pour les clés primaires et `fk_` pour les clés étrangères. Les contraintes de validation peuvent utiliser `ck_`. - Les contraintes métier doivent rester strictes mais réversibles tant que les corpus ne sont pas stabilisés. ## Principe raw et cycle de vie La couche `raw` conserve une seule représentation canonique de chaque transaction Solana. Elle ne conserve pas une copie complète par transport ou fournisseur. Les adaptateurs `kb_rpc` convertissent JSON-RPC, Helius WebSocket ou Yellowstone Protobuf vers le même contrat `kb_model`. Le payload canonique reste la source rejouable pour l’extraction `core`, les décodeurs et les matérialisateurs. La couche `obs` conserve les acquisitions successives : fournisseur, endpoint, protocole, méthode, commitment, timestamps, taille et statut. `kb_sol_obs_transaction_observations` ne contient pas de `raw_json` complet. Les états de rétention s’appliquent à la transaction canonique. Les observations techniques ont une politique de conservation séparée, car elles sont petites et utiles aux mesures de couverture et de latence. Le contrat détaillé est décrit dans `docs/TRANSACTION_ACQUISITION_MODEL.md`. Le cycle de vie est décrit dans `docs/RAW_STORAGE_LIFECYCLE.md`. Le découpage core destiné aux décodeurs est décrit dans `docs/CORE_EXTRACTION_CONTRACTS.md`. ## Replay partiel Le replay ne doit pas être limité à la transaction complète. Après extraction `core`, l'unité de scheduling principale devient l'instruction normalisée. Cela permet de traiter uniquement les instructions `Pending`, `Failed` ou `ReplayRequested`, sans rejouer toute une transaction déjà extraite. Le décodage ne doit cependant pas être limité au payload de l'instruction. Les décodeurs doivent recevoir une entrée contextualisée : instruction ciblée, comptes résolus, inner instructions, logs, deltas de balance et statut de transaction. Les contrats de replay par instruction sont décrits dans `docs/INSTRUCTION_REPLAY_CONTRACTS.md`. Les contrats d'extraction core sont décrits dans `docs/CORE_EXTRACTION_CONTRACTS.md`. Chaque table dérivée doit pouvoir être reconstruite par au moins un des axes suivants quand l'information existe : - module et version ; - signature ; - plage de slots ; - `program_id` ; - surface candidate ; - discriminator ; - état dans `kb_sol_ops_processing_ledger`. ## Frontière Rust store `kb_store_core` définit les contrats indépendants du backend : DTOs, entities, health, pagination, erreurs et traits repository. `kb_store_pg` implémente PostgreSQL : pool, migrations, requêtes SQL, repositories concrets et diagnostics du schéma courant. Les structures Rust ne doivent pas être placées dans `queries/`. Les requêtes SQL, les binds et l'exécution SQL restent dans `queries/`; les types proches des lignes SQL restent dans `entities/`; les contrats applicatifs restent dans `dtos/`; les APIs de stockage restent dans `repositories/`. ## Statut `0.2.0` `0.2.0` est un jalon de cadrage. Il ne doit pas introduire un grand schéma SQL. Les migrations présentes avant cette convention doivent être neutralisées ou remplacées avant d'être exécutées sur une base réelle. ## Ajout `0.3.4` — ledger de traitement La table `kb_sol_ops_processing_ledger` devient la source de vérité de l’idempotence par processor. Pour l’extraction core, elle mémorise la signature, le hash canonique, la version, le statut, le nombre de tentatives et le dernier diagnostic. L’écriture du succès ledger, le passage raw à `core_extracted` et le graphe core sont commités ensemble. Un statut `failed` reste rejouable et ne doit jamais être interprété comme une transaction canonique invalide de façon définitive.