diff --git a/.env.example b/.env.example index cb606ce..f22359f 100644 --- a/.env.example +++ b/.env.example @@ -14,8 +14,9 @@ KS_SECRET_POSTGRES_DEVNET_URL=postgres://solana:solana@localhost:5432/khadhroony # PostgreSQL database reserved for automated integration tests. KS_SECRET_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/khadhroony_test -# Optional configuration-file override. -# KS_CONFIG_PATH=config/example.config.json +# Optional independent configuration-file overrides. +# KS_CONFIG_PATH=config/app.config.json +# KS_LOGGING_CONFIG_PATH=config/logging.config.json # Optional Devnet profile selected by CLI and opt-in scenario tests. # When absent, the first compatible Devnet profile is selected. diff --git a/Cargo.toml b/Cargo.toml index a636976..f13231b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ # file: Cargo.toml -# version: 48 +# version: 49 [workspace] resolver = "3" @@ -18,7 +18,7 @@ members = [ ] [workspace.package] -version = "0.5.1-pre.4" +version = "0.5.1-pre.5" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3" diff --git a/config/README.md b/config/README.md index 9cd7a1b..4e76c08 100644 --- a/config/README.md +++ b/config/README.md @@ -1,29 +1,50 @@ - + # Configuration locale -Ce dossier contient les exemples et le schéma de configuration JSON. +Ce dossier contient les deux documents de configuration runtime, leurs exemples et leurs schémas JSON indépendants. -## Règles +## Fichiers chargés par défaut -- Le fichier versionné doit rester sans secret. -- Les placeholders de clés restent directement dans les URLs. -- Le champ `active_profile` sélectionne un seul profil actif. -- Un profil actif doit être présent et unique. -- Les profils non actifs peuvent rester dans le fichier pour les tests devnet, mainnet lecture seule, backfill ou future production. -- Le contrat courant couvre HTTP JSON-RPC Solana et WebSocket JSON-RPC générique. -- Helius `transactionSubscribe` et Yellowstone gRPC seront ajoutés plus tard dans `ks_onchain_transport`, avec évolution explicite du schéma quand les transports seront réellement utilisés. -- Les IDLs restent des artefacts de développement et ne font pas partie de la configuration runtime. +- `app.config.json` : configuration générale Khadhroony Solana ; +- `logging.config.json` : configuration logging/tracing ; +- `schemas/app.config.schema.json` : schéma du document général ; +- `schemas/logging.config.schema.json` : schéma du document logging. -## Fichiers +Les chemins par défaut peuvent être remplacés indépendamment par : -- `example.config.json` : exemple complet avec profils `local_devnet`, `mainnet_research` et `mainnet`. -- `schema.config.json` : JSON Schema de validation du fichier de configuration. +```text +KS_CONFIG_PATH +KS_LOGGING_CONFIG_PATH +``` -## Variables d’environnement de l’exemple +## Exemples conformes -`example.config.json` conserve la topologie des profils et référence les valeurs locales avec des placeholders : +- `example.app.config.json` : exemple général minimal conforme ; +- `example.logging.config.json` : exemple logging minimal conforme. + +Les exemples servent de référence de structure. Ils ne sont pas sélectionnés automatiquement au démarrage. + +## Sélection indépendante des profils + +Chaque document possède son propre `active_profile` : + +```text +app.config.json + active_profile = mainnet_research + +logging.config.json + active_profile = mainnet_research +``` + +Ces valeurs sont indépendantes. Changer le profil applicatif ne change pas implicitement le profil logging, et inversement. Les noms peuvent être identiques pour faciliter l’exploitation sans créer de couplage contractuel. + +Le document général ne contient plus de propriété `logging`. Les routes, niveaux, formats et filtres sont exclusivement possédés par `logging.config.json` et `ks-logging`. + +## Variables d’environnement + +`app.config.json` référence notamment : ```text KS_SECRET_HELIUS_API_KEY @@ -31,73 +52,35 @@ KS_SECRET_POSTGRES_MAINNET_URL KS_SECRET_POSTGRES_DEVNET_URL ``` -`KS_SECRET_POSTGRES_TEST_URL` n’est pas utilisé par un profil runtime : il reste réservé aux tests d’intégration PostgreSQL. Le profil `local_devnet` utilise `KS_SECRET_POSTGRES_DEVNET_URL`; les profils `mainnet_research` et `mainnet` utilisent `KS_SECRET_POSTGRES_MAINNET_URL`. Les trois bases doivent être distinctes. +`KS_SECRET_POSTGRES_TEST_URL` reste réservé aux tests d’intégration PostgreSQL. Le fichier réel `.env` reste local et ignoré par Git ; `.env.example` est le modèle versionné. -Le fichier réel `.env` reste local et ignoré par Git. `.env.example` est le seul modèle dotenv versionné. +La classification `KS_SECRET_*` / `KS_PUBLIC_*` / `KS_*` et `KB_SECRET_*` / `KB_PUBLIC_*` / `KB_*` est normative. Le camouflage et la propagation de sensibilité dans les valeurs composées sont traités dans la prerelease suivante ; aucun secret ne doit être écrit en clair dans un fichier versionné. -## Phase `0.3.x` +## Schémas -`0.3.x` utilise les endpoints HTTP des profils de recherche existants pour : +Les schémas runtime sont localisés exclusivement sous `config/schemas/`. -```text -getSignaturesForAddress -getTransaction -getSignatureStatuses -``` +`ks-config` embarque `schemas/app.config.schema.json`. `ks-logging` embarque `schemas/logging.config.schema.json`. Les fichiers embarqués et leurs versions sur disque doivent rester identiques. -Aucun profil Helius payant ou Yellowstone n’est activé à ce stade. +## Migration depuis le format combiné -Les sources futures devront déclarer séparément : +L’ancien `example.config.json` combinait configuration générale et logging dans chaque profil. La migration consiste à : -- provider ; -- protocole ; -- rôle ; -- limites de streams et filtres ; -- authentification ; -- région éventuelle. - -## Évolution du schéma - -`schema.config.json` est le contrat de validation runtime. Il évolue seulement lorsqu’un champ est réellement utilisé par l’exécution. +1. conserver dans `app.config.json` les sections `app`, `database`, `data`, `solana`, `wallet`, `execution` et `demo` ; +2. extraire chaque ancien bloc `logging` vers le profil homonyme de `logging.config.json` ; +3. sélectionner explicitement un `active_profile` dans chacun des deux documents ; +4. supprimer l’ancien fichier combiné une fois la migration validée. ## Logging de développement -L’exemple configure, pour chacun des trois profils, quatre fichiers globaux puis trois fichiers dédiés par crate opérationnelle utilisant `tracing` : `debug.log`, `info.log` et `error.jsonl`. +Le fichier `logging.config.json` conserve actuellement les routes globales ainsi que trois fichiers dédiés par crate opérationnelle utilisant `tracing` : `debug.log`, `info.log` et `error.jsonl`. -Les matérialisateurs natifs consolidés rejoignent la console et disposent de leurs routes propres sous : +Les matérialisateurs consolidés disposent de leurs routes sous les targets `ks-lib-materializer.*`. Les tests de `ks-logging` découvrent dynamiquement les crates déclarant `tracing.workspace = true` et vérifient les routes canoniques du document logging par défaut. -```text -logs//ks-lib/materializer/admin/ -logs//ks-lib/materializer/compliance/audit/ -logs//ks-lib/materializer/lifecycle/ -logs//ks-lib/materializer/risk/ -logs//ks-lib/materializer/staking/ -logs//ks-lib/materializer/token/accounts/ -logs//ks-lib/materializer/transaction/annotations/ -``` - -Le test de configuration découvre dynamiquement toutes les crates déclarant `tracing.workspace = true` et vérifie leurs trois routes dans chaque profil. Les logs ne doivent contenir ni secret, ni DSN non masqué, ni payload Config ou bytecode complet. +Les logs ne doivent contenir ni secret, ni DSN non masqué, ni keypair, ni payload de configuration résolue complet. ## Limites du profil public Devnet `api.devnet.solana.com` est un endpoint public partagé. Les limites configurées par rôle ne sont pas des quotas indépendants fournis par le serveur : leur débit cumulé doit rester sous la limite globale de l’endpoint, et chaque méthode RPC doit également rester sous sa propre limite. -L’exemple `local_devnet` utilise donc volontairement des valeurs conservatrices : - -```text -http_queries: - requests_per_second: 3 - burst_capacity: 3 - max_concurrent_requests: 2 - pause_after_rate_limit_ms: 10000 - -http_transactions: - requests_per_second: 1 - burst_capacity: 1 - max_concurrent_requests: 1 - pause_after_rate_limit_ms: 10000 -``` - -Un fichier de configuration local déjà créé n’est pas modifié automatiquement lorsque `example.config.json` évolue. L’opérateur doit reporter explicitement ces valeurs dans son profil `local_devnet`. - -Un warning `retry_http_json_rpc_after_rate_limit` reste possible sur un service public partagé. Il indique que le cooldown et le retry borné ont été activés ; il ne constitue un échec que si les tentatives finissent par être épuisées. +Le profil `local_devnet` de `app.config.json` utilise donc volontairement des valeurs conservatrices pour les rôles HTTP. Un warning `retry_http_json_rpc_after_rate_limit` reste possible sur un service partagé ; il indique que le cooldown et le retry borné ont été activés. diff --git a/config/app.config.json b/config/app.config.json new file mode 100644 index 0000000..c151396 --- /dev/null +++ b/config/app.config.json @@ -0,0 +1,1110 @@ +{ + "active_profile": "mainnet_research", + "profiles": [ + { + "name": "local_devnet", + "app": { + "name": "khadhroony-bot3", + "environment": "development", + "auto_reconnect_default": false + }, + "database": { + "enabled": true, + "backend": "postgres", + "postgres": { + "url": "${KS_SECRET_POSTGRES_DEVNET_URL}", + "max_connections": 8, + "connect_timeout_ms": 5000, + "auto_initialize_schema": true + }, + "sqlite": { + "path": "data/local.sqlite", + "create_if_missing": true, + "busy_timeout_ms": 5000, + "max_connections": 1, + "auto_initialize_schema": true, + "use_wal": true + } + }, + "data": { + "wallets_directory": "wallets", + "logs_directory": "logs" + }, + "solana": { + "http_endpoints": [ + { + "name": "devnet_public_http", + "enabled": true, + "provider": "solana-public", + "cluster": "devnet", + "url": "https://api.devnet.solana.com", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 4, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 10, + "requests_per_second": 3, + "burst_capacity": 3, + "max_concurrent_requests": 2, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 10000 + }, + { + "role": "http_transactions", + "enabled": true, + "request_kinds": [ + "simulate_transaction", + "send_transaction", + "get_signature_statuses" + ], + "priority": 20, + "requests_per_second": 1, + "burst_capacity": 1, + "max_concurrent_requests": 1, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 10000 + } + ] + } + ], + "ws_endpoints": [ + { + "name": "devnet_public_ws", + "enabled": true, + "provider": "solana-public", + "cluster": "devnet", + "url": "wss://api.devnet.solana.com", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 256, + "event_channel_capacity": 1024, + "auto_reconnect": false, + "roles": [ + { + "role": "slot_notifications", + "enabled": true, + "request_kinds": [ + "slot_subscribe", + "slots_updates_subscribe" + ], + "priority": 10, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "program_logs", + "enabled": true, + "request_kinds": [ + "logs_subscribe_mentions", + "program_subscribe", + "account_subscribe", + "signature_subscribe", + "block_subscribe", + "vote_subscribe" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 64, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "root_notifications", + "enabled": true, + "request_kinds": [ + "root_subscribe" + ], + "priority": 15, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "listeners": { + "enabled": true, + "default_commitment": "confirmed", + "log_listeners": [ + { + "name": "pump_swap_logs", + "enabled": false, + "endpoint_role": "program_logs", + "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", + "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." + } + ], + "program_listeners": [ + { + "name": "pump_fun_program_accounts", + "enabled": false, + "endpoint_role": "program_logs", + "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." + } + ], + "account_listeners": [] + } + }, + "wallet": { + "wallet_dir": "wallets/temporary/local_devnet", + "cluster": "devnet", + "temporary_wallet_enabled": true, + "temporary_wallet_alias": "local-devnet-operator", + "temporary_wallet_persist": true, + "localnet_send_enabled": false, + "devnet_send_enabled": true, + "testnet_send_enabled": false, + "mainnet_send_enabled": false + }, + "execution": { + "dry_run_default": true, + "require_simulation": true, + "require_operator_confirmation": true, + "localnet_max_spend_lamports": 0, + "devnet_max_spend_lamports": 100000000, + "testnet_max_spend_lamports": 0, + "mainnet_max_spend_lamports": 0, + "max_fee_lamports": 1000000, + "max_compute_unit_price_micro_lamports": 100000, + "recent_blockhash_max_age_slots": 150, + "send_max_retries": 3, + "confirmation_poll_interval_ms": 500, + "confirmation_max_attempts": 120, + "devnet_airdrop_max_lamports": 2000000000 + }, + "demo": { + "live_demo_enabled": true, + "trading_demo_enabled": false + } + }, + { + "name": "mainnet_research", + "app": { + "name": "khadhroony-bot3", + "environment": "research", + "auto_reconnect_default": false + }, + "database": { + "enabled": true, + "backend": "postgres", + "postgres": { + "url": "${KS_SECRET_POSTGRES_MAINNET_URL}", + "max_connections": 16, + "connect_timeout_ms": 5000, + "auto_initialize_schema": true + }, + "sqlite": { + "path": "data/mainnet-import.sqlite", + "create_if_missing": true, + "busy_timeout_ms": 5000, + "max_connections": 1, + "auto_initialize_schema": true, + "use_wal": true + } + }, + "data": { + "wallets_directory": "wallets", + "logs_directory": "logs" + }, + "solana": { + "http_endpoints": [ + { + "name": "mainnet_public_http", + "enabled": true, + "provider": "solana-public", + "cluster": "mainnet-beta", + "url": "https://api.mainnet.solana.com", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 4, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 50, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "http_fallback", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 90, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + } + ] + }, + { + "name": "helius_primary_http", + "enabled": true, + "provider": "helius", + "cluster": "mainnet-beta", + "url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 8, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 10, + "requests_per_second": 8, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "http_heavy", + "enabled": true, + "request_kinds": [ + "get_block", + "get_program_accounts", + "get_signatures_for_address", + "get_transaction" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 1, + "max_concurrent_requests": 2, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "history_backfill", + "enabled": true, + "request_kinds": [ + "get_block", + "get_program_accounts", + "get_signatures_for_address", + "get_transaction" + ], + "priority": 30, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "http_transactions", + "enabled": false, + "request_kinds": [ + "simulate_transaction", + "send_transaction", + "get_signature_statuses" + ], + "priority": 40, + "requests_per_second": 1, + "burst_capacity": 1, + "max_concurrent_requests": 1, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "ws_endpoints": [ + { + "name": "mainnet_public_ws_slots", + "enabled": true, + "provider": "solana-public", + "cluster": "mainnet-beta", + "url": "wss://api.mainnet.solana.com", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 256, + "event_channel_capacity": 1024, + "auto_reconnect": false, + "roles": [ + { + "role": "slot_notifications", + "enabled": true, + "request_kinds": [ + "slot_subscribe", + "slots_updates_subscribe" + ], + "priority": 10, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "root_notifications", + "enabled": true, + "request_kinds": [ + "root_subscribe" + ], + "priority": 20, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + } + ] + }, + { + "name": "helius_primary_ws_programs", + "enabled": true, + "provider": "helius", + "cluster": "mainnet-beta", + "url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 512, + "event_channel_capacity": 4096, + "auto_reconnect": false, + "roles": [ + { + "role": "logs_subscribe", + "enabled": true, + "request_kinds": [ + "logs_subscribe_mentions" + ], + "priority": 10, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "program_subscribe", + "enabled": true, + "request_kinds": [ + "program_subscribe" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "account_subscribe", + "enabled": true, + "request_kinds": [ + "account_subscribe" + ], + "priority": 30, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "listeners": { + "enabled": true, + "default_commitment": "confirmed", + "log_listeners": [ + { + "name": "pump_swap_logs", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", + "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." + }, + { + "name": "raydium_cpmm_logs", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", + "purpose": "Détecter les créations de pools et swaps Raydium CPMM." + } + ], + "program_listeners": [ + { + "name": "pump_fun_program_accounts", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." + } + ], + "account_listeners": [] + } + }, + "wallet": { + "wallet_dir": "wallets/temporary/mainnet_research", + "cluster": "mainnet-beta", + "temporary_wallet_enabled": false, + "temporary_wallet_alias": "mainnet_research-disabled", + "temporary_wallet_persist": false, + "localnet_send_enabled": false, + "devnet_send_enabled": false, + "testnet_send_enabled": false, + "mainnet_send_enabled": false + }, + "execution": { + "dry_run_default": true, + "require_simulation": true, + "require_operator_confirmation": true, + "localnet_max_spend_lamports": 0, + "devnet_max_spend_lamports": 0, + "testnet_max_spend_lamports": 0, + "mainnet_max_spend_lamports": 0, + "max_fee_lamports": 1000000, + "max_compute_unit_price_micro_lamports": 100000, + "recent_blockhash_max_age_slots": 150, + "send_max_retries": 3, + "confirmation_poll_interval_ms": 500, + "confirmation_max_attempts": 120, + "devnet_airdrop_max_lamports": 0 + }, + "demo": { + "live_demo_enabled": true, + "trading_demo_enabled": false + } + }, + { + "name": "mainnet", + "app": { + "name": "khadhroony-bot3", + "environment": "mainnet", + "auto_reconnect_default": false + }, + "database": { + "enabled": true, + "backend": "postgres", + "postgres": { + "url": "${KS_SECRET_POSTGRES_MAINNET_URL}", + "max_connections": 16, + "connect_timeout_ms": 5000, + "auto_initialize_schema": true + }, + "sqlite": { + "path": "data/mainnet.sqlite", + "create_if_missing": true, + "busy_timeout_ms": 5000, + "max_connections": 1, + "auto_initialize_schema": true, + "use_wal": true + } + }, + "data": { + "wallets_directory": "wallets", + "logs_directory": "logs" + }, + "solana": { + "http_endpoints": [ + { + "name": "mainnet_public_http", + "enabled": true, + "provider": "solana-public", + "cluster": "mainnet-beta", + "url": "https://api.mainnet.solana.com", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 4, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 50, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "http_fallback", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 90, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + } + ] + }, + { + "name": "helius_primary_http", + "enabled": true, + "provider": "helius", + "cluster": "mainnet-beta", + "url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 8, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 10, + "requests_per_second": 8, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "http_heavy", + "enabled": true, + "request_kinds": [ + "get_block", + "get_program_accounts", + "get_signatures_for_address", + "get_transaction" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 1, + "max_concurrent_requests": 2, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "history_backfill", + "enabled": true, + "request_kinds": [ + "get_block", + "get_program_accounts", + "get_signatures_for_address", + "get_transaction" + ], + "priority": 30, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 1500 + }, + { + "role": "http_transactions", + "enabled": false, + "request_kinds": [ + "simulate_transaction", + "send_transaction", + "get_signature_statuses" + ], + "priority": 40, + "requests_per_second": 1, + "burst_capacity": 1, + "max_concurrent_requests": 1, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "ws_endpoints": [ + { + "name": "mainnet_public_ws_slots", + "enabled": true, + "provider": "solana-public", + "cluster": "mainnet-beta", + "url": "wss://api.mainnet.solana.com", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 256, + "event_channel_capacity": 1024, + "auto_reconnect": false, + "roles": [ + { + "role": "slot_notifications", + "enabled": true, + "request_kinds": [ + "slot_subscribe", + "slots_updates_subscribe" + ], + "priority": 10, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "root_notifications", + "enabled": true, + "request_kinds": [ + "root_subscribe" + ], + "priority": 20, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + } + ] + }, + { + "name": "helius_primary_ws_programs", + "enabled": true, + "provider": "helius", + "cluster": "mainnet-beta", + "url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 512, + "event_channel_capacity": 4096, + "auto_reconnect": false, + "roles": [ + { + "role": "logs_subscribe", + "enabled": true, + "request_kinds": [ + "logs_subscribe_mentions" + ], + "priority": 10, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "program_subscribe", + "enabled": true, + "request_kinds": [ + "program_subscribe" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "account_subscribe", + "enabled": true, + "request_kinds": [ + "account_subscribe" + ], + "priority": 30, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 128, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "listeners": { + "enabled": true, + "default_commitment": "confirmed", + "log_listeners": [ + { + "name": "pump_swap_logs", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", + "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." + }, + { + "name": "raydium_cpmm_logs", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", + "purpose": "Détecter les créations de pools et swaps Raydium CPMM." + } + ], + "program_listeners": [ + { + "name": "pump_fun_program_accounts", + "enabled": true, + "endpoint_role": "program_logs", + "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." + } + ], + "account_listeners": [] + } + }, + "wallet": { + "wallet_dir": "wallets/temporary/mainnet", + "cluster": "mainnet-beta", + "temporary_wallet_enabled": false, + "temporary_wallet_alias": "mainnet-disabled", + "temporary_wallet_persist": false, + "localnet_send_enabled": false, + "devnet_send_enabled": false, + "testnet_send_enabled": false, + "mainnet_send_enabled": false + }, + "execution": { + "dry_run_default": true, + "require_simulation": true, + "require_operator_confirmation": true, + "localnet_max_spend_lamports": 0, + "devnet_max_spend_lamports": 0, + "testnet_max_spend_lamports": 0, + "mainnet_max_spend_lamports": 0, + "max_fee_lamports": 1000000, + "max_compute_unit_price_micro_lamports": 100000, + "recent_blockhash_max_age_slots": 150, + "send_max_retries": 3, + "confirmation_poll_interval_ms": 500, + "confirmation_max_attempts": 120, + "devnet_airdrop_max_lamports": 0 + }, + "demo": { + "live_demo_enabled": true, + "trading_demo_enabled": false + } + } + ] +} \ No newline at end of file diff --git a/config/example.app.config.json b/config/example.app.config.json new file mode 100644 index 0000000..0d20136 --- /dev/null +++ b/config/example.app.config.json @@ -0,0 +1,240 @@ +{ + "active_profile": "local_devnet", + "profiles": [ + { + "name": "local_devnet", + "app": { + "name": "khadhroony-bot3", + "environment": "development", + "auto_reconnect_default": false + }, + "database": { + "enabled": true, + "backend": "postgres", + "postgres": { + "url": "${KS_SECRET_POSTGRES_DEVNET_URL}", + "max_connections": 8, + "connect_timeout_ms": 5000, + "auto_initialize_schema": true + }, + "sqlite": { + "path": "data/local.sqlite", + "create_if_missing": true, + "busy_timeout_ms": 5000, + "max_connections": 1, + "auto_initialize_schema": true, + "use_wal": true + } + }, + "data": { + "wallets_directory": "wallets", + "logs_directory": "logs" + }, + "solana": { + "http_endpoints": [ + { + "name": "devnet_public_http", + "enabled": true, + "provider": "solana-public", + "cluster": "devnet", + "url": "https://api.devnet.solana.com", + "connect_timeout_ms": 4000, + "request_timeout_ms": 10000, + "max_idle_connections_per_host": 4, + "roles": [ + { + "role": "http_queries", + "enabled": true, + "request_kinds": [ + "get_account_info", + "get_balance", + "get_block_commitment", + "get_block_height", + "get_block_production", + "get_blocks", + "get_blocks_with_limit", + "get_cluster_nodes", + "get_epoch_info", + "get_epoch_schedule", + "get_fee_for_message", + "get_first_available_block", + "get_genesis_hash", + "get_health", + "get_highest_snapshot_slot", + "get_identity", + "get_inflation_governor", + "get_inflation_rate", + "get_inflation_reward", + "get_largest_accounts", + "get_latest_blockhash", + "get_leader_schedule", + "get_max_retransmit_slot", + "get_max_shred_insert_slot", + "get_minimum_balance_for_rent_exemption", + "get_multiple_accounts", + "get_recent_performance_samples", + "get_recent_prioritization_fees", + "get_signature_statuses", + "get_slot", + "get_slot_leader", + "get_slot_leaders", + "get_stake_activation", + "get_stake_minimum_delegation", + "get_supply", + "get_token_account_balance", + "get_token_accounts_by_delegate", + "get_token_accounts_by_owner", + "get_token_largest_accounts", + "get_token_supply", + "get_transaction", + "get_transaction_count", + "get_version", + "get_vote_accounts", + "is_blockhash_valid", + "request_airdrop" + ], + "priority": 10, + "requests_per_second": 3, + "burst_capacity": 3, + "max_concurrent_requests": 2, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 10000 + }, + { + "role": "http_transactions", + "enabled": true, + "request_kinds": [ + "simulate_transaction", + "send_transaction", + "get_signature_statuses" + ], + "priority": 20, + "requests_per_second": 1, + "burst_capacity": 1, + "max_concurrent_requests": 1, + "max_subscriptions": 0, + "pause_after_rate_limit_ms": 10000 + } + ] + } + ], + "ws_endpoints": [ + { + "name": "devnet_public_ws", + "enabled": true, + "provider": "solana-public", + "cluster": "devnet", + "url": "wss://api.devnet.solana.com", + "connect_timeout_ms": 5000, + "request_timeout_ms": 10000, + "unsubscribe_timeout_ms": 1500, + "write_channel_capacity": 256, + "event_channel_capacity": 1024, + "auto_reconnect": false, + "roles": [ + { + "role": "slot_notifications", + "enabled": true, + "request_kinds": [ + "slot_subscribe", + "slots_updates_subscribe" + ], + "priority": 10, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "program_logs", + "enabled": true, + "request_kinds": [ + "logs_subscribe_mentions", + "program_subscribe", + "account_subscribe", + "signature_subscribe", + "block_subscribe", + "vote_subscribe" + ], + "priority": 20, + "requests_per_second": 2, + "burst_capacity": 4, + "max_concurrent_requests": 2, + "max_subscriptions": 64, + "pause_after_rate_limit_ms": 3000 + }, + { + "role": "root_notifications", + "enabled": true, + "request_kinds": [ + "root_subscribe" + ], + "priority": 15, + "requests_per_second": 4, + "burst_capacity": 8, + "max_concurrent_requests": 4, + "max_subscriptions": 16, + "pause_after_rate_limit_ms": 3000 + } + ] + } + ], + "listeners": { + "enabled": true, + "default_commitment": "confirmed", + "log_listeners": [ + { + "name": "pump_swap_logs", + "enabled": false, + "endpoint_role": "program_logs", + "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", + "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." + } + ], + "program_listeners": [ + { + "name": "pump_fun_program_accounts", + "enabled": false, + "endpoint_role": "program_logs", + "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." + } + ], + "account_listeners": [] + } + }, + "wallet": { + "wallet_dir": "wallets/temporary/local_devnet", + "cluster": "devnet", + "temporary_wallet_enabled": true, + "temporary_wallet_alias": "local-devnet-operator", + "temporary_wallet_persist": true, + "localnet_send_enabled": false, + "devnet_send_enabled": true, + "testnet_send_enabled": false, + "mainnet_send_enabled": false + }, + "execution": { + "dry_run_default": true, + "require_simulation": true, + "require_operator_confirmation": true, + "localnet_max_spend_lamports": 0, + "devnet_max_spend_lamports": 100000000, + "testnet_max_spend_lamports": 0, + "mainnet_max_spend_lamports": 0, + "max_fee_lamports": 1000000, + "max_compute_unit_price_micro_lamports": 100000, + "recent_blockhash_max_age_slots": 150, + "send_max_retries": 3, + "confirmation_poll_interval_ms": 500, + "confirmation_max_attempts": 120, + "devnet_airdrop_max_lamports": 2000000000 + }, + "demo": { + "live_demo_enabled": true, + "trading_demo_enabled": false + } + } + ] +} diff --git a/config/example.config.json b/config/example.config.json deleted file mode 100644 index 3ee3567..0000000 --- a/config/example.config.json +++ /dev/null @@ -1,4659 +0,0 @@ -{ - "active_profile": "mainnet_research", - "profiles": [ - { - "name": "local_devnet", - "app": { - "name": "khadhroony-bot3", - "environment": "development", - "auto_reconnect_default": false - }, - "logging": { - "default_level": "warn", - "targets": [ - { - "name": "console_local_devnet_compact", - "enabled": true, - "sink": "console", - "level": "debug", - "path": "", - "rotation": "none", - "format": "compact", - "ansi": true, - "targets": [ - "*" - ] - }, - { - "name": "file_local_devnet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_local_devnet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_local_devnet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_local_devnet_app", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/app.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks_lib_local_devnet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_local_devnet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_local_devnet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_kb-app-demo-desktop_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/kb-app-demo-desktop/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/kb-app-demo-desktop/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/kb-app-demo-desktop/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/solana/transaction/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/solana/transaction/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/solana/transaction/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks_logging_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-logging/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-logging/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-logging/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks-lib_materializer_admin_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/admin/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/admin/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/admin/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/compliance/audit/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/compliance/audit/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/compliance/audit/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/lifecycle/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/lifecycle/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/lifecycle/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/transaction/annotations/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/transaction/annotations/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/transaction/annotations/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_staking_debug", - "enabled": true, - "level": "debug", - "format": "human", - "path": "logs/devnet/ks-lib/materializer/staking/debug.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_info", - "enabled": true, - "level": "info", - "format": "human", - "path": "logs/devnet/ks-lib/materializer/staking/info.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_error", - "enabled": true, - "level": "error", - "format": "json", - "path": "logs/devnet/ks-lib/materializer/staking/error.jsonl", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-pipeline_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-pipeline/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-pipeline/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-pipeline/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-onchain-transport_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-onchain-transport/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-onchain-transport/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-onchain-transport/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-store_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-store/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-store/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-store/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks_wallet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-wallet/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-wallet/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-wallet/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/token/accounts/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/token/accounts/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/token/accounts/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_risk_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/materializer/risk/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/materializer/risk/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/materializer/risk/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/devnet/ks-lib/executor/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/devnet/ks-lib/executor/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/devnet/ks-lib/executor/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - } - ], - "target_filters": [ - { - "target": "hyper", - "level": "warn" - }, - { - "target": "reqwest", - "level": "warn" - }, - { - "target": "tao", - "level": "warn" - }, - { - "target": "wry", - "level": "warn" - } - ] - }, - "database": { - "enabled": true, - "backend": "postgres", - "postgres": { - "url": "${KS_SECRET_POSTGRES_DEVNET_URL}", - "max_connections": 8, - "connect_timeout_ms": 5000, - "auto_initialize_schema": true - }, - "sqlite": { - "path": "data/local.sqlite", - "create_if_missing": true, - "busy_timeout_ms": 5000, - "max_connections": 1, - "auto_initialize_schema": true, - "use_wal": true - } - }, - "data": { - "wallets_directory": "wallets", - "logs_directory": "logs" - }, - "solana": { - "http_endpoints": [ - { - "name": "devnet_public_http", - "enabled": true, - "provider": "solana-public", - "cluster": "devnet", - "url": "https://api.devnet.solana.com", - "connect_timeout_ms": 4000, - "request_timeout_ms": 10000, - "max_idle_connections_per_host": 4, - "roles": [ - { - "role": "http_queries", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 10, - "requests_per_second": 3, - "burst_capacity": 3, - "max_concurrent_requests": 2, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 10000 - }, - { - "role": "http_transactions", - "enabled": true, - "request_kinds": [ - "simulate_transaction", - "send_transaction", - "get_signature_statuses" - ], - "priority": 20, - "requests_per_second": 1, - "burst_capacity": 1, - "max_concurrent_requests": 1, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 10000 - } - ] - } - ], - "ws_endpoints": [ - { - "name": "devnet_public_ws", - "enabled": true, - "provider": "solana-public", - "cluster": "devnet", - "url": "wss://api.devnet.solana.com", - "connect_timeout_ms": 5000, - "request_timeout_ms": 10000, - "unsubscribe_timeout_ms": 1500, - "write_channel_capacity": 256, - "event_channel_capacity": 1024, - "auto_reconnect": false, - "roles": [ - { - "role": "slot_notifications", - "enabled": true, - "request_kinds": [ - "slot_subscribe", - "slots_updates_subscribe" - ], - "priority": 10, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "program_logs", - "enabled": true, - "request_kinds": [ - "logs_subscribe_mentions", - "program_subscribe", - "account_subscribe", - "signature_subscribe", - "block_subscribe", - "vote_subscribe" - ], - "priority": 20, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 64, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "root_notifications", - "enabled": true, - "request_kinds": [ - "root_subscribe" - ], - "priority": 15, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - } - ] - } - ], - "listeners": { - "enabled": true, - "default_commitment": "confirmed", - "log_listeners": [ - { - "name": "pump_swap_logs", - "enabled": false, - "endpoint_role": "program_logs", - "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", - "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." - } - ], - "program_listeners": [ - { - "name": "pump_fun_program_accounts", - "enabled": false, - "endpoint_role": "program_logs", - "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." - } - ], - "account_listeners": [] - } - }, - "wallet": { - "wallet_dir": "wallets/temporary/local_devnet", - "cluster": "devnet", - "temporary_wallet_enabled": true, - "temporary_wallet_alias": "local-devnet-operator", - "temporary_wallet_persist": true, - "localnet_send_enabled": false, - "devnet_send_enabled": true, - "testnet_send_enabled": false, - "mainnet_send_enabled": false - }, - "execution": { - "dry_run_default": true, - "require_simulation": true, - "require_operator_confirmation": true, - "localnet_max_spend_lamports": 0, - "devnet_max_spend_lamports": 100000000, - "testnet_max_spend_lamports": 0, - "mainnet_max_spend_lamports": 0, - "max_fee_lamports": 1000000, - "max_compute_unit_price_micro_lamports": 100000, - "recent_blockhash_max_age_slots": 150, - "send_max_retries": 3, - "confirmation_poll_interval_ms": 500, - "confirmation_max_attempts": 120, - "devnet_airdrop_max_lamports": 2000000000 - }, - "demo": { - "live_demo_enabled": true, - "trading_demo_enabled": false - } - }, - { - "name": "mainnet_research", - "app": { - "name": "khadhroony-bot3", - "environment": "research", - "auto_reconnect_default": false - }, - "logging": { - "default_level": "warn", - "targets": [ - { - "name": "console_mainnet_research_compact", - "enabled": true, - "sink": "console", - "level": "debug", - "path": "", - "rotation": "none", - "format": "compact", - "ansi": true, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_research_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_research_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_research_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_research_app", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/app.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks_lib_mainnet_research_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_mainnet_research_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_mainnet_research_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_kb-app-demo-desktop_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/kb-app-demo-desktop/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/kb-app-demo-desktop/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/kb-app-demo-desktop/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks_logging_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-logging/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-logging/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-logging/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks-lib_materializer_admin_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/admin/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/admin/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/admin/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_staking_debug", - "enabled": true, - "level": "debug", - "format": "human", - "path": "logs/mainnet_research/ks-lib/materializer/staking/debug.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_info", - "enabled": true, - "level": "info", - "format": "human", - "path": "logs/mainnet_research/ks-lib/materializer/staking/info.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_error", - "enabled": true, - "level": "error", - "format": "json", - "path": "logs/mainnet_research/ks-lib/materializer/staking/error.jsonl", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-pipeline_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-pipeline/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-pipeline/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-pipeline/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-onchain-transport_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-onchain-transport/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-onchain-transport/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-onchain-transport/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-store_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-store/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-store/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-store/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks_wallet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-wallet/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-wallet/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-wallet/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_risk_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/materializer/risk/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/materializer/risk/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/materializer/risk/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - } - ], - "target_filters": [ - { - "target": "hyper", - "level": "warn" - }, - { - "target": "reqwest", - "level": "warn" - }, - { - "target": "tao", - "level": "warn" - }, - { - "target": "wry", - "level": "warn" - } - ] - }, - "database": { - "enabled": true, - "backend": "postgres", - "postgres": { - "url": "${KS_SECRET_POSTGRES_MAINNET_URL}", - "max_connections": 16, - "connect_timeout_ms": 5000, - "auto_initialize_schema": true - }, - "sqlite": { - "path": "data/mainnet-import.sqlite", - "create_if_missing": true, - "busy_timeout_ms": 5000, - "max_connections": 1, - "auto_initialize_schema": true, - "use_wal": true - } - }, - "data": { - "wallets_directory": "wallets", - "logs_directory": "logs" - }, - "solana": { - "http_endpoints": [ - { - "name": "mainnet_public_http", - "enabled": true, - "provider": "solana-public", - "cluster": "mainnet-beta", - "url": "https://api.mainnet.solana.com", - "connect_timeout_ms": 4000, - "request_timeout_ms": 10000, - "max_idle_connections_per_host": 4, - "roles": [ - { - "role": "http_queries", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 50, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "http_fallback", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 90, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - } - ] - }, - { - "name": "helius_primary_http", - "enabled": true, - "provider": "helius", - "cluster": "mainnet-beta", - "url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", - "connect_timeout_ms": 4000, - "request_timeout_ms": 10000, - "max_idle_connections_per_host": 8, - "roles": [ - { - "role": "http_queries", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 10, - "requests_per_second": 8, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "http_heavy", - "enabled": true, - "request_kinds": [ - "get_block", - "get_program_accounts", - "get_signatures_for_address", - "get_transaction" - ], - "priority": 20, - "requests_per_second": 2, - "burst_capacity": 1, - "max_concurrent_requests": 2, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "history_backfill", - "enabled": true, - "request_kinds": [ - "get_block", - "get_program_accounts", - "get_signatures_for_address", - "get_transaction" - ], - "priority": 30, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "http_transactions", - "enabled": false, - "request_kinds": [ - "simulate_transaction", - "send_transaction", - "get_signature_statuses" - ], - "priority": 40, - "requests_per_second": 1, - "burst_capacity": 1, - "max_concurrent_requests": 1, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - } - ] - } - ], - "ws_endpoints": [ - { - "name": "mainnet_public_ws_slots", - "enabled": true, - "provider": "solana-public", - "cluster": "mainnet-beta", - "url": "wss://api.mainnet.solana.com", - "connect_timeout_ms": 5000, - "request_timeout_ms": 10000, - "unsubscribe_timeout_ms": 1500, - "write_channel_capacity": 256, - "event_channel_capacity": 1024, - "auto_reconnect": false, - "roles": [ - { - "role": "slot_notifications", - "enabled": true, - "request_kinds": [ - "slot_subscribe", - "slots_updates_subscribe" - ], - "priority": 10, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "root_notifications", - "enabled": true, - "request_kinds": [ - "root_subscribe" - ], - "priority": 20, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - } - ] - }, - { - "name": "helius_primary_ws_programs", - "enabled": true, - "provider": "helius", - "cluster": "mainnet-beta", - "url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", - "connect_timeout_ms": 5000, - "request_timeout_ms": 10000, - "unsubscribe_timeout_ms": 1500, - "write_channel_capacity": 512, - "event_channel_capacity": 4096, - "auto_reconnect": false, - "roles": [ - { - "role": "logs_subscribe", - "enabled": true, - "request_kinds": [ - "logs_subscribe_mentions" - ], - "priority": 10, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "program_subscribe", - "enabled": true, - "request_kinds": [ - "program_subscribe" - ], - "priority": 20, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "account_subscribe", - "enabled": true, - "request_kinds": [ - "account_subscribe" - ], - "priority": 30, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - } - ] - } - ], - "listeners": { - "enabled": true, - "default_commitment": "confirmed", - "log_listeners": [ - { - "name": "pump_swap_logs", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", - "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." - }, - { - "name": "raydium_cpmm_logs", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", - "purpose": "Détecter les créations de pools et swaps Raydium CPMM." - } - ], - "program_listeners": [ - { - "name": "pump_fun_program_accounts", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." - } - ], - "account_listeners": [] - } - }, - "wallet": { - "wallet_dir": "wallets/temporary/mainnet_research", - "cluster": "mainnet-beta", - "temporary_wallet_enabled": false, - "temporary_wallet_alias": "mainnet_research-disabled", - "temporary_wallet_persist": false, - "localnet_send_enabled": false, - "devnet_send_enabled": false, - "testnet_send_enabled": false, - "mainnet_send_enabled": false - }, - "execution": { - "dry_run_default": true, - "require_simulation": true, - "require_operator_confirmation": true, - "localnet_max_spend_lamports": 0, - "devnet_max_spend_lamports": 0, - "testnet_max_spend_lamports": 0, - "mainnet_max_spend_lamports": 0, - "max_fee_lamports": 1000000, - "max_compute_unit_price_micro_lamports": 100000, - "recent_blockhash_max_age_slots": 150, - "send_max_retries": 3, - "confirmation_poll_interval_ms": 500, - "confirmation_max_attempts": 120, - "devnet_airdrop_max_lamports": 0 - }, - "demo": { - "live_demo_enabled": true, - "trading_demo_enabled": false - } - }, - { - "name": "mainnet", - "app": { - "name": "khadhroony-bot3", - "environment": "mainnet", - "auto_reconnect_default": false - }, - "logging": { - "default_level": "warn", - "targets": [ - { - "name": "console_mainnet_compact", - "enabled": true, - "sink": "console", - "level": "debug", - "path": "", - "rotation": "none", - "format": "compact", - "ansi": true, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "*" - ] - }, - { - "name": "file_mainnet_app", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/app.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks_lib_mainnet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_mainnet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_ks_lib_mainnet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib" - ] - }, - { - "name": "file_kb-app-demo-desktop_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/kb-app-demo-desktop/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/kb-app-demo-desktop/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_kb-app-demo-desktop_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/kb-app-demo-desktop/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "kb-app-demo-desktop" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.solana.core" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.memo" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/solana/core/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/solana/core/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_core_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/solana/core/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.core" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/solana/transaction/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/solana/transaction/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_solana_transaction_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/solana/transaction/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.solana.transaction" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/spl/memo/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/spl/memo/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_memo_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/spl/memo/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.memo" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_associated_token_account_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.associated_token_account" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/spl/token/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/spl/token/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/spl/token/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token" - ] - }, - { - "name": "file_ks_logging_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-logging/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-logging/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks_logging_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-logging/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-logging" - ] - }, - { - "name": "file_ks-lib_materializer_admin_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/admin/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/admin/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_admin_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/admin/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.admin" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/compliance/audit/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/compliance/audit/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_compliance_audit_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/compliance/audit/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.compliance.audit" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/lifecycle/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/lifecycle/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_lifecycle_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/lifecycle/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.lifecycle" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_transaction_annotations_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.transaction.annotations" - ] - }, - { - "name": "file_ks-lib_materializer_staking_debug", - "enabled": true, - "level": "debug", - "format": "human", - "path": "logs/mainnet/ks-lib/materializer/staking/debug.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_info", - "enabled": true, - "level": "info", - "format": "human", - "path": "logs/mainnet/ks-lib/materializer/staking/info.log", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-lib_materializer_staking_error", - "enabled": true, - "level": "error", - "format": "json", - "path": "logs/mainnet/ks-lib/materializer/staking/error.jsonl", - "targets": [ - "ks-lib-materializer.staking" - ], - "sink": "file", - "rotation": "daily", - "ansi": false - }, - { - "name": "file_ks-pipeline_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-pipeline/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-pipeline/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-pipeline_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-pipeline/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-pipeline", - "ks-pipeline-demo-scenarios" - ] - }, - { - "name": "file_ks-onchain-transport_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-onchain-transport/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-onchain-transport/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-onchain-transport_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-onchain-transport/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-onchain-transport" - ] - }, - { - "name": "file_ks-store_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-store/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-store/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks-store_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-store/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-store" - ] - }, - { - "name": "file_ks_wallet_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-wallet/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-wallet/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks_wallet_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-wallet/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-wallet" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/token/accounts/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/token/accounts/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_token_accounts_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/token/accounts/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.token.accounts" - ] - }, - { - "name": "file_ks-lib_materializer_risk_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/materializer/risk/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/materializer/risk/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_materializer_risk_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/materializer/risk/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-materializer.risk" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.metadata.metaplex_token_metadata" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_decoder_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-decoder.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_elgamal_registry_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.elgamal_registry" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_debug", - "enabled": true, - "sink": "file", - "level": "debug", - "path": "logs/mainnet/ks-lib/executor/spl/token_2022/debug.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_info", - "enabled": true, - "sink": "file", - "level": "info", - "path": "logs/mainnet/ks-lib/executor/spl/token_2022/info.log", - "rotation": "daily", - "format": "human", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - }, - { - "name": "file_ks-lib_executor_spl_token_2022_error", - "enabled": true, - "sink": "file", - "level": "error", - "path": "logs/mainnet/ks-lib/executor/spl/token_2022/error.jsonl", - "rotation": "daily", - "format": "json", - "ansi": false, - "targets": [ - "ks-lib-executor.spl.token_2022" - ] - } - ], - "target_filters": [ - { - "target": "hyper", - "level": "warn" - }, - { - "target": "reqwest", - "level": "warn" - }, - { - "target": "tao", - "level": "warn" - }, - { - "target": "wry", - "level": "warn" - } - ] - }, - "database": { - "enabled": true, - "backend": "postgres", - "postgres": { - "url": "${KS_SECRET_POSTGRES_MAINNET_URL}", - "max_connections": 16, - "connect_timeout_ms": 5000, - "auto_initialize_schema": true - }, - "sqlite": { - "path": "data/mainnet.sqlite", - "create_if_missing": true, - "busy_timeout_ms": 5000, - "max_connections": 1, - "auto_initialize_schema": true, - "use_wal": true - } - }, - "data": { - "wallets_directory": "wallets", - "logs_directory": "logs" - }, - "solana": { - "http_endpoints": [ - { - "name": "mainnet_public_http", - "enabled": true, - "provider": "solana-public", - "cluster": "mainnet-beta", - "url": "https://api.mainnet.solana.com", - "connect_timeout_ms": 4000, - "request_timeout_ms": 10000, - "max_idle_connections_per_host": 4, - "roles": [ - { - "role": "http_queries", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 50, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "http_fallback", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 90, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - } - ] - }, - { - "name": "helius_primary_http", - "enabled": true, - "provider": "helius", - "cluster": "mainnet-beta", - "url": "https://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", - "connect_timeout_ms": 4000, - "request_timeout_ms": 10000, - "max_idle_connections_per_host": 8, - "roles": [ - { - "role": "http_queries", - "enabled": true, - "request_kinds": [ - "get_account_info", - "get_balance", - "get_block_commitment", - "get_block_height", - "get_block_production", - "get_blocks", - "get_blocks_with_limit", - "get_cluster_nodes", - "get_epoch_info", - "get_epoch_schedule", - "get_fee_for_message", - "get_first_available_block", - "get_genesis_hash", - "get_health", - "get_highest_snapshot_slot", - "get_identity", - "get_inflation_governor", - "get_inflation_rate", - "get_inflation_reward", - "get_largest_accounts", - "get_latest_blockhash", - "get_leader_schedule", - "get_max_retransmit_slot", - "get_max_shred_insert_slot", - "get_minimum_balance_for_rent_exemption", - "get_multiple_accounts", - "get_recent_performance_samples", - "get_recent_prioritization_fees", - "get_signature_statuses", - "get_slot", - "get_slot_leader", - "get_slot_leaders", - "get_stake_activation", - "get_stake_minimum_delegation", - "get_supply", - "get_token_account_balance", - "get_token_accounts_by_delegate", - "get_token_accounts_by_owner", - "get_token_largest_accounts", - "get_token_supply", - "get_transaction_count", - "get_version", - "get_vote_accounts", - "is_blockhash_valid", - "request_airdrop" - ], - "priority": 10, - "requests_per_second": 8, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "http_heavy", - "enabled": true, - "request_kinds": [ - "get_block", - "get_program_accounts", - "get_signatures_for_address", - "get_transaction" - ], - "priority": 20, - "requests_per_second": 2, - "burst_capacity": 1, - "max_concurrent_requests": 2, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "history_backfill", - "enabled": true, - "request_kinds": [ - "get_block", - "get_program_accounts", - "get_signatures_for_address", - "get_transaction" - ], - "priority": 30, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 1500 - }, - { - "role": "http_transactions", - "enabled": false, - "request_kinds": [ - "simulate_transaction", - "send_transaction", - "get_signature_statuses" - ], - "priority": 40, - "requests_per_second": 1, - "burst_capacity": 1, - "max_concurrent_requests": 1, - "max_subscriptions": 0, - "pause_after_rate_limit_ms": 3000 - } - ] - } - ], - "ws_endpoints": [ - { - "name": "mainnet_public_ws_slots", - "enabled": true, - "provider": "solana-public", - "cluster": "mainnet-beta", - "url": "wss://api.mainnet.solana.com", - "connect_timeout_ms": 5000, - "request_timeout_ms": 10000, - "unsubscribe_timeout_ms": 1500, - "write_channel_capacity": 256, - "event_channel_capacity": 1024, - "auto_reconnect": false, - "roles": [ - { - "role": "slot_notifications", - "enabled": true, - "request_kinds": [ - "slot_subscribe", - "slots_updates_subscribe" - ], - "priority": 10, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "root_notifications", - "enabled": true, - "request_kinds": [ - "root_subscribe" - ], - "priority": 20, - "requests_per_second": 4, - "burst_capacity": 8, - "max_concurrent_requests": 4, - "max_subscriptions": 16, - "pause_after_rate_limit_ms": 3000 - } - ] - }, - { - "name": "helius_primary_ws_programs", - "enabled": true, - "provider": "helius", - "cluster": "mainnet-beta", - "url": "wss://mainnet.helius-rpc.com/?api-key=${KS_SECRET_HELIUS_API_KEY}", - "connect_timeout_ms": 5000, - "request_timeout_ms": 10000, - "unsubscribe_timeout_ms": 1500, - "write_channel_capacity": 512, - "event_channel_capacity": 4096, - "auto_reconnect": false, - "roles": [ - { - "role": "logs_subscribe", - "enabled": true, - "request_kinds": [ - "logs_subscribe_mentions" - ], - "priority": 10, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "program_subscribe", - "enabled": true, - "request_kinds": [ - "program_subscribe" - ], - "priority": 20, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - }, - { - "role": "account_subscribe", - "enabled": true, - "request_kinds": [ - "account_subscribe" - ], - "priority": 30, - "requests_per_second": 2, - "burst_capacity": 4, - "max_concurrent_requests": 2, - "max_subscriptions": 128, - "pause_after_rate_limit_ms": 3000 - } - ] - } - ], - "listeners": { - "enabled": true, - "default_commitment": "confirmed", - "log_listeners": [ - { - "name": "pump_swap_logs", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", - "purpose": "Détecter les swaps, créations de pool et changements de liquidité Pump Swap." - }, - { - "name": "raydium_cpmm_logs", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", - "purpose": "Détecter les créations de pools et swaps Raydium CPMM." - } - ], - "program_listeners": [ - { - "name": "pump_fun_program_accounts", - "enabled": true, - "endpoint_role": "program_logs", - "program_id": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "purpose": "Détecter les changements de comptes utiles à la création ou migration de tokens Pump Fun." - } - ], - "account_listeners": [] - } - }, - "wallet": { - "wallet_dir": "wallets/temporary/mainnet", - "cluster": "mainnet-beta", - "temporary_wallet_enabled": false, - "temporary_wallet_alias": "mainnet-disabled", - "temporary_wallet_persist": false, - "localnet_send_enabled": false, - "devnet_send_enabled": false, - "testnet_send_enabled": false, - "mainnet_send_enabled": false - }, - "execution": { - "dry_run_default": true, - "require_simulation": true, - "require_operator_confirmation": true, - "localnet_max_spend_lamports": 0, - "devnet_max_spend_lamports": 0, - "testnet_max_spend_lamports": 0, - "mainnet_max_spend_lamports": 0, - "max_fee_lamports": 1000000, - "max_compute_unit_price_micro_lamports": 100000, - "recent_blockhash_max_age_slots": 150, - "send_max_retries": 3, - "confirmation_poll_interval_ms": 500, - "confirmation_max_attempts": 120, - "devnet_airdrop_max_lamports": 0 - }, - "demo": { - "live_demo_enabled": true, - "trading_demo_enabled": false - } - } - ] -} diff --git a/config/example.logging.config.json b/config/example.logging.config.json new file mode 100644 index 0000000..1025d17 --- /dev/null +++ b/config/example.logging.config.json @@ -0,0 +1,55 @@ +{ + "active_profile": "local_devnet", + "profiles": [ + { + "name": "local_devnet", + "default_level": "warn", + "targets": [ + { + "name": "console_local_devnet_compact", + "enabled": true, + "sink": "console", + "level": "debug", + "path": "", + "rotation": "none", + "format": "compact", + "ansi": true, + "targets": [ + "*" + ] + }, + { + "name": "file_local_devnet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + } + ], + "target_filters": [ + { + "target": "hyper", + "level": "warn" + }, + { + "target": "reqwest", + "level": "warn" + }, + { + "target": "tao", + "level": "warn" + }, + { + "target": "wry", + "level": "warn" + } + ] + } + ] +} diff --git a/config/logging.config.json b/config/logging.config.json new file mode 100644 index 0000000..f702ef9 --- /dev/null +++ b/config/logging.config.json @@ -0,0 +1,3557 @@ +{ + "active_profile": "mainnet_research", + "profiles": [ + { + "name": "local_devnet", + "default_level": "warn", + "targets": [ + { + "name": "console_local_devnet_compact", + "enabled": true, + "sink": "console", + "level": "debug", + "path": "", + "rotation": "none", + "format": "compact", + "ansi": true, + "targets": [ + "*" + ] + }, + { + "name": "file_local_devnet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_local_devnet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_local_devnet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_local_devnet_app", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/app.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks_lib_local_devnet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_local_devnet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_local_devnet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_kb-app-demo-desktop_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/kb-app-demo-desktop/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/kb-app-demo-desktop/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/kb-app-demo-desktop/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/solana/transaction/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/solana/transaction/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/solana/transaction/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks_logging_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-logging/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-logging/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-logging/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks-lib_materializer_admin_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/admin/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/admin/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/admin/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/compliance/audit/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/compliance/audit/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/compliance/audit/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/lifecycle/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/lifecycle/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/lifecycle/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/transaction/annotations/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/transaction/annotations/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/transaction/annotations/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_staking_debug", + "enabled": true, + "level": "debug", + "format": "human", + "path": "logs/devnet/ks-lib/materializer/staking/debug.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_info", + "enabled": true, + "level": "info", + "format": "human", + "path": "logs/devnet/ks-lib/materializer/staking/info.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_error", + "enabled": true, + "level": "error", + "format": "json", + "path": "logs/devnet/ks-lib/materializer/staking/error.jsonl", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-pipeline_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-pipeline/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-pipeline/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-pipeline/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-onchain-transport_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-onchain-transport/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-onchain-transport/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-onchain-transport/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-store_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-store/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-store/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-store/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks_wallet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-wallet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-wallet/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-wallet/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/token/accounts/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/token/accounts/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/token/accounts/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_risk_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/materializer/risk/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/materializer/risk/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/materializer/risk/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/decoder/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/devnet/ks-lib/executor/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/devnet/ks-lib/executor/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/devnet/ks-lib/executor/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + } + ], + "target_filters": [ + { + "target": "hyper", + "level": "warn" + }, + { + "target": "reqwest", + "level": "warn" + }, + { + "target": "tao", + "level": "warn" + }, + { + "target": "wry", + "level": "warn" + } + ] + }, + { + "name": "mainnet_research", + "default_level": "warn", + "targets": [ + { + "name": "console_mainnet_research_compact", + "enabled": true, + "sink": "console", + "level": "debug", + "path": "", + "rotation": "none", + "format": "compact", + "ansi": true, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_research_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_research_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_research_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_research_app", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/app.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks_lib_mainnet_research_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_mainnet_research_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_mainnet_research_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_kb-app-demo-desktop_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/kb-app-demo-desktop/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/kb-app-demo-desktop/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/kb-app-demo-desktop/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/solana/transaction/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks_logging_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-logging/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-logging/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-logging/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks-lib_materializer_admin_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/admin/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/admin/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/admin/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/compliance/audit/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/lifecycle/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/transaction/annotations/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_staking_debug", + "enabled": true, + "level": "debug", + "format": "human", + "path": "logs/mainnet_research/ks-lib/materializer/staking/debug.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_info", + "enabled": true, + "level": "info", + "format": "human", + "path": "logs/mainnet_research/ks-lib/materializer/staking/info.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_error", + "enabled": true, + "level": "error", + "format": "json", + "path": "logs/mainnet_research/ks-lib/materializer/staking/error.jsonl", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-pipeline_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-pipeline/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-pipeline/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-pipeline/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-onchain-transport_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-onchain-transport/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-onchain-transport/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-onchain-transport/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-store_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-store/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-store/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-store/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks_wallet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-wallet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-wallet/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-wallet/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/token/accounts/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_risk_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/materializer/risk/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/materializer/risk/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/materializer/risk/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/decoder/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet_research/ks-lib/executor/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + } + ], + "target_filters": [ + { + "target": "hyper", + "level": "warn" + }, + { + "target": "reqwest", + "level": "warn" + }, + { + "target": "tao", + "level": "warn" + }, + { + "target": "wry", + "level": "warn" + } + ] + }, + { + "name": "mainnet", + "default_level": "warn", + "targets": [ + { + "name": "console_mainnet_compact", + "enabled": true, + "sink": "console", + "level": "debug", + "path": "", + "rotation": "none", + "format": "compact", + "ansi": true, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "*" + ] + }, + { + "name": "file_mainnet_app", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/app.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks_lib_mainnet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_mainnet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_ks_lib_mainnet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib" + ] + }, + { + "name": "file_kb-app-demo-desktop_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/kb-app-demo-desktop/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/kb-app-demo-desktop/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_kb-app-demo-desktop_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/kb-app-demo-desktop/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "kb-app-demo-desktop" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.solana.core" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.memo" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/solana/core/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/solana/core/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_core_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/solana/core/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.core" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/solana/transaction/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/solana/transaction/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_solana_transaction_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/solana/transaction/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.solana.transaction" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/spl/memo/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/spl/memo/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_memo_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/spl/memo/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.memo" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_associated_token_account_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/spl/associated_token_account/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.associated_token_account" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/spl/token/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/spl/token/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/spl/token/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token" + ] + }, + { + "name": "file_ks_logging_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-logging/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-logging/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks_logging_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-logging/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-logging" + ] + }, + { + "name": "file_ks-lib_materializer_admin_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/admin/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/admin/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_admin_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/admin/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.admin" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/compliance/audit/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/compliance/audit/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_compliance_audit_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/compliance/audit/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.compliance.audit" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/lifecycle/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/lifecycle/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_lifecycle_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/lifecycle/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.lifecycle" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_transaction_annotations_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/transaction/annotations/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.transaction.annotations" + ] + }, + { + "name": "file_ks-lib_materializer_staking_debug", + "enabled": true, + "level": "debug", + "format": "human", + "path": "logs/mainnet/ks-lib/materializer/staking/debug.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_info", + "enabled": true, + "level": "info", + "format": "human", + "path": "logs/mainnet/ks-lib/materializer/staking/info.log", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-lib_materializer_staking_error", + "enabled": true, + "level": "error", + "format": "json", + "path": "logs/mainnet/ks-lib/materializer/staking/error.jsonl", + "targets": [ + "ks-lib-materializer.staking" + ], + "sink": "file", + "rotation": "daily", + "ansi": false + }, + { + "name": "file_ks-pipeline_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-pipeline/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-pipeline/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-pipeline_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-pipeline/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-pipeline", + "ks-pipeline-demo-scenarios" + ] + }, + { + "name": "file_ks-onchain-transport_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-onchain-transport/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-onchain-transport/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-onchain-transport_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-onchain-transport/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-onchain-transport" + ] + }, + { + "name": "file_ks-store_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-store/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-store/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks-store_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-store/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-store" + ] + }, + { + "name": "file_ks_wallet_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-wallet/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-wallet/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks_wallet_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-wallet/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-wallet" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/token/accounts/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/token/accounts/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_token_accounts_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/token/accounts/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.token.accounts" + ] + }, + { + "name": "file_ks-lib_materializer_risk_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/materializer/risk/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/materializer/risk/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_materializer_risk_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/materializer/risk/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-materializer.risk" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_metadata_metaplex_token_metadata_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/metadata/metaplex_token_metadata/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.metadata.metaplex_token_metadata" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_decoder_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/decoder/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-decoder.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_elgamal_registry_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/spl/elgamal_registry/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.elgamal_registry" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_debug", + "enabled": true, + "sink": "file", + "level": "debug", + "path": "logs/mainnet/ks-lib/executor/spl/token_2022/debug.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_info", + "enabled": true, + "sink": "file", + "level": "info", + "path": "logs/mainnet/ks-lib/executor/spl/token_2022/info.log", + "rotation": "daily", + "format": "human", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + }, + { + "name": "file_ks-lib_executor_spl_token_2022_error", + "enabled": true, + "sink": "file", + "level": "error", + "path": "logs/mainnet/ks-lib/executor/spl/token_2022/error.jsonl", + "rotation": "daily", + "format": "json", + "ansi": false, + "targets": [ + "ks-lib-executor.spl.token_2022" + ] + } + ], + "target_filters": [ + { + "target": "hyper", + "level": "warn" + }, + { + "target": "reqwest", + "level": "warn" + }, + { + "target": "tao", + "level": "warn" + }, + { + "target": "wry", + "level": "warn" + } + ] + } + ] +} diff --git a/config/schema.config.json b/config/schemas/app.config.schema.json similarity index 85% rename from config/schema.config.json rename to config/schemas/app.config.schema.json index f048a85..c8526fe 100644 --- a/config/schema.config.json +++ b/config/schemas/app.config.schema.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://khadhroony.local/schema/config.schema.json", - "title": "Khadhroony Bot3 configuration", + "$id": "https://khadhroony.local/schema/app.config.schema.json", + "title": "Khadhroony Solana application configuration", "type": "object", "additionalProperties": false, "required": [ @@ -25,24 +25,12 @@ "type": "string", "minLength": 1 }, - "log_level": { - "type": "string", - "enum": [ - "trace", - "debug", - "info", - "warn", - "error", - "off" - ] - }, "profile": { "type": "object", "additionalProperties": false, "required": [ "name", "app", - "logging", "database", "data", "solana", @@ -57,9 +45,6 @@ "app": { "$ref": "#/$defs/app_section" }, - "logging": { - "$ref": "#/$defs/logging" - }, "database": { "$ref": "#/$defs/database" }, @@ -100,112 +85,6 @@ } } }, - "logging": { - "type": "object", - "additionalProperties": false, - "required": [ - "default_level", - "targets", - "target_filters" - ], - "properties": { - "default_level": { - "$ref": "#/$defs/log_level" - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/log_target" - } - }, - "target_filters": { - "type": "array", - "items": { - "$ref": "#/$defs/log_target_filter" - } - } - } - }, - "log_target": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "enabled", - "sink", - "level", - "path", - "rotation", - "format", - "ansi", - "targets" - ], - "properties": { - "name": { - "$ref": "#/$defs/non_empty_string" - }, - "enabled": { - "type": "boolean" - }, - "sink": { - "type": "string", - "enum": [ - "console", - "file" - ] - }, - "level": { - "$ref": "#/$defs/log_level" - }, - "path": { - "type": "string" - }, - "rotation": { - "type": "string", - "enum": [ - "none", - "never", - "daily", - "hourly" - ] - }, - "format": { - "type": "string", - "enum": [ - "human", - "compact", - "pretty", - "json" - ] - }, - "ansi": { - "type": "boolean" - }, - "targets": { - "type": "array", - "items": { - "$ref": "#/$defs/non_empty_string" - } - } - } - }, - "log_target_filter": { - "type": "object", - "additionalProperties": false, - "required": [ - "target", - "level" - ], - "properties": { - "target": { - "$ref": "#/$defs/non_empty_string" - }, - "level": { - "$ref": "#/$defs/log_level" - } - } - }, "database": { "type": "object", "additionalProperties": false, diff --git a/config/schemas/logging.config.schema.json b/config/schemas/logging.config.schema.json new file mode 100644 index 0000000..2974c71 --- /dev/null +++ b/config/schemas/logging.config.schema.json @@ -0,0 +1,150 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://khadhroony.local/schema/logging.config.schema.json", + "title": "Khadhroony Solana logging configuration", + "type": "object", + "additionalProperties": false, + "required": [ + "active_profile", + "profiles" + ], + "properties": { + "active_profile": { + "$ref": "#/$defs/non_empty_string" + }, + "profiles": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/logging_profile" + } + } + }, + "$defs": { + "non_empty_string": { + "type": "string", + "minLength": 1 + }, + "log_level": { + "type": "string", + "enum": [ + "trace", + "debug", + "info", + "warn", + "error", + "off" + ] + }, + "logging_profile": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "default_level", + "targets", + "target_filters" + ], + "properties": { + "name": { + "$ref": "#/$defs/non_empty_string" + }, + "default_level": { + "$ref": "#/$defs/log_level" + }, + "targets": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/log_target" + } + }, + "target_filters": { + "type": "array", + "items": { + "$ref": "#/$defs/log_target_filter" + } + } + } + }, + "log_target": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "enabled", + "sink", + "level", + "path", + "rotation", + "format", + "ansi", + "targets" + ], + "properties": { + "name": { + "$ref": "#/$defs/non_empty_string" + }, + "enabled": { + "type": "boolean" + }, + "sink": { + "type": "string", + "enum": [ + "console", + "file" + ] + }, + "level": { + "$ref": "#/$defs/log_level" + }, + "path": { + "type": "string" + }, + "rotation": { + "type": "string", + "enum": [ + "none", + "never", + "daily", + "hourly" + ] + }, + "format": { + "type": "string", + "enum": [ + "human", + "compact", + "pretty", + "json" + ] + }, + "ansi": { + "type": "boolean" + }, + "targets": { + "type": "array", + "items": { + "$ref": "#/$defs/non_empty_string" + } + } + } + }, + "log_target_filter": { + "type": "object", + "additionalProperties": false, + "required": [ + "target", + "level" + ], + "properties": { + "target": { + "$ref": "#/$defs/non_empty_string" + }, + "level": { + "$ref": "#/$defs/log_level" + } + } + } + } +} diff --git a/docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md b/docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md index 839db4d..3bf605d 100644 --- a/docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md +++ b/docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md @@ -1,5 +1,5 @@ - + # Politique de namespace Khadhroony Solana @@ -65,8 +65,9 @@ La classification d'une valeur sensible doit survivre à la substitution. Une ch La restructuration `0.5.1` doit séparer au minimum : -- la configuration généraliste dans son propre document et son propre schéma ; -- la configuration logging dans un document et un schéma indépendants, avec des profils logging sélectionnables indépendamment des profils réseau/applicatifs. +- la configuration généraliste dans `config/app.config.json`, avec son schéma sous `config/schemas/app.config.schema.json` ; +- la configuration logging dans `config/logging.config.json`, avec son schéma sous `config/schemas/logging.config.schema.json` et des profils logging sélectionnables indépendamment des profils réseau/applicatifs ; +- des exemples conformes mais non chargés par défaut sous `config/example.app.config.json` et `config/example.logging.config.json`. D'autres documents spécialisés ne sont créés que si l'audit démontre une responsabilité, un cycle de vie ou une validation réellement indépendants. diff --git a/docs/guides/CONFIGURATION.md b/docs/guides/CONFIGURATION.md index ecaedab..f5efb13 100644 --- a/docs/guides/CONFIGURATION.md +++ b/docs/guides/CONFIGURATION.md @@ -1,85 +1,95 @@ - + # Guide de configuration ## Objectif -Ce guide décrit le chargement et l’utilisation de la configuration bot3. La référence d’API détaillée reste `ks-config/USAGE.md`. +Ce guide décrit le chargement des documents de configuration après leur séparation. La référence d’API générale reste `ks-config/USAGE.md` et la configuration logging appartient à `ks-logging`. ## Fichiers actifs -- `config/example.config.json` : exemple utilisateur complet ; -- `config/schema.config.json` : contrat JSON formel ; +- `config/app.config.json` : configuration générale chargée par défaut ; +- `config/logging.config.json` : configuration logging chargée par défaut ; +- `config/example.app.config.json` et `config/example.logging.config.json` : exemples minimaux conformes ; +- `config/schemas/app.config.schema.json` : schéma général ; +- `config/schemas/logging.config.schema.json` : schéma logging ; - `.env`, ou le fichier sélectionné par `KS_ENV_FILE` : valeurs d’environnement non versionnées ; -- `.env.example` : noms de variables attendues sans secrets. +- `.env.example` : noms de variables attendues sans secrets réels. -Le format actif est JSON. Le futur split de configuration prévu en `0.5.x` ne modifie pas le contrat actuel. +`KS_CONFIG_PATH` et `KS_LOGGING_CONFIG_PATH` permettent de remplacer indépendamment les deux chemins par défaut. -## Séquence de chargement +## Configuration générale -L’API recommandée est `read_config_json_file_with_environment`. Elle : +L’API recommandée reste `ks_config::read_config_json_file_with_environment`. Elle : -1. charge `.env`, ou le fichier explicitement sélectionné par `KS_ENV_FILE`, sans écraser les variables du processus ; -2. lit le JSON ; -3. résout les placeholders namespacés `${KS_*}` / `${KB_*}` et les fallbacks éventuels ; -4. valide le schéma JSON ; -5. désérialise les types de configuration et applique les invariants métier ; -6. laisse ensuite `active_profile` sélectionner le profil actif. - -## Exemple opérateur +1. charge `.env`, ou le fichier sélectionné par `KS_ENV_FILE`, sans écraser les variables du processus ; +2. lit le JSON général ; +3. résout les placeholders `${KS_*}` / `${KB_*}` ; +4. valide `config/schemas/app.config.schema.json` ; +5. désérialise `AppConfig` et applique les invariants métier ; +6. laisse `active_profile` sélectionner le profil applicatif actif. ```rust let config = match ks_config::read_config_json_file_with_environment( - std::path::Path::new("config/example.config.json"), + std::path::Path::new("config/app.config.json"), std::path::Path::new("."), ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let profile = match ks_config::active_profile(&config) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - -println!("active profile={}", profile.name); ``` +Le profil général ne contient plus de bloc `logging`. + +## Configuration logging + +`ks_logging::read_logging_json_file_with_environment` charge séparément le document logging et `ks_logging::active_logging_profile` sélectionne son profil actif. + +```rust +let logging = match ks_logging::read_logging_json_file_with_environment( + std::path::Path::new("config/logging.config.json"), + std::path::Path::new("."), +) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => return std::result::Result::Err(error), +}; +let logging_profile = match ks_logging::active_logging_profile(&logging) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => return std::result::Result::Err(error), +}; +``` + +Les deux `active_profile` sont indépendants. Il n’existe aucun fallback implicite du profil logging vers le nom du profil applicatif. + ## Invariants -- aucun secret ne doit être ajouté à l’exemple versionné ; -- les placeholders non résolus doivent provoquer un diagnostic explicite ; -- le schéma embarqué et `config/schema.config.json` doivent rester identiques ; -- tant que `0.5.1-pre.006` n’a pas introduit les DTO publics sûrs, la configuration runtime résolue reste strictement backend et ne doit pas être exposée telle quelle ; -- les noms de profils et rôles d’endpoints doivent rester cohérents avec leurs consommateurs. - -## Quotas HTTP cumulés - -Les limites HTTP sont déclarées par rôle, mais les quotas d’un endpoint public s’appliquent généralement à l’endpoint ou à l’adresse IP entière. Pour un endpoint unique, il faut donc considérer au minimum : - -- la somme des `requests_per_second` de tous les rôles actifs ; -- la somme des bursts pouvant partir dans la même fenêtre ; -- la limite propre à une méthode RPC répétée ; -- les autres processus utilisant la même IP ou le même fournisseur. - -Le profil public Devnet de l’exemple utilise `3 r/s` pour `http_queries` et `1 r/s` pour `http_transactions`. Un profil privé ou payant peut utiliser d’autres valeurs, mais elles doivent suivre le contrat réel du fournisseur. +- aucun secret réel ne doit être ajouté aux fichiers versionnés ; +- les placeholders non résolus doivent rester détectables ; +- chaque schéma embarqué doit rester identique au fichier sous `config/schemas/` ; +- les profils applicatifs et logging sont validés indépendamment ; +- `ks-config` ne possède plus de types logging ; +- tant que `0.5.1-pre.006` n’a pas introduit les DTO sûrs, la configuration runtime résolue reste strictement backend et ne doit pas être exposée telle quelle. ## Diagnostic Pour isoler une erreur : -1. afficher la liste des fichiers d’environnement chargés ; -2. résoudre le JSON sans l’écrire dans les logs s’il contient des secrets ; -3. valider le schéma ; -4. valider le modèle typé ; -5. vérifier le profil actif ; -6. vérifier les rôles HTTP, WebSocket, stockage et logging. +1. vérifier le fichier d’environnement chargé ; +2. vérifier séparément les chemins app et logging ; +3. valider chaque document contre son schéma ; +4. vérifier son `active_profile` ; +5. vérifier ensuite les rôles HTTP/WebSocket, stockage ou routes logging concernés. + +Ne jamais écrire dans les logs le JSON résolu complet s’il contient une valeur issue de `KS_SECRET_*` ou `KB_SECRET_*`. ## Références -- `ks-config/README.md` ; -- `ks-config/USAGE.md` ; -- `ks-config/TODO.md` ; +- `ks-config/README.md` et `ks-config/USAGE.md` ; +- `ks-logging/README.md` et `ks-logging/USAGE.md` ; - `config/README.md` ; -- `docs/decisions/WINCODE_COMPATIBILITY_POLICY.md`. +- `docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`. diff --git a/docs/guides/LOGGING.md b/docs/guides/LOGGING.md index ef4f617..4567bfb 100644 --- a/docs/guides/LOGGING.md +++ b/docs/guides/LOGGING.md @@ -1,34 +1,43 @@ - + # Guide de logging et tracing ## Objectif -`ks-logging` initialise les routes de tracing définies par la configuration et conserve les guards nécessaires à leur durée de vie. +`ks-logging` possède désormais le contrat logging, son document de profils, son schéma JSON et l’initialisation runtime `tracing`. ## Flux de démarrage -1. charger et valider la configuration avec `ks-config` ; -2. construire `LoggingConfig` ; +1. charger `config/logging.config.json` avec `ks_logging::read_logging_json_file_with_environment` ; +2. sélectionner le profil avec `ks_logging::active_logging_profile` ; 3. appeler `ks_logging::init_logging` une seule fois ; 4. conserver `LoggingGuard` jusqu’à la fermeture du processus ; 5. émettre les événements avec des targets canoniques. ```rust -let guard = match ks_logging::init_logging(&config.logging) { +let document = match ks_logging::read_logging_json_file_with_environment( + std::path::Path::new("config/logging.config.json"), + std::path::Path::new("."), +) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => return std::result::Result::Err(error), +}; +let config = match ks_logging::active_logging_profile(&document) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => return std::result::Result::Err(error), +}; +let guard = match ks_logging::init_logging(config) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - -tracing::info!( - target: ks_logging::tracing_target(), - routes = guard.route_count(), - "logging initialized" -); ``` -## Routes +Le profil logging est sélectionné indépendamment du profil général de `app.config.json`. + +## Contrat JSON + +Le schéma est `config/schemas/logging.config.schema.json`. Les exemples sont `config/logging.config.json` pour la configuration runtime de référence et `config/example.logging.config.json` pour un exemple minimal. Une route définit notamment : @@ -52,28 +61,28 @@ ks-onchain-transport.http ks-lib-executor.spl.token-2022 ks-lib-materializer.compliance.audit ks-lib-materializer.token.accounts -ks-lib-materializer.transaction.annotations ``` -Pour un matérialisateur, la target de tracing est l’identité runtime `ks-lib-materializer.[.]`. Elle reste distincte du `processorName` persisté `materializer.[.]`, qui ne doit pas être utilisé comme target de logs. - -Une nouvelle target doit être ajoutée selon `docs/OPERATION_NAMING_CONVENTION.md` et les règles Khadhroony. +Pour un matérialisateur, la target de tracing reste distincte du `processorName` persisté. ## Frontend desktop -Les fenêtres Tauri utilisent la permission tracing prévue par leurs capabilities. Les logs frontend sont adaptés vers le backend sans permettre au frontend de choisir arbitrairement une target sensible. +Le desktop charge les documents app et logging séparément. Il ne convertit plus un type `ks_config::LoggingConfig` vers `ks_logging::LoggingConfig` : le type runtime est possédé directement par `ks-logging`. + +La surface publique de diagnostic/configuration reste volontairement inchangée jusqu’à `0.5.1-pre.006`, qui supprimera l’exposition des configurations résolues complètes. ## Diagnostic -- vérifier les routes actives via `route_names()` ; +- vérifier `KS_LOGGING_CONFIG_PATH` si le fichier par défaut n’est pas utilisé ; +- vérifier le profil logging actif indépendamment du profil app ; +- valider le document contre son schéma ; - confirmer le niveau global et les filtres spécifiques ; -- vérifier le chemin et les permissions d’une route fichier ; -- vérifier que le guard n’est pas détruit prématurément ; +- vérifier les chemins et permissions des routes fichier ; - ne pas réinitialiser le subscriber global pendant l’exécution. ## Références - `ks-logging/README.md` ; - `ks-logging/USAGE.md` ; -- `ks-config/USAGE.md` ; -- `docs/architecture/ARCHITECTURE.md`. +- `config/README.md` ; +- `docs/OPERATION_NAMING_CONVENTION.md`. diff --git a/docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md b/docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md index 88c7cb2..b9eb9cb 100644 --- a/docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md +++ b/docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md @@ -1,5 +1,5 @@ - + # Plan temporaire `0.5.1` — namespace Khadhroony Solana et configuration sûre @@ -408,7 +408,7 @@ Les targets de tracing de crates génériques doivent également migrer vers `ks L'audit distingue trois ensembles afin de ne pas transformer des exemples historiques en contrats runtime : -- **85 noms** actuellement utilisés/référencés par le code, les tests, `.env.example`, les fixtures ou `config/example.config.json` ; +- **85 noms** actuellement utilisés/référencés par le code, les tests, `.env.example`, les fixtures ou `config/app.config.json` ; - **17 noms supplémentaires** présents uniquement dans le guide opérateur Devnet actif ; - soit **102 noms historiques actifs à migrer ou consolider**, dont plusieurs convergent volontairement vers une même cible canonique. @@ -561,10 +561,12 @@ Les anciennes fixtures `TOKEN_2022_*` et les alias opérateur déjà préfixés L'audit `0.5.0` a confirmé une duplication importante : chaque profil généraliste transporte un bloc logging volumineux. La cible minimale devient : ```text -config/example.config.json -config/example.logging.json -config/schema.config.json -config/schema.logging.json +config/app.config.json +config/logging.config.json +config/example.app.config.json +config/example.logging.config.json +config/schemas/app.config.schema.json +config/schemas/logging.config.schema.json ``` Les profils applicatifs/réseau et les profils logging sont sélectionnables indépendamment. Un profil `devnet` n'impose donc pas un profil logging `debug`, et `mainnet` n'impose pas mécaniquement un profil logging `release`. @@ -575,7 +577,7 @@ Le code duplique actuellement dans `ks-config` et `ks-logging` les concepts : - `LogTargetConfig` ; - `LogTargetFilterConfig`. -`kb-app-demo-desktop` contient en plus une conversion manuelle de `ks_config::LoggingConfig` vers `ks_logging::LoggingConfig`. `0.5.1` doit supprimer cette duplication en donnant au logging un contrat possédé par `ks-logging`, tout en laissant `ks-config` charger/valider/composer les documents sans réinventer les types runtime du logging. +La migration `pre.005` ferme cette dette : `ks-config` ne définit plus de type logging, `ks-logging` possède le document, le schéma et les types runtime, et le desktop charge les deux fichiers indépendamment. `ks-logging` réutilise uniquement les helpers génériques d’environnement de `ks-config`, sans créer de dépendance inverse. Aucun troisième document spécialisé n'est créé dans `0.5.1` sans bénéfice de découplage démontré. @@ -628,7 +630,7 @@ Avant chaque changement structurel correspondant, conserver ou ajouter des tests - l'interdiction des variables de configuration possédées par le workspace hors namespace d'ownership `KS_*` ou `KB_*` ; - la propagation de sensibilité depuis `KS_SECRET_*` vers les valeurs composées ; - l'impossibilité pour une sentinelle secrète d'apparaître dans `Debug`, logs, erreurs, payloads Tauri, sérialisation publique ou diagnostic ; -- la validation indépendante de `schema.config.json` et `schema.logging.json` ; +- la validation indépendante de `config/schemas/app.config.schema.json` et `config/schemas/logging.config.schema.json` ; - l'indépendance des profils généralistes et logging ; - l'absence de duplication structurelle des types logging entre `ks-config` et `ks-logging` ; - le maintien des contrats publics réellement nécessaires après remplacement des types de configuration exposés. @@ -672,10 +674,12 @@ Les tests ne doivent pas figer comme comportement légitime la fuite actuelle de ### `0.5.1-pre.005` — split config/logging -- extraire `example.logging.json` et `schema.logging.json` ; -- rendre profils logging et généralistes indépendants ; -- supprimer les structures logging dupliquées et la conversion desktop manuelle ; -- maintenir schémas, exemples et documentation synchronisés. +- **implémenté** : `config/app.config.json` et `config/logging.config.json` deviennent les deux documents chargés par défaut ; +- **implémenté** : les schémas sont centralisés sous `config/schemas/app.config.schema.json` et `config/schemas/logging.config.schema.json` ; +- **implémenté** : `example.app.config.json` et `example.logging.config.json` fournissent des exemples minimaux conformes ; +- **implémenté** : les profils logging et généralistes possèdent chacun leur propre `active_profile` ; +- **implémenté** : `ks-logging` devient propriétaire unique du contrat logging et de sa validation ; +- **implémenté** : le desktop supprime la conversion `ks_config::LoggingConfig` -> `ks_logging::LoggingConfig`. ### `0.5.1-pre.006` — surfaces publiques sûres diff --git a/docs/rules/RULES_SPECIFIC_KHADHROONY.md b/docs/rules/RULES_SPECIFIC_KHADHROONY.md index c04829f..a087b30 100644 --- a/docs/rules/RULES_SPECIFIC_KHADHROONY.md +++ b/docs/rules/RULES_SPECIFIC_KHADHROONY.md @@ -1,5 +1,5 @@ - + # Règles spécifiques à `khadhroony-bot3` @@ -238,6 +238,9 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi ## Règles de configuration - La configuration applicative commune doit passer par `ks-config`. +- Les fichiers runtime chargés par défaut sont `config/app.config.json` pour la configuration générale et `config/logging.config.json` pour le logging ; leurs sélections de profils sont indépendantes. +- Les schémas JSON de configuration actifs sont conservés sous `config/schemas/`, notamment `app.config.schema.json` et `logging.config.schema.json`. +- Les exemples conformes sont conservés sous `config/` avec des noms distincts des fichiers runtime, notamment `example.app.config.json` et `example.logging.config.json`. - Les fichiers JSON de configuration ne doivent pas contenir de commentaires. - Les secrets ne doivent pas être écrits en clair dans le dépôt. - Les valeurs sensibles doivent utiliser des variables d'environnement ou un stockage chiffré dédié. diff --git a/kb-app-demo-desktop/CHANGELOG.md b/kb-app-demo-desktop/CHANGELOG.md index ae567b6..134bd4d 100644 --- a/kb-app-demo-desktop/CHANGELOG.md +++ b/kb-app-demo-desktop/CHANGELOG.md @@ -1,8 +1,15 @@ - + # CHANGELOG — kb-app-demo-desktop +## `0.5.1-pre.005` + +- charge séparément `config/app.config.json` et `config/logging.config.json` ; +- ajoute `KS_LOGGING_CONFIG_PATH` sans coupler sa sélection à `KS_CONFIG_PATH` ; +- initialise `ks-logging` directement depuis son profil actif et supprime la conversion manuelle depuis un type logging de `ks-config` ; +- conserve les payloads Tauri de configuration existants jusqu’à la fermeture de la surface publique en `pre.006`. + ## `0.5.1-pre.004` - lit désormais le chemin de configuration Solana via `KS_CONFIG_PATH` et les fixtures Token-2022 via leurs noms `KS_PUBLIC_*` canoniques ; diff --git a/kb-app-demo-desktop/src/app_state.rs b/kb-app-demo-desktop/src/app_state.rs index 29373be..955ce09 100644 --- a/kb-app-demo-desktop/src/app_state.rs +++ b/kb-app-demo-desktop/src/app_state.rs @@ -1,11 +1,12 @@ // file: kb-app-demo-desktop/src/app_state.rs -// version: 12 +// version: 13 //! Shared Tauri application state and startup initialization. /// Shared state managed by Tauri for the desktop demo application. pub(crate) struct AppState { config_path: std::string::String, + logging_config_path: std::string::String, app_config: ks_config::AppConfig, active_profile: ks_config::ProfileConfig, logging_guard: std::sync::Mutex, @@ -30,6 +31,7 @@ impl crate::AppState { /// Initializes configuration, logging and shared runtime state. pub(crate) fn initialize() -> ks_core::Result { let config_path = resolve_config_path(); + let logging_config_path = resolve_logging_config_path(); let workspace_root = crate::workspace_root_dir(); let app_config = match ks_config::read_config_json_file_with_environment( &config_path, @@ -42,7 +44,17 @@ impl crate::AppState { std::result::Result::Ok(profile) => profile.clone(), std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let logging_config = convert_logging_config(&active_profile.logging); + let logging_document = match ks_logging::read_logging_json_file_with_environment( + &logging_config_path, + &workspace_root, + ) { + std::result::Result::Ok(config) => config, + std::result::Result::Err(error) => return std::result::Result::Err(error), + }; + let logging_config = match ks_logging::active_logging_profile(&logging_document) { + std::result::Result::Ok(profile) => profile.clone(), + std::result::Result::Err(error) => return std::result::Result::Err(error), + }; let logging_guard = match ks_logging::init_logging(&logging_config) { std::result::Result::Ok(guard) => guard, std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -54,6 +66,7 @@ impl crate::AppState { }; return std::result::Result::Ok(crate::AppState { config_path: config_path.display().to_string(), + logging_config_path: logging_config_path.display().to_string(), app_config, active_profile, logging_guard: std::sync::Mutex::new(logging_guard), @@ -78,6 +91,11 @@ impl crate::AppState { return self.config_path.as_str(); } + /// Returns the path used to load the logging configuration file. + pub(crate) fn logging_config_path(&self) -> &str { + return self.logging_config_path.as_str(); + } + /// Returns the complete parsed application configuration. pub(crate) fn app_config(&self) -> &ks_config::AppConfig { return &self.app_config; @@ -198,40 +216,26 @@ impl crate::AppState { } } -fn convert_logging_config(config: &ks_config::LoggingConfig) -> ks_logging::LoggingConfig { - let mut targets = std::vec::Vec::::new(); - for target in &config.targets { - targets.push(ks_logging::LogTargetConfig { - name: target.name.clone(), - enabled: target.enabled, - sink: target.sink.clone(), - level: target.level.clone(), - path: target.path.clone(), - rotation: target.rotation.clone(), - format: target.format.clone(), - ansi: target.ansi, - targets: target.targets.clone(), - }); - } - let mut target_filters = std::vec::Vec::::new(); - for filter in &config.target_filters { - target_filters.push(ks_logging::LogTargetFilterConfig { - target: filter.target.clone(), - level: filter.level.clone(), - }); - } - return ks_logging::LoggingConfig { - default_level: config.default_level.clone(), - targets, - target_filters, - }; -} - fn resolve_config_path() -> std::path::PathBuf { let configured = std::env::var("KS_CONFIG_PATH").ok(); return resolve_config_path_from_value(configured.as_deref()); } +fn resolve_logging_config_path() -> std::path::PathBuf { + let configured = std::env::var("KS_LOGGING_CONFIG_PATH").ok(); + return resolve_logging_config_path_from_value(configured.as_deref()); +} + +fn resolve_logging_config_path_from_value(value: std::option::Option<&str>) -> std::path::PathBuf { + if let std::option::Option::Some(configured) = value { + let trimmed = configured.trim(); + if !trimmed.is_empty() { + return std::path::PathBuf::from(trimmed); + } + } + return crate::workspace_root_dir().join("config/logging.config.json"); +} + fn resolve_config_path_from_value(value: std::option::Option<&str>) -> std::path::PathBuf { if let std::option::Option::Some(configured) = value { let trimmed = configured.trim(); @@ -239,17 +243,26 @@ fn resolve_config_path_from_value(value: std::option::Option<&str>) -> std::path return std::path::PathBuf::from(trimmed); } } - return crate::workspace_root_dir().join("config/example.config.json"); + return crate::workspace_root_dir().join("config/app.config.json"); } #[cfg(test)] mod tests { #[test] - fn resolve_config_path_uses_workspace_example_by_default() { + fn resolve_config_path_uses_workspace_default_by_default() { let path = super::resolve_config_path_from_value(std::option::Option::None); assert_eq!( path.file_name().and_then(std::ffi::OsStr::to_str), - std::option::Option::Some("example.config.json") + std::option::Option::Some("app.config.json") + ); + } + + #[test] + fn resolve_logging_config_path_uses_workspace_default_by_default() { + let path = super::resolve_logging_config_path_from_value(std::option::Option::None); + assert_eq!( + path.file_name().and_then(std::ffi::OsStr::to_str), + std::option::Option::Some("logging.config.json") ); } } diff --git a/kb-app-demo-desktop/src/demo_execution_solana_core.rs b/kb-app-demo-desktop/src/demo_execution_solana_core.rs index 8354cea..04cb3f6 100644 --- a/kb-app-demo-desktop/src/demo_execution_solana_core.rs +++ b/kb-app-demo-desktop/src/demo_execution_solana_core.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/demo_execution_solana_core.rs -// version: 14 +// version: 15 //! Tauri adapter for bounded Solana Core execution on Devnet. @@ -851,7 +851,7 @@ mod tests { #[test] fn example_config_exposes_one_devnet_execution_profile() { let config = - match ks_config::parse_config_json(include_str!("../../config/example.config.json")) { + match ks_config::parse_config_json(include_str!("../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), }; @@ -865,7 +865,7 @@ mod tests { #[test] fn profile_selection_rejects_mainnet_profiles() { let config = - match ks_config::parse_config_json(include_str!("../../config/example.config.json")) { + match ks_config::parse_config_json(include_str!("../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), }; diff --git a/kb-app-demo-desktop/src/tauri.rs b/kb-app-demo-desktop/src/tauri.rs index ada91f3..cd2be0f 100644 --- a/kb-app-demo-desktop/src/tauri.rs +++ b/kb-app-demo-desktop/src/tauri.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/tauri.rs -// version: 35 +// version: 36 //! Tauri runtime assembly and private command wrappers. @@ -21,6 +21,7 @@ pub fn run() -> ks_core::Result<()> { tracing::info!( target: crate::TRACING_TARGET, config_path = app_state.config_path(), + logging_config_path = app_state.logging_config_path(), active_profile = app_state.active_profile().name.as_str(), logging_routes = app_state.logging_route_count(), configured_profiles = app_state.app_config().profiles.len(), diff --git a/ks-config/CHANGELOG.md b/ks-config/CHANGELOG.md index 2e0714b..9877c1e 100644 --- a/ks-config/CHANGELOG.md +++ b/ks-config/CHANGELOG.md @@ -1,8 +1,15 @@ - + # CHANGELOG — ks-config +## `0.5.1-pre.005` + +- retire définitivement le bloc `logging` de `ProfileConfig` et du schéma général ; +- aligne le contrat général et le desktop sur `config/app.config.json`, validé par `config/schemas/app.config.schema.json` ; +- conserve des profils applicatifs indépendants du document logging possédé par `ks-logging` ; +- ajoute `config/example.app.config.json` comme exemple minimal conforme. + ## `0.5.1-pre.004` - migre le sélecteur d'environnement vers `KS_ENV_FILE` et les placeholders PostgreSQL/Helius vers `KS_SECRET_*` ; diff --git a/ks-config/README.md b/ks-config/README.md index ec97e96..7dcef31 100644 --- a/ks-config/README.md +++ b/ks-config/README.md @@ -1,41 +1,47 @@ - + # ks-config -`ks-config` définit le contrat de configuration typé du workspace, son schéma JSON embarqué et les fonctions de chargement, résolution d’environnement, validation et sérialisation. +`ks-config` définit le contrat de configuration générale typé du workspace, son schéma JSON embarqué et les fonctions de chargement, résolution d’environnement, validation et sérialisation. ## Responsabilités -- exposer `AppConfig` et les sections de configuration publiques ; -- valider le JSON contre le schéma embarqué ; +- exposer `AppConfig` et les sections de configuration générale ; +- valider le JSON général contre `config/schemas/app.config.schema.json` ; - appliquer les invariants métier après désérialisation ; -- charger `.env`, ou le fichier explicitement sélectionné par `KS_ENV_FILE`, depuis la racine du workspace ; +- charger `.env`, ou le fichier sélectionné par `KS_ENV_FILE`, depuis la racine du workspace ; - résoudre les placeholders namespacés `${KS_*}` / `${KB_*}` et leurs fallbacks ; -- sélectionner le profil actif ; -- exporter les types nécessaires au frontend avec `ts-rs`. +- sélectionner le profil applicatif actif ; +- exporter les types généraux nécessaires au frontend avec `ts-rs`. ## Hors périmètre -La crate n’initialise ni le logging, ni PostgreSQL, ni les transports et ne manipule aucun secret de wallet. Elle fournit uniquement la configuration validée à ces consommateurs. +`ks-config` ne possède plus le contrat logging. `LoggingConfig`, les routes, filtres, profils logging et `config/schemas/logging.config.schema.json` appartiennent à `ks-logging`. + +La crate n’initialise ni PostgreSQL, ni les transports et ne manipule aucun secret de wallet. Elle fournit uniquement la configuration générale validée à ces consommateurs. ## Surface publique -Les principales fonctions sont `read_config_json_file_with_environment`, `parse_config_json`, `validate_config`, `validate_config_json_schema`, `active_profile` et les sérialiseurs JSON. Les types publics couvrent les profils, endpoints, listeners, logging, base de données, wallet, exécution et démonstration. +Les principales fonctions sont `read_config_json_file_with_environment`, `parse_config_json`, `validate_config`, `validate_config_json_schema`, `active_profile` et les sérialiseurs JSON. + +Les types publics couvrent les profils applicatifs, endpoints, listeners, base de données, wallet, exécution et démonstration. ## Relations - dépend de `ks-core` pour les erreurs structurées ; -- alimente `ks-logging`, `ks-store`, `ks-onchain-transport`, `ks-pipeline`, `ks-wallet` et les applications ; -- utilise [`../config/example.config.json`](../config/example.config.json) et [`../config/schema.config.json`](../config/schema.config.json) comme exemple utilisateur et contrat de schéma actifs. +- fournit les profils généraux à `ks-store`, `ks-onchain-transport`, `ks-pipeline`, `ks-wallet` et aux applications ; +- fournit à `ks-logging` les helpers génériques de chargement `.env` et de résolution des placeholders ; +- embarque [`../config/schemas/app.config.schema.json`](../config/schemas/app.config.schema.json) ; +- utilise [`../config/app.config.json`](../config/app.config.json) comme configuration générale chargée par défaut et [`../config/example.app.config.json`](../config/example.app.config.json) comme exemple minimal conforme. ## Statut -La configuration actuelle est fonctionnelle et validée, mais son format `0.4.8` reste monolithique. Le cadrage `0.5.0-pre.002` confirme que `0.5.1` séparera la configuration générale et le logging en documents et schémas distincts, applique les namespaces d’environnement `KS_*` / `KB_*` par ownership et séparera les représentations source, runtime et publiques afin qu’aucun secret résolu ne soit exposé. +Le split config/logging est effectif : un profil applicatif ne transporte plus de bloc logging et la sélection logging est indépendante. La prerelease suivante sépare les représentations source/runtime/public/diagnostic et ferme l’exposition des secrets résolus. ## Documents - [Utilisation](USAGE.md) - [Travaux restants](TODO.md) - [Historique](CHANGELOG.md) -- [Architecture](../docs/architecture/ARCHITECTURE.md) +- [Configuration locale](../config/README.md) diff --git a/ks-config/TODO.md b/ks-config/TODO.md index 676e13a..a0fb048 100644 --- a/ks-config/TODO.md +++ b/ks-config/TODO.md @@ -1,18 +1,15 @@ - + # TODO — ks-config ## Série `0.5.x` -- [ ] `0.5.1` - séparer la configuration générale et le logging en documents et schémas JSON distincts. -- [ ] `0.5.1` - rendre la sélection du profil logging indépendante du profil généraliste. -- [ ] `0.5.1` - définir un propriétaire unique du contrat source logging et supprimer la conversion manuelle du desktop. - [ ] `0.5.1` - appliquer à l’exécution les classes `KS_SECRET_*` / `KB_SECRET_*`, `KS_PUBLIC_*` / `KB_PUBLIC_*` et internes, avec propagation de sensibilité aux valeurs composées. - [ ] `0.5.1` - séparer les représentations source, runtime résolue, publique et diagnostic. - [ ] `0.5.1` - interdire qu’un secret résolu soit sérialisé, loggé, inclus dans une erreur ou transmis via Tauri. - [ ] `0.5.1` - supprimer l’exposition frontend de `AppConfig` et `ProfileConfig` résolus complets. -- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/`. -- [ ] Tests - ajouter les tests d’API externe, de migration multi-fichiers et les canaris de non-divulgation. -- [ ] Documentation - mettre à jour guides, exemples et `.env.example` seulement avec l’implémentation correspondante. -- [ ] Intégration - coordonner la migration avec logging, transports, pipeline, scénarios et applications. +- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/schemas/`. +- [ ] Tests - ajouter les tests d’API externe et les canaris de non-divulgation. +- [ ] Documentation - maintenir guides, exemples et `.env.example` avec l’implémentation correspondante. +- [ ] Intégration - coordonner les surfaces publiques sûres avec logging, transports, pipeline, scénarios et applications. diff --git a/ks-config/USAGE.md b/ks-config/USAGE.md index 6bbfe9d..89884f1 100644 --- a/ks-config/USAGE.md +++ b/ks-config/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de ks-config @@ -7,7 +7,7 @@ ```rust let config_result = ks_config::read_config_json_file_with_environment( - std::path::Path::new("config/example.config.json"), + std::path::Path::new("config/app.config.json"), std::path::Path::new("."), ); let config = match config_result { @@ -20,7 +20,9 @@ let profile = match ks_config::active_profile(&config) { }; ``` -Cette fonction charge l’environnement du workspace, résout les placeholders puis applique successivement le schéma JSON, la désérialisation typée et les invariants métier. +Cette API charge l’environnement du workspace, résout les placeholders puis applique successivement le schéma JSON général, la désérialisation typée et les invariants métier. + +Le fichier chargé par défaut par le desktop est `config/app.config.json`. `KS_CONFIG_PATH` permet de remplacer explicitement ce chemin. ## Chargement de l’environnement @@ -35,18 +37,20 @@ if let Some(path) = report.loaded_path { } ``` -`EnvironmentLoadReport` indique le fichier chargé, s’il existe. Par défaut, `ks-config` sélectionne `.env`; `KS_ENV_FILE` permet de choisir explicitement un autre fichier sans écraser les variables déjà présentes dans le processus. Les placeholders non résolus sans fallback restent visibles afin que la validation ou le consommateur puisse les signaler explicitement. Les contrats d’environnement du workspace utilisent désormais `KS_*` pour Khadhroony Solana et `KB_*` pour les futurs besoins réellement propres au Bot. +`EnvironmentLoadReport` indique le fichier chargé. Par défaut, `ks-config` sélectionne `.env`; `KS_ENV_FILE` permet d’en choisir un autre sans écraser les variables déjà présentes dans le processus. + +Les contrats d’environnement utilisent `KS_*` pour Khadhroony Solana et `KB_*` pour les besoins réellement propres au Bot. ## Résolution explicite des placeholders ```rust -let raw = r#"{"databaseUrl":"${KS_SECRET_POSTGRES_DEVNET_URL:-postgres://localhost/kb}"}"#; +let raw = r#"{"databaseUrl":"${KS_SECRET_POSTGRES_DEVNET_URL:-postgres://localhost/ks}"}"#; let resolved = ks_config::resolve_environment_placeholders(raw); assert!(resolved.contains("databaseUrl")); ``` -Cette API retourne actuellement une chaîne résolue ordinaire et peut donc contenir des secrets issus de l’environnement. Elle doit rester strictement backend et ne doit pas être utilisée pour afficher, logger ou transmettre le JSON résolu. `0.5.1` remplacera cette frontière par une résolution conservant la classification de sensibilité. +Cette API retourne encore une chaîne ordinaire pouvant contenir des secrets résolus. Elle reste strictement backend jusqu’à l’introduction de la représentation sensible de `0.5.1-pre.006`. ## Validation et parsing @@ -65,29 +69,6 @@ if let Err(error) = ks_config::validate_config(&config) { `parse_config_json` effectue déjà les deux validations ; les appels séparés servent aux outils de diagnostic. -## Sérialisation - -```rust -let compact = match ks_config::serialize_config_json(&config) { - Ok(value) => value, - Err(error) => return Err(error), -}; -let pretty = match ks_config::serialize_config_json_pretty(&config) { - Ok(value) => value, - Err(error) => return Err(error), -}; - -let write_result = std::fs::write("config/generated.config.json", pretty); -if let Err(error) = write_result { - return Err(ks_core::Error::new( - "config_write_failed", - format!("cannot write generated configuration: {error}"), - )); -} -``` - -La configuration est validée avant sérialisation. - ## Schéma embarqué ```rust @@ -97,15 +78,11 @@ let schema_value = match ks_config::config_json_schema_value() { Err(error) => return Err(error), }; -let property_count = schema_value - .get("properties") - .and_then(serde_json::Value::as_object) - .map_or(0, serde_json::Map::len); - -println!("embedded schema bytes={}, properties={property_count}", schema_text.len()); +println!("embedded app schema bytes={}", schema_text.len()); +assert!(schema_value.is_object()); ``` -Le schéma actif est aussi disponible sous [`../config/schema.config.json`](../config/schema.config.json). Le fichier [`../config/example.config.json`](../config/example.config.json) fournit un exemple utilisateur complet. +Le schéma actif est [`../config/schemas/app.config.schema.json`](../config/schemas/app.config.schema.json). Les fichiers [`../config/app.config.json`](../config/app.config.json) et [`../config/example.app.config.json`](../config/example.app.config.json) doivent tous deux être conformes. ## Sélection du profil actif @@ -120,24 +97,47 @@ println!("http endpoints: {}", profile.solana.http_endpoints.len()); println!("websocket endpoints: {}", profile.solana.ws_endpoints.len()); ``` +Le profil applicatif ne contient plus de configuration logging. Le document logging et son `active_profile` sont chargés par `ks-logging`. + +## Sérialisation + +```rust +let pretty = match ks_config::serialize_config_json_pretty(&config) { + Ok(value) => value, + Err(error) => return Err(error), +}; + +let write_result = std::fs::write("config/generated.app.config.json", pretty); +if let Err(error) = write_result { + return Err(ks_core::Error::new( + "config_write_failed", + format!("cannot write generated configuration: {error}"), + )); +} +``` + +La configuration est validée avant sérialisation. + ## Types publics importants - `AppConfig`, `ProfileConfig`, `AppSectionConfig` ; - `DatabaseConfig`, `PostgresConfig`, `SqliteConfig`, `DataConfig` ; - `SolanaConfig`, `HttpEndpointConfig`, `WsEndpointConfig`, `EndpointRoleConfig` ; - `ListenerConfig` et ses variantes ; -- `LoggingConfig`, `LogTargetConfig`, `LogTargetFilterConfig` ; - `WalletConfig`, `ExecutionConfig`, `DemoConfig`. +Les types logging ne font plus partie de `ks-config`. + ## Erreurs et invariants -Les erreurs utilisent `ks_core::Error` avec un code stable. Les validations couvrent notamment l’unicité des profils, l’existence du profil actif, les URLs, les rôles d’endpoints, les limites d’exécution, les routes de logging et les contraintes wallet. +Les erreurs utilisent `ks_core::Error` avec un code stable. Les validations couvrent notamment l’unicité des profils, l’existence du profil actif, les URLs, les rôles d’endpoints, les limites d’exécution et les contraintes wallet. ## Tests instructifs -Les tests `example_config_validates_against_schema`, `example_config_parses_and_resolves_active_profile` et `example_config_routes_global_and_operational_crate_files` démontrent le contrat complet de l’exemple actif. Les tests `parser_rejects_*` et `schema_rejects_*` documentent les invariants refusés. +Les tests vérifient séparément `app.config.json` et `example.app.config.json`, le roundtrip du document général et les invariants `parser_rejects_*` / `schema_rejects_*`. ## Limites - format JSON uniquement ; -- la crate valide les références et paramètres, mais n’ouvre aucune connexion externe. +- aucune connexion externe n’est ouverte par la crate ; +- la politique de camouflage des valeurs résolues appartient à `0.5.1-pre.006`. diff --git a/ks-config/src/lib.rs b/ks-config/src/lib.rs index 7d8e766..45daec0 100644 --- a/ks-config/src/lib.rs +++ b/ks-config/src/lib.rs @@ -1,7 +1,7 @@ // file: ks-config/src/lib.rs -// version: 5 +// version: 6 -//! Khadhroony Bot3 workspace configuration contract and loading helpers. +//! Khadhroony Solana application configuration contract and loading helpers. #![warn(missing_docs)] #![deny(unreachable_pub)] #![forbid(unsafe_code)] @@ -37,12 +37,6 @@ pub use self::settings::HttpEndpointConfig; pub use self::settings::ListenerConfig; /// Exposes the log listener configuration type. pub use self::settings::LogListenerConfig; -/// Exposes the logging target configuration type. -pub use self::settings::LogTargetConfig; -/// Exposes the logging target filter configuration type. -pub use self::settings::LogTargetFilterConfig; -/// Exposes the logging configuration type. -pub use self::settings::LoggingConfig; /// Exposes the PostgreSQL configuration type. pub use self::settings::PostgresConfig; /// Exposes the profile configuration type. diff --git a/ks-config/src/settings.rs b/ks-config/src/settings.rs index e9caf9a..92e7e9d 100644 --- a/ks-config/src/settings.rs +++ b/ks-config/src/settings.rs @@ -1,11 +1,11 @@ // file: ks-config/src/settings.rs -// version: 19 +// version: 20 //! Typed configuration models shared by applications and workers. use ts_rs::TS; // rust-rules: derive-import -const CONFIG_JSON_SCHEMA: &str = include_str!("../../config/schema.config.json"); +const CONFIG_JSON_SCHEMA: &str = include_str!("../../config/schemas/app.config.schema.json"); /// Root configuration containing every named profile. #[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)] @@ -28,8 +28,6 @@ pub struct ProfileConfig { pub name: std::string::String, /// Application metadata. pub app: AppSectionConfig, - /// Logging configuration. - pub logging: LoggingConfig, /// Database configuration. pub database: DatabaseConfig, /// Local data directories. @@ -59,61 +57,6 @@ pub struct AppSectionConfig { pub auto_reconnect_default: bool, } -/// Logging configuration shared by apps and worker processes. -#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)] -#[ts( - export, - export_to = "../frontend/ts/bindings/ks_config/settings/LoggingConfig.ts" -)] -pub struct LoggingConfig { - /// Default log level. - pub default_level: std::string::String, - /// Output targets. - pub targets: std::vec::Vec, - /// Target-specific filters. - pub target_filters: std::vec::Vec, -} - -/// Single logging output target. -#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)] -#[ts( - export, - export_to = "../frontend/ts/bindings/ks_config/settings/LogTargetConfig.ts" -)] -pub struct LogTargetConfig { - /// Output target name. - pub name: std::string::String, - /// Enables this target. - pub enabled: bool, - /// Sink kind, such as console or file. - pub sink: std::string::String, - /// Minimum level for this target. - pub level: std::string::String, - /// File path for file sinks or an empty string for console sinks. - pub path: std::string::String, - /// Rotation mode for file sinks. - pub rotation: std::string::String, - /// Message format, such as human or json. - pub format: std::string::String, - /// Enables ANSI escape sequences for this target. - pub ansi: bool, - /// Included tracing targets or globs. - pub targets: std::vec::Vec, -} - -/// Per-target logging filter. -#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)] -#[ts( - export, - export_to = "../frontend/ts/bindings/ks_config/settings/LogTargetFilterConfig.ts" -)] -pub struct LogTargetFilterConfig { - /// Tracing target or crate prefix. - pub target: std::string::String, - /// Level assigned to the target. - pub level: std::string::String, -} - /// Database backend configuration. #[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)] #[ts( @@ -650,10 +593,6 @@ fn validate_profile(profile: &ProfileConfig) -> ks_core::Result<()> { std::result::Result::Ok(()) => (), std::result::Result::Err(error) => return std::result::Result::Err(error), } - match validate_logging(&profile.logging) { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } match validate_database(&profile.database) { std::result::Result::Ok(()) => (), std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -685,109 +624,6 @@ fn validate_app_section(config: &AppSectionConfig) -> ks_core::Result<()> { return require_non_empty(&config.environment, "app.environment"); } -fn validate_logging(config: &LoggingConfig) -> ks_core::Result<()> { - match validate_log_level(&config.default_level, "logging.default_level") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - if config.targets.is_empty() { - return std::result::Result::Err(ks_core::Error::new( - "logging_targets_empty", - "at least one logging target is required", - )); - } - let mut enabled_count = 0_u32; - let mut names = std::collections::BTreeSet::::new(); - for target in &config.targets { - if target.enabled { - enabled_count += 1; - } - if !names.insert(target.name.clone()) { - return std::result::Result::Err(ks_core::Error::new( - "logging_target_duplicate", - target.name.clone(), - )); - } - match validate_log_target(target) { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - } - for filter in &config.target_filters { - match require_non_empty(&filter.target, "logging.target_filters.target") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - match validate_log_level(&filter.level, "logging.target_filters.level") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - } - if enabled_count == 0 { - return std::result::Result::Err(ks_core::Error::new( - "logging_no_enabled_targets", - "at least one logging target must be enabled", - )); - } - return std::result::Result::Ok(()); -} - -fn validate_log_target(config: &LogTargetConfig) -> ks_core::Result<()> { - match require_non_empty(&config.name, "logging.targets.name") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - match validate_log_level(&config.level, "logging.targets.level") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - if config.sink != "console" && config.sink != "file" { - return std::result::Result::Err(ks_core::Error::new( - "logging_sink_invalid", - config.sink.clone(), - )); - } - if config.rotation != "none" - && config.rotation != "never" - && config.rotation != "daily" - && config.rotation != "hourly" - { - return std::result::Result::Err(ks_core::Error::new( - "logging_rotation_invalid", - config.rotation.clone(), - )); - } - if config.format != "human" - && config.format != "compact" - && config.format != "pretty" - && config.format != "json" - { - return std::result::Result::Err(ks_core::Error::new( - "logging_format_invalid", - config.format.clone(), - )); - } - if config.sink == "file" && config.path.trim().is_empty() { - return std::result::Result::Err(ks_core::Error::new( - "logging_file_path_empty", - config.name.clone(), - )); - } - if config.sink == "console" && !config.path.trim().is_empty() { - return std::result::Result::Err(ks_core::Error::new( - "logging_console_path_not_empty", - config.name.clone(), - )); - } - for target in &config.targets { - match require_non_empty(target, "logging.targets.targets") { - std::result::Result::Ok(()) => (), - std::result::Result::Err(error) => return std::result::Result::Err(error), - } - } - return std::result::Result::Ok(()); -} - fn validate_database(config: &DatabaseConfig) -> ks_core::Result<()> { if config.backend != "postgres" && config.backend != "sqlite" { return std::result::Result::Err(ks_core::Error::new( @@ -1179,22 +1015,6 @@ fn validate_wallet_execution_pair( return std::result::Result::Ok(()); } -fn validate_log_level(value: &str, field_name: &str) -> ks_core::Result<()> { - if value == "trace" - || value == "debug" - || value == "info" - || value == "warn" - || value == "error" - || value == "off" - { - return std::result::Result::Ok(()); - } - return std::result::Result::Err(ks_core::Error::new( - "log_level_invalid", - format!("{field_name}: {value}"), - )); -} - fn require_non_empty(value: &str, field_name: &str) -> ks_core::Result<()> { if value.trim().is_empty() { return std::result::Result::Err(ks_core::Error::new( @@ -1225,13 +1045,14 @@ mod tests { } } - const EXAMPLE_CONFIG: &str = include_str!("../../config/example.config.json"); + const DEFAULT_CONFIG: &str = include_str!("../../config/app.config.json"); + const EXAMPLE_CONFIG: &str = include_str!("../../config/example.app.config.json"); - fn parse_example_value() -> serde_json::Value { - let result = serde_json::from_str::(EXAMPLE_CONFIG); + fn parse_default_value() -> serde_json::Value { + let result = serde_json::from_str::(DEFAULT_CONFIG); match result { std::result::Result::Ok(value) => return value, - std::result::Result::Err(error) => panic!("example config must be valid JSON: {error}"), + std::result::Result::Err(error) => panic!("default app config must be valid JSON: {error}"), } } @@ -1243,57 +1064,6 @@ mod tests { } } - fn tracing_crate_names() -> std::vec::Vec { - let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let workspace_root = match manifest_dir.parent() { - std::option::Option::Some(path) => path, - std::option::Option::None => panic!("workspace root must exist"), - }; - let read_result = std::fs::read_dir(workspace_root); - let entries = match read_result { - std::result::Result::Ok(entries) => entries, - std::result::Result::Err(error) => panic!("workspace must be readable: {error}"), - }; - let mut names = std::vec::Vec::::new(); - for entry_result in entries { - let entry = match entry_result { - std::result::Result::Ok(entry) => entry, - std::result::Result::Err(error) => { - panic!("workspace entry must be readable: {error}") - }, - }; - let cargo_path = entry.path().join("Cargo.toml"); - if !cargo_path.is_file() { - continue; - } - let cargo_result = std::fs::read_to_string(&cargo_path); - let cargo_toml = match cargo_result { - std::result::Result::Ok(content) => content, - std::result::Result::Err(error) => panic!("Cargo.toml must be readable: {error}"), - }; - if !cargo_toml.lines().any(|line| return line.trim() == "tracing.workspace = true") { - continue; - } - let mut in_package = false; - for line in cargo_toml.lines() { - let trimmed = line.trim(); - if trimmed == "[package]" { - in_package = true; - continue; - } - if in_package && trimmed.starts_with('[') { - break; - } - if in_package && trimmed.starts_with("name = ") { - names.push(trimmed.trim_start_matches("name = ").trim_matches('"').to_string()); - break; - } - } - } - names.sort(); - return names; - } - #[test] fn schema_text_is_valid_json() { let result = super::config_json_schema_value(); @@ -1301,110 +1071,18 @@ mod tests { } #[test] - fn example_config_validates_against_schema() { - let result = super::validate_config_json_schema(EXAMPLE_CONFIG); - assert!(result.is_ok()); + fn default_and_example_app_configs_validate_against_schema() { + assert!(super::validate_config_json_schema(DEFAULT_CONFIG).is_ok()); + assert!(super::validate_config_json_schema(EXAMPLE_CONFIG).is_ok()); } #[test] - fn example_config_routes_global_and_operational_crate_files() { - let config_result = super::parse_config_json(EXAMPLE_CONFIG); - let config = match config_result { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => panic!("example config must parse: {error}"), - }; - let operational_crates = tracing_crate_names(); - assert!(!operational_crates.is_empty()); - for profile in config.profiles { - let directory = match profile.name.as_str() { - "local_devnet" => "devnet", - "mainnet_research" => "mainnet_research", - "mainnet" => "mainnet", - value => panic!("unexpected example profile: {value}"), - }; - for (suffix, level, format) in [ - ("debug.log", "debug", "human"), - ("info.log", "info", "human"), - ("error.jsonl", "error", "json"), - ] { - let expected_path = format!("logs/{directory}/{suffix}"); - assert!(profile.logging.targets.iter().any(|target| { - return target.enabled - && target.path == expected_path - && target.level == level - && target.format == format - && target.targets == std::vec!["*".to_string()]; - })); - } - assert!(profile.logging.targets.iter().any(|target| { - return target.enabled - && target.path == format!("logs/{directory}/app.log") - && target.level == "debug" - && target.format == "human" - && target.targets == std::vec!["kb-app-demo-desktop".to_string()]; - })); - for crate_name in &operational_crates { - for (suffix, level, format) in [ - ("debug.log", "debug", "human"), - ("info.log", "info", "human"), - ("error.jsonl", "error", "json"), - ] { - let route_directory = if crate_name == "ks-pipeline-demo-scenarios" { - "ks-pipeline" - } else { - crate_name.as_str() - }; - let expected_path = format!("logs/{directory}/{route_directory}/{suffix}"); - let route_exists = profile.logging.targets.iter().any(|target| { - return target.enabled - && target.path == expected_path - && target.level == level - && target.format == format - && target.targets.iter().any(|value| return value == crate_name); - }); - assert!( - route_exists, - "profile {} is missing the canonical {} route for {} at {}", - profile.name, level, crate_name, expected_path - ); - } - } - } - } - - #[test] - fn example_config_uses_canonical_wallet_tracing_routes_without_embedded_secrets() { - let config_result = super::parse_config_json(EXAMPLE_CONFIG); - let config = match config_result { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => panic!("example config must parse: {error}"), - }; - assert!(!EXAMPLE_CONFIG.contains("api-key=95e73621")); - assert!(!EXAMPLE_CONFIG.contains("\"ks_wallet\"")); - for profile in config.profiles { - assert!(profile.logging.targets.iter().any(|target| { - return target.enabled && target.targets == std::vec!["ks-wallet".to_string()]; - })); - } - } - - #[test] - fn example_config_uses_canonical_pipeline_tracing_routes() { - let source = include_str!("../../config/example.config.json"); - assert!(source.contains("\"ks-pipeline\"")); - assert!(source.contains("logs/devnet/ks-pipeline/debug.log")); - assert!(source.contains("logs/mainnet_research/ks-pipeline/info.log")); - assert!(source.contains("logs/mainnet/ks-pipeline/error.jsonl")); - assert!(!source.contains("ks_pipeline")); - } - - #[test] - fn example_config_parses_and_resolves_active_profile() { - let config_result = super::parse_config_json(EXAMPLE_CONFIG); + fn default_app_config_parses_and_resolves_active_profile() { + let config_result = super::parse_config_json(DEFAULT_CONFIG); assert!(config_result.is_ok()); let config = match config_result { std::result::Result::Ok(config) => config, - std::result::Result::Err(error) => panic!("example config must parse: {error}"), + std::result::Result::Err(error) => panic!("default app config must parse: {error}"), }; let active_result = super::active_profile(&config); assert!(active_result.is_ok()); @@ -1417,18 +1095,18 @@ mod tests { } #[test] - fn example_config_serializes_and_roundtrips() { - let config_result = super::parse_config_json(EXAMPLE_CONFIG); + fn default_app_config_serializes_and_roundtrips() { + let config_result = super::parse_config_json(DEFAULT_CONFIG); assert!(config_result.is_ok()); let config = match config_result { std::result::Result::Ok(config) => config, - std::result::Result::Err(error) => panic!("example config must parse: {error}"), + std::result::Result::Err(error) => panic!("default app config must parse: {error}"), }; let serialized_result = super::serialize_config_json_pretty(&config); assert!(serialized_result.is_ok()); let serialized = match serialized_result { std::result::Result::Ok(serialized) => serialized, - std::result::Result::Err(error) => panic!("example config must serialize: {error}"), + std::result::Result::Err(error) => panic!("default app config must serialize: {error}"), }; let reparsed_result = super::parse_config_json(&serialized); assert!(reparsed_result.is_ok()); @@ -1441,7 +1119,7 @@ mod tests { #[test] fn parser_rejects_missing_active_profile() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["active_profile"] = serde_json::Value::String("missing_profile".to_string()); let raw_json = value_to_json(&value); let result = super::parse_config_json(&raw_json); @@ -1449,8 +1127,8 @@ mod tests { } #[test] - fn example_config_separates_runtime_postgres_profiles() { - let value = parse_example_value(); + fn default_app_config_separates_runtime_postgres_profiles() { + let value = parse_default_value(); assert_eq!( value["profiles"][0]["database"]["postgres"]["url"], serde_json::Value::String("${KS_SECRET_POSTGRES_DEVNET_URL}".to_string()) @@ -1467,7 +1145,7 @@ mod tests { #[test] fn schema_rejects_profile_enabled_field() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["enabled"] = serde_json::Value::Bool(true); let raw_json = value_to_json(&value); let result = super::validate_config_json_schema(&raw_json); @@ -1476,7 +1154,7 @@ mod tests { #[test] fn parser_rejects_duplicate_profile_names() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][1]["name"] = serde_json::Value::String("local_devnet".to_string()); let raw_json = value_to_json(&value); let result = super::parse_config_json(&raw_json); @@ -1485,7 +1163,7 @@ mod tests { #[test] fn schema_rejects_unknown_endpoint_secret_field() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["solana"]["http_endpoints"][0]["secret_env_field"] = serde_json::Value::String("KS_SECRET_HELIUS_API_KEY".to_string()); let raw_json = value_to_json(&value); @@ -1495,7 +1173,7 @@ mod tests { #[test] fn schema_rejects_runtime_idls_directory_field() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["data"]["idls_directory"] = serde_json::Value::String("idls".to_string()); let raw_json = value_to_json(&value); @@ -1505,7 +1183,7 @@ mod tests { #[test] fn schema_rejects_unsupported_transport_surface() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["solana"]["advanced_streams"] = serde_json::json!([]); let raw_json = value_to_json(&value); let result = super::validate_config_json_schema(&raw_json); @@ -1514,7 +1192,7 @@ mod tests { #[test] fn parser_rejects_invalid_http_endpoint_url() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["solana"]["http_endpoints"][0]["url"] = serde_json::Value::String("wss://api.devnet.solana.com".to_string()); let raw_json = value_to_json(&value); @@ -1524,7 +1202,7 @@ mod tests { #[test] fn parser_rejects_invalid_ws_endpoint_url() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["solana"]["ws_endpoints"][0]["url"] = serde_json::Value::String("https://api.devnet.solana.com".to_string()); let raw_json = value_to_json(&value); @@ -1532,19 +1210,9 @@ mod tests { assert!(result.is_err()); } - #[test] - fn parser_rejects_file_logging_target_without_path() { - let mut value = parse_example_value(); - value["profiles"][0]["logging"]["targets"][1]["path"] = - serde_json::Value::String("".to_string()); - let raw_json = value_to_json(&value); - let result = super::parse_config_json(&raw_json); - assert!(result.is_err()); - } - #[test] fn parser_rejects_invalid_temporary_wallet_alias() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["wallet"]["temporary_wallet_alias"] = serde_json::Value::String("../wallet".to_string()); let raw_json = value_to_json(&value); @@ -1554,7 +1222,7 @@ mod tests { #[test] fn parser_rejects_persistent_disabled_temporary_wallet() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["wallet"]["temporary_wallet_enabled"] = serde_json::Value::Bool(false); let raw_json = value_to_json(&value); let result = super::parse_config_json(&raw_json); @@ -1563,7 +1231,7 @@ mod tests { #[test] fn parser_rejects_enabled_cluster_without_spend_limit() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["execution"]["devnet_max_spend_lamports"] = serde_json::Value::Number(serde_json::Number::from(0)); let raw_json = value_to_json(&value); @@ -1579,7 +1247,7 @@ mod tests { "confirmation_poll_interval_ms", "confirmation_max_attempts", ] { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["execution"][field] = serde_json::Value::Number(serde_json::Number::from(0)); let raw_json = value_to_json(&value); @@ -1590,7 +1258,7 @@ mod tests { #[test] fn parser_rejects_http_role_with_subscriptions() { - let mut value = parse_example_value(); + let mut value = parse_default_value(); value["profiles"][0]["solana"]["http_endpoints"][0]["roles"][0]["max_subscriptions"] = serde_json::Value::Number(serde_json::Number::from(1)); let raw_json = value_to_json(&value); diff --git a/ks-logging/CHANGELOG.md b/ks-logging/CHANGELOG.md index a541c82..11339f2 100644 --- a/ks-logging/CHANGELOG.md +++ b/ks-logging/CHANGELOG.md @@ -1,8 +1,16 @@ - + # CHANGELOG — ks-logging +## `0.5.1-pre.005` + +- devient propriétaire unique des types `LoggingConfig`, `LogTargetConfig` et `LogTargetFilterConfig` ; +- ajoute `LoggingConfigDocument`, les profils logging indépendants et leur chargement avec résolution d’environnement ; +- embarque et valide `config/schemas/logging.config.schema.json` ; +- charge `config/logging.config.json` par défaut via le desktop et supprime la conversion champ par champ depuis `ks-config` ; +- ajoute les tests de schéma, profil actif et routes canoniques du document logging. + ## `0.5.1-pre.003` - aligne les routes de référence et la documentation de logging sur les identités `ks-lib-decoder.*`, `ks-lib-executor.*` et `ks-lib-materializer.*` ; diff --git a/ks-logging/Cargo.toml b/ks-logging/Cargo.toml index 1f5661a..06ef087 100644 --- a/ks-logging/Cargo.toml +++ b/ks-logging/Cargo.toml @@ -1,5 +1,5 @@ # file: ks-logging/Cargo.toml -# version: 3 +# version: 4 [package] name = "ks-logging" @@ -9,7 +9,11 @@ license.workspace = true publish.workspace = true [dependencies] +jsonschema.workspace = true +ks-config = { path = "../ks-config" } ks-core = { path = "../ks-core" } +serde.workspace = true +serde_json.workspace = true tracing.workspace = true tracing-appender.workspace = true tracing-subscriber.workspace = true diff --git a/ks-logging/README.md b/ks-logging/README.md index f663937..89e7ba8 100644 --- a/ks-logging/README.md +++ b/ks-logging/README.md @@ -1,38 +1,45 @@ - + # ks-logging -`ks-logging` initialise le subscriber global `tracing` à partir d’une configuration de routes explicites vers la console ou des fichiers. +`ks-logging` possède le contrat logging indépendant du workspace et initialise le subscriber global `tracing` à partir du profil logging sélectionné. ## Responsabilités +- charger `logging.config.json` et résoudre ses placeholders d’environnement ; +- valider `config/schemas/logging.config.schema.json` ; +- sélectionner un profil logging indépendamment du profil applicatif ; +- posséder `LoggingConfig`, `LogTargetConfig` et `LogTargetFilterConfig` ; - sélectionner les routes activées ; - appliquer niveaux, targets exactes et préfixes wildcard ; -- créer les writers non bloquants ; -- gérer les formats human, compact, pretty et JSON ; -- gérer les rotations de fichiers supportées ; +- créer les writers non bloquants et gérer les formats/rotations ; - conserver les `WorkerGuard` pendant toute la durée du processus. -## Hors périmètre +## Relations -La crate ne charge pas actuellement le fichier de configuration et ne définit pas les targets des autres crates. Le cadrage `0.5.0-pre.002` confirme qu’un document logging séparé sera introduit en `0.5.1`; la propriété exacte du DTO source sera fixée sans faire dépendre la configuration générale du runtime tracing. +`ks-logging` dépend de `ks-config` uniquement pour le chargement du fichier `.env` et la résolution générique `${KS_*}` / `${KB_*}`. `ks-config` ne dépend pas de `ks-logging` et ne duplique aucun type logging. + +Le desktop charge `config/app.config.json` et `config/logging.config.json` séparément puis transmet directement le profil logging actif à `init_logging`. ## API publique +- `read_logging_json_file_with_environment` charge le document logging ; +- `parse_logging_json` et `validate_logging_json_schema` valident le format ; +- `active_logging_profile` sélectionne le profil actif ; +- `LoggingConfigDocument` et `LoggingProfileConfig` décrivent le document ; +- `LoggingConfig`, `LogTargetConfig` et `LogTargetFilterConfig` décrivent le runtime ; - `init_logging` initialise le subscriber global ; -- `LoggingConfig`, `LogTargetConfig` et `LogTargetFilterConfig` décrivent les routes ; -- `LoggingGuard` maintient les writers et expose les routes installées ; -- `tracing_target` retourne le target canonique de la crate ; -- `LogFileRoute` reste disponible pour les anciens appelants file-only. +- `LoggingGuard` maintient les writers ; +- `tracing_target` retourne le target canonique de la crate. ## Statut -L’initialisation multi-routes est fonctionnelle. Elle échoue explicitement si aucune route n’est activée ou si le subscriber global a déjà été initialisé. +Le split config/logging est fonctionnel. Les profils logging sont indépendants des profils applicatifs et les routes existantes restent conservées dans `config/logging.config.json`. ## Documents - [Utilisation](USAGE.md) - [Travaux restants](TODO.md) - [Historique](CHANGELOG.md) -- [Guide de configuration](../ks-config/USAGE.md) +- [Configuration locale](../config/README.md) diff --git a/ks-logging/TODO.md b/ks-logging/TODO.md index 25c9b2f..afe4a06 100644 --- a/ks-logging/TODO.md +++ b/ks-logging/TODO.md @@ -1,14 +1,12 @@ - + # TODO — ks-logging ## Série `0.5.x` -- [ ] `0.5.1` - consommer un document logging et un schéma distincts de la configuration généraliste. -- [ ] `0.5.1` - définir avec `ks-config` un propriétaire unique du DTO source logging sans coupler `ks-config` au runtime tracing. -- [ ] `0.5.1` - supprimer la conversion champ par champ actuellement portée par le desktop. -- [ ] Compatibilité - préserver targets, niveaux, filtres, formats, routes et sémantique wildcard pendant la migration. +- [ ] `0.5.1` - intégrer la propagation de sensibilité et le camouflage des valeurs provenant de `KS_SECRET_*` / `KB_SECRET_*` avant tout diagnostic ou log. +- [ ] Compatibilité - préserver targets, niveaux, filtres, formats, routes et sémantique wildcard pendant les prochaines migrations. - [ ] Contrat - réévaluer `LogFileRoute`, actuellement sans consommateur actif hors de la crate. -- [ ] Tests - ajouter les tests d’API externe et de migration du futur format logging. -- [ ] Documentation - mettre à jour les exemples après implémentation du nouveau chargement. +- [ ] Tests - ajouter les canaris garantissant qu’un secret résolu n’atteint jamais une sortie logging. +- [ ] Documentation - maintenir le schéma et les exemples logging alignés avec les types possédés par la crate. diff --git a/ks-logging/USAGE.md b/ks-logging/USAGE.md index ff252f9..136509e 100644 --- a/ks-logging/USAGE.md +++ b/ks-logging/USAGE.md @@ -1,9 +1,57 @@ - + # Utilisation de ks-logging -## Initialisation +## Chargement recommandé + +```rust +let document = match ks_logging::read_logging_json_file_with_environment( + std::path::Path::new("config/logging.config.json"), + std::path::Path::new("."), +) { + Ok(value) => value, + Err(error) => return Err(error), +}; +let config = match ks_logging::active_logging_profile(&document) { + Ok(value) => value, + Err(error) => return Err(error), +}; +let guard = match ks_logging::init_logging(config) { + Ok(value) => value, + Err(error) => return Err(error), +}; +``` + +Le desktop utilise `config/logging.config.json` par défaut. `KS_LOGGING_CONFIG_PATH` peut sélectionner un autre document sans modifier `KS_CONFIG_PATH` ni le profil applicatif. + +## Format du document + +```json +{ + "active_profile": "local_devnet", + "profiles": [ + { + "name": "local_devnet", + "default_level": "info", + "targets": [], + "target_filters": [] + } + ] +} +``` + +Le schéma formel est `config/schemas/logging.config.schema.json`. `config/example.logging.config.json` fournit un exemple minimal conforme avec des routes valides. + +`targets` doit contenir au moins une route et au moins une route doit être activée. + +## Sélection indépendante + +Le `active_profile` logging n’est jamais déduit de `app.config.json`. Un opérateur peut donc utiliser, par exemple, un profil applicatif `mainnet_research` avec un profil logging `local_devnet` ou tout autre profil logging explicitement défini. + +## Construction directe + +Les tests ou consommateurs spécialisés peuvent toujours construire directement `LoggingConfig` puis appeler `init_logging` : ```rust let config = ks_logging::LoggingConfig { @@ -17,7 +65,7 @@ let config = ks_logging::LoggingConfig { rotation: "none".to_string(), format: "compact".to_string(), ansi: true, - targets: vec!["kb-*".to_string()], + targets: vec!["ks-*".to_string()], }], target_filters: Vec::new(), }; @@ -27,16 +75,6 @@ let guard = match ks_logging::init_logging(&config) { }; ``` -`init_logging` doit être appelée une seule fois par processus. Le `LoggingGuard` retourné doit rester vivant jusqu’à l’arrêt afin de ne pas interrompre les writers non bloquants. - -## Inspection des routes - -```rust -assert_eq!(guard.route_count(), 1); -assert_eq!(guard.guard_count(), 1); -assert_eq!(guard.route_names(), &["console".to_string()]); -``` - ## Route fichier JSON ```rust @@ -49,76 +87,13 @@ let file_route = ks_logging::LogTargetConfig { rotation: "daily".to_string(), format: "json".to_string(), ansi: false, - targets: vec![ - "ks-pipeline*".to_string(), - "ks-onchain-transport*".to_string(), - ], -}; - -let config = ks_logging::LoggingConfig { - default_level: "info".to_string(), - targets: vec![file_route], - target_filters: Vec::new(), -}; - -let guard = match ks_logging::init_logging(&config) { - Ok(value) => value, - Err(error) => return Err(error), + targets: vec!["ks-pipeline*".to_string()], }; ``` -Pour une route `file`, `path` doit désigner le fichier cible et `rotation` doit être une valeur supportée (`none`, `never`, `daily` ou `hourly`). Les formats supportés sont `human`, `compact`, `pretty` et `json`. +Les rotations supportées sont `none`, `never`, `daily` et `hourly`. Les formats supportés sont `human`, `compact`, `pretty` et `json`. -## Filtres de targets - -```rust -let config = ks_logging::LoggingConfig { - default_level: "warn".to_string(), - targets: vec![ks_logging::LogTargetConfig { - name: "console".to_string(), - enabled: true, - sink: "console".to_string(), - level: "info".to_string(), - path: String::new(), - rotation: "none".to_string(), - format: "compact".to_string(), - ansi: true, - targets: vec!["kb-*".to_string()], - }], - target_filters: vec![ - ks_logging::LogTargetFilterConfig { - target: "ks-pipeline".to_string(), - level: "debug".to_string(), - }, - ks_logging::LogTargetFilterConfig { - target: "ks-store".to_string(), - level: "info".to_string(), - }, - ], -}; -``` - -Les routes acceptent des targets exactes et des préfixes wildcard. Les `target_filters` ajoutent des niveaux spécifiques aux routes wildcard. Une route d’erreur conserve la sémantique stricte prévue par l’implémentation. - -## Émission d’événements après initialisation - -```rust -tracing::info!( - target: ks_logging::tracing_target(), - action = "startup", - "logging runtime initialized" -); - -tracing::debug!( - target: "ks-pipeline.demo", - scenario = "token_2022", - "scenario preparation started" -); -``` - -Les targets doivent suivre la nomenclature canonique du workspace pour que les routes et filtres restent prévisibles. - -## Inspection des routes actives +## Inspection des routes ```rust for route_name in guard.route_names() { @@ -132,6 +107,8 @@ assert_eq!(guard.route_count(), guard.route_names().len()); Les erreurs utilisent `ks_core::Error`. Les cas principaux sont : +- document ou schéma invalide ; +- profil actif absent ou dupliqué ; - aucune route activée ; - sink, format, rotation ou niveau inconnu ; - chemin fichier invalide ; @@ -139,12 +116,11 @@ Les erreurs utilisent `ks_core::Error`. Les cas principaux sont : ## Tests instructifs -- `enabled_routes_keep_all_configured_outputs` vérifie l’installation multi-routes ; -- `route_writer_filter_preserves_target_and_level_semantics` vérifie l’admission finale ; -- `more_than_64_routes_compose_without_filtered_layer_ids` couvre un volume élevé de routes ; -- `every_tracing_crate_exposes_canonical_targets` vérifie la cohérence des targets du workspace. +- les tests de `document` vérifient les deux fichiers logging versionnés et les profils indépendants ; +- `default_logging_config_routes_global_and_operational_crate_files` vérifie les routes canoniques ; +- les tests de `tracing_runtime` vérifient l’installation, les filtres et le volume de routes. ## Limites - initialisation globale unique par processus ; -- configuration fournie par l’appelant ; +- la politique de redaction des valeurs secrètes avant logging est renforcée dans `0.5.1-pre.006`. diff --git a/ks-logging/src/config.rs b/ks-logging/src/config.rs index a4ae01e..848b4c3 100644 --- a/ks-logging/src/config.rs +++ b/ks-logging/src/config.rs @@ -1,5 +1,5 @@ // file: ks-logging/src/config.rs -// version: 5 +// version: 6 //! Logging configuration data structures consumed by the tracing runtime. @@ -15,7 +15,7 @@ pub struct LogFileRoute { } /// One target-level filter shared by routes that include the wildcard target. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)] pub struct LogTargetFilterConfig { /// Tracing target or crate prefix. pub target: std::string::String, @@ -24,7 +24,7 @@ pub struct LogTargetFilterConfig { } /// One logging output route. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)] pub struct LogTargetConfig { /// Route name used for diagnostics. pub name: std::string::String, @@ -46,8 +46,8 @@ pub struct LogTargetConfig { pub targets: std::vec::Vec, } -/// Logging configuration consumed by `ks-logging` before profile binding exists. -#[derive(Clone, Debug, Eq, PartialEq)] +/// Logging configuration consumed by `ks-logging` for one named profile. +#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)] pub struct LoggingConfig { /// Default log level used when a route does not provide target directives. pub default_level: std::string::String, diff --git a/ks-logging/src/document.rs b/ks-logging/src/document.rs new file mode 100644 index 0000000..e4556c9 --- /dev/null +++ b/ks-logging/src/document.rs @@ -0,0 +1,519 @@ +// file: ks-logging/src/document.rs +// version: 1 + +//! Independent logging configuration document loading and validation. + +const LOGGING_JSON_SCHEMA: &str = include_str!("../../config/schemas/logging.config.schema.json"); + +/// Root logging document containing independently selectable named profiles. +#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)] +pub struct LoggingConfigDocument { + /// Active logging profile name. + pub active_profile: std::string::String, + /// Named logging profiles available in this document. + pub profiles: std::vec::Vec, +} + +/// Named logging profile wrapping the runtime logging configuration. +#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)] +pub struct LoggingProfileConfig { + /// Profile code selected independently from the application profile. + pub name: std::string::String, + /// Runtime logging configuration owned by `ks-logging`. + #[serde(flatten)] + pub config: crate::LoggingConfig, +} + +/// Returns the embedded JSON Schema text used for logging configuration validation. +pub fn logging_json_schema_text() -> &'static str { + return LOGGING_JSON_SCHEMA; +} + +/// Parses the embedded logging JSON Schema into a JSON value. +pub fn logging_json_schema_value() -> ks_core::Result { + let schema_result = serde_json::from_str::(LOGGING_JSON_SCHEMA); + return match schema_result { + std::result::Result::Ok(schema) => std::result::Result::Ok(schema), + std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new( + "logging_config_schema_parse_failed", + error.to_string(), + )), + }; +} + +/// Validates raw logging JSON against the embedded logging schema. +pub fn validate_logging_json_schema(raw_json: &str) -> ks_core::Result<()> { + let schema = match logging_json_schema_value() { + std::result::Result::Ok(schema) => schema, + std::result::Result::Err(error) => return std::result::Result::Err(error), + }; + let instance = match serde_json::from_str::(raw_json) { + std::result::Result::Ok(instance) => instance, + std::result::Result::Err(error) => { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_json_parse_failed", + error.to_string(), + )); + }, + }; + let validator = match jsonschema::validator_for(&schema) { + std::result::Result::Ok(validator) => validator, + std::result::Result::Err(error) => { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_schema_compile_failed", + error.to_string(), + )); + }, + }; + let validation_result = validator.validate(&instance); + return match validation_result { + std::result::Result::Ok(()) => std::result::Result::Ok(()), + std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new( + "logging_config_schema_validation_failed", + error.to_string(), + )), + }; +} + +/// Parses and validates one independent logging configuration document. +pub fn parse_logging_json(raw_json: &str) -> ks_core::Result { + match validate_logging_json_schema(raw_json) { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + let document = match serde_json::from_str::(raw_json) { + std::result::Result::Ok(document) => document, + std::result::Result::Err(error) => { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_json_decode_failed", + error.to_string(), + )); + }, + }; + return match validate_logging_document(&document) { + std::result::Result::Ok(()) => std::result::Result::Ok(document), + std::result::Result::Err(error) => std::result::Result::Err(error), + }; +} + +/// Reads and parses one logging configuration document from a filesystem path. +pub fn read_logging_json_file(path: &std::path::Path) -> ks_core::Result { + let raw_json = match std::fs::read_to_string(path) { + std::result::Result::Ok(content) => content, + std::result::Result::Err(error) => { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_file_read_failed", + error.to_string(), + )); + }, + }; + return parse_logging_json(&raw_json); +} + +/// Loads workspace environment values, resolves placeholders and parses logging configuration. +pub fn read_logging_json_file_with_environment( + path: &std::path::Path, + workspace_root: &std::path::Path, +) -> ks_core::Result { + match ks_config::load_workspace_environment(workspace_root) { + std::result::Result::Ok(_) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + let raw_json = match std::fs::read_to_string(path) { + std::result::Result::Ok(content) => content, + std::result::Result::Err(error) => { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_file_read_failed", + error.to_string(), + )); + }, + }; + let resolved = ks_config::resolve_environment_placeholders(&raw_json); + return parse_logging_json(&resolved); +} + +/// Returns the active runtime logging profile selected by the logging document. +pub fn active_logging_profile( + document: &LoggingConfigDocument, +) -> ks_core::Result<&crate::LoggingConfig> { + for profile in &document.profiles { + if profile.name == document.active_profile { + return std::result::Result::Ok(&profile.config); + } + } + return std::result::Result::Err(ks_core::Error::new( + "active_logging_profile_not_found", + document.active_profile.clone(), + )); +} + +/// Validates a typed logging configuration document. +pub fn validate_logging_document(document: &LoggingConfigDocument) -> ks_core::Result<()> { + match require_non_empty(&document.active_profile, "active_profile") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + if document.profiles.is_empty() { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_profiles_empty", + "at least one logging profile is required", + )); + } + let mut names = std::collections::BTreeSet::::new(); + let mut active_count = 0_u32; + for profile in &document.profiles { + match require_non_empty(&profile.name, "logging.profile.name") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + if !names.insert(profile.name.clone()) { + return std::result::Result::Err(ks_core::Error::new( + "logging_profile_name_duplicate", + profile.name.clone(), + )); + } + if profile.name == document.active_profile { + active_count += 1; + } + match validate_logging_config(&profile.config) { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + } + if active_count != 1 { + return std::result::Result::Err(ks_core::Error::new( + "active_logging_profile_count_invalid", + format!( + "active logging profile '{}' must match exactly one profile", + document.active_profile + ), + )); + } + return std::result::Result::Ok(()); +} + +fn validate_logging_config(config: &crate::LoggingConfig) -> ks_core::Result<()> { + match validate_log_level(&config.default_level, "logging.default_level") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + if config.targets.is_empty() { + return std::result::Result::Err(ks_core::Error::new( + "logging_targets_empty", + "at least one logging target is required", + )); + } + let mut enabled_count = 0_u32; + let mut names = std::collections::BTreeSet::::new(); + for target in &config.targets { + if target.enabled { + enabled_count += 1; + } + if !names.insert(target.name.clone()) { + return std::result::Result::Err(ks_core::Error::new( + "logging_target_duplicate", + target.name.clone(), + )); + } + match validate_log_target(target) { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + } + for filter in &config.target_filters { + match require_non_empty(&filter.target, "logging.target_filters.target") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + match validate_log_level(&filter.level, "logging.target_filters.level") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + } + if enabled_count == 0 { + return std::result::Result::Err(ks_core::Error::new( + "logging_no_enabled_targets", + "at least one logging target must be enabled", + )); + } + return std::result::Result::Ok(()); +} + +fn validate_log_target(config: &crate::LogTargetConfig) -> ks_core::Result<()> { + match require_non_empty(&config.name, "logging.targets.name") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + match validate_log_level(&config.level, "logging.targets.level") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + if config.sink != "console" && config.sink != "file" { + return std::result::Result::Err(ks_core::Error::new( + "logging_sink_invalid", + config.sink.clone(), + )); + } + if config.rotation != "none" + && config.rotation != "never" + && config.rotation != "daily" + && config.rotation != "hourly" + { + return std::result::Result::Err(ks_core::Error::new( + "logging_rotation_invalid", + config.rotation.clone(), + )); + } + if config.format != "human" + && config.format != "compact" + && config.format != "pretty" + && config.format != "json" + { + return std::result::Result::Err(ks_core::Error::new( + "logging_format_invalid", + config.format.clone(), + )); + } + if config.sink == "file" && config.path.trim().is_empty() { + return std::result::Result::Err(ks_core::Error::new( + "logging_file_path_empty", + config.name.clone(), + )); + } + if config.sink == "console" && !config.path.trim().is_empty() { + return std::result::Result::Err(ks_core::Error::new( + "logging_console_path_not_empty", + config.name.clone(), + )); + } + for target in &config.targets { + match require_non_empty(target, "logging.targets.targets") { + std::result::Result::Ok(()) => (), + std::result::Result::Err(error) => return std::result::Result::Err(error), + } + } + return std::result::Result::Ok(()); +} + +fn validate_log_level(value: &str, field_name: &str) -> ks_core::Result<()> { + if value == "trace" + || value == "debug" + || value == "info" + || value == "warn" + || value == "error" + || value == "off" + { + return std::result::Result::Ok(()); + } + return std::result::Result::Err(ks_core::Error::new( + "log_level_invalid", + format!("{field_name}: {value}"), + )); +} + +fn require_non_empty(value: &str, field_name: &str) -> ks_core::Result<()> { + if value.trim().is_empty() { + return std::result::Result::Err(ks_core::Error::new( + "logging_config_field_empty", + field_name.to_string(), + )); + } + return std::result::Result::Ok(()); +} + +#[cfg(test)] +mod tests { + const DEFAULT_LOGGING_CONFIG: &str = include_str!("../../config/logging.config.json"); + const EXAMPLE_LOGGING_CONFIG: &str = include_str!("../../config/example.logging.config.json"); + + fn parse_default_value() -> serde_json::Value { + let result = serde_json::from_str::(DEFAULT_LOGGING_CONFIG); + return match result { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("default logging config must be JSON: {error}"), + }; + } + + fn value_to_json(value: &serde_json::Value) -> std::string::String { + let result = serde_json::to_string(value); + return match result { + std::result::Result::Ok(raw_json) => raw_json, + std::result::Result::Err(error) => panic!("test logging value must serialize: {error}"), + }; + } + + fn tracing_crate_names() -> std::vec::Vec { + let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let workspace_root = match manifest_dir.parent() { + std::option::Option::Some(path) => path, + std::option::Option::None => panic!("workspace root must exist"), + }; + let read_result = std::fs::read_dir(workspace_root); + let entries = match read_result { + std::result::Result::Ok(entries) => entries, + std::result::Result::Err(error) => panic!("workspace must be readable: {error}"), + }; + let mut names = std::vec::Vec::::new(); + for entry_result in entries { + let entry = match entry_result { + std::result::Result::Ok(entry) => entry, + std::result::Result::Err(error) => panic!("workspace entry must be readable: {error}"), + }; + let cargo_path = entry.path().join("Cargo.toml"); + if !cargo_path.is_file() { + continue; + } + let cargo_result = std::fs::read_to_string(&cargo_path); + let cargo_toml = match cargo_result { + std::result::Result::Ok(content) => content, + std::result::Result::Err(error) => panic!("Cargo.toml must be readable: {error}"), + }; + if !cargo_toml.lines().any(|line| return line.trim() == "tracing.workspace = true") { + continue; + } + let mut in_package = false; + for line in cargo_toml.lines() { + let trimmed = line.trim(); + if trimmed == "[package]" { + in_package = true; + continue; + } + if in_package && trimmed.starts_with('[') { + break; + } + if in_package && trimmed.starts_with("name = ") { + names.push(trimmed.trim_start_matches("name = ").trim_matches('"').to_string()); + break; + } + } + } + names.sort(); + return names; + } + + #[test] + fn logging_schema_text_is_valid_json() { + let result = super::logging_json_schema_value(); + assert!(result.is_ok()); + } + + #[test] + fn default_and_example_logging_configs_validate_against_schema() { + assert!(super::validate_logging_json_schema(DEFAULT_LOGGING_CONFIG).is_ok()); + assert!(super::validate_logging_json_schema(EXAMPLE_LOGGING_CONFIG).is_ok()); + } + + #[test] + fn logging_profiles_are_independent_and_active_profile_resolves() { + let document_result = super::parse_logging_json(DEFAULT_LOGGING_CONFIG); + let document = match document_result { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("default logging config must parse: {error}"), + }; + assert_eq!(document.active_profile, "mainnet_research"); + assert_eq!(document.profiles.len(), 3); + assert!(super::active_logging_profile(&document).is_ok()); + } + + #[test] + fn default_logging_config_routes_global_and_operational_crate_files() { + let document_result = super::parse_logging_json(DEFAULT_LOGGING_CONFIG); + let document = match document_result { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("default logging config must parse: {error}"), + }; + let operational_crates = tracing_crate_names(); + assert!(!operational_crates.is_empty()); + for profile in document.profiles { + let directory = match profile.name.as_str() { + "local_devnet" => "devnet", + "mainnet_research" => "mainnet_research", + "mainnet" => "mainnet", + value => panic!("unexpected logging profile: {value}"), + }; + for (suffix, level, format) in [ + ("debug.log", "debug", "human"), + ("info.log", "info", "human"), + ("error.jsonl", "error", "json"), + ] { + let expected_path = format!("logs/{directory}/{suffix}"); + assert!(profile.config.targets.iter().any(|target| { + return target.enabled + && target.path == expected_path + && target.level == level + && target.format == format + && target.targets == std::vec!["*".to_string()]; + })); + } + assert!(profile.config.targets.iter().any(|target| { + return target.enabled + && target.path == format!("logs/{directory}/app.log") + && target.level == "debug" + && target.format == "human" + && target.targets == std::vec!["kb-app-demo-desktop".to_string()]; + })); + for crate_name in &operational_crates { + for (suffix, level, format) in [ + ("debug.log", "debug", "human"), + ("info.log", "info", "human"), + ("error.jsonl", "error", "json"), + ] { + let route_directory = if crate_name == "ks-pipeline-demo-scenarios" { + "ks-pipeline" + } else { + crate_name.as_str() + }; + let expected_path = format!("logs/{directory}/{route_directory}/{suffix}"); + let route_exists = profile.config.targets.iter().any(|target| { + return target.enabled + && target.path == expected_path + && target.level == level + && target.format == format + && target.targets.iter().any(|value| return value == crate_name); + }); + assert!( + route_exists, + "logging profile {} is missing the canonical {} route for {} at {}", + profile.name, level, crate_name, expected_path + ); + } + } + } + } + + #[test] + fn default_logging_config_uses_canonical_wallet_and_pipeline_routes() { + assert!(!DEFAULT_LOGGING_CONFIG.contains("api-key=95e73621")); + assert!(!DEFAULT_LOGGING_CONFIG.contains("\"ks_wallet\"")); + assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-wallet\"")); + assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-pipeline\"")); + assert!(DEFAULT_LOGGING_CONFIG.contains("logs/devnet/ks-pipeline/debug.log")); + assert!(DEFAULT_LOGGING_CONFIG.contains("logs/mainnet_research/ks-pipeline/info.log")); + assert!(DEFAULT_LOGGING_CONFIG.contains("logs/mainnet/ks-pipeline/error.jsonl")); + assert!(!DEFAULT_LOGGING_CONFIG.contains("ks_pipeline")); + } + + #[test] + fn logging_parser_rejects_missing_active_profile() { + let mut value = parse_default_value(); + value["active_profile"] = serde_json::Value::String("missing_profile".to_string()); + let result = super::parse_logging_json(&value_to_json(&value)); + assert!(result.is_err()); + } + + #[test] + fn logging_parser_rejects_duplicate_profile_names() { + let mut value = parse_default_value(); + value["profiles"][1]["name"] = serde_json::Value::String("local_devnet".to_string()); + let result = super::parse_logging_json(&value_to_json(&value)); + assert!(result.is_err()); + } + + #[test] + fn logging_parser_rejects_file_target_without_path() { + let mut value = parse_default_value(); + value["profiles"][0]["targets"][1]["path"] = serde_json::Value::String("".to_string()); + let result = super::parse_logging_json(&value_to_json(&value)); + assert!(result.is_err()); + } +} diff --git a/ks-logging/src/lib.rs b/ks-logging/src/lib.rs index be0c0df..27b5297 100644 --- a/ks-logging/src/lib.rs +++ b/ks-logging/src/lib.rs @@ -1,5 +1,5 @@ // file: ks-logging/src/lib.rs -// version: 7 +// version: 8 //! Logging and tracing initialization for applications and workers. #![warn(missing_docs)] @@ -8,6 +8,7 @@ mod config; mod constants; +mod document; mod tracing_runtime; /// Canonical tracing target for this crate. @@ -21,6 +22,26 @@ pub use self::config::LogTargetConfig; pub use self::config::LogTargetFilterConfig; /// Exposes the logging configuration consumed by this crate. pub use self::config::LoggingConfig; +/// Exposes the root independent logging configuration document. +pub use self::document::LoggingConfigDocument; +/// Exposes one named logging profile. +pub use self::document::LoggingProfileConfig; +/// Exposes active logging profile resolution. +pub use self::document::active_logging_profile; +/// Exposes the embedded logging JSON Schema text. +pub use self::document::logging_json_schema_text; +/// Exposes the embedded logging JSON Schema parser. +pub use self::document::logging_json_schema_value; +/// Exposes logging configuration parsing from JSON. +pub use self::document::parse_logging_json; +/// Exposes logging configuration loading from a filesystem path. +pub use self::document::read_logging_json_file; +/// Exposes logging loading with workspace environment resolution. +pub use self::document::read_logging_json_file_with_environment; +/// Exposes typed logging document validation. +pub use self::document::validate_logging_document; +/// Exposes logging JSON Schema validation. +pub use self::document::validate_logging_json_schema; /// Exposes the guard that keeps non-blocking logging workers alive. pub use self::tracing_runtime::LoggingGuard; /// Exposes initialization from a raw logging configuration section. diff --git a/ks-pipeline-demo-scenarios/CHANGELOG.md b/ks-pipeline-demo-scenarios/CHANGELOG.md index 96482cb..004bd98 100644 --- a/ks-pipeline-demo-scenarios/CHANGELOG.md +++ b/ks-pipeline-demo-scenarios/CHANGELOG.md @@ -1,8 +1,13 @@ - + # CHANGELOG — ks-pipeline-demo-scenarios +## `0.5.1-pre.005` + +- aligne les scénarios et fixtures sur `config/app.config.json` comme document général par défaut ; +- conserve `KS_DEVNET_CONFIG_PATH` comme override du document applicatif des scénarios, sans dépendre du document logging. + ## `0.5.1-pre.004` - migre les paramètres d'environnement des scénarios réutilisables vers `KS_*` et les DSN de test vers `KS_SECRET_*` ; diff --git a/ks-pipeline-demo-scenarios/USAGE.md b/ks-pipeline-demo-scenarios/USAGE.md index 3d03ca7..b859e9d 100644 --- a/ks-pipeline-demo-scenarios/USAGE.md +++ b/ks-pipeline-demo-scenarios/USAGE.md @@ -1,5 +1,5 @@ - + # Utilisation de ks-pipeline-demo-scenarios @@ -113,7 +113,7 @@ KS_SECRET_POSTGRES_TEST_URL='postgresql://…' \ cargo test -p ks-pipeline-demo-scenarios optional_devnet_token_2022_metadata_campaign_from_env -- --nocapture ``` -`KS_DEVNET_PROFILE` peut sélectionner explicitement le profil Devnet et `KS_DEVNET_CONFIG_PATH` peut remplacer `config/example.config.json`. Le profil doit utiliser un wallet persistant, autoriser les soumissions Devnet et respecter les plafonds de dépense et de frais. +`KS_DEVNET_PROFILE` peut sélectionner explicitement le profil Devnet et `KS_DEVNET_CONFIG_PATH` peut remplacer `config/app.config.json`. Le profil doit utiliser un wallet persistant, autoriser les soumissions Devnet et respecter les plafonds de dépense et de frais. La sortie `TOKEN_2022_METADATA_FIXTURE` conserve le mint et la signature de préparation. Chaque ligne `TOKEN_2022_METADATA_STEP` conserve l’opération, la signature, le slot, la postcondition, le nombre de matérialisations et, pour `Emit`, la taille du `returnData`. La campagne de référence de `pre.012` a été exécutée avec succès et ses preuves sont conservées dans `SPL_TOKEN_2022_METADATA_DEVNET_VALIDATION_MATRIX.json` et dans le rapport `docs/validation/V0_4_8_METADATA_VALIDATION_REPORT.md` ; le rapport détaillé `pre.012` est archivé sous `olddocs/archivekbot3/docs/validation/`. Une nouvelle exécution produit de nouvelles transactions et ne remplace ces preuves qu’après validation explicite. diff --git a/ks-pipeline-demo-scenarios/src/environment.rs b/ks-pipeline-demo-scenarios/src/environment.rs index 046c41b..88c68ed 100644 --- a/ks-pipeline-demo-scenarios/src/environment.rs +++ b/ks-pipeline-demo-scenarios/src/environment.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/environment.rs -// version: 4 +// version: 5 //! Environment initialization for opt-in demonstration scenarios. @@ -151,7 +151,7 @@ pub async fn prepare_demo_devnet_profile_store( #[cfg(test)] mod tests { fn example_config() -> ks_config::AppConfig { - return match ks_config::parse_config_json(include_str!("../../config/example.config.json")) + return match ks_config::parse_config_json(include_str!("../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs index 61bcc00..acbe406 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/collection_verify_campaign.rs -// version: 3 +// version: 4 //! Confirmed Devnet collection parent/member `Verify -> Unverify` campaign. @@ -648,7 +648,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs index 167b33e..7f27937 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/create_mint_campaign.rs -// version: 11 +// version: 12 //! Confirmed Devnet `Create -> Mint` campaign for one Metaplex asset family. @@ -813,7 +813,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs index d38d803..5ee48e7 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/devnet_execution.rs -// version: 19 +// version: 20 //! Real Devnet simulation and submission for current Metaplex Token Metadata operations. @@ -1267,7 +1267,7 @@ fn validate_available_signers( mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = match ks_config::parse_config_json(include_str!( - "../../../../config/example.config.json" + "../../../../config/app.config.json" )) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs index d7abc9f..0ec675f 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/escrow_campaign.rs -// version: 3 +// version: 4 //! Confirmed Devnet Token Owned Escrow campaign for current Metaplex escrow operations. @@ -973,7 +973,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs index c98a362..c5f2d8f 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/maintenance_campaign.rs -// version: 5 +// version: 6 //! Final bounded Devnet qualification campaign for current Metaplex maintenance operations. @@ -577,7 +577,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs index 356206c..f92e84a 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/pnft_lifecycle_campaign.rs -// version: 5 +// version: 6 //! Confirmed Devnet pNFT delegate, lock, unlock, revoke and transfer campaign. @@ -1071,7 +1071,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs index 01e73e9..e170219 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/print_burn_campaign.rs -// version: 6 +// version: 7 //! Devnet printable master NFT `Print -> Burn` campaign. @@ -1180,7 +1180,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs index 61d9343..383c7d9 100644 --- a/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs +++ b/ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/metadata/metaplex_token_metadata/use_campaign.rs -// version: 3 +// version: 4 //! Bounded Devnet availability probe for the current Metaplex `Use` surface. @@ -425,7 +425,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline-demo-scenarios/src/solana.rs b/ks-pipeline-demo-scenarios/src/solana.rs index e016355..83bf8d6 100644 --- a/ks-pipeline-demo-scenarios/src/solana.rs +++ b/ks-pipeline-demo-scenarios/src/solana.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/solana.rs -// version: 13 +// version: 14 //! Devnet Solana execution orchestration with canonical post-validation. @@ -1225,7 +1225,7 @@ pub(crate) fn emit( mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = - match ks_config::parse_config_json(include_str!("../../config/example.config.json")) { + match ks_config::parse_config_json(include_str!("../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), }; diff --git a/ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs b/ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs index 4b33b39..84417d3 100644 --- a/ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs +++ b/ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/spl/associated_token_account.rs -// version: 12 +// version: 13 //! Devnet ATA execution with stateful and canonical post-validation. @@ -994,7 +994,7 @@ mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = - match ks_config::parse_config_json(include_str!("../../../config/example.config.json")) + match ks_config::parse_config_json(include_str!("../../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/spl/memo.rs b/ks-pipeline-demo-scenarios/src/spl/memo.rs index adb3d8b..af515e9 100644 --- a/ks-pipeline-demo-scenarios/src/spl/memo.rs +++ b/ks-pipeline-demo-scenarios/src/spl/memo.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/spl/memo.rs -// version: 8 +// version: 9 //! Devnet SPL Memo v4 execution with canonical post-validation. @@ -755,7 +755,7 @@ fn decode_completed(summary: &ks_pipeline::DecodeReplaySummary) -> bool { mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = - match ks_config::parse_config_json(include_str!("../../../config/example.config.json")) + match ks_config::parse_config_json(include_str!("../../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/spl/token/execution.rs b/ks-pipeline-demo-scenarios/src/spl/token/execution.rs index dcb8ba9..264ff72 100644 --- a/ks-pipeline-demo-scenarios/src/spl/token/execution.rs +++ b/ks-pipeline-demo-scenarios/src/spl/token/execution.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/spl/token/execution.rs -// version: 12 +// version: 13 //! Devnet classic SPL Token execution with stateful and canonical post-validation. @@ -975,7 +975,7 @@ pub(crate) fn decode_completed(summary: &ks_pipeline::DecodeReplaySummary) -> bo mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = match ks_config::parse_config_json(include_str!( - "../../../../config/example.config.json" + "../../../../config/app.config.json" )) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs b/ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs index 044316e..b7cd250 100644 --- a/ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs +++ b/ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/spl/token/lifecycle.rs -// version: 11 +// version: 12 //! Controlled Devnet lifecycle for freshly prepared classic SPL Token accounts. @@ -1688,7 +1688,7 @@ mod tests { fn example_devnet_profile() -> ks_config::ProfileConfig { let config = match ks_config::parse_config_json(include_str!( - "../../../../config/example.config.json" + "../../../../config/app.config.json" )) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), diff --git a/ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs b/ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs index facc17b..90ebe68 100644 --- a/ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs +++ b/ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs @@ -1,5 +1,5 @@ // file: ks-pipeline-demo-scenarios/src/spl/token_2022/metadata/campaign.rs -// version: 6 +// version: 7 //! Ordered confirmed Devnet campaign for the five Token-2022 Token Metadata instructions. @@ -502,7 +502,7 @@ mod tests { let path = std::path::PathBuf::from(value); if path.is_absolute() { path } else { workspace_root.join(path) } }, - std::result::Result::Err(_) => workspace_root.join("config/example.config.json"), + std::result::Result::Err(_) => workspace_root.join("config/app.config.json"), }; let config = ks_config::read_config_json_file_with_environment( config_path.as_path(), diff --git a/ks-pipeline/CHANGELOG.md b/ks-pipeline/CHANGELOG.md index 77ed20e..14f9985 100644 --- a/ks-pipeline/CHANGELOG.md +++ b/ks-pipeline/CHANGELOG.md @@ -1,8 +1,13 @@ - + # CHANGELOG — ks-pipeline +## `0.5.1-pre.005` + +- aligne les tests de configuration sur le nouveau document général `config/app.config.json` après extraction du logging ; +- ne modifie aucune orchestration ou qualification réseau. + ## `0.5.1-pre.004` - migre les variables des tests Devnet SPL Token vers le namespace interne `KS_*` ; diff --git a/ks-pipeline/src/spl_token_stateful.rs b/ks-pipeline/src/spl_token_stateful.rs index 67a7726..d7f61ab 100644 --- a/ks-pipeline/src/spl_token_stateful.rs +++ b/ks-pipeline/src/spl_token_stateful.rs @@ -1,5 +1,5 @@ // file: ks-pipeline/src/spl_token_stateful.rs -// version: 4 +// version: 5 //! Stateful Localnet and Devnet readiness checks for classic SPL Token operations. @@ -1440,7 +1440,7 @@ mod tests { fn local_devnet_profile() -> ks_config::ProfileConfig { let config = - match ks_config::parse_config_json(include_str!("../../config/example.config.json")) { + match ks_config::parse_config_json(include_str!("../../config/app.config.json")) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("example config parse failed: {error}"), }; diff --git a/prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md b/prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md index 493ab68..65072bd 100644 --- a/prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md +++ b/prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md @@ -1,5 +1,5 @@ - + # Khadhroony Bot3 — `0.5.1` — migration Khadhroony Solana et configuration sûre @@ -61,7 +61,7 @@ Le workspace, le dépôt et le répertoire racine restent nommés `khadhroony-bo - `VERSION_DEVELOPMENT_LIFECYCLE.md` ; 4. `docs/architecture/PROJECT_OBJECTIVES.md`, `CRATE_MAP.md`, `ARCHITECTURE.md`, `PIPELINE_ARCHITECTURE.md`, `STORAGE_ARCHITECTURE.md` et `SURFACE_CRATE_MATRIX.md` ; 5. `README.md`, `USAGE.md`, `TODO.md` et `CHANGELOG.md` des dix crates à renommer et de `kb-app-demo-desktop` ; -6. `config/example.config.json`, `config/schema.config.json`, `.env.example` et tous les exemples/configurations de test ; +6. `config/app.config.json`, `config/logging.config.json`, leurs schémas sous `config/schemas/`, `.env.example` et tous les exemples/configurations de test ; 7. les tests d'API externe, tests TS-RS, scripts d'audit et références de noms de crates/targets/identités ; 8. les documents archivés `0.5.0` uniquement comme historique, jamais comme source prioritaire face à la politique active et au code courant. diff --git a/scripts/audit_khadhroony_workspace_rules.py b/scripts/audit_khadhroony_workspace_rules.py index 6c1bc45..366a158 100755 --- a/scripts/audit_khadhroony_workspace_rules.py +++ b/scripts/audit_khadhroony_workspace_rules.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # file: scripts/audit_khadhroony_workspace_rules.py -# version: 20 +# version: 21 """Audit mechanically verifiable rules specific to khadhroony-bot3.""" @@ -562,7 +562,7 @@ def audit_materializer_conventions(root: pathlib.Path) -> list[Violation]: f"materializer tracing target `{match.group(1)}` must equal one component name", ) ) - config_path = root / "config/example.config.json" + config_path = root / "config/logging.config.json" if config_path.exists(): try: config = json.loads(config_path.read_text(encoding="utf-8")) @@ -583,7 +583,7 @@ def audit_materializer_conventions(root: pathlib.Path) -> list[Violation]: violations.append( Violation( "KH_MT020", - "config/example.config.json", + "config/logging.config.json", 1, f"logging target `{target}` is not a declared materializer component", ) @@ -906,10 +906,17 @@ def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]: f"workspace environment example `{match.group(1)}` must use a `KS_*` or `KB_*` namespace", ) ) - config = root / "config/example.config.json" - if config.is_file(): + placeholder = re.compile(r"\$\{([A-Z][A-Z0-9_]*)") + for relative in [ + "config/app.config.json", + "config/logging.config.json", + "config/example.app.config.json", + "config/example.logging.config.json", + ]: + config = root / relative + if not config.is_file(): + continue text = config.read_text(encoding="utf-8") - placeholder = re.compile(r"\$\{([A-Z][A-Z0-9_]*)") for match in placeholder.finditer(text): name = match.group(1) if name.startswith(("KS_", "KB_")): @@ -917,7 +924,7 @@ def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]: violations.append( Violation( "KH_ENV003", - "config/example.config.json", + relative, text[: match.start()].count("\n") + 1, f"configuration placeholder `{name}` must use a `KS_*` or `KB_*` namespace", ) @@ -941,6 +948,86 @@ def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]: return violations +def audit_configuration_split(root: pathlib.Path) -> list[Violation]: + """Require the independent application and logging configuration contract.""" + + violations: list[Violation] = [] + required_files = [ + "config/app.config.json", + "config/logging.config.json", + "config/example.app.config.json", + "config/example.logging.config.json", + "config/schemas/app.config.schema.json", + "config/schemas/logging.config.schema.json", + ] + for relative in required_files: + if (root / relative).is_file(): + continue + violations.append( + Violation( + "KH_CFG001", + relative, + 1, + "required split configuration file is missing", + ) + ) + app_path = root / "config/app.config.json" + if app_path.is_file(): + try: + app = json.loads(app_path.read_text(encoding="utf-8")) + except json.JSONDecodeError: + app = None + if isinstance(app, dict): + for index, profile in enumerate(app.get("profiles", []), 1): + if isinstance(profile, dict) and "logging" in profile: + violations.append( + Violation( + "KH_CFG002", + "config/app.config.json", + index, + "application profiles must not embed logging configuration", + ) + ) + logging_path = root / "config/logging.config.json" + if logging_path.is_file(): + try: + logging = json.loads(logging_path.read_text(encoding="utf-8")) + except json.JSONDecodeError: + logging = None + if isinstance(logging, dict): + if not isinstance(logging.get("active_profile"), str): + violations.append( + Violation( + "KH_CFG003", + "config/logging.config.json", + 1, + "logging configuration must define its own active_profile", + ) + ) + if not isinstance(logging.get("profiles"), list) or not logging.get("profiles"): + violations.append( + Violation( + "KH_CFG004", + "config/logging.config.json", + 1, + "logging configuration must define independent named profiles", + ) + ) + legacy = ["config/example.config.json", "config/schema.config.json"] + for relative in legacy: + if not (root / relative).exists(): + continue + violations.append( + Violation( + "KH_CFG005", + relative, + 1, + "legacy combined configuration file must be removed after the split", + ) + ) + return violations + + def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]: """Require the currently compatible Solana wincode dependency family.""" @@ -1024,6 +1111,7 @@ def main() -> int: +audit_private_ks_lib_paths_in_active_docs(root) +audit_solana_types(root) +audit_environment_namespaces(root) + +audit_configuration_split(root) +audit_wincode_resolution(root) ) violations.sort(key=lambda item: (item.code, item.path, item.line, item.message))